> And p_sigmask is copied during fork, so that needs a bit of thought.
> I guess it doesn't matter for the new child, as it isn't running yet
> and therefore can't invoke sigprocmask(2).  And the parent should be
> safe as well, as it is in fork(2) and therefore can't call
> sigprocmask(2) either.

memcpy(p_startcopy) which is, tadaaa, p_sigmask!  From implementations
of memcpy I've seen (usage of SSE or non-temporal instructions to begin
with) it seems that no guarantee about how big a chunk does it copy
atomically can be assumed...

So a multithreaded process doing sigprocmask(2) in one thread and
simultaneously fork(2) in the other?  Not a problem either, because
1003.1 2004 edition says that sigprocmask(2) is equivalent to
pthread_sigmask(3) and the fork only copies the other thread, not
bothering with the sigprocmask-ing one.
I haven't checked the code that thoroughly but this is what POSIX says.

> There's also a couple of additional p->p_sigmask |= ... in kern_sig.c.
> 
> All of these need to become atomic_setbits_int/atomic_clearbits_int calls.

Does the third one do the charm?  I haven't compiled the other arch's,
but i386 is running fine.
--
Martin Pelikan


Index: arch/hp300/hp300/trap.c
===================================================================
RCS file: /cvs/src/sys/arch/hp300/hp300/trap.c,v
retrieving revision 1.62
diff -u -p -r1.62 trap.c
--- arch/hp300/hp300/trap.c     31 Dec 2012 06:46:13 -0000      1.62
+++ arch/hp300/hp300/trap.c     20 Jun 2013 12:51:46 -0000
@@ -321,7 +321,7 @@ dopanic:
                i = sigmask(SIGILL);
                p->p_sigacts->ps_sigignore &= ~i;
                p->p_sigacts->ps_sigcatch &= ~i;
-               p->p_sigmask &= ~i;
+               atomic_clearbits_int(&p->p_sigmask, i);
                i = SIGILL;
                ucode = frame.f_format; /* XXX was ILL_RESAD_FAULT */
                typ = ILL_COPROC;
Index: arch/mvme68k/mvme68k/trap.c
===================================================================
RCS file: /cvs/src/sys/arch/mvme68k/mvme68k/trap.c,v
retrieving revision 1.77
diff -u -p -r1.77 trap.c
--- arch/mvme68k/mvme68k/trap.c 31 Dec 2012 06:46:13 -0000      1.77
+++ arch/mvme68k/mvme68k/trap.c 20 Jun 2013 12:51:47 -0000
@@ -260,7 +260,7 @@ copyfault:
                i = sigmask(SIGILL);
                p->p_sigacts->ps_sigignore &= ~i;
                p->p_sigacts->ps_sigcatch &= ~i;
-               p->p_sigmask &= ~i;
+               atomic_clearbits_int(&p->p_sigmask, i);
                i = SIGILL;
                ucode = frame.f_format; /* XXX was ILL_RESAD_FAULT */
                typ = ILL_COPROC;
Index: compat/linux/linux_signal.c
===================================================================
RCS file: /cvs/src/sys/compat/linux/linux_signal.c,v
retrieving revision 1.15
diff -u -p -r1.15 linux_signal.c
--- compat/linux/linux_signal.c 19 Jun 2012 11:35:29 -0000      1.15
+++ compat/linux/linux_signal.c 20 Jun 2013 12:51:49 -0000
@@ -584,7 +584,6 @@ linux_sys_sigprocmask(p, v, retval)
        linux_old_sigset_t ss;
        sigset_t bs;
        int error = 0;
-       int s;
 
        *retval = 0;
 
@@ -604,19 +603,18 @@ linux_sys_sigprocmask(p, v, retval)
 
        linux_old_to_bsd_sigset(&ss, &bs);
 
-       s = splhigh();
-
+       bs &= ~sigcantmask;
        switch (SCARG(uap, how)) {
        case LINUX_SIG_BLOCK:
-               p->p_sigmask |= bs & ~sigcantmask;
+               atomic_setbits_int(&p->p_sigmask, bs);
                break;
 
        case LINUX_SIG_UNBLOCK:
-               p->p_sigmask &= ~bs;
+               atomic_clearbits_int(&p->p_sigmask, bs);
                break;
 
        case LINUX_SIG_SETMASK:
-               p->p_sigmask = bs & ~sigcantmask;
+               p->p_sigmask = bs;
                break;
 
        default:
@@ -624,8 +622,6 @@ linux_sys_sigprocmask(p, v, retval)
                break;
        }
 
-       splx(s);
-
        return (error);
 }
 
@@ -644,7 +640,6 @@ linux_sys_rt_sigprocmask(p, v, retval)
        linux_sigset_t ls;
        sigset_t bs;
        int error = 0;
-       int s;
 
        if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
                return (EINVAL);
@@ -667,19 +662,18 @@ linux_sys_rt_sigprocmask(p, v, retval)
 
        linux_to_bsd_sigset(&ls, &bs);
 
-       s = splhigh();
-
+       bs &= ~sigcantmask;
        switch (SCARG(uap, how)) {
        case LINUX_SIG_BLOCK:
-               p->p_sigmask |= bs & ~sigcantmask;
+               atomic_setbits_int(&p->p_sigmask, bs);
                break;
 
        case LINUX_SIG_UNBLOCK:
-               p->p_sigmask &= ~bs;
+               atomic_clearbits_int(&p->p_sigmask, bs);
                break;
 
        case LINUX_SIG_SETMASK:
-               p->p_sigmask = bs & ~sigcantmask;
+               p->p_sigmask = bs;
                break;
 
        default:
@@ -687,8 +681,6 @@ linux_sys_rt_sigprocmask(p, v, retval)
                break;
        }
 
-       splx(s);
-
        return (error);
 }
 
@@ -727,16 +719,13 @@ linux_sys_sigsetmask(p, v, retval)
        } */ *uap = v;
        linux_old_sigset_t mask;
        sigset_t bsdsig;
-       int s;
 
        bsd_to_linux_old_sigset(&p->p_sigmask, (linux_old_sigset_t *)retval);
 
        mask = SCARG(uap, mask);
        bsd_to_linux_old_sigset(&bsdsig, &mask);
 
-       s = splhigh();
        p->p_sigmask = bsdsig & ~sigcantmask;
-       splx(s);
 
        return (0);
 }
Index: kern/init_sysent.c
===================================================================
RCS file: /cvs/src/sys/kern/init_sysent.c,v
retrieving revision 1.145
diff -u -p -r1.145 init_sysent.c
--- kern/init_sysent.c  9 Jun 2013 13:10:27 -0000       1.145
+++ kern/init_sysent.c  20 Jun 2013 12:51:49 -0000
@@ -136,7 +136,7 @@ struct sysent sysent[] = {
            sys_sigaction },                    /* 46 = sigaction */
        { 0, 0, 0,
            sys_getgid },                       /* 47 = getgid */
-       { 2, s(struct sys_sigprocmask_args), 0,
+       { 2, s(struct sys_sigprocmask_args), SY_NOLOCK | 0,
            sys_sigprocmask },                  /* 48 = sigprocmask */
        { 2, s(struct sys_getlogin_args), 0,
            sys_getlogin },                     /* 49 = getlogin */
Index: kern/kern_sig.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_sig.c,v
retrieving revision 1.152
diff -u -p -r1.152 kern_sig.c
--- kern/kern_sig.c     1 Jun 2013 04:05:26 -0000       1.152
+++ kern/kern_sig.c     20 Jun 2013 12:51:49 -0000
@@ -429,28 +429,25 @@ sys_sigprocmask(struct proc *p, void *v,
                syscallarg(sigset_t) mask;
        } */ *uap = v;
        int error = 0;
-       int s;
        sigset_t mask;
 
        *retval = p->p_sigmask;
-       mask = SCARG(uap, mask);
-       s = splhigh();
+       mask = SCARG(uap, mask) &~ sigcantmask;
 
        switch (SCARG(uap, how)) {
        case SIG_BLOCK:
-               p->p_sigmask |= mask &~ sigcantmask;
+               atomic_setbits_int(&p->p_sigmask, mask);
                break;
        case SIG_UNBLOCK:
-               p->p_sigmask &= ~mask;
+               atomic_clearbits_int(&p->p_sigmask, mask);
                break;
        case SIG_SETMASK:
-               p->p_sigmask = mask &~ sigcantmask;
+               p->p_sigmask = mask;
                break;
        default:
                error = EINVAL;
                break;
        }
-       splx(s);
        return (error);
 }
 
@@ -739,7 +736,7 @@ trapsignal(struct proc *p, int signum, u
                p->p_ru.ru_nsignals++;
                (*p->p_emul->e_sendsig)(ps->ps_sigact[signum], signum,
                    p->p_sigmask, trapno, code, sigval);
-               p->p_sigmask |= ps->ps_catchmask[signum];
+               atomic_setbits_int(&p->p_sigmask, ps->ps_catchmask[signum]);
                if ((ps->ps_sigreset & mask) != 0) {
                        ps->ps_sigcatch &= ~mask;
                        if (signum != SIGCONT && sigprop[signum] & SA_IGNORE)
@@ -1334,7 +1331,7 @@ postsig(int signum)
                } else {
                        returnmask = p->p_sigmask;
                }
-               p->p_sigmask |= ps->ps_catchmask[signum];
+               atomic_setbits_int(&p->p_sigmask, ps->ps_catchmask[signum]);
                if ((ps->ps_sigreset & mask) != 0) {
                        ps->ps_sigcatch &= ~mask;
                        if (signum != SIGCONT && sigprop[signum] & SA_IGNORE)
Index: kern/syscalls.master
===================================================================
RCS file: /cvs/src/sys/kern/syscalls.master,v
retrieving revision 1.133
diff -u -p -r1.133 syscalls.master
--- kern/syscalls.master        9 Jun 2013 13:10:19 -0000       1.133
+++ kern/syscalls.master        20 Jun 2013 12:51:49 -0000
@@ -123,7 +123,7 @@
                            const struct sigaction *nsa, \
                            struct sigaction *osa); }
 47     STD             { gid_t sys_getgid(void); }
-48     STD             { int sys_sigprocmask(int how, sigset_t mask); }
+48     STD NOLOCK      { int sys_sigprocmask(int how, sigset_t mask); }
 49     STD             { int sys_getlogin(char *namebuf, u_int namelen); }
 50     STD             { int sys_setlogin(const char *namebuf); }
 #ifdef ACCOUNTING

Reply via email to