#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>
{
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)) {
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 &&
&& (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 */
* 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;
/*
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);
spin_unlock_irq(¤t->sighand->siglock);
}
-#ifndef HAVE_ARCH_GET_SIGNAL_TO_DELIVER
-
static void
finish_stop(int stop_count)
{
return signr;
}
-#endif
-
EXPORT_SYMBOL(recalc_sigpending);
EXPORT_SYMBOL_GPL(dequeue_signal);
EXPORT_SYMBOL(flush_signals);
{
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 = ¤t->sighand->action[sig-1];