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