aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/sched.h5
-rw-r--r--kernel/signal.c18
-rw-r--r--security/selinux/hooks.c3
3 files changed, 13 insertions, 13 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 41285a0e7258..03b68a7b4b82 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
1084#define SEND_SIG_PRIV ((struct siginfo *) 1) 1084#define SEND_SIG_PRIV ((struct siginfo *) 1)
1085#define SEND_SIG_FORCED ((struct siginfo *) 2) 1085#define SEND_SIG_FORCED ((struct siginfo *) 2)
1086 1086
1087static inline int is_si_special(const struct siginfo *info)
1088{
1089 return info <= SEND_SIG_FORCED;
1090}
1091
1087/* True if we are on the alternate signal stack. */ 1092/* True if we are on the alternate signal stack. */
1088 1093
1089static inline int on_sig_stack(unsigned long sp) 1094static inline int on_sig_stack(unsigned long sp)
diff --git a/kernel/signal.c b/kernel/signal.c
index 1f7b2aaa4a39..27533b90c347 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -651,9 +651,7 @@ static int check_kill_permission(int sig, struct siginfo *info,
651 if (!valid_signal(sig)) 651 if (!valid_signal(sig))
652 return error; 652 return error;
653 error = -EPERM; 653 error = -EPERM;
654 if ((info == SEND_SIG_NOINFO || 654 if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info)))
655 (info != SEND_SIG_PRIV && info != SEND_SIG_FORCED
656 && SI_FROMUSER(info)))
657 && ((sig != SIGCONT) || 655 && ((sig != SIGCONT) ||
658 (current->signal->session != t->signal->session)) 656 (current->signal->session != t->signal->session))
659 && (current->euid ^ t->suid) && (current->euid ^ t->uid) 657 && (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,
802 pass on the info struct. */ 800 pass on the info struct. */
803 801
804 q = __sigqueue_alloc(t, GFP_ATOMIC, (sig < SIGRTMIN && 802 q = __sigqueue_alloc(t, GFP_ATOMIC, (sig < SIGRTMIN &&
805 (info < SEND_SIG_FORCED || 803 (is_si_special(info) ||
806 info->si_code >= 0))); 804 info->si_code >= 0)));
807 if (q) { 805 if (q) {
808 list_add_tail(&q->list, &signals->list); 806 list_add_tail(&q->list, &signals->list);
@@ -825,16 +823,14 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
825 copy_siginfo(&q->info, info); 823 copy_siginfo(&q->info, info);
826 break; 824 break;
827 } 825 }
828 } else { 826 } else if (!is_si_special(info)) {
829 if (sig >= SIGRTMIN 827 if (sig >= SIGRTMIN && info->si_code != SI_USER)
830 && info != SEND_SIG_NOINFO && info != SEND_SIG_PRIV
831 && info->si_code != SI_USER)
832 /* 828 /*
833 * Queue overflow, abort. We may abort if the signal was rt 829 * Queue overflow, abort. We may abort if the signal was rt
834 * and sent by user using something other than kill(). 830 * and sent by user using something other than kill().
835 */ 831 */
836 return -EAGAIN; 832 return -EAGAIN;
837 if ((info > SEND_SIG_PRIV) && (info->si_code == SI_TIMER)) 833 if (info->si_code == SI_TIMER)
838 /* 834 /*
839 * Set up a return to indicate that we dropped 835 * Set up a return to indicate that we dropped
840 * the signal. 836 * the signal.
@@ -860,7 +856,7 @@ specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
860 BUG(); 856 BUG();
861 assert_spin_locked(&t->sighand->siglock); 857 assert_spin_locked(&t->sighand->siglock);
862 858
863 if ((info > SEND_SIG_FORCED) && (info->si_code == SI_TIMER)) 859 if (!is_si_special(info) && (info->si_code == SI_TIMER))
864 /* 860 /*
865 * Set up a return to indicate that we dropped the signal. 861 * Set up a return to indicate that we dropped the signal.
866 */ 862 */
@@ -1052,7 +1048,7 @@ __group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
1052 assert_spin_locked(&p->sighand->siglock); 1048 assert_spin_locked(&p->sighand->siglock);
1053 handle_stop_signal(sig, p); 1049 handle_stop_signal(sig, p);
1054 1050
1055 if ((info > SEND_SIG_FORCED) && (info->si_code == SI_TIMER)) 1051 if (!is_si_special(info) && (info->si_code == SI_TIMER))
1056 /* 1052 /*
1057 * Set up a return to indicate that we dropped the signal. 1053 * Set up a return to indicate that we dropped the signal.
1058 */ 1054 */
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 295ac472faf1..45c41490d521 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
2713 if (rc) 2713 if (rc)
2714 return rc; 2714 return rc;
2715 2715
2716 if (info != SEND_SIG_NOINFO && (info == SEND_SIG_PRIV || 2716 if (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info)))
2717 info == SEND_SIG_FORCED || SI_FROMKERNEL(info)))
2718 return 0; 2717 return 0;
2719 2718
2720 if (!sig) 2719 if (!sig)