diff options
-rw-r--r-- | include/linux/sched.h | 5 | ||||
-rw-r--r-- | kernel/signal.c | 18 | ||||
-rw-r--r-- | security/selinux/hooks.c | 3 |
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 | ||
1087 | static 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 | ||
1089 | static inline int on_sig_stack(unsigned long sp) | 1094 | static 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) |