Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only 2 : : /* 3 : : * Copyright (C) 2004 IBM Corporation 4 : : * 5 : : * Author: Serge Hallyn <serue@us.ibm.com> 6 : : */ 7 : : 8 : : #include <linux/export.h> 9 : : #include <linux/uts.h> 10 : : #include <linux/utsname.h> 11 : : #include <linux/err.h> 12 : : #include <linux/slab.h> 13 : : #include <linux/cred.h> 14 : : #include <linux/user_namespace.h> 15 : : #include <linux/proc_ns.h> 16 : : #include <linux/sched/task.h> 17 : : 18 : : static struct kmem_cache *uts_ns_cache __ro_after_init; 19 : : 20 : 0 : static struct ucounts *inc_uts_namespaces(struct user_namespace *ns) 21 : : { 22 : 0 : return inc_ucount(ns, current_euid(), UCOUNT_UTS_NAMESPACES); 23 : : } 24 : : 25 : : static void dec_uts_namespaces(struct ucounts *ucounts) 26 : : { 27 : 0 : dec_ucount(ucounts, UCOUNT_UTS_NAMESPACES); 28 : : } 29 : : 30 : 0 : static struct uts_namespace *create_uts_ns(void) 31 : : { 32 : : struct uts_namespace *uts_ns; 33 : : 34 : 0 : uts_ns = kmem_cache_alloc(uts_ns_cache, GFP_KERNEL); 35 : 0 : if (uts_ns) 36 : : kref_init(&uts_ns->kref); 37 : 0 : return uts_ns; 38 : : } 39 : : 40 : : /* 41 : : * Clone a new ns copying an original utsname, setting refcount to 1 42 : : * @old_ns: namespace to clone 43 : : * Return ERR_PTR(-ENOMEM) on error (failure to allocate), new ns otherwise 44 : : */ 45 : 0 : static struct uts_namespace *clone_uts_ns(struct user_namespace *user_ns, 46 : : struct uts_namespace *old_ns) 47 : : { 48 : : struct uts_namespace *ns; 49 : : struct ucounts *ucounts; 50 : : int err; 51 : : 52 : : err = -ENOSPC; 53 : 0 : ucounts = inc_uts_namespaces(user_ns); 54 : 0 : if (!ucounts) 55 : : goto fail; 56 : : 57 : : err = -ENOMEM; 58 : 0 : ns = create_uts_ns(); 59 : 0 : if (!ns) 60 : : goto fail_dec; 61 : : 62 : : err = ns_alloc_inum(&ns->ns); 63 : 0 : if (err) 64 : : goto fail_free; 65 : : 66 : 0 : ns->ucounts = ucounts; 67 : 0 : ns->ns.ops = &utsns_operations; 68 : : 69 : 0 : down_read(&uts_sem); 70 : 0 : memcpy(&ns->name, &old_ns->name, sizeof(ns->name)); 71 : 0 : ns->user_ns = get_user_ns(user_ns); 72 : 0 : up_read(&uts_sem); 73 : 0 : return ns; 74 : : 75 : : fail_free: 76 : 0 : kmem_cache_free(uts_ns_cache, ns); 77 : : fail_dec: 78 : : dec_uts_namespaces(ucounts); 79 : : fail: 80 : 0 : return ERR_PTR(err); 81 : : } 82 : : 83 : : /* 84 : : * Copy task tsk's utsname namespace, or clone it if flags 85 : : * specifies CLONE_NEWUTS. In latter case, changes to the 86 : : * utsname of this process won't be seen by parent, and vice 87 : : * versa. 88 : : */ 89 : 3 : struct uts_namespace *copy_utsname(unsigned long flags, 90 : : struct user_namespace *user_ns, struct uts_namespace *old_ns) 91 : : { 92 : : struct uts_namespace *new_ns; 93 : : 94 : 3 : BUG_ON(!old_ns); 95 : : get_uts_ns(old_ns); 96 : : 97 : 3 : if (!(flags & CLONE_NEWUTS)) 98 : : return old_ns; 99 : : 100 : 0 : new_ns = clone_uts_ns(user_ns, old_ns); 101 : : 102 : : put_uts_ns(old_ns); 103 : 0 : return new_ns; 104 : : } 105 : : 106 : 0 : void free_uts_ns(struct kref *kref) 107 : : { 108 : : struct uts_namespace *ns; 109 : : 110 : : ns = container_of(kref, struct uts_namespace, kref); 111 : 0 : dec_uts_namespaces(ns->ucounts); 112 : 0 : put_user_ns(ns->user_ns); 113 : 0 : ns_free_inum(&ns->ns); 114 : 0 : kmem_cache_free(uts_ns_cache, ns); 115 : 0 : } 116 : : 117 : : static inline struct uts_namespace *to_uts_ns(struct ns_common *ns) 118 : : { 119 : 0 : return container_of(ns, struct uts_namespace, ns); 120 : : } 121 : : 122 : 0 : static struct ns_common *utsns_get(struct task_struct *task) 123 : : { 124 : : struct uts_namespace *ns = NULL; 125 : : struct nsproxy *nsproxy; 126 : : 127 : : task_lock(task); 128 : 0 : nsproxy = task->nsproxy; 129 : 0 : if (nsproxy) { 130 : 0 : ns = nsproxy->uts_ns; 131 : : get_uts_ns(ns); 132 : : } 133 : : task_unlock(task); 134 : : 135 : 0 : return ns ? &ns->ns : NULL; 136 : : } 137 : : 138 : 0 : static void utsns_put(struct ns_common *ns) 139 : : { 140 : : put_uts_ns(to_uts_ns(ns)); 141 : 0 : } 142 : : 143 : 0 : static int utsns_install(struct nsproxy *nsproxy, struct ns_common *new) 144 : : { 145 : : struct uts_namespace *ns = to_uts_ns(new); 146 : : 147 : 0 : if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) || 148 : 0 : !ns_capable(current_user_ns(), CAP_SYS_ADMIN)) 149 : : return -EPERM; 150 : : 151 : : get_uts_ns(ns); 152 : 0 : put_uts_ns(nsproxy->uts_ns); 153 : 0 : nsproxy->uts_ns = ns; 154 : 0 : return 0; 155 : : } 156 : : 157 : 0 : static struct user_namespace *utsns_owner(struct ns_common *ns) 158 : : { 159 : 0 : return to_uts_ns(ns)->user_ns; 160 : : } 161 : : 162 : : const struct proc_ns_operations utsns_operations = { 163 : : .name = "uts", 164 : : .type = CLONE_NEWUTS, 165 : : .get = utsns_get, 166 : : .put = utsns_put, 167 : : .install = utsns_install, 168 : : .owner = utsns_owner, 169 : : }; 170 : : 171 : 3 : void __init uts_ns_init(void) 172 : : { 173 : 3 : uts_ns_cache = kmem_cache_create_usercopy( 174 : : "uts_namespace", sizeof(struct uts_namespace), 0, 175 : : SLAB_PANIC|SLAB_ACCOUNT, 176 : : offsetof(struct uts_namespace, name), 177 : : sizeof_field(struct uts_namespace, name), 178 : : NULL); 179 : 3 : }