2.1.91: SIGKILL and SIGSTOP are blockable

Andrew Lewycky (alewycky@globalserve.net)
Sun, 05 Apr 1998 18:00:58 -0400


I just discovered that a process can become unkillable by putting
SIGKILL into
the sa_mask field of a sigaction, and then looping or whatever in the
signal
handler. According to /proc/pid/status, all of the first 32 signals are
blocked,
and the process no longer responds to kill -9, etc.

Surely it isn't supposed to work like this?

The reason is that neither sys_sigaction, nor do_signal check the
sa_mask for
these signals, while send_sig_info always checks against t->blocked
before
setting t->sigpending to 1 (kernel/signal.c, lines 341-2).

The fix is trivial: (I hope. I haven't tested it since I would have to
upgrade
to 2.1.92, which is causing me trouble. (I'm starting to suspect my
compiler.))

--- signal.c Sun Apr 5 17:30:52 1998
+++ signal.c Sun Apr 5 17:36:32 1998
@@ -788,6 +788,9 @@

if (act) {
*k = *act;
+ /* Don't let the user block SIGKILL or SIGSTOP
+ * even while handling a signal. */
+ k->sa.sa_mask.sig[0] &= ~(SIGKILL | SIGSTOP);

/*
* POSIX 3.3.1.3:

A program to demonstrate this problem follows. Once you have run it, it
can't
bekilled. I suggest renicing it to 20 until you can reboot.

Andrew Lewycky
alewycky@globalserve.net

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

void handler(int dummy)
{
printf("in handler\n");
while (1) ;
}

int main(int argc, char *argv[])
{
struct sigaction newsig, oldsig;

newsig.sa_handler = handler;
newsig.sa_flags = SA_RESTART;
sigfillset(&newsig.sa_mask);
newsig.sa_restorer = NULL;

sigaction(SIGUSR1, &newsig, &oldsig);

raise(SIGUSR1);

return 0;
}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu