This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / kernel / signal.c
index cc50f25..a56f3d9 100644 (file)
@@ -436,6 +436,7 @@ flush_signal_handlers(struct task_struct *t, int force_default)
        }
 }
 
+EXPORT_SYMBOL_GPL(flush_signal_handlers);
 
 /* Notify the system that a driver wants to block all signals for this
  * process, and wants to be notified if any signals at all were to be
@@ -621,17 +622,28 @@ static int check_kill_permission(int sig, struct siginfo *info,
                                 struct task_struct *t)
 {
        int error = -EINVAL;
+       int user;
+
        if (sig < 0 || sig > _NSIG)
                return error;
+
+       user = (!info ||
+               (info != SEND_SIG_PRIV &&
+                info != SEND_SIG_FORCED &&
+                SI_FROMUSER(info)));
+
        error = -EPERM;
-       if ((!info || ((unsigned long)info != 1 &&
-                       (unsigned long)info != 2 && SI_FROMUSER(info)))
-           && ((sig != SIGCONT) ||
-               (current->signal->session != t->signal->session))
+       if (user && (sig != SIGCONT ||
+                    current->signal->session != t->signal->session)
            && (current->euid ^ t->suid) && (current->euid ^ t->uid)
            && (current->uid ^ t->suid) && (current->uid ^ t->uid)
            && !capable(CAP_KILL))
                return error;
+
+       error = -ESRCH;
+       if (user && !vx_check(vx_task_xid(t), VX_ADMIN|VX_IDENT))
+               return error;
+
        return security_task_kill(t, info, sig);
 }
 
@@ -1607,6 +1619,35 @@ void ptrace_notify(int exit_code)
        spin_unlock_irq(&current->sighand->siglock);
 }
 
+int print_fatal_signals = 0;
+
+static void print_fatal_signal(struct pt_regs *regs, int signr)
+{
+       int i;
+       unsigned char insn;
+       printk("%s/%d: potentially unexpected fatal signal %d.\n",
+               current->comm, current->pid, signr);
+
+#ifdef __i386__
+       printk("code at %08lx: ", regs->eip);
+       for (i = 0; i < 16; i++) {
+               __get_user(insn, (unsigned char *)(regs->eip + i));
+               printk("%02x ", insn);
+       }
+#endif
+       printk("\n");
+       show_regs(regs);
+}
+
+static int __init setup_print_fatal_signals(char *str)
+{
+       get_option (&str, &print_fatal_signals);
+
+       return 1;
+}
+
+__setup("print-fatal-signals=", setup_print_fatal_signals);
+
 #ifndef HAVE_ARCH_GET_SIGNAL_TO_DELIVER
 
 static void
@@ -1807,6 +1848,12 @@ relock:
                if (!signr)
                        break; /* will return 0 */
 
+               if ((signr == SIGSEGV) && print_fatal_signals) {
+                       spin_unlock_irq(&current->sighand->siglock);
+                       print_fatal_signal(regs, signr);
+                       spin_lock_irq(&current->sighand->siglock);
+               }
+
                if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
                        ptrace_signal_deliver(regs, cookie);
 
@@ -1903,6 +1950,8 @@ relock:
                 * Anything else is fatal, maybe with a core dump.
                 */
                current->flags |= PF_SIGNALED;
+               if (print_fatal_signals)
+                       print_fatal_signal(regs, signr);
                if (sig_kernel_coredump(signr)) {
                        /*
                         * If it was able to dump core, this kills all
@@ -1940,7 +1989,6 @@ EXPORT_SYMBOL(sigprocmask);
 EXPORT_SYMBOL(block_all_signals);
 EXPORT_SYMBOL(unblock_all_signals);
 
-
 /*
  * System call entry points.
  */