Blame view

kernel/utsname.c 3.83 KB
b886d83c5   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
4865ecf13   Serge E. Hallyn   [PATCH] namespace...
2
3
4
5
  /*
   *  Copyright (C) 2004 IBM Corporation
   *
   *  Author: Serge Hallyn <serue@us.ibm.com>
4865ecf13   Serge E. Hallyn   [PATCH] namespace...
6
   */
9984de1a5   Paul Gortmaker   kernel: Map most ...
7
  #include <linux/export.h>
4865ecf13   Serge E. Hallyn   [PATCH] namespace...
8
9
  #include <linux/uts.h>
  #include <linux/utsname.h>
467e9f4b5   Cedric Le Goater   fix create_new_na...
10
  #include <linux/err.h>
1aeb272cf   Robert P. J. Day   kernel: explicitl...
11
  #include <linux/slab.h>
5b825c3af   Ingo Molnar   sched/headers: Pr...
12
  #include <linux/cred.h>
59607db36   Serge E. Hallyn   userns: add a use...
13
  #include <linux/user_namespace.h>
0bb80f240   David Howells   proc: Split the n...
14
  #include <linux/proc_ns.h>
f719ff9bc   Ingo Molnar   sched/headers: Pr...
15
  #include <linux/sched/task.h>
4865ecf13   Serge E. Hallyn   [PATCH] namespace...
16

3ea056c50   Alexey Dobriyan   uts: create "stru...
17
  static struct kmem_cache *uts_ns_cache __ro_after_init;
f7af3d1c0   Eric W. Biederman   utsns: Add a limi...
18
19
20
21
22
23
24
25
26
  static struct ucounts *inc_uts_namespaces(struct user_namespace *ns)
  {
  	return inc_ucount(ns, current_euid(), UCOUNT_UTS_NAMESPACES);
  }
  
  static void dec_uts_namespaces(struct ucounts *ucounts)
  {
  	dec_ucount(ucounts, UCOUNT_UTS_NAMESPACES);
  }
4c2a7e72d   Alexey Dobriyan   utsns: extract cr...
27
28
29
  static struct uts_namespace *create_uts_ns(void)
  {
  	struct uts_namespace *uts_ns;
3ea056c50   Alexey Dobriyan   uts: create "stru...
30
  	uts_ns = kmem_cache_alloc(uts_ns_cache, GFP_KERNEL);
4c2a7e72d   Alexey Dobriyan   utsns: extract cr...
31
32
33
34
  	if (uts_ns)
  		kref_init(&uts_ns->kref);
  	return uts_ns;
  }
4865ecf13   Serge E. Hallyn   [PATCH] namespace...
35
  /*
071df104f   Serge E. Hallyn   [PATCH] namespace...
36
37
   * Clone a new ns copying an original utsname, setting refcount to 1
   * @old_ns: namespace to clone
3ea056c50   Alexey Dobriyan   uts: create "stru...
38
   * Return ERR_PTR(-ENOMEM) on error (failure to allocate), new ns otherwise
071df104f   Serge E. Hallyn   [PATCH] namespace...
39
   */
bcf58e725   Eric W. Biederman   userns: Make crea...
40
  static struct uts_namespace *clone_uts_ns(struct user_namespace *user_ns,
bb96a6f50   Serge E. Hallyn   userns: allow set...
41
  					  struct uts_namespace *old_ns)
071df104f   Serge E. Hallyn   [PATCH] namespace...
42
43
  {
  	struct uts_namespace *ns;
f7af3d1c0   Eric W. Biederman   utsns: Add a limi...
44
  	struct ucounts *ucounts;
98f842e67   Eric W. Biederman   proc: Usable inod...
45
  	int err;
071df104f   Serge E. Hallyn   [PATCH] namespace...
46

df75e7748   Eric W. Biederman   userns: When the ...
47
  	err = -ENOSPC;
f7af3d1c0   Eric W. Biederman   utsns: Add a limi...
48
49
50
51
52
  	ucounts = inc_uts_namespaces(user_ns);
  	if (!ucounts)
  		goto fail;
  
  	err = -ENOMEM;
4c2a7e72d   Alexey Dobriyan   utsns: extract cr...
53
  	ns = create_uts_ns();
467e9f4b5   Cedric Le Goater   fix create_new_na...
54
  	if (!ns)
f7af3d1c0   Eric W. Biederman   utsns: Add a limi...
55
  		goto fail_dec;
467e9f4b5   Cedric Le Goater   fix create_new_na...
56

6344c433a   Al Viro   new helpers: ns_a...
57
  	err = ns_alloc_inum(&ns->ns);
f7af3d1c0   Eric W. Biederman   utsns: Add a limi...
58
59
  	if (err)
  		goto fail_free;
98f842e67   Eric W. Biederman   proc: Usable inod...
60

f7af3d1c0   Eric W. Biederman   utsns: Add a limi...
61
  	ns->ucounts = ucounts;
33c429405   Al Viro   copy address of p...
62
  	ns->ns.ops = &utsns_operations;
efc63c4fb   Alexey Dobriyan   Fix UTS corruptio...
63
  	down_read(&uts_sem);
467e9f4b5   Cedric Le Goater   fix create_new_na...
64
  	memcpy(&ns->name, &old_ns->name, sizeof(ns->name));
bcf58e725   Eric W. Biederman   userns: Make crea...
65
  	ns->user_ns = get_user_ns(user_ns);
efc63c4fb   Alexey Dobriyan   Fix UTS corruptio...
66
  	up_read(&uts_sem);
071df104f   Serge E. Hallyn   [PATCH] namespace...
67
  	return ns;
f7af3d1c0   Eric W. Biederman   utsns: Add a limi...
68
69
  
  fail_free:
3ea056c50   Alexey Dobriyan   uts: create "stru...
70
  	kmem_cache_free(uts_ns_cache, ns);
f7af3d1c0   Eric W. Biederman   utsns: Add a limi...
71
72
73
74
  fail_dec:
  	dec_uts_namespaces(ucounts);
  fail:
  	return ERR_PTR(err);
071df104f   Serge E. Hallyn   [PATCH] namespace...
75
76
77
  }
  
  /*
4865ecf13   Serge E. Hallyn   [PATCH] namespace...
78
79
80
81
82
   * Copy task tsk's utsname namespace, or clone it if flags
   * specifies CLONE_NEWUTS.  In latter case, changes to the
   * utsname of this process won't be seen by parent, and vice
   * versa.
   */
bb96a6f50   Serge E. Hallyn   userns: allow set...
83
  struct uts_namespace *copy_utsname(unsigned long flags,
bcf58e725   Eric W. Biederman   userns: Make crea...
84
  	struct user_namespace *user_ns, struct uts_namespace *old_ns)
4865ecf13   Serge E. Hallyn   [PATCH] namespace...
85
  {
071df104f   Serge E. Hallyn   [PATCH] namespace...
86
  	struct uts_namespace *new_ns;
4865ecf13   Serge E. Hallyn   [PATCH] namespace...
87

e3222c4ec   Badari Pulavarty   Merge sys_clone()...
88
  	BUG_ON(!old_ns);
4865ecf13   Serge E. Hallyn   [PATCH] namespace...
89
  	get_uts_ns(old_ns);
071df104f   Serge E. Hallyn   [PATCH] namespace...
90
  	if (!(flags & CLONE_NEWUTS))
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
91
  		return old_ns;
071df104f   Serge E. Hallyn   [PATCH] namespace...
92

bcf58e725   Eric W. Biederman   userns: Make crea...
93
  	new_ns = clone_uts_ns(user_ns, old_ns);
071df104f   Serge E. Hallyn   [PATCH] namespace...
94

071df104f   Serge E. Hallyn   [PATCH] namespace...
95
  	put_uts_ns(old_ns);
e3222c4ec   Badari Pulavarty   Merge sys_clone()...
96
  	return new_ns;
4865ecf13   Serge E. Hallyn   [PATCH] namespace...
97
98
99
100
101
102
103
  }
  
  void free_uts_ns(struct kref *kref)
  {
  	struct uts_namespace *ns;
  
  	ns = container_of(kref, struct uts_namespace, kref);
f7af3d1c0   Eric W. Biederman   utsns: Add a limi...
104
  	dec_uts_namespaces(ns->ucounts);
59607db36   Serge E. Hallyn   userns: add a use...
105
  	put_user_ns(ns->user_ns);
6344c433a   Al Viro   new helpers: ns_a...
106
  	ns_free_inum(&ns->ns);
3ea056c50   Alexey Dobriyan   uts: create "stru...
107
  	kmem_cache_free(uts_ns_cache, ns);
4865ecf13   Serge E. Hallyn   [PATCH] namespace...
108
  }
34482e89a   Eric W. Biederman   ns proc: Add supp...
109

3c0411846   Al Viro   switch the rest o...
110
111
112
113
  static inline struct uts_namespace *to_uts_ns(struct ns_common *ns)
  {
  	return container_of(ns, struct uts_namespace, ns);
  }
64964528b   Al Viro   make proc_ns_oper...
114
  static struct ns_common *utsns_get(struct task_struct *task)
34482e89a   Eric W. Biederman   ns proc: Add supp...
115
116
117
  {
  	struct uts_namespace *ns = NULL;
  	struct nsproxy *nsproxy;
728dba3a3   Eric W. Biederman   namespaces: Use t...
118
119
  	task_lock(task);
  	nsproxy = task->nsproxy;
34482e89a   Eric W. Biederman   ns proc: Add supp...
120
121
122
123
  	if (nsproxy) {
  		ns = nsproxy->uts_ns;
  		get_uts_ns(ns);
  	}
728dba3a3   Eric W. Biederman   namespaces: Use t...
124
  	task_unlock(task);
34482e89a   Eric W. Biederman   ns proc: Add supp...
125

3c0411846   Al Viro   switch the rest o...
126
  	return ns ? &ns->ns : NULL;
34482e89a   Eric W. Biederman   ns proc: Add supp...
127
  }
64964528b   Al Viro   make proc_ns_oper...
128
  static void utsns_put(struct ns_common *ns)
34482e89a   Eric W. Biederman   ns proc: Add supp...
129
  {
3c0411846   Al Viro   switch the rest o...
130
  	put_uts_ns(to_uts_ns(ns));
34482e89a   Eric W. Biederman   ns proc: Add supp...
131
  }
f2a8d52e0   Christian Brauner   nsproxy: add stru...
132
  static int utsns_install(struct nsset *nsset, struct ns_common *new)
34482e89a   Eric W. Biederman   ns proc: Add supp...
133
  {
f2a8d52e0   Christian Brauner   nsproxy: add stru...
134
  	struct nsproxy *nsproxy = nsset->nsproxy;
3c0411846   Al Viro   switch the rest o...
135
  	struct uts_namespace *ns = to_uts_ns(new);
142e1d1d5   Eric W. Biederman   userns: Allow unp...
136

5e4a08476   Eric W. Biederman   userns: Require C...
137
  	if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) ||
f2a8d52e0   Christian Brauner   nsproxy: add stru...
138
  	    !ns_capable(nsset->cred->user_ns, CAP_SYS_ADMIN))
142e1d1d5   Eric W. Biederman   userns: Allow unp...
139
  		return -EPERM;
34482e89a   Eric W. Biederman   ns proc: Add supp...
140
141
142
143
144
  	get_uts_ns(ns);
  	put_uts_ns(nsproxy->uts_ns);
  	nsproxy->uts_ns = ns;
  	return 0;
  }
bcac25a58   Andrey Vagin   kernel: add a hel...
145
146
147
148
  static struct user_namespace *utsns_owner(struct ns_common *ns)
  {
  	return to_uts_ns(ns)->user_ns;
  }
34482e89a   Eric W. Biederman   ns proc: Add supp...
149
150
151
152
153
154
  const struct proc_ns_operations utsns_operations = {
  	.name		= "uts",
  	.type		= CLONE_NEWUTS,
  	.get		= utsns_get,
  	.put		= utsns_put,
  	.install	= utsns_install,
bcac25a58   Andrey Vagin   kernel: add a hel...
155
  	.owner		= utsns_owner,
34482e89a   Eric W. Biederman   ns proc: Add supp...
156
  };
3ea056c50   Alexey Dobriyan   uts: create "stru...
157
158
159
160
161
162
163
164
165
166
  
  void __init uts_ns_init(void)
  {
  	uts_ns_cache = kmem_cache_create_usercopy(
  			"uts_namespace", sizeof(struct uts_namespace), 0,
  			SLAB_PANIC|SLAB_ACCOUNT,
  			offsetof(struct uts_namespace, name),
  			sizeof_field(struct uts_namespace, name),
  			NULL);
  }