]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - kernel/signal.c
[SPARC64]: Fix cmsg length checks in Solaris emulation layer.
[linux-2.6-omap-h63xx.git] / kernel / signal.c
index e6567d7f2b623b53e5a73e168054b042ab89ac10..c89821b69ae3e10be8447d29d3f8bca893beb233 100644 (file)
@@ -23,6 +23,8 @@
 #include <linux/syscalls.h>
 #include <linux/ptrace.h>
 #include <linux/posix-timers.h>
+#include <linux/signal.h>
+#include <linux/audit.h>
 #include <asm/param.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -521,7 +523,16 @@ static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
 {
        int sig = 0;
 
-       sig = next_signal(pending, mask);
+       /* SIGKILL must have priority, otherwise it is quite easy
+        * to create an unkillable process, sending sig < SIGKILL
+        * to self */
+       if (unlikely(sigismember(&pending->signal, SIGKILL))) {
+               if (!sigismember(mask, SIGKILL))
+                       sig = SIGKILL;
+       }
+
+       if (likely(!sig))
+               sig = next_signal(pending, mask);
        if (sig) {
                if (current->notifier) {
                        if (sigismember(current->notifier_mask, sig)) {
@@ -646,7 +657,7 @@ static int check_kill_permission(int sig, struct siginfo *info,
                                 struct task_struct *t)
 {
        int error = -EINVAL;
-       if (sig < 0 || sig > _NSIG)
+       if (!valid_signal(sig))
                return error;
        error = -EPERM;
        if ((!info || ((unsigned long)info != 1 &&
@@ -657,7 +668,11 @@ static int check_kill_permission(int sig, struct siginfo *info,
            && (current->uid ^ t->suid) && (current->uid ^ t->uid)
            && !capable(CAP_KILL))
                return error;
-       return security_task_kill(t, info, sig);
+
+       error = security_task_kill(t, info, sig);
+       if (!error)
+               audit_signal_info(sig, t); /* Let audit system see the signal */
+       return error;
 }
 
 /* forward decl */
@@ -1245,7 +1260,7 @@ send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
         * Make sure legacy kernel users don't send in bad values
         * (normal paths check this in check_kill_permission).
         */
-       if (sig < 0 || sig > _NSIG)
+       if (!valid_signal(sig))
                return -EINVAL;
 
        /*
@@ -1520,7 +1535,7 @@ void do_notify_parent(struct task_struct *tsk, int sig)
                if (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN)
                        sig = 0;
        }
-       if (sig > 0 && sig <= _NSIG)
+       if (valid_signal(sig) && sig > 0)
                __group_send_sig_info(sig, &info, tsk->parent);
        __wake_up_parent(tsk, tsk->parent);
        spin_unlock_irqrestore(&psig->siglock, flags);
@@ -2364,7 +2379,7 @@ do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact)
 {
        struct k_sigaction *k;
 
-       if (sig < 1 || sig > _NSIG || (act && sig_kernel_only(sig)))
+       if (!valid_signal(sig) || sig < 1 || (act && sig_kernel_only(sig)))
                return -EINVAL;
 
        k = &current->sighand->action[sig-1];