Bugtraq mailing list archives

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


From: Glynn Clements <glynn () gclements plus com>
Date: Fri, 17 Aug 2007 14:37:30 +0100


Dan Yefimov wrote:

However, the bug in question allows sending signals which cannot be
blocked or ignored (SIGKILL, SIGSTOP). Moreover, the cause (PDEATHSIG)
cannot be disabled

Really? An what if we fork right after startup and perform operations as a 
child?

That would work, but might have undesirable consequences of its own. 

In particular, it prevents a non-malicious caller from using PDEATHSIG
to send e.g. SIGINT, which the setuid program may reasonably handle.

SIGKILL and SIGSTOP cannot be blocked, handled or ignored.

As for SIGKILL, I again repeat that the program must operate in a fail safe way 
when that makes sense.

It's really a question of whether it's possible rather than "making
sense". Eliminating critical sections is desirable, but it isn't
always possible.

BTW, SIGKILL and SIGSTOP can be issued by an O_ASYNC file I/O also (look in 
fcntl(2) at F_SETSIG section). If you use F_SETSIG for sending SIGKILL or 
SIGSTOP, there's nothing to be done with that - that behaviour is well 
documented and setuid root program must know which file descriptor should be 
closed to prevent that, which is of course not possible. The only cure here is 
closing every file descriptor above 2, but that is still insufficient, since 
fcntl() might be issued on file descriptors from 0 to 2.

The fcntl(2) manpage says:

    Sending  a  signal  to  the  owner  process (group) specified by
    F_SETOWN is subject  to  the  same  permissions  checks  as  are
    described for kill(2), where the sending process is the one that
    employs F_SETOWN (but see BUGS below).

Also, note the use of the term "permissions checks"; this is
considered a security mechanism.

Signals
which don't terminate the process may still have undesirable
consequences, e.g. use of SIGUSR1 as a secure signalling mechanism (at
least, it's supposed to be secure).

Supposed by whom and why? Where is the guarantee? As I said previously, 
arbitrary signal can be issued in a couple of ways.

Here's a hint: EPERM is amongst the possible error codes for kill().
Also, the capabilities(7) manpage lists:

       CAP_KILL
              Bypass permission checks  for  sending  signals  (see  kill(2)).
              This includes use of the KDSIGACCEPT ioctl.

Again, use of the term "permissions checks".

The ability to send signals to a process is subject to security
restrictions. Therefore, any bug which allows these restrictions to be
bypassed is a security bug.

Linux attempts to apply similar checks to PDEATHSIG, but this bug
allows them to be circumvented.

Sending asynchronous signals to setuid/setgid children is supposed to
be impossible, and that restriction is considered a security
mechanism.

And this IS generally impossible. Once spawned setuid root binary that will
send a signal while dying, you have no control over the moment the signal is 
being sent at. The exploitation scenario for this bug is a bit artificial.

IMO, privilege elevation is a security issue regardless of whether or
not one can provide a "useful" scenario immediately upon the issue
becoming known.

-- 
Glynn Clements <glynn () gclements plus com>


Current thread: