Fix nptl :: sighandler_setxid() to handle negated pids
Suzuki
suzuki@in.ibm.com
Fri Apr 7 13:31:00 GMT 2006
Hi,
I was facing a hang with a multithreaded program (testcase to simulate
a problem we were facing) which is as follows :
The program spawns three threads, 2 of which sleeps indefinitely. The
next child thread does a fork. Now, the main thread does a setreuid().
This caused the application hang with glibc-2.3.3-98.61 (or later).
The main thread was waiting on futex() for the counter to become 0. The
forked thread was not doing the syscall as well as the futex(), even
though it recieved the signal.
The problem has the following root cause:
The setxid() calls are implemented by sending SIGSETXID signal to each
threads in the group, with signal handler as sighandler_setxid(). Now in
__libc_fork(), we set the pid in the THREAD_SELF(), to -pid before
issuing the syscall.
So, with 2.6 kernels, if the thread recieves the SIGSETXID signal while
doing a fork(),
static void
sighandler_setxid (int sig, siginfo_t *si, void *ctx)
{
/* Safety check. It would be possible to call this function for
other signals and send a signal from another process. This is not
correct and might even be a security problem. Try to catch as
many incorrect invocations as possible. */
if (sig != SIGSETXID
#ifdef __ASSUME_CORRECT_SI_PID
/* Kernels before 2.5.75 stored the thread ID and not the process
ID in si_pid so we skip this test. */
|| si->si_pid != THREAD_GETMEM (THREAD_SELF, pid)
The above condition would fail, which causes the thread to return
without doing the syscall and futex().
#endif
|| si->si_code != SI_TKILL)
return;
Attached here is a patch which I think could solve this issue.
Could you please comment on this ?
Thanks.
Suzuki K P <suzuki@in.ibm.com>
Linux Technology Centre,
IBM Software Labs,
* npt/init.c: Fix sighandler_setxid() to take care of negated pid in
THREAD_SELF while we are doing a fork().
--- nptl/init.c 2006-04-07 20:22:39.000000000 +0530
+++ nptl/init.c.mod 2006-04-07 21:02:39.000000000 +0530
@@ -195,12 +195,19 @@ sighandler_setxid (int sig, siginfo_t *s
/* Safety check. It would be possible to call this function for
other signals and send a signal from another process. This is not
correct and might even be a security problem. Try to catch as
- many incorrect invocations as possible. */
+ many incorrect invocations as possible. If we are in the middle
+ of a fork, the pid is stored negated. */
+#ifdef __ASSUME_CORRECT_SI_PID
+ pid_t pid = THREAD_GETMEM (THREAD_SELF, pid);
+ if (__builtin_expect (pid < 0, 0))
+ pid = -pid;
+#endif
+
if (sig != SIGSETXID
#ifdef __ASSUME_CORRECT_SI_PID
/* Kernels before 2.5.75 stored the thread ID and not the process
ID in si_pid so we skip this test. */
- || si->si_pid != THREAD_GETMEM (THREAD_SELF, pid)
+ || si->si_pid != pid
#endif
|| si->si_code != SI_TKILL)
return;
More information about the Libc-alpha
mailing list