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>