[PATCH/RFC future] nptl: reinstate SIGCANCEL/SIGSETXID safeguards

Peter Mazinger ps.m at gmx.net
Tue May 10 21:06:40 UTC 2011


Hi,

> 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?

no comment ;-)

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

I am for only one implementation (that should go only into libc), else you have unpredictable/different results depending on which linking order you choose libc/libpthread

Peter
> 
> 
> 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);
> }

-- 
Empfehlen Sie GMX DSL Ihren Freunden und Bekannten und wir
belohnen Sie mit bis zu 50,- Euro! https://freundschaftswerbung.gmx.de


More information about the uClibc mailing list