x86: Allow users to change PSL_RF via ptrace(PT_SETREGS...)

Debuggers may need to change PSL_RF.  Note that tf_eflags is already stored
in the signal context during signal handling and PSL_RF previously could be
modified via sigreturn, so this change should not provide any new ability
to userspace.

For background see the thread at:
http://lists.freebsd.org/pipermail/freebsd-i386/2007-September/005910.html

Reviewed by:	jhb, kib
Sponsored by:	DARPA, AFRL
This commit is contained in:
Ed Maste 2013-11-14 15:37:20 +00:00
parent e4e01d9cec
commit 3d271aaab0
8 changed files with 24 additions and 146 deletions

View File

@ -486,17 +486,7 @@ sys_sigreturn(td, uap)
/*
* Don't allow users to change privileged or reserved flags.
*/
/*
* XXX do allow users to change the privileged flag PSL_RF.
* The cpu sets PSL_RF in tf_rflags for faults. Debuggers
* should sometimes set it there too. tf_rflags is kept in
* the signal context during signal handling and there is no
* other place to remember it, so the PSL_RF bit may be
* corrupted by the signal handler without us knowing.
* Corruption of the PSL_RF bit at worst causes one more or
* one less debugger trap, so allowing it is fairly harmless.
*/
if (!EFL_SECURE(rflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) {
if (!EFL_SECURE(rflags, regs->tf_rflags)) {
uprintf("pid %d (%s): sigreturn rflags = 0x%lx\n", p->p_pid,
td->td_name, rflags);
return (EINVAL);

View File

@ -719,7 +719,7 @@ ofreebsd32_sigreturn(struct thread *td, struct ofreebsd32_sigreturn_args *uap)
return (error);
scp = ≻
eflags = scp->sc_eflags;
if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) {
if (!EFL_SECURE(eflags, regs->tf_rflags)) {
return (EINVAL);
}
if (!CS_SECURE(scp->sc_cs)) {
@ -787,17 +787,7 @@ freebsd4_freebsd32_sigreturn(td, uap)
/*
* Don't allow users to change privileged or reserved flags.
*/
/*
* XXX do allow users to change the privileged flag PSL_RF.
* The cpu sets PSL_RF in tf_eflags for faults. Debuggers
* should sometimes set it there too. tf_eflags is kept in
* the signal context during signal handling and there is no
* other place to remember it, so the PSL_RF bit may be
* corrupted by the signal handler without us knowing.
* Corruption of the PSL_RF bit at worst causes one more or
* one less debugger trap, so allowing it is fairly harmless.
*/
if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) {
if (!EFL_SECURE(eflags, regs->tf_rflags)) {
uprintf("pid %d (%s): freebsd4_freebsd32_sigreturn eflags = 0x%x\n",
td->td_proc->p_pid, td->td_name, eflags);
return (EINVAL);
@ -873,17 +863,7 @@ freebsd32_sigreturn(td, uap)
/*
* Don't allow users to change privileged or reserved flags.
*/
/*
* XXX do allow users to change the privileged flag PSL_RF.
* The cpu sets PSL_RF in tf_eflags for faults. Debuggers
* should sometimes set it there too. tf_eflags is kept in
* the signal context during signal handling and there is no
* other place to remember it, so the PSL_RF bit may be
* corrupted by the signal handler without us knowing.
* Corruption of the PSL_RF bit at worst causes one more or
* one less debugger trap, so allowing it is fairly harmless.
*/
if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) {
if (!EFL_SECURE(eflags, regs->tf_rflags)) {
uprintf("pid %d (%s): freebsd32_sigreturn eflags = 0x%x\n",
td->td_proc->p_pid, td->td_name, eflags);
return (EINVAL);

View File

@ -587,17 +587,7 @@ linux_sigreturn(struct thread *td, struct linux_sigreturn_args *args)
*/
#define EFLAGS_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
eflags = frame.sf_sc.sc_eflags;
/*
* XXX do allow users to change the privileged flag PSL_RF. The
* cpu sets PSL_RF in tf_eflags for faults. Debuggers should
* sometimes set it there too. tf_eflags is kept in the signal
* context during signal handling and there is no other place
* to remember it, so the PSL_RF bit may be corrupted by the
* signal handler without us knowing. Corruption of the PSL_RF
* bit at worst causes one more or one less debugger trap, so
* allowing it is fairly harmless.
*/
if (!EFLAGS_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF))
if (!EFLAGS_SECURE(eflags, regs->tf_rflags))
return(EINVAL);
/*
@ -689,17 +679,7 @@ linux_rt_sigreturn(struct thread *td, struct linux_rt_sigreturn_args *args)
*/
#define EFLAGS_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
eflags = context->sc_eflags;
/*
* XXX do allow users to change the privileged flag PSL_RF. The
* cpu sets PSL_RF in tf_eflags for faults. Debuggers should
* sometimes set it there too. tf_eflags is kept in the signal
* context during signal handling and there is no other place
* to remember it, so the PSL_RF bit may be corrupted by the
* signal handler without us knowing. Corruption of the PSL_RF
* bit at worst causes one more or one less debugger trap, so
* allowing it is fairly harmless.
*/
if (!EFLAGS_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF))
if (!EFLAGS_SECURE(eflags, regs->tf_rflags))
return(EINVAL);
/*

View File

@ -842,17 +842,7 @@ osigreturn(td, uap)
/*
* Don't allow users to change privileged or reserved flags.
*/
/*
* XXX do allow users to change the privileged flag PSL_RF.
* The cpu sets PSL_RF in tf_eflags for faults. Debuggers
* should sometimes set it there too. tf_eflags is kept in
* the signal context during signal handling and there is no
* other place to remember it, so the PSL_RF bit may be
* corrupted by the signal handler without us knowing.
* Corruption of the PSL_RF bit at worst causes one more or
* one less debugger trap, so allowing it is fairly harmless.
*/
if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) {
if (!EFL_SECURE(eflags, regs->tf_eflags)) {
return (EINVAL);
}
@ -968,17 +958,7 @@ freebsd4_sigreturn(td, uap)
/*
* Don't allow users to change privileged or reserved flags.
*/
/*
* XXX do allow users to change the privileged flag PSL_RF.
* The cpu sets PSL_RF in tf_eflags for faults. Debuggers
* should sometimes set it there too. tf_eflags is kept in
* the signal context during signal handling and there is no
* other place to remember it, so the PSL_RF bit may be
* corrupted by the signal handler without us knowing.
* Corruption of the PSL_RF bit at worst causes one more or
* one less debugger trap, so allowing it is fairly harmless.
*/
if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) {
if (!EFL_SECURE(eflags, regs->tf_eflags)) {
uprintf("pid %d (%s): freebsd4_sigreturn eflags = 0x%x\n",
td->td_proc->p_pid, td->td_name, eflags);
return (EINVAL);
@ -1082,17 +1062,7 @@ sys_sigreturn(td, uap)
/*
* Don't allow users to change privileged or reserved flags.
*/
/*
* XXX do allow users to change the privileged flag PSL_RF.
* The cpu sets PSL_RF in tf_eflags for faults. Debuggers
* should sometimes set it there too. tf_eflags is kept in
* the signal context during signal handling and there is no
* other place to remember it, so the PSL_RF bit may be
* corrupted by the signal handler without us knowing.
* Corruption of the PSL_RF bit at worst causes one more or
* one less debugger trap, so allowing it is fairly harmless.
*/
if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) {
if (!EFL_SECURE(eflags, regs->tf_eflags)) {
uprintf("pid %d (%s): sigreturn eflags = 0x%x\n",
td->td_proc->p_pid, td->td_name, eflags);
return (EINVAL);

View File

@ -113,7 +113,7 @@ struct vm86context {
} pmap[VM86_PMAPSIZE];
};
#define VM_USERCHANGE (PSL_USERCHANGE | PSL_RF)
#define VM_USERCHANGE (PSL_USERCHANGE)
#define VME_USERCHANGE (VM_USERCHANGE | PSL_VIP | PSL_VIF)
struct vm86_kernel {

View File

@ -684,17 +684,7 @@ linux_sigreturn(struct thread *td, struct linux_sigreturn_args *args)
*/
#define EFLAGS_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
eflags = frame.sf_sc.sc_eflags;
/*
* XXX do allow users to change the privileged flag PSL_RF. The
* cpu sets PSL_RF in tf_eflags for faults. Debuggers should
* sometimes set it there too. tf_eflags is kept in the signal
* context during signal handling and there is no other place
* to remember it, so the PSL_RF bit may be corrupted by the
* signal handler without us knowing. Corruption of the PSL_RF
* bit at worst causes one more or one less debugger trap, so
* allowing it is fairly harmless.
*/
if (!EFLAGS_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF))
if (!EFLAGS_SECURE(eflags, regs->tf_eflags))
return(EINVAL);
/*
@ -785,17 +775,7 @@ linux_rt_sigreturn(struct thread *td, struct linux_rt_sigreturn_args *args)
*/
#define EFLAGS_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
eflags = context->sc_eflags;
/*
* XXX do allow users to change the privileged flag PSL_RF. The
* cpu sets PSL_RF in tf_eflags for faults. Debuggers should
* sometimes set it there too. tf_eflags is kept in the signal
* context during signal handling and there is no other place
* to remember it, so the PSL_RF bit may be corrupted by the
* signal handler without us knowing. Corruption of the PSL_RF
* bit at worst causes one more or one less debugger trap, so
* allowing it is fairly harmless.
*/
if (!EFLAGS_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF))
if (!EFLAGS_SECURE(eflags, regs->tf_eflags))
return(EINVAL);
/*

View File

@ -773,17 +773,7 @@ osigreturn(td, uap)
/*
* Don't allow users to change privileged or reserved flags.
*/
/*
* XXX do allow users to change the privileged flag PSL_RF.
* The cpu sets PSL_RF in tf_eflags for faults. Debuggers
* should sometimes set it there too. tf_eflags is kept in
* the signal context during signal handling and there is no
* other place to remember it, so the PSL_RF bit may be
* corrupted by the signal handler without us knowing.
* Corruption of the PSL_RF bit at worst causes one more or
* one less debugger trap, so allowing it is fairly harmless.
*/
if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) {
if (!EFL_SECURE(eflags, regs->tf_eflags)) {
return (EINVAL);
}
@ -899,17 +889,7 @@ freebsd4_sigreturn(td, uap)
/*
* Don't allow users to change privileged or reserved flags.
*/
/*
* XXX do allow users to change the privileged flag PSL_RF.
* The cpu sets PSL_RF in tf_eflags for faults. Debuggers
* should sometimes set it there too. tf_eflags is kept in
* the signal context during signal handling and there is no
* other place to remember it, so the PSL_RF bit may be
* corrupted by the signal handler without us knowing.
* Corruption of the PSL_RF bit at worst causes one more or
* one less debugger trap, so allowing it is fairly harmless.
*/
if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) {
if (!EFL_SECURE(eflags, regs->tf_eflags)) {
uprintf("pid %d (%s): freebsd4_sigreturn eflags = 0x%x\n",
td->td_proc->p_pid, td->td_name, eflags);
return (EINVAL);
@ -1013,17 +993,7 @@ sys_sigreturn(td, uap)
/*
* Don't allow users to change privileged or reserved flags.
*/
/*
* XXX do allow users to change the privileged flag PSL_RF.
* The cpu sets PSL_RF in tf_eflags for faults. Debuggers
* should sometimes set it there too. tf_eflags is kept in
* the signal context during signal handling and there is no
* other place to remember it, so the PSL_RF bit may be
* corrupted by the signal handler without us knowing.
* Corruption of the PSL_RF bit at worst causes one more or
* one less debugger trap, so allowing it is fairly harmless.
*/
if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) {
if (!EFL_SECURE(eflags, regs->tf_eflags)) {
uprintf("pid %d (%s): sigreturn eflags = 0x%x\n",
td->td_proc->p_pid, td->td_name, eflags);
return (EINVAL);

View File

@ -77,8 +77,16 @@
* is undesirable but it may as well be allowed since users can inflict
* it on the kernel directly. Changes to PSL_AC are silently ignored on
* 386's.
*
* Users are allowed to change the privileged flag PSL_RF. The cpu sets PSL_RF
* in tf_eflags for faults. Debuggers should sometimes set it there too.
* tf_eflags is kept in the signal context during signal handling and there is
* no other place to remember it, so the PSL_RF bit may be corrupted by the
* signal handler without us knowing. Corruption of the PSL_RF bit at worst
* causes one more or one less debugger trap, so allowing it is fairly
* harmless.
*/
#define PSL_USERCHANGE (PSL_C | PSL_PF | PSL_AF | PSL_Z | PSL_N | PSL_T \
| PSL_D | PSL_V | PSL_NT | PSL_AC | PSL_ID)
| PSL_D | PSL_V | PSL_NT | PSL_RF | PSL_AC | PSL_ID)
#endif /* !_MACHINE_PSL_H_ */