diff options
author | kib <kib@FreeBSD.org> | 2009-10-27 10:47:58 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2009-10-27 10:47:58 +0000 |
commit | ce081b037e7a762f0dd090a207cafc5121f39f51 (patch) | |
tree | 359a5b0885ae5a789f55ba40dc485621e67c34b1 /sys/amd64/ia32 | |
parent | eb4c68098b66d84de3abc7be00acfdc6d2f8f980 (diff) | |
download | FreeBSD-src-ce081b037e7a762f0dd090a207cafc5121f39f51.zip FreeBSD-src-ce081b037e7a762f0dd090a207cafc5121f39f51.tar.gz |
In r197963, a race with thread being selected for signal delivery
while in kernel mode, and later changing signal mask to block the
signal, was fixed for sigprocmask(2) and ptread_exit(3). The same race
exists for sigreturn(2), setcontext(2) and swapcontext(2) syscalls.
Use kern_sigprocmask() instead of direct manipulation of td_sigmask to
reschedule newly blocked signals, closing the race.
Reviewed by: davidxu
Tested by: pho
MFC after: 1 month
Diffstat (limited to 'sys/amd64/ia32')
-rw-r--r-- | sys/amd64/ia32/ia32_signal.c | 30 |
1 files changed, 8 insertions, 22 deletions
diff --git a/sys/amd64/ia32/ia32_signal.c b/sys/amd64/ia32/ia32_signal.c index d7c1dd5..10ec641 100644 --- a/sys/amd64/ia32/ia32_signal.c +++ b/sys/amd64/ia32/ia32_signal.c @@ -244,10 +244,8 @@ freebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap) if (ret == 0) { ret = ia32_set_mcontext(td, &uc.uc_mcontext); if (ret == 0) { - SIG_CANTMASK(uc.uc_sigmask); - PROC_LOCK(td->td_proc); - td->td_sigmask = uc.uc_sigmask; - PROC_UNLOCK(td->td_proc); + kern_sigprocmask(td, SIG_SETMASK, + &uc.uc_sigmask, NULL, 0); } } } @@ -273,10 +271,8 @@ freebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap) if (ret == 0) { ret = ia32_set_mcontext(td, &uc.uc_mcontext); if (ret == 0) { - SIG_CANTMASK(uc.uc_sigmask); - PROC_LOCK(td->td_proc); - td->td_sigmask = uc.uc_sigmask; - PROC_UNLOCK(td->td_proc); + kern_sigprocmask(td, SIG_SETMASK, + &uc.uc_sigmask, NULL, 0); } } } @@ -544,9 +540,8 @@ freebsd4_freebsd32_sigreturn(td, uap) } */ *uap; { struct ia32_ucontext4 uc; - struct proc *p = td->td_proc; struct trapframe *regs; - const struct ia32_ucontext4 *ucp; + struct ia32_ucontext4 *ucp; int cs, eflags, error; ksiginfo_t ksi; @@ -610,11 +605,7 @@ freebsd4_freebsd32_sigreturn(td, uap) regs->tf_fs = ucp->uc_mcontext.mc_fs; regs->tf_gs = ucp->uc_mcontext.mc_gs; - PROC_LOCK(p); - td->td_sigmask = ucp->uc_sigmask; - SIG_CANTMASK(td->td_sigmask); - signotify(td); - PROC_UNLOCK(p); + kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0); td->td_pcb->pcb_full_iret = 1; return (EJUSTRETURN); } @@ -631,9 +622,8 @@ freebsd32_sigreturn(td, uap) } */ *uap; { struct ia32_ucontext uc; - struct proc *p = td->td_proc; struct trapframe *regs; - const struct ia32_ucontext *ucp; + struct ia32_ucontext *ucp; int cs, eflags, error, ret; ksiginfo_t ksi; @@ -702,11 +692,7 @@ freebsd32_sigreturn(td, uap) regs->tf_gs = ucp->uc_mcontext.mc_gs; regs->tf_flags = TF_HASSEGS; - PROC_LOCK(p); - td->td_sigmask = ucp->uc_sigmask; - SIG_CANTMASK(td->td_sigmask); - signotify(td); - PROC_UNLOCK(p); + kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0); td->td_pcb->pcb_full_iret = 1; return (EJUSTRETURN); } |