Commit bb96a6f50be27390dc959ff67d9ea0ea0cfbe177

Authored by Serge E. Hallyn
Committed by Linus Torvalds
1 parent 3486740a4f

userns: allow sethostname in a container

Changelog:
	Feb 23: let clone_uts_ns() handle setting uts->user_ns
		To do so we need to pass in the task_struct who'll
		get the utsname, so we can get its user_ns.
	Feb 23: As per Oleg's coment, just pass in tsk, instead of two
		of its members.

Signed-off-by: Serge E. Hallyn <serge.hallyn@canonical.com>
Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>
Acked-by: Daniel Lezcano <daniel.lezcano@free.fr>
Acked-by: David Howells <dhowells@redhat.com>
Cc: James Morris <jmorris@namei.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 4 changed files with 12 additions and 15 deletions Side-by-side Diff

include/linux/utsname.h
... ... @@ -54,7 +54,7 @@
54 54 }
55 55  
56 56 extern struct uts_namespace *copy_utsname(unsigned long flags,
57   - struct uts_namespace *ns);
  57 + struct task_struct *tsk);
58 58 extern void free_uts_ns(struct kref *kref);
59 59  
60 60 static inline void put_uts_ns(struct uts_namespace *ns)
61 61  
... ... @@ -71,12 +71,12 @@
71 71 }
72 72  
73 73 static inline struct uts_namespace *copy_utsname(unsigned long flags,
74   - struct uts_namespace *ns)
  74 + struct task_struct *tsk)
75 75 {
76 76 if (flags & CLONE_NEWUTS)
77 77 return ERR_PTR(-EINVAL);
78 78  
79   - return ns;
  79 + return tsk->nsproxy->uts_ns;
80 80 }
81 81 #endif
82 82  
... ... @@ -69,15 +69,10 @@
69 69 goto out_ns;
70 70 }
71 71  
72   - new_nsp->uts_ns = copy_utsname(flags, tsk->nsproxy->uts_ns);
  72 + new_nsp->uts_ns = copy_utsname(flags, tsk);
73 73 if (IS_ERR(new_nsp->uts_ns)) {
74 74 err = PTR_ERR(new_nsp->uts_ns);
75 75 goto out_uts;
76   - }
77   - if (new_nsp->uts_ns != tsk->nsproxy->uts_ns) {
78   - put_user_ns(new_nsp->uts_ns->user_ns);
79   - new_nsp->uts_ns->user_ns = task_cred_xxx(tsk, user)->user_ns;
80   - get_user_ns(new_nsp->uts_ns->user_ns);
81 76 }
82 77  
83 78 new_nsp->ipc_ns = copy_ipcs(flags, tsk->nsproxy->ipc_ns);
... ... @@ -1181,7 +1181,7 @@
1181 1181 int errno;
1182 1182 char tmp[__NEW_UTS_LEN];
1183 1183  
1184   - if (!capable(CAP_SYS_ADMIN))
  1184 + if (!ns_capable(current->nsproxy->uts_ns->user_ns, CAP_SYS_ADMIN))
1185 1185 return -EPERM;
1186 1186 if (len < 0 || len > __NEW_UTS_LEN)
1187 1187 return -EINVAL;
... ... @@ -31,7 +31,8 @@
31 31 * @old_ns: namespace to clone
32 32 * Return NULL on error (failure to kmalloc), new ns otherwise
33 33 */
34   -static struct uts_namespace *clone_uts_ns(struct uts_namespace *old_ns)
  34 +static struct uts_namespace *clone_uts_ns(struct task_struct *tsk,
  35 + struct uts_namespace *old_ns)
35 36 {
36 37 struct uts_namespace *ns;
37 38  
... ... @@ -41,8 +42,7 @@
41 42  
42 43 down_read(&uts_sem);
43 44 memcpy(&ns->name, &old_ns->name, sizeof(ns->name));
44   - ns->user_ns = old_ns->user_ns;
45   - get_user_ns(ns->user_ns);
  45 + ns->user_ns = get_user_ns(task_cred_xxx(tsk, user)->user_ns);
46 46 up_read(&uts_sem);
47 47 return ns;
48 48 }
49 49  
... ... @@ -53,8 +53,10 @@
53 53 * utsname of this process won't be seen by parent, and vice
54 54 * versa.
55 55 */
56   -struct uts_namespace *copy_utsname(unsigned long flags, struct uts_namespace *old_ns)
  56 +struct uts_namespace *copy_utsname(unsigned long flags,
  57 + struct task_struct *tsk)
57 58 {
  59 + struct uts_namespace *old_ns = tsk->nsproxy->uts_ns;
58 60 struct uts_namespace *new_ns;
59 61  
60 62 BUG_ON(!old_ns);
... ... @@ -63,7 +65,7 @@
63 65 if (!(flags & CLONE_NEWUTS))
64 66 return old_ns;
65 67  
66   - new_ns = clone_uts_ns(old_ns);
  68 + new_ns = clone_uts_ns(tsk, old_ns);
67 69  
68 70 put_uts_ns(old_ns);
69 71 return new_ns;