From: Corey Minyard <minyard@acm.org>
To: linux-kernel@vger.kernel.org
Subject: Race in signal handling with reproducer program
Date: Fri, 12 Mar 2004 20:07:31 -0600 [thread overview]
Message-ID: <40526CE3.7000509@acm.org> (raw)
In-Reply-To: <404F8FDE.3050305@acm.org>
I have a program to reproduce this problem. The attached program will
segv pretty quickly on 2.4 and 2.6 kernels on SMP machines, and I assume
this is possible (although less likely) with preempt on a uniprocessor
(I could not reproduce the problem that way, but I didn't try very
hard). It ends up crashing because the program counter is set to
0x00000001, not surprisingly the value of SIG_IGN. Just to test and see
if the program was ok, I changed the SIG_IGN to a second signal handler
function and everything worked ok, so I think the program is valid.
The program below has three threads that share signal handlers. Thread
1 changes the signal handler for a signal from a handler to SIG_IGN and
back. Thread 0 sends signals to thread 3, which just receives them.
What I believe is happening is that thread 1 changes the signal handler
in the process of thread 3 receiving the signal, between the time that
thread 3 fetches the signal info using get_signal_to_deliver() and
actually delivers the signal with handle_signal().
Although the program is obvously an extreme case, it seems like any time
you set the handler value of a signal to SIG_IGN or SIG_DFL, you can
have this happen. Changing signal attributes might also cause problems,
although I am not so sure about that.
Has anyone seen this? Is there a fix available? It seems to me that to
fix this properly, get_signal_to_deliver() would have to return all the
information about the signal delivery and that's a pretty major change
that would affect all architectures.
The program....
#include <signal.h>
#include <stdio.h>
#include <sched.h>
char stack1[4096];
char stack2[4096];
void
sighnd(int sig)
{
}
int
child1(void *data)
{
struct sigaction act;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
for (;;) {
act.sa_handler = sighnd;
sigaction(45, &act, NULL);
act.sa_handler = SIG_IGN;
sigaction(45, &act, NULL);
}
}
int
child2(void *data)
{
for (;;) {
sleep(100);
}
}
int
main(int argc, char *argv[])
{
int pid1, pid2;
signal(45, SIG_IGN);
pid2 = clone(child2, stack2+4092, CLONE_SIGHAND | CLONE_VM, NULL);
pid1 = clone(child1, stack1+4092, CLONE_SIGHAND | CLONE_VM, NULL);
for (;;) {
kill(pid2, 45);
}
}
Corey Minyard wrote:
> I'm hoping I am wrong, but I think I have found a race in signal
> handling. I believe this can only happen in an SMP system or a system
> with preempt on. I'll use 2.6 for the example, but I think it applies
> to 2.4, too.
>
> In arch/i386/signal.c, in the do_signal() function, it calls
> get_signal_to_deliver() which returns the signal number to deliver
> (along with siginfo). get_signal_to_deliver() grabs and releases the
> lock, so the signal handler lock is not held in do_signal(). Then the
> do_signal() calls handle_signal(), which uses the signal number to
> extract the sa_handler, etc.
>
> Since no lock is held, it seems like another thread with the same
> signal handler set can come in and call sigaction(), it can change
> sa_handler between the call to get_signal_to_deliver() and fetching
> the value of sa_handler. If the sigaction() call set it to SIG_IGN,
> SIG_DFL, or some other fundamental change, that bad things can happen.
>
> Am I correct here, or am I missing something?
>
> -Corey
>
> -
> To unsubscribe from this list: send the line "unsubscribe
> linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
prev parent reply other threads:[~2004-03-13 2:07 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-03-10 21:59 Possible race in signal handling Corey Minyard
2004-03-13 2:07 ` Corey Minyard [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=40526CE3.7000509@acm.org \
--to=minyard@acm.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.