diff options
| author | Linus Torvalds <torvalds@home.transmeta.com> | 2003-02-16 19:51:37 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2003-02-16 19:51:37 -0800 |
| commit | 2c707d9bf1f45ce6cec9eb99e4a288e5aef87929 (patch) | |
| tree | 3a3c95eda2f2b4c7f23cba3d7d28ee40369ff850 /kernel | |
| parent | 00742b03fdb9a1ad038b7fc713df0112a03116f1 (diff) | |
Fix locking for "send_sig_info()", to avoid possible races with signal
state changes due to execve() and exit(). We need to hold the tasklist
lock to guarantee stability of "task->sighand".
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/signal.c | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index b8fc6a05c031..b7ac6a557ddb 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1109,21 +1109,31 @@ static int kill_something_info(int sig, struct siginfo *info, int pid) * These are for backward compatibility with the rest of the kernel source. */ +/* + * XXX should probably nix these interfaces and update the kernel + * to specify explicitly whether the signal is a group signal or + * specific to a thread. + */ int send_sig_info(int sig, struct siginfo *info, struct task_struct *p) { int ret; - /* XXX should nix these interfaces and update the kernel */ + /* + * We need the tasklist lock even for the specific + * thread case (when we don't need to follow the group + * lists) in order to avoid races with "p->sighand" + * going away or changing from under us. + */ + read_lock(&tasklist_lock); if (T(sig, SIG_KERNEL_BROADCAST_MASK)) { - read_lock(&tasklist_lock); ret = group_send_sig_info(sig, info, p); - read_unlock(&tasklist_lock); } else { spin_lock_irq(&p->sighand->siglock); ret = specific_send_sig_info(sig, info, p); spin_unlock_irq(&p->sighand->siglock); } + read_unlock(&tasklist_lock); return ret; } |
