diff options
-rw-r--r-- | ipc/mqueue.c | 7 | ||||
-rw-r--r-- | kernel/signal.c | 43 |
2 files changed, 46 insertions, 4 deletions
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 9a142a290749..9b7c8ab7d75c 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/nsproxy.h> | 32 | #include <linux/nsproxy.h> |
33 | #include <linux/pid.h> | 33 | #include <linux/pid.h> |
34 | #include <linux/ipc_namespace.h> | 34 | #include <linux/ipc_namespace.h> |
35 | #include <linux/user_namespace.h> | ||
35 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
36 | 37 | ||
37 | #include <net/sock.h> | 38 | #include <net/sock.h> |
@@ -542,9 +543,13 @@ static void __do_notify(struct mqueue_inode_info *info) | |||
542 | sig_i.si_errno = 0; | 543 | sig_i.si_errno = 0; |
543 | sig_i.si_code = SI_MESGQ; | 544 | sig_i.si_code = SI_MESGQ; |
544 | sig_i.si_value = info->notify.sigev_value; | 545 | sig_i.si_value = info->notify.sigev_value; |
546 | /* map current pid/uid into info->owner's namespaces */ | ||
547 | rcu_read_lock(); | ||
545 | sig_i.si_pid = task_tgid_nr_ns(current, | 548 | sig_i.si_pid = task_tgid_nr_ns(current, |
546 | ns_of_pid(info->notify_owner)); | 549 | ns_of_pid(info->notify_owner)); |
547 | sig_i.si_uid = current_uid(); | 550 | sig_i.si_uid = user_ns_map_uid(info->user->user_ns, |
551 | current_cred(), current_uid()); | ||
552 | rcu_read_unlock(); | ||
548 | 553 | ||
549 | kill_pid_info(info->notify.sigev_signo, | 554 | kill_pid_info(info->notify.sigev_signo, |
550 | &sig_i, info->notify_owner); | 555 | &sig_i, info->notify_owner); |
diff --git a/kernel/signal.c b/kernel/signal.c index d532f1709fbf..c73c4284160e 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/freezer.h> | 28 | #include <linux/freezer.h> |
29 | #include <linux/pid_namespace.h> | 29 | #include <linux/pid_namespace.h> |
30 | #include <linux/nsproxy.h> | 30 | #include <linux/nsproxy.h> |
31 | #include <linux/user_namespace.h> | ||
31 | #define CREATE_TRACE_POINTS | 32 | #define CREATE_TRACE_POINTS |
32 | #include <trace/events/signal.h> | 33 | #include <trace/events/signal.h> |
33 | 34 | ||
@@ -1019,6 +1020,34 @@ static inline int legacy_queue(struct sigpending *signals, int sig) | |||
1019 | return (sig < SIGRTMIN) && sigismember(&signals->signal, sig); | 1020 | return (sig < SIGRTMIN) && sigismember(&signals->signal, sig); |
1020 | } | 1021 | } |
1021 | 1022 | ||
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 | ||
1033 | static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_struct *t) | ||
1034 | { | ||
1035 | if (current_user_ns() == task_cred_xxx(t, user_ns)) | ||
1036 | return; | ||
1037 | |||
1038 | if (SI_FROMKERNEL(info)) | ||
1039 | return; | ||
1040 | |||
1041 | info->si_uid = user_ns_map_uid(task_cred_xxx(t, user_ns), | ||
1042 | current_cred(), info->si_uid); | ||
1043 | } | ||
1044 | #else | ||
1045 | static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_struct *t) | ||
1046 | { | ||
1047 | return; | ||
1048 | } | ||
1049 | #endif | ||
1050 | |||
1022 | static int __send_signal(int sig, struct siginfo *info, struct task_struct *t, | 1051 | static int __send_signal(int sig, struct siginfo *info, struct task_struct *t, |
1023 | int group, int from_ancestor_ns) | 1052 | int group, int from_ancestor_ns) |
1024 | { | 1053 | { |
@@ -1088,6 +1117,9 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t, | |||
1088 | q->info.si_pid = 0; | 1117 | q->info.si_pid = 0; |
1089 | break; | 1118 | break; |
1090 | } | 1119 | } |
1120 | |||
1121 | userns_fixup_signal_uid(&q->info, t); | ||
1122 | |||
1091 | } else if (!is_si_special(info)) { | 1123 | } else if (!is_si_special(info)) { |
1092 | if (sig >= SIGRTMIN && info->si_code != SI_USER) { | 1124 | if (sig >= SIGRTMIN && info->si_code != SI_USER) { |
1093 | /* | 1125 | /* |
@@ -1626,7 +1658,8 @@ bool do_notify_parent(struct task_struct *tsk, int sig) | |||
1626 | */ | 1658 | */ |
1627 | rcu_read_lock(); | 1659 | rcu_read_lock(); |
1628 | info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns); | 1660 | info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns); |
1629 | info.si_uid = __task_cred(tsk)->uid; | 1661 | info.si_uid = map_cred_ns(__task_cred(tsk), |
1662 | task_cred_xxx(tsk->parent, user_ns)); | ||
1630 | rcu_read_unlock(); | 1663 | rcu_read_unlock(); |
1631 | 1664 | ||
1632 | info.si_utime = cputime_to_clock_t(tsk->utime + tsk->signal->utime); | 1665 | info.si_utime = cputime_to_clock_t(tsk->utime + tsk->signal->utime); |
@@ -1709,7 +1742,8 @@ static void do_notify_parent_cldstop(struct task_struct *tsk, | |||
1709 | */ | 1742 | */ |
1710 | rcu_read_lock(); | 1743 | rcu_read_lock(); |
1711 | info.si_pid = task_pid_nr_ns(tsk, parent->nsproxy->pid_ns); | 1744 | info.si_pid = task_pid_nr_ns(tsk, parent->nsproxy->pid_ns); |
1712 | info.si_uid = __task_cred(tsk)->uid; | 1745 | info.si_uid = map_cred_ns(__task_cred(tsk), |
1746 | task_cred_xxx(parent, user_ns)); | ||
1713 | rcu_read_unlock(); | 1747 | rcu_read_unlock(); |
1714 | 1748 | ||
1715 | info.si_utime = cputime_to_clock_t(tsk->utime); | 1749 | info.si_utime = cputime_to_clock_t(tsk->utime); |
@@ -2125,8 +2159,11 @@ static int ptrace_signal(int signr, siginfo_t *info, | |||
2125 | info->si_signo = signr; | 2159 | info->si_signo = signr; |
2126 | info->si_errno = 0; | 2160 | info->si_errno = 0; |
2127 | info->si_code = SI_USER; | 2161 | info->si_code = SI_USER; |
2162 | rcu_read_lock(); | ||
2128 | info->si_pid = task_pid_vnr(current->parent); | 2163 | info->si_pid = task_pid_vnr(current->parent); |
2129 | info->si_uid = task_uid(current->parent); | 2164 | info->si_uid = map_cred_ns(__task_cred(current->parent), |
2165 | current_user_ns()); | ||
2166 | rcu_read_unlock(); | ||
2130 | } | 2167 | } |
2131 | 2168 | ||
2132 | /* If the (new) signal is now blocked, requeue it. */ | 2169 | /* If the (new) signal is now blocked, requeue it. */ |