Bugtraq mailing list archives

Re: COSEINC Linux Advisory #1: Linux Kernel Parent Process Death Signal Vulnerability


From: Dan Yefimov <dan () ns15 lightwave net ru>
Date: Tue, 14 Aug 2007 22:20:32 +0400 (MSD)

On Tue, 14 Aug 2007, Wojciech Purczynski wrote:


===[ ABSTRACT ]=========================================================

An unprivileged local user may send arbitrary signal to a child process
despite security restrictions.


===[ AFFECTED SOFTWARE ]================================================

Linux 2.6
Linux 2.4

For the exact kernel version please refer to an information provided by
your vendor.


===[ DESCRIPTION ]======================================================

Typically unprivileged user can not send signal to processes running
with different UID. Due to vulnerability found in the Linux kernel any
local user may bypass security restrictions and send arbitrary signal to
any child process executed by the user.

When a parent process dies or exits its child processes may receive a
signal.  Each child process may choose and set its own "parent process
death signal" using PR_SET_PDEATHSIG function of the prctl() system
call.

      PARENT          CHILD
      ----------------------------------------------------------------
      fork()
                      prctl(PR_SET_PDEATHSIG)
      exit()'ed or killed
                      child receives the signal

The parent process death signal is not reset over execve() system call
and is inherited by spawned process:

      PARENT          CHILD
      ----------------------------------------------------------------
      fork()
                      prctl(PR_SET_PDEATHSIG)
                      execve("./a.out")
      exit()'ed or killed
                      child receives the signal

The signal gets delivered only if parent process has sufficient
privileges to send signals to child processes. Typically any child
process running with higher privilege than its parent will receive no
signal.

      PARENT          CHILD
      ----------------------------------------------------------------
      fork()
                      prctl(PR_SET_PDEATHSIG)
                      execve("/bin/setuid-binary")
      exit()'ed or killed
                      child receives NO signal this time

However, above restriction may be bypassed if parent process execute
setuid-root binary which dies afterwards.

      PARENT          CHILD
      ----------------------------------------------------------------
      fork()
                      prctl(PR_SET_PDEATHSIG)
                      execve("/bin/setuid-binary")
      execve("/bin/setuid-binary")
      exit()'ed or killed
                      privileged process receives the signal


I'm not sure this is a real security issue. If some process has the same 
effective UID as the given one, the former can always send any signal to the 
latter. Thus the behaviour you described is IMHO normal. If setuid program just 
trusts the environment in that it doesn't properly handle or block signals 
whose default action is terminating the process and doesn't perform it's
actions in a fail-safe manner, it is certainly broken. Setuid program must 
always be careful in signal handling and data processing. From another hand, 
PDEATHSIG should be always reset on exec() like signal handlers are (I'm not 
sure though if that is directly specified by any standard). Please correct me
if I'm wrong.
-- 

    Sincerely Your, Dan.


Current thread: