Commit 6b550f9495947fc279d12c38feaf98500e8d0646

Authored by Serge E. Hallyn
Committed by Linus Torvalds
1 parent b196be89cd

user namespace: make signal.c respect user namespaces

ipc/mqueue.c: for __SI_MESQ, convert the uid being sent to recipient's
user namespace. (new, thanks Oleg)

__send_signal: convert current's uid to the recipient's user namespace
for any siginfo which is not SI_FROMKERNEL (patch from Oleg, thanks
again :)

do_notify_parent and do_notify_parent_cldstop: map task's uid to parent's
user namespace

ptrace_signal maps parent's uid into current's user namespace before
including in signal to current.  IIUC Oleg has argued that this shouldn't
matter as the debugger will play with it, but it seems like not converting
the value currently being set is misleading.

Changelog:
Sep 20: Inspired by Oleg's suggestion, define map_cred_ns() helper to
	simplify callers and help make clear what we are translating
        (which uid into which namespace).  Passing the target task would
	make callers even easier to read, but we pass in user_ns because
	current_user_ns() != task_cred_xxx(current, user_ns).
Sep 20: As recommended by Oleg, also put task_pid_vnr() under rcu_read_lock
	in ptrace_signal().
Sep 23: In send_signal(), detect when (user) signal is coming from an
	ancestor or unrelated user namespace.  Pass that on to __send_signal,
	which sets si_uid to 0 or overflowuid if needed.
Oct 12: Base on Oleg's fixup_uid() patch.  On top of that, handle all
	SI_FROMKERNEL cases at callers, because we can't assume sender is
	current in those cases.
Nov 10: (mhelsley) rename fixup_uid to more meaningful usern_fixup_signal_uid
Nov 10: (akpm) make the !CONFIG_USER_NS case clearer

Signed-off-by: Serge Hallyn <serge.hallyn@canonical.com>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Matt Helsley <matthltc@us.ibm.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
From: Serge Hallyn <serge.hallyn@canonical.com>
Subject: __send_signal: pass q->info, not info, to userns_fixup_signal_uid (v2)

Eric Biederman pointed out that passing info is a bug and could lead to a
NULL pointer deref to boot.

A collection of signal, securebits, filecaps, cap_bounds, and a few other
ltp tests passed with this kernel.

Changelog:
    Nov 18: previous patch missed a leading '&'

Signed-off-by: Serge Hallyn <serge.hallyn@canonical.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
From: Dan Carpenter <dan.carpenter@oracle.com>
Subject: ipc/mqueue: lock() => unlock() typo

There was a double lock typo introduced in b085f4bd6b21 "user namespace:
make signal.c respect user namespaces"

Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Matt Helsley <matthltc@us.ibm.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Acked-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 2 changed files with 46 additions and 4 deletions Side-by-side Diff

... ... @@ -32,6 +32,7 @@
32 32 #include <linux/nsproxy.h>
33 33 #include <linux/pid.h>
34 34 #include <linux/ipc_namespace.h>
  35 +#include <linux/user_namespace.h>
35 36 #include <linux/slab.h>
36 37  
37 38 #include <net/sock.h>
38 39  
... ... @@ -542,9 +543,13 @@
542 543 sig_i.si_errno = 0;
543 544 sig_i.si_code = SI_MESGQ;
544 545 sig_i.si_value = info->notify.sigev_value;
  546 + /* map current pid/uid into info->owner's namespaces */
  547 + rcu_read_lock();
545 548 sig_i.si_pid = task_tgid_nr_ns(current,
546 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 554 kill_pid_info(info->notify.sigev_signo,
550 555 &sig_i, info->notify_owner);
... ... @@ -28,6 +28,7 @@
28 28 #include <linux/freezer.h>
29 29 #include <linux/pid_namespace.h>
30 30 #include <linux/nsproxy.h>
  31 +#include <linux/user_namespace.h>
31 32 #define CREATE_TRACE_POINTS
32 33 #include <trace/events/signal.h>
33 34  
... ... @@ -1019,6 +1020,34 @@
1019 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 1051 static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,
1023 1052 int group, int from_ancestor_ns)
1024 1053 {
... ... @@ -1088,6 +1117,9 @@
1088 1117 q->info.si_pid = 0;
1089 1118 break;
1090 1119 }
  1120 +
  1121 + userns_fixup_signal_uid(&q->info, t);
  1122 +
1091 1123 } else if (!is_si_special(info)) {
1092 1124 if (sig >= SIGRTMIN && info->si_code != SI_USER) {
1093 1125 /*
... ... @@ -1626,7 +1658,8 @@
1626 1658 */
1627 1659 rcu_read_lock();
1628 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 1663 rcu_read_unlock();
1631 1664  
1632 1665 info.si_utime = cputime_to_clock_t(tsk->utime + tsk->signal->utime);
... ... @@ -1709,7 +1742,8 @@
1709 1742 */
1710 1743 rcu_read_lock();
1711 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 1747 rcu_read_unlock();
1714 1748  
1715 1749 info.si_utime = cputime_to_clock_t(tsk->utime);
1716 1750  
... ... @@ -2125,8 +2159,11 @@
2125 2159 info->si_signo = signr;
2126 2160 info->si_errno = 0;
2127 2161 info->si_code = SI_USER;
  2162 + rcu_read_lock();
2128 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 2169 /* If the (new) signal is now blocked, requeue it. */