aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/signal.c')
-rw-r--r--kernel/signal.c38
1 files changed, 20 insertions, 18 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index f67545f9394c..d09692b40376 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -423,7 +423,7 @@ still_pending:
423 */ 423 */
424 info->si_signo = sig; 424 info->si_signo = sig;
425 info->si_errno = 0; 425 info->si_errno = 0;
426 info->si_code = 0; 426 info->si_code = SI_USER;
427 info->si_pid = 0; 427 info->si_pid = 0;
428 info->si_uid = 0; 428 info->si_uid = 0;
429 } 429 }
@@ -607,6 +607,17 @@ static int rm_from_queue(unsigned long mask, struct sigpending *s)
607 return 1; 607 return 1;
608} 608}
609 609
610static inline int is_si_special(const struct siginfo *info)
611{
612 return info <= SEND_SIG_FORCED;
613}
614
615static inline bool si_fromuser(const struct siginfo *info)
616{
617 return info == SEND_SIG_NOINFO ||
618 (!is_si_special(info) && SI_FROMUSER(info));
619}
620
610/* 621/*
611 * Bad permissions for sending the signal 622 * Bad permissions for sending the signal
612 * - the caller must hold at least the RCU read lock 623 * - the caller must hold at least the RCU read lock
@@ -621,7 +632,7 @@ static int check_kill_permission(int sig, struct siginfo *info,
621 if (!valid_signal(sig)) 632 if (!valid_signal(sig))
622 return -EINVAL; 633 return -EINVAL;
623 634
624 if (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info))) 635 if (!si_fromuser(info))
625 return 0; 636 return 0;
626 637
627 error = audit_signal_info(sig, t); /* Let audit system see the signal */ 638 error = audit_signal_info(sig, t); /* Let audit system see the signal */
@@ -949,9 +960,8 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
949 int from_ancestor_ns = 0; 960 int from_ancestor_ns = 0;
950 961
951#ifdef CONFIG_PID_NS 962#ifdef CONFIG_PID_NS
952 if (!is_si_special(info) && SI_FROMUSER(info) && 963 from_ancestor_ns = si_fromuser(info) &&
953 task_pid_nr_ns(current, task_active_pid_ns(t)) <= 0) 964 !task_pid_nr_ns(current, task_active_pid_ns(t));
954 from_ancestor_ns = 1;
955#endif 965#endif
956 966
957 return __send_signal(sig, info, t, group, from_ancestor_ns); 967 return __send_signal(sig, info, t, group, from_ancestor_ns);
@@ -1052,12 +1062,6 @@ force_sig_info(int sig, struct siginfo *info, struct task_struct *t)
1052 return ret; 1062 return ret;
1053} 1063}
1054 1064
1055void
1056force_sig_specific(int sig, struct task_struct *t)
1057{
1058 force_sig_info(sig, SEND_SIG_FORCED, t);
1059}
1060
1061/* 1065/*
1062 * Nuke all other threads in the group. 1066 * Nuke all other threads in the group.
1063 */ 1067 */
@@ -1187,8 +1191,7 @@ int kill_pid_info_as_uid(int sig, struct siginfo *info, struct pid *pid,
1187 goto out_unlock; 1191 goto out_unlock;
1188 } 1192 }
1189 pcred = __task_cred(p); 1193 pcred = __task_cred(p);
1190 if ((info == SEND_SIG_NOINFO || 1194 if (si_fromuser(info) &&
1191 (!is_si_special(info) && SI_FROMUSER(info))) &&
1192 euid != pcred->suid && euid != pcred->uid && 1195 euid != pcred->suid && euid != pcred->uid &&
1193 uid != pcred->suid && uid != pcred->uid) { 1196 uid != pcred->suid && uid != pcred->uid) {
1194 ret = -EPERM; 1197 ret = -EPERM;
@@ -1840,11 +1843,6 @@ relock:
1840 1843
1841 for (;;) { 1844 for (;;) {
1842 struct k_sigaction *ka; 1845 struct k_sigaction *ka;
1843
1844 if (unlikely(signal->group_stop_count > 0) &&
1845 do_signal_stop(0))
1846 goto relock;
1847
1848 /* 1846 /*
1849 * Tracing can induce an artifical signal and choose sigaction. 1847 * Tracing can induce an artifical signal and choose sigaction.
1850 * The return value in @signr determines the default action, 1848 * The return value in @signr determines the default action,
@@ -1856,6 +1854,10 @@ relock:
1856 if (unlikely(signr != 0)) 1854 if (unlikely(signr != 0))
1857 ka = return_ka; 1855 ka = return_ka;
1858 else { 1856 else {
1857 if (unlikely(signal->group_stop_count > 0) &&
1858 do_signal_stop(0))
1859 goto relock;
1860
1859 signr = dequeue_signal(current, &current->blocked, 1861 signr = dequeue_signal(current, &current->blocked,
1860 info); 1862 info);
1861 1863