summaryrefslogtreecommitdiffstats
path: root/sys/i386/linux/linux_sysvec.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2009-10-27 10:47:58 +0000
committerkib <kib@FreeBSD.org>2009-10-27 10:47:58 +0000
commitce081b037e7a762f0dd090a207cafc5121f39f51 (patch)
tree359a5b0885ae5a789f55ba40dc485621e67c34b1 /sys/i386/linux/linux_sysvec.c
parenteb4c68098b66d84de3abc7be00acfdc6d2f8f980 (diff)
downloadFreeBSD-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/i386/linux/linux_sysvec.c')
-rw-r--r--sys/i386/linux/linux_sysvec.c18
1 files changed, 6 insertions, 12 deletions
diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c
index d07f655..069b5bb 100644
--- a/sys/i386/linux/linux_sysvec.c
+++ b/sys/i386/linux/linux_sysvec.c
@@ -667,10 +667,10 @@ linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
int
linux_sigreturn(struct thread *td, struct linux_sigreturn_args *args)
{
- struct proc *p = td->td_proc;
struct l_sigframe frame;
struct trapframe *regs;
l_sigset_t lmask;
+ sigset_t bmask;
int eflags, i;
ksiginfo_t ksi;
@@ -725,11 +725,8 @@ linux_sigreturn(struct thread *td, struct linux_sigreturn_args *args)
lmask.__bits[0] = frame.sf_sc.sc_mask;
for (i = 0; i < (LINUX_NSIG_WORDS-1); i++)
lmask.__bits[i+1] = frame.sf_extramask[i];
- PROC_LOCK(p);
- linux_to_bsd_sigset(&lmask, &td->td_sigmask);
- SIG_CANTMASK(td->td_sigmask);
- signotify(td);
- PROC_UNLOCK(p);
+ linux_to_bsd_sigset(&lmask, &bmask);
+ kern_sigprocmask(td, SIG_SETMASK, &bmask, NULL, 0);
/*
* Restore signal context.
@@ -767,9 +764,9 @@ linux_sigreturn(struct thread *td, struct linux_sigreturn_args *args)
int
linux_rt_sigreturn(struct thread *td, struct linux_rt_sigreturn_args *args)
{
- struct proc *p = td->td_proc;
struct l_ucontext uc;
struct l_sigcontext *context;
+ sigset_t bmask;
l_stack_t *lss;
stack_t ss;
struct trapframe *regs;
@@ -826,11 +823,8 @@ linux_rt_sigreturn(struct thread *td, struct linux_rt_sigreturn_args *args)
return(EINVAL);
}
- PROC_LOCK(p);
- linux_to_bsd_sigset(&uc.uc_sigmask, &td->td_sigmask);
- SIG_CANTMASK(td->td_sigmask);
- signotify(td);
- PROC_UNLOCK(p);
+ linux_to_bsd_sigset(&uc.uc_sigmask, &bmask);
+ kern_sigprocmask(td, SIG_SETMASK, &bmask, NULL, 0);
/*
* Restore signal context
OpenPOWER on IntegriCloud