diff options
Diffstat (limited to 'kernel/signal.c')
-rw-r--r-- | kernel/signal.c | 51 |
1 files changed, 20 insertions, 31 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index 1a006b5d9d9d..21ebe75ff85f 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -767,14 +767,13 @@ static int kill_ok_by_cred(struct task_struct *t) | |||
767 | const struct cred *cred = current_cred(); | 767 | const struct cred *cred = current_cred(); |
768 | const struct cred *tcred = __task_cred(t); | 768 | const struct cred *tcred = __task_cred(t); |
769 | 769 | ||
770 | if (cred->user->user_ns == tcred->user->user_ns && | 770 | if (uid_eq(cred->euid, tcred->suid) || |
771 | (cred->euid == tcred->suid || | 771 | uid_eq(cred->euid, tcred->uid) || |
772 | cred->euid == tcred->uid || | 772 | uid_eq(cred->uid, tcred->suid) || |
773 | cred->uid == tcred->suid || | 773 | uid_eq(cred->uid, tcred->uid)) |
774 | cred->uid == tcred->uid)) | ||
775 | return 1; | 774 | return 1; |
776 | 775 | ||
777 | if (ns_capable(tcred->user->user_ns, CAP_KILL)) | 776 | if (ns_capable(tcred->user_ns, CAP_KILL)) |
778 | return 1; | 777 | return 1; |
779 | 778 | ||
780 | return 0; | 779 | return 0; |
@@ -1020,15 +1019,6 @@ static inline int legacy_queue(struct sigpending *signals, int sig) | |||
1020 | return (sig < SIGRTMIN) && sigismember(&signals->signal, sig); | 1019 | return (sig < SIGRTMIN) && sigismember(&signals->signal, sig); |
1021 | } | 1020 | } |
1022 | 1021 | ||
1023 | /* | ||
1024 | * map the uid in struct cred into user namespace *ns | ||
1025 | */ | ||
1026 | static inline uid_t map_cred_ns(const struct cred *cred, | ||
1027 | struct user_namespace *ns) | ||
1028 | { | ||
1029 | return user_ns_map_uid(ns, cred, cred->uid); | ||
1030 | } | ||
1031 | |||
1032 | #ifdef CONFIG_USER_NS | 1022 | #ifdef CONFIG_USER_NS |
1033 | static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_struct *t) | 1023 | static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_struct *t) |
1034 | { | 1024 | { |
@@ -1038,8 +1028,10 @@ static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_str | |||
1038 | if (SI_FROMKERNEL(info)) | 1028 | if (SI_FROMKERNEL(info)) |
1039 | return; | 1029 | return; |
1040 | 1030 | ||
1041 | info->si_uid = user_ns_map_uid(task_cred_xxx(t, user_ns), | 1031 | rcu_read_lock(); |
1042 | current_cred(), info->si_uid); | 1032 | info->si_uid = from_kuid_munged(task_cred_xxx(t, user_ns), |
1033 | make_kuid(current_user_ns(), info->si_uid)); | ||
1034 | rcu_read_unlock(); | ||
1043 | } | 1035 | } |
1044 | #else | 1036 | #else |
1045 | static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_struct *t) | 1037 | static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_struct *t) |
@@ -1106,7 +1098,7 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t, | |||
1106 | q->info.si_code = SI_USER; | 1098 | q->info.si_code = SI_USER; |
1107 | q->info.si_pid = task_tgid_nr_ns(current, | 1099 | q->info.si_pid = task_tgid_nr_ns(current, |
1108 | task_active_pid_ns(t)); | 1100 | task_active_pid_ns(t)); |
1109 | q->info.si_uid = current_uid(); | 1101 | q->info.si_uid = from_kuid_munged(current_user_ns(), current_uid()); |
1110 | break; | 1102 | break; |
1111 | case (unsigned long) SEND_SIG_PRIV: | 1103 | case (unsigned long) SEND_SIG_PRIV: |
1112 | q->info.si_signo = sig; | 1104 | q->info.si_signo = sig; |
@@ -1387,10 +1379,8 @@ static int kill_as_cred_perm(const struct cred *cred, | |||
1387 | struct task_struct *target) | 1379 | struct task_struct *target) |
1388 | { | 1380 | { |
1389 | const struct cred *pcred = __task_cred(target); | 1381 | const struct cred *pcred = __task_cred(target); |
1390 | if (cred->user_ns != pcred->user_ns) | 1382 | if (!uid_eq(cred->euid, pcred->suid) && !uid_eq(cred->euid, pcred->uid) && |
1391 | return 0; | 1383 | !uid_eq(cred->uid, pcred->suid) && !uid_eq(cred->uid, pcred->uid)) |
1392 | if (cred->euid != pcred->suid && cred->euid != pcred->uid && | ||
1393 | cred->uid != pcred->suid && cred->uid != pcred->uid) | ||
1394 | return 0; | 1384 | return 0; |
1395 | return 1; | 1385 | return 1; |
1396 | } | 1386 | } |
@@ -1678,8 +1668,8 @@ bool do_notify_parent(struct task_struct *tsk, int sig) | |||
1678 | */ | 1668 | */ |
1679 | rcu_read_lock(); | 1669 | rcu_read_lock(); |
1680 | info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns); | 1670 | info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns); |
1681 | info.si_uid = map_cred_ns(__task_cred(tsk), | 1671 | info.si_uid = from_kuid_munged(task_cred_xxx(tsk->parent, user_ns), |
1682 | task_cred_xxx(tsk->parent, user_ns)); | 1672 | task_uid(tsk)); |
1683 | rcu_read_unlock(); | 1673 | rcu_read_unlock(); |
1684 | 1674 | ||
1685 | info.si_utime = cputime_to_clock_t(tsk->utime + tsk->signal->utime); | 1675 | info.si_utime = cputime_to_clock_t(tsk->utime + tsk->signal->utime); |
@@ -1762,8 +1752,7 @@ static void do_notify_parent_cldstop(struct task_struct *tsk, | |||
1762 | */ | 1752 | */ |
1763 | rcu_read_lock(); | 1753 | rcu_read_lock(); |
1764 | info.si_pid = task_pid_nr_ns(tsk, parent->nsproxy->pid_ns); | 1754 | info.si_pid = task_pid_nr_ns(tsk, parent->nsproxy->pid_ns); |
1765 | info.si_uid = map_cred_ns(__task_cred(tsk), | 1755 | info.si_uid = from_kuid_munged(task_cred_xxx(parent, user_ns), task_uid(tsk)); |
1766 | task_cred_xxx(parent, user_ns)); | ||
1767 | rcu_read_unlock(); | 1756 | rcu_read_unlock(); |
1768 | 1757 | ||
1769 | info.si_utime = cputime_to_clock_t(tsk->utime); | 1758 | info.si_utime = cputime_to_clock_t(tsk->utime); |
@@ -1973,7 +1962,7 @@ static void ptrace_do_notify(int signr, int exit_code, int why) | |||
1973 | info.si_signo = signr; | 1962 | info.si_signo = signr; |
1974 | info.si_code = exit_code; | 1963 | info.si_code = exit_code; |
1975 | info.si_pid = task_pid_vnr(current); | 1964 | info.si_pid = task_pid_vnr(current); |
1976 | info.si_uid = current_uid(); | 1965 | info.si_uid = from_kuid_munged(current_user_ns(), current_uid()); |
1977 | 1966 | ||
1978 | /* Let the debugger run. */ | 1967 | /* Let the debugger run. */ |
1979 | ptrace_stop(exit_code, why, 1, &info); | 1968 | ptrace_stop(exit_code, why, 1, &info); |
@@ -2181,8 +2170,8 @@ static int ptrace_signal(int signr, siginfo_t *info, | |||
2181 | info->si_code = SI_USER; | 2170 | info->si_code = SI_USER; |
2182 | rcu_read_lock(); | 2171 | rcu_read_lock(); |
2183 | info->si_pid = task_pid_vnr(current->parent); | 2172 | info->si_pid = task_pid_vnr(current->parent); |
2184 | info->si_uid = map_cred_ns(__task_cred(current->parent), | 2173 | info->si_uid = from_kuid_munged(current_user_ns(), |
2185 | current_user_ns()); | 2174 | task_uid(current->parent)); |
2186 | rcu_read_unlock(); | 2175 | rcu_read_unlock(); |
2187 | } | 2176 | } |
2188 | 2177 | ||
@@ -2835,7 +2824,7 @@ SYSCALL_DEFINE2(kill, pid_t, pid, int, sig) | |||
2835 | info.si_errno = 0; | 2824 | info.si_errno = 0; |
2836 | info.si_code = SI_USER; | 2825 | info.si_code = SI_USER; |
2837 | info.si_pid = task_tgid_vnr(current); | 2826 | info.si_pid = task_tgid_vnr(current); |
2838 | info.si_uid = current_uid(); | 2827 | info.si_uid = from_kuid_munged(current_user_ns(), current_uid()); |
2839 | 2828 | ||
2840 | return kill_something_info(sig, &info, pid); | 2829 | return kill_something_info(sig, &info, pid); |
2841 | } | 2830 | } |
@@ -2878,7 +2867,7 @@ static int do_tkill(pid_t tgid, pid_t pid, int sig) | |||
2878 | info.si_errno = 0; | 2867 | info.si_errno = 0; |
2879 | info.si_code = SI_TKILL; | 2868 | info.si_code = SI_TKILL; |
2880 | info.si_pid = task_tgid_vnr(current); | 2869 | info.si_pid = task_tgid_vnr(current); |
2881 | info.si_uid = current_uid(); | 2870 | info.si_uid = from_kuid_munged(current_user_ns(), current_uid()); |
2882 | 2871 | ||
2883 | return do_send_specific(tgid, pid, sig, &info); | 2872 | return do_send_specific(tgid, pid, sig, &info); |
2884 | } | 2873 | } |