Couple more data points to muddy the waters:

x86 glibc 2.11.1 (same result for -pthread and non -pthread):

sigfillset refused to set: 32 (Unknown signal 32)
sigfillset refused to set: 33 (Unknown signal 33)
sigprocmask refused to mask: 9 (Killed)
sigprocmask refused to mask: 19 (Stopped (signal))
sending SIGINT
sending SIGQUIT
caught sig 3 (Quit)

MIPS uClibc 0.9.32-rc3 unpatched, built with -pthread:

sigfillset refused to set: 32 (Unknown signal 32)
sigfillset refused to set: 33 (Unknown signal 33)
sigprocmask refused to mask: 9 (Killed)
sigprocmask refused to mask: 23 (Stopped (signal))
sigprocmask refused to mask: 32 (Unknown signal 32)
sigprocmask refused to mask: 33 (Unknown signal 33)
sending SIGINT
sending SIGQUIT
caught sig 3 (Quit)

MIPS uClibc 0.9.32-rc3 unpatched, built without -pthread:

sigprocmask refused to mask: 9 (Killed)
sigprocmask refused to mask: 23 (Stopped (signal))
sending SIGINT
sending SIGQUIT
caught sig 3 (Quit)

MIPS uClibc 0.9.32-rc3 with Austin's patch + my patch (same result for
-pthread and non -pthread):

sigfillset refused to set: 32 (Unknown signal 32)
sigfillset refused to set: 33 (Unknown signal 33)
sigprocmask refused to mask: 9 (Killed)
sigprocmask refused to mask: 23 (Stopped (signal))
sigprocmask refused to mask: 32 (Unknown signal 32)
sigprocmask refused to mask: 33 (Unknown signal 33)
sending SIGINT
sending SIGQUIT
caught sig 3 (Quit)


glibc has two sigprocmask implementations:

./sysdeps/unix/sysv/linux/sigprocmask.c - this has the same SIGCANCEL
and SIGSETXID code as uClibc but does not include pthreadP.h, so the
extra checks remain inactive.

./nptl/sysdeps/pthread/sigprocmask.c is just:

#include <nptl/pthreadP.h>
#include <sysdeps/unix/sysv/linux/sigprocmask.c>

So the latter implementation will refuse to mask SIGCANCEL +
SIGSETXID.  But the former implementation gets built into libc, and
the latter implementation never gets built.  Therefore glibc
sigprocmask() does NOT block tampering with SIGCANCEL/SIGSETXID.


glibc also has two sigfillset implementations:

./signal/sigfillset.c - this has the same SIGCANCEL and SIGSETXID code
as uClibc but does not include pthreadP.h, so the extra checks remain
inactive.

./nptl/sysdeps/pthread/sigfillset.c is just:

#include <nptl/pthreadP.h>
#include <signal/sigfillset.c>

So the latter implementation will refuse to mask SIGCANCEL +
SIGSETXID.  The latter implementation gets built into libc, and the
former implementation never gets built by itself.  Therefore glibc
sigfillset() DOES avoid setting bits for SIGCANCEL/SIGSETXID.


I am left wondering:

1) How much of the observed glibc behavior is the result of an
explicit design decision?  Or did it wind up working this way by
accident?

2) How much of the observed glibc behavior should we try to emulate in uClibc?


Updated test program:

-- 8< --

#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

void fn(int sig, siginfo_t *si, void *vctx)
{
        printf("caught sig %d (%s)\n", sig, strsignal(sig));
        exit(0);
}

int main(int argc, char **argv)
{
        sigset_t s, old;
        struct sigaction sa, sa_old;
        int i;

        /* see if sigfillset/sigaddset/sigprocmask skip certain signals */

        sigfillset(&s);
        for (i = 1; i <= SIGRTMAX; i++)
                if (!sigismember(&s, i))
                        printf("sigfillset refused to set: %d (%s)\n",
                                i, strsignal(i));

        /* try to fill in the holes left by sigfillset() */
        for (i = 1; i <= SIGRTMAX; i++) {
                sigaddset(&s, i);
                if (!sigismember(&s, i))
                        printf("sigaddset refused to set: %d (%s)\n",
                                i, strsignal(i));
        }
        sigprocmask(SIG_BLOCK, &s, &old);
        sigprocmask(SIG_BLOCK, NULL, &s);
        for (i = 1; i <= SIGRTMAX; i++) {
                if (!sigismember(&s, i))
                        printf("sigprocmask refused to mask: %d (%s)\n",
                                i, strsignal(i));
        }

        /* send ourselves a signal to see if sigaction works properly */

        sigfillset(&s);
        sigdelset(&s, SIGQUIT);
        sigprocmask(SIG_SETMASK, &s, &old);

        memset(&sa, 0, sizeof(sa));
        sa.sa_sigaction = fn;
        sa.sa_flags = SA_SIGINFO;
        sigaction(SIGQUIT, &sa, &sa_old);

        printf("sending SIGINT\n");
        usleep(100000);
        kill(0, SIGINT);
        usleep(100000);

        printf("sending SIGQUIT\n");
        usleep(100000);
        kill(0, SIGQUIT);
        usleep(100000);

        printf("failed to catch SIGQUIT\n");
        exit(1);
}
_______________________________________________
uClibc mailing list
uClibc@uclibc.org
http://lists.busybox.net/mailman/listinfo/uclibc

Reply via email to