aboutsummaryrefslogtreecommitdiff
path: root/sys/amd64/linux32/linux32_sysvec.c
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2009-10-27 10:47:58 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2009-10-27 10:47:58 +0000
commitd6e029adbef6c202441fc41b455610b4cc906ca5 (patch)
tree359a5b0885ae5a789f55ba40dc485621e67c34b1 /sys/amd64/linux32/linux32_sysvec.c
parent84440afb54cdee80c5515edf360a4c60d526d0ff (diff)
downloadsrc-d6e029adbef6c202441fc41b455610b4cc906ca5.tar.gz
src-d6e029adbef6c202441fc41b455610b4cc906ca5.zip
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
Notes
Notes: svn path=/head/; revision=198507
Diffstat (limited to 'sys/amd64/linux32/linux32_sysvec.c')
-rw-r--r--sys/amd64/linux32/linux32_sysvec.c18
1 files changed, 6 insertions, 12 deletions
diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c
index 54a04eea5810..6e3e32622bf0 100644
--- a/sys/amd64/linux32/linux32_sysvec.c
+++ b/sys/amd64/linux32/linux32_sysvec.c
@@ -565,9 +565,9 @@ 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;
+ sigset_t bmask;
l_sigset_t lmask;
int eflags, i;
ksiginfo_t ksi;
@@ -623,11 +623,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.
@@ -666,9 +663,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;
@@ -725,11 +722,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