]> git.hungrycats.org Git - linux/commitdiff
Fix locking for "send_sig_info()", to avoid possible races with signal
authorLinus Torvalds <torvalds@home.transmeta.com>
Mon, 17 Feb 2003 03:51:37 +0000 (19:51 -0800)
committerLinus Torvalds <torvalds@home.transmeta.com>
Mon, 17 Feb 2003 03:51:37 +0000 (19:51 -0800)
state changes due to execve() and exit(). We need to hold the tasklist
lock to guarantee stability of "task->sighand".

kernel/signal.c

index b8fc6a05c03157f9990329fe04599f518f4890df..b7ac6a557ddbcea6bf02f39ccc2bf6a188562278 100644 (file)
@@ -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;
 }