diff --git a/include/linux/sched.h b/include/linux/sched.h index 41285a0e7258eb45e164a24bb1055050aa8e35d8..03b68a7b4b82ae7c775a375f1fe3aa0b6a9909ec 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1084,6 +1084,11 @@ extern int do_sigaltstack(const stack_t __user *, stack_t __user *, unsigned lon #define SEND_SIG_PRIV ((struct siginfo *) 1) #define SEND_SIG_FORCED ((struct siginfo *) 2) +static inline int is_si_special(const struct siginfo *info) +{ + return info <= SEND_SIG_FORCED; +} + /* True if we are on the alternate signal stack. */ static inline int on_sig_stack(unsigned long sp) diff --git a/kernel/signal.c b/kernel/signal.c index 1f7b2aaa4a39c7c128b18181b990d0b945a5dfff..27533b90c3476790460a72d6440f58d4271b8982 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -651,9 +651,7 @@ static int check_kill_permission(int sig, struct siginfo *info, if (!valid_signal(sig)) return error; error = -EPERM; - if ((info == SEND_SIG_NOINFO || - (info != SEND_SIG_PRIV && info != SEND_SIG_FORCED - && SI_FROMUSER(info))) + if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info))) && ((sig != SIGCONT) || (current->signal->session != t->signal->session)) && (current->euid ^ t->suid) && (current->euid ^ t->uid) @@ -802,7 +800,7 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t, pass on the info struct. */ q = __sigqueue_alloc(t, GFP_ATOMIC, (sig < SIGRTMIN && - (info < SEND_SIG_FORCED || + (is_si_special(info) || info->si_code >= 0))); if (q) { list_add_tail(&q->list, &signals->list); @@ -825,16 +823,14 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t, copy_siginfo(&q->info, info); break; } - } else { - if (sig >= SIGRTMIN - && info != SEND_SIG_NOINFO && info != SEND_SIG_PRIV - && info->si_code != SI_USER) + } else if (!is_si_special(info)) { + if (sig >= SIGRTMIN && info->si_code != SI_USER) /* * Queue overflow, abort. We may abort if the signal was rt * and sent by user using something other than kill(). */ return -EAGAIN; - if ((info > SEND_SIG_PRIV) && (info->si_code == SI_TIMER)) + if (info->si_code == SI_TIMER) /* * Set up a return to indicate that we dropped * the signal. @@ -860,7 +856,7 @@ specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t) BUG(); assert_spin_locked(&t->sighand->siglock); - if ((info > SEND_SIG_FORCED) && (info->si_code == SI_TIMER)) + if (!is_si_special(info) && (info->si_code == SI_TIMER)) /* * Set up a return to indicate that we dropped the signal. */ @@ -1052,7 +1048,7 @@ __group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p) assert_spin_locked(&p->sighand->siglock); handle_stop_signal(sig, p); - if ((info > SEND_SIG_FORCED) && (info->si_code == SI_TIMER)) + if (!is_si_special(info) && (info->si_code == SI_TIMER)) /* * Set up a return to indicate that we dropped the signal. */ diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 295ac472faf199fdb2f99caa08d1235599646bb5..45c41490d521e22b07219345fe195f02e171ac27 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2713,8 +2713,7 @@ static int selinux_task_kill(struct task_struct *p, struct siginfo *info, int si if (rc) return rc; - if (info != SEND_SIG_NOINFO && (info == SEND_SIG_PRIV || - info == SEND_SIG_FORCED || SI_FROMKERNEL(info))) + if (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info))) return 0; if (!sig)