This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Fix nptl :: sighandler_setxid() to handle negated pids
- From: Suzuki <suzuki at in dot ibm dot com>
- To: libc <libc-alpha at sources dot redhat dot com>
- Cc: Ulrich Drepper <drepper at redhat dot com>, Roland McGrath <roland at redhat dot com>, sripathi at in dot ibm dot com, Suresh Kodati <skodati at in dot ibm dot com>
- Date: Fri, 07 Apr 2006 19:08:00 +0530
- Subject: Fix nptl :: sighandler_setxid() to handle negated pids
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;