1 /* 2 * Copyright (C) 2004 IBM Corporation 3 * 4 * Author: Serge Hallyn <serue@us.ibm.com> 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 task_struct *tsk, 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(task_cred_xxx(tsk, 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 task_struct *tsk) 59 { 60 struct uts_namespace *old_ns = tsk->nsproxy->uts_ns; 61 struct uts_namespace *new_ns; 62 63 BUG_ON(!old_ns); 64 get_uts_ns(old_ns); 65 66 if (!(flags & CLONE_NEWUTS)) 67 return old_ns; 68 69 new_ns = clone_uts_ns(tsk, old_ns); 70 71 put_uts_ns(old_ns); 72 return new_ns; 73 } 74 75 void free_uts_ns(struct kref *kref) 76 { 77 struct uts_namespace *ns; 78 79 ns = container_of(kref, struct uts_namespace, kref); 80 put_user_ns(ns->user_ns); 81 kfree(ns); 82 } 83 84 static void *utsns_get(struct task_struct *task) 85 { 86 struct uts_namespace *ns = NULL; 87 struct nsproxy *nsproxy; 88 89 rcu_read_lock(); 90 nsproxy = task_nsproxy(task); 91 if (nsproxy) { 92 ns = nsproxy->uts_ns; 93 get_uts_ns(ns); 94 } 95 rcu_read_unlock(); 96 97 return ns; 98 } 99 100 static void utsns_put(void *ns) 101 { 102 put_uts_ns(ns); 103 } 104 105 static int utsns_install(struct nsproxy *nsproxy, void *ns) 106 { 107 get_uts_ns(ns); 108 put_uts_ns(nsproxy->uts_ns); 109 nsproxy->uts_ns = ns; 110 return 0; 111 } 112 113 const struct proc_ns_operations utsns_operations = { 114 .name = "uts", 115 .type = CLONE_NEWUTS, 116 .get = utsns_get, 117 .put = utsns_put, 118 .install = utsns_install, 119 }; 120 121