aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/utsname.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/utsname.c')
-rw-r--r--kernel/utsname.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/kernel/utsname.c b/kernel/utsname.c
index 1824384ecfa3..c859164a6993 100644
--- a/kernel/utsname.c
+++ b/kernel/utsname.c
@@ -15,6 +15,41 @@
15#include <linux/version.h> 15#include <linux/version.h>
16 16
17/* 17/*
18 * Clone a new ns copying an original utsname, setting refcount to 1
19 * @old_ns: namespace to clone
20 * Return NULL on error (failure to kmalloc), new ns otherwise
21 */
22static struct uts_namespace *clone_uts_ns(struct uts_namespace *old_ns)
23{
24 struct uts_namespace *ns;
25
26 ns = kmalloc(sizeof(struct uts_namespace), GFP_KERNEL);
27 if (ns) {
28 memcpy(&ns->name, &old_ns->name, sizeof(ns->name));
29 kref_init(&ns->kref);
30 }
31 return ns;
32}
33
34/*
35 * unshare the current process' utsname namespace.
36 * called only in sys_unshare()
37 */
38int unshare_utsname(unsigned long unshare_flags, struct uts_namespace **new_uts)
39{
40 if (unshare_flags & CLONE_NEWUTS) {
41 if (!capable(CAP_SYS_ADMIN))
42 return -EPERM;
43
44 *new_uts = clone_uts_ns(current->nsproxy->uts_ns);
45 if (!*new_uts)
46 return -ENOMEM;
47 }
48
49 return 0;
50}
51
52/*
18 * Copy task tsk's utsname namespace, or clone it if flags 53 * Copy task tsk's utsname namespace, or clone it if flags
19 * specifies CLONE_NEWUTS. In latter case, changes to the 54 * specifies CLONE_NEWUTS. In latter case, changes to the
20 * utsname of this process won't be seen by parent, and vice 55 * utsname of this process won't be seen by parent, and vice
@@ -23,6 +58,7 @@
23int copy_utsname(int flags, struct task_struct *tsk) 58int copy_utsname(int flags, struct task_struct *tsk)
24{ 59{
25 struct uts_namespace *old_ns = tsk->nsproxy->uts_ns; 60 struct uts_namespace *old_ns = tsk->nsproxy->uts_ns;
61 struct uts_namespace *new_ns;
26 int err = 0; 62 int err = 0;
27 63
28 if (!old_ns) 64 if (!old_ns)
@@ -30,6 +66,23 @@ int copy_utsname(int flags, struct task_struct *tsk)
30 66
31 get_uts_ns(old_ns); 67 get_uts_ns(old_ns);
32 68
69 if (!(flags & CLONE_NEWUTS))
70 return 0;
71
72 if (!capable(CAP_SYS_ADMIN)) {
73 err = -EPERM;
74 goto out;
75 }
76
77 new_ns = clone_uts_ns(old_ns);
78 if (!new_ns) {
79 err = -ENOMEM;
80 goto out;
81 }
82 tsk->nsproxy->uts_ns = new_ns;
83
84out:
85 put_uts_ns(old_ns);
33 return err; 86 return err;
34} 87}
35 88