1 /* 2 * Copyright (C) 2004 IBM Corporation 3 * 4 * Author: Serge Hallyn <[email protected]> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation, version 2 of the 9 * License. 10 */ 11 12 #include <linux/export.h> 13 #include <linux/uts.h> 14 #include <linux/utsname.h> 15 #include <linux/err.h> 16 #include <linux/slab.h> 17 #include <linux/user_namespace.h> 18 #include <linux/proc_fs.h> 19 20 static struct uts_namespace *create_uts_ns(void) 21 { 22 struct uts_namespace *uts_ns; 23 24 uts_ns = kmalloc(sizeof(struct uts_namespace), GFP_KERNEL); 25 if (uts_ns) 26 kref_init(&uts_ns->kref); 27 return uts_ns; 28 } 29 30 /* 31 * Clone a new ns copying an original utsname, setting refcount to 1 32 * @old_ns: namespace to clone 33 * Return NULL on error (failure to kmalloc), new ns otherwise 34 */ 35 static struct uts_namespace *clone_uts_ns(struct user_namespace *user_ns, 36 struct uts_namespace *old_ns) 37 { 38 struct uts_namespace *ns; 39 40 ns = create_uts_ns(); 41 if (!ns) 42 return ERR_PTR(-ENOMEM); 43 44 down_read(&uts_sem); 45 memcpy(&ns->name, &old_ns->name, sizeof(ns->name)); 46 ns->user_ns = get_user_ns(user_ns); 47 up_read(&uts_sem); 48 return ns; 49 } 50 51 /* 52 * Copy task tsk's utsname namespace, or clone it if flags 53 * specifies CLONE_NEWUTS. In latter case, changes to the 54 * utsname of this process won't be seen by parent, and vice 55 * versa. 56 */ 57 struct uts_namespace *copy_utsname(unsigned long flags, 58 struct user_namespace *user_ns, struct uts_namespace *old_ns) 59 { 60 struct uts_namespace *new_ns; 61 62 BUG_ON(!old_ns); 63 get_uts_ns(old_ns); 64 65 if (!(flags & CLONE_NEWUTS)) 66 return old_ns; 67 68 new_ns = clone_uts_ns(user_ns, old_ns); 69 70 put_uts_ns(old_ns); 71 return new_ns; 72 } 73 74 void free_uts_ns(struct kref *kref) 75 { 76 struct uts_namespace *ns; 77 78 ns = container_of(kref, struct uts_namespace, kref); 79 put_user_ns(ns->user_ns); 80 kfree(ns); 81 } 82 83 static void *utsns_get(struct task_struct *task) 84 { 85 struct uts_namespace *ns = NULL; 86 struct nsproxy *nsproxy; 87 88 rcu_read_lock(); 89 nsproxy = task_nsproxy(task); 90 if (nsproxy) { 91 ns = nsproxy->uts_ns; 92 get_uts_ns(ns); 93 } 94 rcu_read_unlock(); 95 96 return ns; 97 } 98 99 static void utsns_put(void *ns) 100 { 101 put_uts_ns(ns); 102 } 103 104 static int utsns_install(struct nsproxy *nsproxy, void *new) 105 { 106 struct uts_namespace *ns = new; 107 108 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN)) 109 return -EPERM; 110 111 get_uts_ns(ns); 112 put_uts_ns(nsproxy->uts_ns); 113 nsproxy->uts_ns = ns; 114 return 0; 115 } 116 117 const struct proc_ns_operations utsns_operations = { 118 .name = "uts", 119 .type = CLONE_NEWUTS, 120 .get = utsns_get, 121 .put = utsns_put, 122 .install = utsns_install, 123 }; 124 125