xref: /linux-6.15/include/linux/user_namespace.h (revision b4dc0bee)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
2acce292cSCedric Le Goater #ifndef _LINUX_USER_NAMESPACE_H
3acce292cSCedric Le Goater #define _LINUX_USER_NAMESPACE_H
4acce292cSCedric Le Goater 
5acce292cSCedric Le Goater #include <linux/kref.h>
6acce292cSCedric Le Goater #include <linux/nsproxy.h>
7435d5f4bSAl Viro #include <linux/ns_common.h>
85f01a22cSSebastian Andrzej Siewior #include <linux/rculist_nulls.h>
9acce292cSCedric Le Goater #include <linux/sched.h>
10b2d5bfeaSIngo Molnar #include <linux/workqueue.h>
11*b4dc0beeSSebastian Andrzej Siewior #include <linux/rcuref.h>
12cd9c513bSIngo Molnar #include <linux/rwsem.h>
13cc5efc23SIngo Molnar #include <linux/sysctl.h>
1477ec739dSSerge E. Hallyn #include <linux/err.h>
15acce292cSCedric Le Goater 
166397fac4SChristian Brauner #define UID_GID_MAP_MAX_BASE_EXTENTS 5
176397fac4SChristian Brauner #define UID_GID_MAP_MAX_EXTENTS 340
1822d917d8SEric W. Biederman 
1922d917d8SEric W. Biederman struct uid_gid_extent {
2022d917d8SEric W. Biederman 	u32 first;
2122d917d8SEric W. Biederman 	u32 lower_first;
2222d917d8SEric W. Biederman 	u32 count;
23aa4bf44dSChristian Brauner };
24aa4bf44dSChristian Brauner 
25aa4bf44dSChristian Brauner struct uid_gid_map { /* 64 bytes -- 1 cache line */
26aa4bf44dSChristian Brauner 	union {
272077006dSChristian Brauner 		struct {
286397fac4SChristian Brauner 			struct uid_gid_extent extent[UID_GID_MAP_MAX_BASE_EXTENTS];
292077006dSChristian Brauner 			u32 nr_extents;
302077006dSChristian Brauner 		};
31aa4bf44dSChristian Brauner 		struct {
32aa4bf44dSChristian Brauner 			struct uid_gid_extent *forward;
33aa4bf44dSChristian Brauner 			struct uid_gid_extent *reverse;
34aa4bf44dSChristian Brauner 		};
35aa4bf44dSChristian Brauner 	};
3622d917d8SEric W. Biederman };
3722d917d8SEric W. Biederman 
389cc46516SEric W. Biederman #define USERNS_SETGROUPS_ALLOWED 1UL
399cc46516SEric W. Biederman 
409cc46516SEric W. Biederman #define USERNS_INIT_FLAGS USERNS_SETGROUPS_ALLOWED
419cc46516SEric W. Biederman 
42f6b2db1aSEric W. Biederman struct ucounts;
4325f9c081SEric W. Biederman 
4425f9c081SEric W. Biederman enum ucount_type {
4525f9c081SEric W. Biederman 	UCOUNT_USER_NAMESPACES,
46f333c700SEric W. Biederman 	UCOUNT_PID_NAMESPACES,
47f7af3d1cSEric W. Biederman 	UCOUNT_UTS_NAMESPACES,
48aba35661SEric W. Biederman 	UCOUNT_IPC_NAMESPACES,
4970328660SEric W. Biederman 	UCOUNT_NET_NAMESPACES,
50537f7ccbSEric W. Biederman 	UCOUNT_MNT_NAMESPACES,
51d08311ddSEric W. Biederman 	UCOUNT_CGROUP_NAMESPACES,
52769071acSAndrei Vagin 	UCOUNT_TIME_NAMESPACES,
531cce1eeaSNikolay Borisov #ifdef CONFIG_INOTIFY_USER
541cce1eeaSNikolay Borisov 	UCOUNT_INOTIFY_INSTANCES,
551cce1eeaSNikolay Borisov 	UCOUNT_INOTIFY_WATCHES,
561cce1eeaSNikolay Borisov #endif
575b8fea65SAmir Goldstein #ifdef CONFIG_FANOTIFY
585b8fea65SAmir Goldstein 	UCOUNT_FANOTIFY_GROUPS,
595b8fea65SAmir Goldstein 	UCOUNT_FANOTIFY_MARKS,
605b8fea65SAmir Goldstein #endif
61de399236SAlexey Gladkov 	UCOUNT_COUNTS,
62de399236SAlexey Gladkov };
63de399236SAlexey Gladkov 
64de399236SAlexey Gladkov enum rlimit_type {
6521d1c5e3SAlexey Gladkov 	UCOUNT_RLIMIT_NPROC,
666e52a9f0SAlexey Gladkov 	UCOUNT_RLIMIT_MSGQUEUE,
67d6469690SAlexey Gladkov 	UCOUNT_RLIMIT_SIGPENDING,
68d7c9e99aSAlexey Gladkov 	UCOUNT_RLIMIT_MEMLOCK,
69de399236SAlexey Gladkov 	UCOUNT_RLIMIT_COUNTS,
7025f9c081SEric W. Biederman };
7125f9c081SEric W. Biederman 
7221ca59b3SChristian Brauner #if IS_ENABLED(CONFIG_BINFMT_MISC)
7321ca59b3SChristian Brauner struct binfmt_misc;
7421ca59b3SChristian Brauner #endif
7521ca59b3SChristian Brauner 
76acce292cSCedric Le Goater struct user_namespace {
7722d917d8SEric W. Biederman 	struct uid_gid_map	uid_map;
7822d917d8SEric W. Biederman 	struct uid_gid_map	gid_map;
79f76d207aSEric W. Biederman 	struct uid_gid_map	projid_map;
80aeb3ae9dSEric W. Biederman 	struct user_namespace	*parent;
818742f229SOleg Nesterov 	int			level;
82783291e6SEric W. Biederman 	kuid_t			owner;
83783291e6SEric W. Biederman 	kgid_t			group;
84435d5f4bSAl Viro 	struct ns_common	ns;
859cc46516SEric W. Biederman 	unsigned long		flags;
86db2e718aSSerge E. Hallyn 	/* parent_could_setfcap: true if the creator if this ns had CAP_SETFCAP
87db2e718aSSerge E. Hallyn 	 * in its effective capability set at the child ns creation time. */
88db2e718aSSerge E. Hallyn 	bool			parent_could_setfcap;
89f36f8c75SDavid Howells 
90b206f281SDavid Howells #ifdef CONFIG_KEYS
910f44e4d9SDavid Howells 	/* List of joinable keyrings in this namespace.  Modification access of
920f44e4d9SDavid Howells 	 * these pointers is controlled by keyring_sem.  Once
930f44e4d9SDavid Howells 	 * user_keyring_register is set, it won't be changed, so it can be
940f44e4d9SDavid Howells 	 * accessed directly with READ_ONCE().
950f44e4d9SDavid Howells 	 */
96b206f281SDavid Howells 	struct list_head	keyring_name_list;
970f44e4d9SDavid Howells 	struct key		*user_keyring_register;
980f44e4d9SDavid Howells 	struct rw_semaphore	keyring_sem;
99b206f281SDavid Howells #endif
100b206f281SDavid Howells 
101f36f8c75SDavid Howells 	/* Register of per-UID persistent keyrings for this namespace */
102f36f8c75SDavid Howells #ifdef CONFIG_PERSISTENT_KEYRINGS
103f36f8c75SDavid Howells 	struct key		*persistent_keyring_register;
104f36f8c75SDavid Howells #endif
105b032132cSEric W. Biederman 	struct work_struct	work;
106dbec2846SEric W. Biederman #ifdef CONFIG_SYSCTL
107dbec2846SEric W. Biederman 	struct ctl_table_set	set;
108dbec2846SEric W. Biederman 	struct ctl_table_header *sysctls;
109dbec2846SEric W. Biederman #endif
110f6b2db1aSEric W. Biederman 	struct ucounts		*ucounts;
111f9c82a4eSAlexey Gladkov 	long ucount_max[UCOUNT_COUNTS];
112de399236SAlexey Gladkov 	long rlimit_max[UCOUNT_RLIMIT_COUNTS];
11321ca59b3SChristian Brauner 
11421ca59b3SChristian Brauner #if IS_ENABLED(CONFIG_BINFMT_MISC)
11521ca59b3SChristian Brauner 	struct binfmt_misc *binfmt_misc;
11621ca59b3SChristian Brauner #endif
1173859a271SKees Cook } __randomize_layout;
118f6b2db1aSEric W. Biederman 
119f6b2db1aSEric W. Biederman struct ucounts {
1205f01a22cSSebastian Andrzej Siewior 	struct hlist_nulls_node node;
121f6b2db1aSEric W. Biederman 	struct user_namespace *ns;
122f6b2db1aSEric W. Biederman 	kuid_t uid;
1235f01a22cSSebastian Andrzej Siewior 	struct rcu_head rcu;
124*b4dc0beeSSebastian Andrzej Siewior 	rcuref_t count;
125f9c82a4eSAlexey Gladkov 	atomic_long_t ucount[UCOUNT_COUNTS];
126de399236SAlexey Gladkov 	atomic_long_t rlimit[UCOUNT_RLIMIT_COUNTS];
127acce292cSCedric Le Goater };
128acce292cSCedric Le Goater 
129acce292cSCedric Le Goater extern struct user_namespace init_user_ns;
130905ae01cSAlexey Gladkov extern struct ucounts init_ucounts;
131f6b2db1aSEric W. Biederman 
132f6b2db1aSEric W. Biederman bool setup_userns_sysctls(struct user_namespace *ns);
133f6b2db1aSEric W. Biederman void retire_userns_sysctls(struct user_namespace *ns);
13425f9c081SEric W. Biederman struct ucounts *inc_ucount(struct user_namespace *ns, kuid_t uid, enum ucount_type type);
13525f9c081SEric W. Biederman void dec_ucount(struct ucounts *ucounts, enum ucount_type type);
136905ae01cSAlexey Gladkov struct ucounts *alloc_ucounts(struct user_namespace *ns, kuid_t uid);
137905ae01cSAlexey Gladkov void put_ucounts(struct ucounts *ucounts);
138acce292cSCedric Le Goater 
get_ucounts(struct ucounts * ucounts)139*b4dc0beeSSebastian Andrzej Siewior static inline struct ucounts * __must_check get_ucounts(struct ucounts *ucounts)
140*b4dc0beeSSebastian Andrzej Siewior {
141*b4dc0beeSSebastian Andrzej Siewior 	if (rcuref_get(&ucounts->count))
142*b4dc0beeSSebastian Andrzej Siewior 		return ucounts;
143*b4dc0beeSSebastian Andrzej Siewior 	return NULL;
144*b4dc0beeSSebastian Andrzej Siewior }
145*b4dc0beeSSebastian Andrzej Siewior 
get_rlimit_value(struct ucounts * ucounts,enum rlimit_type type)146de399236SAlexey Gladkov static inline long get_rlimit_value(struct ucounts *ucounts, enum rlimit_type type)
14721d1c5e3SAlexey Gladkov {
148de399236SAlexey Gladkov 	return atomic_long_read(&ucounts->rlimit[type]);
14921d1c5e3SAlexey Gladkov }
15021d1c5e3SAlexey Gladkov 
151de399236SAlexey Gladkov long inc_rlimit_ucounts(struct ucounts *ucounts, enum rlimit_type type, long v);
152de399236SAlexey Gladkov bool dec_rlimit_ucounts(struct ucounts *ucounts, enum rlimit_type type, long v);
1539e05e5c7SRoman Gushchin long inc_rlimit_get_ucounts(struct ucounts *ucounts, enum rlimit_type type,
1549e05e5c7SRoman Gushchin 			    bool override_rlimit);
155de399236SAlexey Gladkov void dec_rlimit_put_ucounts(struct ucounts *ucounts, enum rlimit_type type);
156de399236SAlexey Gladkov bool is_rlimit_overlimit(struct ucounts *ucounts, enum rlimit_type type, unsigned long max);
15721d1c5e3SAlexey Gladkov 
get_userns_rlimit_max(struct user_namespace * ns,enum rlimit_type type)158de399236SAlexey Gladkov static inline long get_userns_rlimit_max(struct user_namespace *ns, enum rlimit_type type)
159c1ada3dcSAlexey Gladkov {
160de399236SAlexey Gladkov 	return READ_ONCE(ns->rlimit_max[type]);
161de399236SAlexey Gladkov }
162de399236SAlexey Gladkov 
set_userns_rlimit_max(struct user_namespace * ns,enum rlimit_type type,unsigned long max)163de399236SAlexey Gladkov static inline void set_userns_rlimit_max(struct user_namespace *ns,
164de399236SAlexey Gladkov 		enum rlimit_type type, unsigned long max)
165de399236SAlexey Gladkov {
166de399236SAlexey Gladkov 	ns->rlimit_max[type] = max <= LONG_MAX ? max : LONG_MAX;
167c1ada3dcSAlexey Gladkov }
168acce292cSCedric Le Goater 
169acce292cSCedric Le Goater #ifdef CONFIG_USER_NS
170acce292cSCedric Le Goater 
get_user_ns(struct user_namespace * ns)171acce292cSCedric Le Goater static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
172acce292cSCedric Le Goater {
173acce292cSCedric Le Goater 	if (ns)
174265cbd62SKirill Tkhai 		refcount_inc(&ns->ns.count);
175acce292cSCedric Le Goater 	return ns;
176acce292cSCedric Le Goater }
177acce292cSCedric Le Goater 
17818b6e041SSerge Hallyn extern int create_user_ns(struct cred *new);
179b2e0d987SEric W. Biederman extern int unshare_userns(unsigned long unshare_flags, struct cred **new_cred);
180b032132cSEric W. Biederman extern void __put_user_ns(struct user_namespace *ns);
181acce292cSCedric Le Goater 
put_user_ns(struct user_namespace * ns)182acce292cSCedric Le Goater static inline void put_user_ns(struct user_namespace *ns)
183acce292cSCedric Le Goater {
184265cbd62SKirill Tkhai 	if (ns && refcount_dec_and_test(&ns->ns.count))
185b032132cSEric W. Biederman 		__put_user_ns(ns);
186acce292cSCedric Le Goater }
187acce292cSCedric Le Goater 
18822d917d8SEric W. Biederman struct seq_operations;
189ccf94f1bSFabian Frederick extern const struct seq_operations proc_uid_seq_operations;
190ccf94f1bSFabian Frederick extern const struct seq_operations proc_gid_seq_operations;
191ccf94f1bSFabian Frederick extern const struct seq_operations proc_projid_seq_operations;
19222d917d8SEric W. Biederman extern ssize_t proc_uid_map_write(struct file *, const char __user *, size_t, loff_t *);
19322d917d8SEric W. Biederman extern ssize_t proc_gid_map_write(struct file *, const char __user *, size_t, loff_t *);
194f76d207aSEric W. Biederman extern ssize_t proc_projid_map_write(struct file *, const char __user *, size_t, loff_t *);
1959cc46516SEric W. Biederman extern ssize_t proc_setgroups_write(struct file *, const char __user *, size_t, loff_t *);
1969cc46516SEric W. Biederman extern int proc_setgroups_show(struct seq_file *m, void *v);
197273d2c67SEric W. Biederman extern bool userns_may_setgroups(const struct user_namespace *ns);
198a2b42626SEric W. Biederman extern bool in_userns(const struct user_namespace *ancestor,
199a2b42626SEric W. Biederman 		       const struct user_namespace *child);
200d07b846fSSeth Forshee extern bool current_in_userns(const struct user_namespace *target_ns);
201bcac25a5SAndrey Vagin struct ns_common *ns_get_owner(struct ns_common *ns);
202acce292cSCedric Le Goater #else
203acce292cSCedric Le Goater 
get_user_ns(struct user_namespace * ns)204acce292cSCedric Le Goater static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
205acce292cSCedric Le Goater {
206acce292cSCedric Le Goater 	return &init_user_ns;
207acce292cSCedric Le Goater }
208acce292cSCedric Le Goater 
create_user_ns(struct cred * new)20918b6e041SSerge Hallyn static inline int create_user_ns(struct cred *new)
210acce292cSCedric Le Goater {
21118b6e041SSerge Hallyn 	return -EINVAL;
212acce292cSCedric Le Goater }
213acce292cSCedric Le Goater 
unshare_userns(unsigned long unshare_flags,struct cred ** new_cred)214b2e0d987SEric W. Biederman static inline int unshare_userns(unsigned long unshare_flags,
215b2e0d987SEric W. Biederman 				 struct cred **new_cred)
216b2e0d987SEric W. Biederman {
217b2e0d987SEric W. Biederman 	if (unshare_flags & CLONE_NEWUSER)
218b2e0d987SEric W. Biederman 		return -EINVAL;
219b2e0d987SEric W. Biederman 	return 0;
220b2e0d987SEric W. Biederman }
221b2e0d987SEric W. Biederman 
put_user_ns(struct user_namespace * ns)222acce292cSCedric Le Goater static inline void put_user_ns(struct user_namespace *ns)
223acce292cSCedric Le Goater {
224acce292cSCedric Le Goater }
225acce292cSCedric Le Goater 
userns_may_setgroups(const struct user_namespace * ns)226273d2c67SEric W. Biederman static inline bool userns_may_setgroups(const struct user_namespace *ns)
227273d2c67SEric W. Biederman {
228273d2c67SEric W. Biederman 	return true;
229273d2c67SEric W. Biederman }
230d07b846fSSeth Forshee 
in_userns(const struct user_namespace * ancestor,const struct user_namespace * child)231a2b42626SEric W. Biederman static inline bool in_userns(const struct user_namespace *ancestor,
232a2b42626SEric W. Biederman 			     const struct user_namespace *child)
233a2b42626SEric W. Biederman {
234a2b42626SEric W. Biederman 	return true;
235a2b42626SEric W. Biederman }
236a2b42626SEric W. Biederman 
current_in_userns(const struct user_namespace * target_ns)237d07b846fSSeth Forshee static inline bool current_in_userns(const struct user_namespace *target_ns)
238d07b846fSSeth Forshee {
239d07b846fSSeth Forshee 	return true;
240d07b846fSSeth Forshee }
241bcac25a5SAndrey Vagin 
ns_get_owner(struct ns_common * ns)242bcac25a5SAndrey Vagin static inline struct ns_common *ns_get_owner(struct ns_common *ns)
243bcac25a5SAndrey Vagin {
244bcac25a5SAndrey Vagin 	return ERR_PTR(-EPERM);
245bcac25a5SAndrey Vagin }
24622d917d8SEric W. Biederman #endif
24722d917d8SEric W. Biederman 
248acce292cSCedric Le Goater #endif /* _LINUX_USER_H */
249