root/kernel/utsname.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. inc_uts_namespaces
  2. dec_uts_namespaces
  3. create_uts_ns
  4. clone_uts_ns
  5. copy_utsname
  6. free_uts_ns
  7. to_uts_ns
  8. utsns_get
  9. utsns_put
  10. utsns_install
  11. utsns_owner
  12. uts_ns_init

   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 static struct ucounts *inc_uts_namespaces(struct user_namespace *ns)
  21 {
  22         return inc_ucount(ns, current_euid(), UCOUNT_UTS_NAMESPACES);
  23 }
  24 
  25 static void dec_uts_namespaces(struct ucounts *ucounts)
  26 {
  27         dec_ucount(ucounts, UCOUNT_UTS_NAMESPACES);
  28 }
  29 
  30 static struct uts_namespace *create_uts_ns(void)
  31 {
  32         struct uts_namespace *uts_ns;
  33 
  34         uts_ns = kmem_cache_alloc(uts_ns_cache, GFP_KERNEL);
  35         if (uts_ns)
  36                 kref_init(&uts_ns->kref);
  37         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 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         ucounts = inc_uts_namespaces(user_ns);
  54         if (!ucounts)
  55                 goto fail;
  56 
  57         err = -ENOMEM;
  58         ns = create_uts_ns();
  59         if (!ns)
  60                 goto fail_dec;
  61 
  62         err = ns_alloc_inum(&ns->ns);
  63         if (err)
  64                 goto fail_free;
  65 
  66         ns->ucounts = ucounts;
  67         ns->ns.ops = &utsns_operations;
  68 
  69         down_read(&uts_sem);
  70         memcpy(&ns->name, &old_ns->name, sizeof(ns->name));
  71         ns->user_ns = get_user_ns(user_ns);
  72         up_read(&uts_sem);
  73         return ns;
  74 
  75 fail_free:
  76         kmem_cache_free(uts_ns_cache, ns);
  77 fail_dec:
  78         dec_uts_namespaces(ucounts);
  79 fail:
  80         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 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         BUG_ON(!old_ns);
  95         get_uts_ns(old_ns);
  96 
  97         if (!(flags & CLONE_NEWUTS))
  98                 return old_ns;
  99 
 100         new_ns = clone_uts_ns(user_ns, old_ns);
 101 
 102         put_uts_ns(old_ns);
 103         return new_ns;
 104 }
 105 
 106 void free_uts_ns(struct kref *kref)
 107 {
 108         struct uts_namespace *ns;
 109 
 110         ns = container_of(kref, struct uts_namespace, kref);
 111         dec_uts_namespaces(ns->ucounts);
 112         put_user_ns(ns->user_ns);
 113         ns_free_inum(&ns->ns);
 114         kmem_cache_free(uts_ns_cache, ns);
 115 }
 116 
 117 static inline struct uts_namespace *to_uts_ns(struct ns_common *ns)
 118 {
 119         return container_of(ns, struct uts_namespace, ns);
 120 }
 121 
 122 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         nsproxy = task->nsproxy;
 129         if (nsproxy) {
 130                 ns = nsproxy->uts_ns;
 131                 get_uts_ns(ns);
 132         }
 133         task_unlock(task);
 134 
 135         return ns ? &ns->ns : NULL;
 136 }
 137 
 138 static void utsns_put(struct ns_common *ns)
 139 {
 140         put_uts_ns(to_uts_ns(ns));
 141 }
 142 
 143 static int utsns_install(struct nsproxy *nsproxy, struct ns_common *new)
 144 {
 145         struct uts_namespace *ns = to_uts_ns(new);
 146 
 147         if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) ||
 148             !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
 149                 return -EPERM;
 150 
 151         get_uts_ns(ns);
 152         put_uts_ns(nsproxy->uts_ns);
 153         nsproxy->uts_ns = ns;
 154         return 0;
 155 }
 156 
 157 static struct user_namespace *utsns_owner(struct ns_common *ns)
 158 {
 159         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 void __init uts_ns_init(void)
 172 {
 173         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 }

/* [<][>][^][v][top][bottom][index][help] */