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>
8acce292cSCedric Le Goater #include <linux/sched.h>
9b2d5bfeaSIngo Molnar #include <linux/workqueue.h>
10cd9c513bSIngo Molnar #include <linux/rwsem.h>
11cc5efc23SIngo Molnar #include <linux/sysctl.h>
1277ec739dSSerge E. Hallyn #include <linux/err.h>
13acce292cSCedric Le Goater 
146397fac4SChristian Brauner #define UID_GID_MAP_MAX_BASE_EXTENTS 5
156397fac4SChristian Brauner #define UID_GID_MAP_MAX_EXTENTS 340
1622d917d8SEric W. Biederman 
1722d917d8SEric W. Biederman struct uid_gid_extent {
1822d917d8SEric W. Biederman 	u32 first;
1922d917d8SEric W. Biederman 	u32 lower_first;
2022d917d8SEric W. Biederman 	u32 count;
21aa4bf44dSChristian Brauner };
22aa4bf44dSChristian Brauner 
23aa4bf44dSChristian Brauner struct uid_gid_map { /* 64 bytes -- 1 cache line */
24aa4bf44dSChristian Brauner 	u32 nr_extents;
25aa4bf44dSChristian Brauner 	union {
266397fac4SChristian Brauner 		struct uid_gid_extent extent[UID_GID_MAP_MAX_BASE_EXTENTS];
27aa4bf44dSChristian Brauner 		struct {
28aa4bf44dSChristian Brauner 			struct uid_gid_extent *forward;
29aa4bf44dSChristian Brauner 			struct uid_gid_extent *reverse;
30aa4bf44dSChristian Brauner 		};
31aa4bf44dSChristian Brauner 	};
3222d917d8SEric W. Biederman };
3322d917d8SEric W. Biederman 
349cc46516SEric W. Biederman #define USERNS_SETGROUPS_ALLOWED 1UL
359cc46516SEric W. Biederman 
369cc46516SEric W. Biederman #define USERNS_INIT_FLAGS USERNS_SETGROUPS_ALLOWED
379cc46516SEric W. Biederman 
38f6b2db1aSEric W. Biederman struct ucounts;
3925f9c081SEric W. Biederman 
4025f9c081SEric W. Biederman enum ucount_type {
4125f9c081SEric W. Biederman 	UCOUNT_USER_NAMESPACES,
42f333c700SEric W. Biederman 	UCOUNT_PID_NAMESPACES,
43f7af3d1cSEric W. Biederman 	UCOUNT_UTS_NAMESPACES,
44aba35661SEric W. Biederman 	UCOUNT_IPC_NAMESPACES,
4570328660SEric W. Biederman 	UCOUNT_NET_NAMESPACES,
46537f7ccbSEric W. Biederman 	UCOUNT_MNT_NAMESPACES,
47d08311ddSEric W. Biederman 	UCOUNT_CGROUP_NAMESPACES,
48769071acSAndrei Vagin 	UCOUNT_TIME_NAMESPACES,
491cce1eeaSNikolay Borisov #ifdef CONFIG_INOTIFY_USER
501cce1eeaSNikolay Borisov 	UCOUNT_INOTIFY_INSTANCES,
511cce1eeaSNikolay Borisov 	UCOUNT_INOTIFY_WATCHES,
521cce1eeaSNikolay Borisov #endif
535b8fea65SAmir Goldstein #ifdef CONFIG_FANOTIFY
545b8fea65SAmir Goldstein 	UCOUNT_FANOTIFY_GROUPS,
555b8fea65SAmir Goldstein 	UCOUNT_FANOTIFY_MARKS,
565b8fea65SAmir Goldstein #endif
57*de399236SAlexey Gladkov 	UCOUNT_COUNTS,
58*de399236SAlexey Gladkov };
59*de399236SAlexey Gladkov 
60*de399236SAlexey Gladkov enum rlimit_type {
6121d1c5e3SAlexey Gladkov 	UCOUNT_RLIMIT_NPROC,
626e52a9f0SAlexey Gladkov 	UCOUNT_RLIMIT_MSGQUEUE,
63d6469690SAlexey Gladkov 	UCOUNT_RLIMIT_SIGPENDING,
64d7c9e99aSAlexey Gladkov 	UCOUNT_RLIMIT_MEMLOCK,
65*de399236SAlexey Gladkov 	UCOUNT_RLIMIT_COUNTS,
6625f9c081SEric W. Biederman };
6725f9c081SEric W. Biederman 
68acce292cSCedric Le Goater struct user_namespace {
6922d917d8SEric W. Biederman 	struct uid_gid_map	uid_map;
7022d917d8SEric W. Biederman 	struct uid_gid_map	gid_map;
71f76d207aSEric W. Biederman 	struct uid_gid_map	projid_map;
72aeb3ae9dSEric W. Biederman 	struct user_namespace	*parent;
738742f229SOleg Nesterov 	int			level;
74783291e6SEric W. Biederman 	kuid_t			owner;
75783291e6SEric W. Biederman 	kgid_t			group;
76435d5f4bSAl Viro 	struct ns_common	ns;
779cc46516SEric W. Biederman 	unsigned long		flags;
78db2e718aSSerge E. Hallyn 	/* parent_could_setfcap: true if the creator if this ns had CAP_SETFCAP
79db2e718aSSerge E. Hallyn 	 * in its effective capability set at the child ns creation time. */
80db2e718aSSerge E. Hallyn 	bool			parent_could_setfcap;
81f36f8c75SDavid Howells 
82b206f281SDavid Howells #ifdef CONFIG_KEYS
830f44e4d9SDavid Howells 	/* List of joinable keyrings in this namespace.  Modification access of
840f44e4d9SDavid Howells 	 * these pointers is controlled by keyring_sem.  Once
850f44e4d9SDavid Howells 	 * user_keyring_register is set, it won't be changed, so it can be
860f44e4d9SDavid Howells 	 * accessed directly with READ_ONCE().
870f44e4d9SDavid Howells 	 */
88b206f281SDavid Howells 	struct list_head	keyring_name_list;
890f44e4d9SDavid Howells 	struct key		*user_keyring_register;
900f44e4d9SDavid Howells 	struct rw_semaphore	keyring_sem;
91b206f281SDavid Howells #endif
92b206f281SDavid Howells 
93f36f8c75SDavid Howells 	/* Register of per-UID persistent keyrings for this namespace */
94f36f8c75SDavid Howells #ifdef CONFIG_PERSISTENT_KEYRINGS
95f36f8c75SDavid Howells 	struct key		*persistent_keyring_register;
96f36f8c75SDavid Howells #endif
97b032132cSEric W. Biederman 	struct work_struct	work;
98dbec2846SEric W. Biederman #ifdef CONFIG_SYSCTL
99dbec2846SEric W. Biederman 	struct ctl_table_set	set;
100dbec2846SEric W. Biederman 	struct ctl_table_header *sysctls;
101dbec2846SEric W. Biederman #endif
102f6b2db1aSEric W. Biederman 	struct ucounts		*ucounts;
103f9c82a4eSAlexey Gladkov 	long ucount_max[UCOUNT_COUNTS];
104*de399236SAlexey Gladkov 	long rlimit_max[UCOUNT_RLIMIT_COUNTS];
1053859a271SKees Cook } __randomize_layout;
106f6b2db1aSEric W. Biederman 
107f6b2db1aSEric W. Biederman struct ucounts {
108f6b2db1aSEric W. Biederman 	struct hlist_node node;
109f6b2db1aSEric W. Biederman 	struct user_namespace *ns;
110f6b2db1aSEric W. Biederman 	kuid_t uid;
111b6c33652SAlexey Gladkov 	atomic_t count;
112f9c82a4eSAlexey Gladkov 	atomic_long_t ucount[UCOUNT_COUNTS];
113*de399236SAlexey Gladkov 	atomic_long_t rlimit[UCOUNT_RLIMIT_COUNTS];
114acce292cSCedric Le Goater };
115acce292cSCedric Le Goater 
116acce292cSCedric Le Goater extern struct user_namespace init_user_ns;
117905ae01cSAlexey Gladkov extern struct ucounts init_ucounts;
118f6b2db1aSEric W. Biederman 
119f6b2db1aSEric W. Biederman bool setup_userns_sysctls(struct user_namespace *ns);
120f6b2db1aSEric W. Biederman void retire_userns_sysctls(struct user_namespace *ns);
12125f9c081SEric W. Biederman struct ucounts *inc_ucount(struct user_namespace *ns, kuid_t uid, enum ucount_type type);
12225f9c081SEric W. Biederman void dec_ucount(struct ucounts *ucounts, enum ucount_type type);
123905ae01cSAlexey Gladkov struct ucounts *alloc_ucounts(struct user_namespace *ns, kuid_t uid);
124b6c33652SAlexey Gladkov struct ucounts * __must_check get_ucounts(struct ucounts *ucounts);
125905ae01cSAlexey Gladkov void put_ucounts(struct ucounts *ucounts);
126acce292cSCedric Le Goater 
get_rlimit_value(struct ucounts * ucounts,enum rlimit_type type)127*de399236SAlexey Gladkov static inline long get_rlimit_value(struct ucounts *ucounts, enum rlimit_type type)
12821d1c5e3SAlexey Gladkov {
129*de399236SAlexey Gladkov 	return atomic_long_read(&ucounts->rlimit[type]);
13021d1c5e3SAlexey Gladkov }
13121d1c5e3SAlexey Gladkov 
132*de399236SAlexey Gladkov long inc_rlimit_ucounts(struct ucounts *ucounts, enum rlimit_type type, long v);
133*de399236SAlexey Gladkov bool dec_rlimit_ucounts(struct ucounts *ucounts, enum rlimit_type type, long v);
134*de399236SAlexey Gladkov long inc_rlimit_get_ucounts(struct ucounts *ucounts, enum rlimit_type type);
135*de399236SAlexey Gladkov void dec_rlimit_put_ucounts(struct ucounts *ucounts, enum rlimit_type type);
136*de399236SAlexey Gladkov bool is_rlimit_overlimit(struct ucounts *ucounts, enum rlimit_type type, unsigned long max);
13721d1c5e3SAlexey Gladkov 
get_userns_rlimit_max(struct user_namespace * ns,enum rlimit_type type)138*de399236SAlexey Gladkov static inline long get_userns_rlimit_max(struct user_namespace *ns, enum rlimit_type type)
139c1ada3dcSAlexey Gladkov {
140*de399236SAlexey Gladkov 	return READ_ONCE(ns->rlimit_max[type]);
141*de399236SAlexey Gladkov }
142*de399236SAlexey Gladkov 
set_userns_rlimit_max(struct user_namespace * ns,enum rlimit_type type,unsigned long max)143*de399236SAlexey Gladkov static inline void set_userns_rlimit_max(struct user_namespace *ns,
144*de399236SAlexey Gladkov 		enum rlimit_type type, unsigned long max)
145*de399236SAlexey Gladkov {
146*de399236SAlexey Gladkov 	ns->rlimit_max[type] = max <= LONG_MAX ? max : LONG_MAX;
147c1ada3dcSAlexey Gladkov }
148acce292cSCedric Le Goater 
149acce292cSCedric Le Goater #ifdef CONFIG_USER_NS
150acce292cSCedric Le Goater 
get_user_ns(struct user_namespace * ns)151acce292cSCedric Le Goater static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
152acce292cSCedric Le Goater {
153acce292cSCedric Le Goater 	if (ns)
154265cbd62SKirill Tkhai 		refcount_inc(&ns->ns.count);
155acce292cSCedric Le Goater 	return ns;
156acce292cSCedric Le Goater }
157acce292cSCedric Le Goater 
15818b6e041SSerge Hallyn extern int create_user_ns(struct cred *new);
159b2e0d987SEric W. Biederman extern int unshare_userns(unsigned long unshare_flags, struct cred **new_cred);
160b032132cSEric W. Biederman extern void __put_user_ns(struct user_namespace *ns);
161acce292cSCedric Le Goater 
put_user_ns(struct user_namespace * ns)162acce292cSCedric Le Goater static inline void put_user_ns(struct user_namespace *ns)
163acce292cSCedric Le Goater {
164265cbd62SKirill Tkhai 	if (ns && refcount_dec_and_test(&ns->ns.count))
165b032132cSEric W. Biederman 		__put_user_ns(ns);
166acce292cSCedric Le Goater }
167acce292cSCedric Le Goater 
16822d917d8SEric W. Biederman struct seq_operations;
169ccf94f1bSFabian Frederick extern const struct seq_operations proc_uid_seq_operations;
170ccf94f1bSFabian Frederick extern const struct seq_operations proc_gid_seq_operations;
171ccf94f1bSFabian Frederick extern const struct seq_operations proc_projid_seq_operations;
17222d917d8SEric W. Biederman extern ssize_t proc_uid_map_write(struct file *, const char __user *, size_t, loff_t *);
17322d917d8SEric W. Biederman extern ssize_t proc_gid_map_write(struct file *, const char __user *, size_t, loff_t *);
174f76d207aSEric W. Biederman extern ssize_t proc_projid_map_write(struct file *, const char __user *, size_t, loff_t *);
1759cc46516SEric W. Biederman extern ssize_t proc_setgroups_write(struct file *, const char __user *, size_t, loff_t *);
1769cc46516SEric W. Biederman extern int proc_setgroups_show(struct seq_file *m, void *v);
177273d2c67SEric W. Biederman extern bool userns_may_setgroups(const struct user_namespace *ns);
178a2b42626SEric W. Biederman extern bool in_userns(const struct user_namespace *ancestor,
179a2b42626SEric W. Biederman 		       const struct user_namespace *child);
180d07b846fSSeth Forshee extern bool current_in_userns(const struct user_namespace *target_ns);
181bcac25a5SAndrey Vagin struct ns_common *ns_get_owner(struct ns_common *ns);
182acce292cSCedric Le Goater #else
183acce292cSCedric Le Goater 
get_user_ns(struct user_namespace * ns)184acce292cSCedric Le Goater static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
185acce292cSCedric Le Goater {
186acce292cSCedric Le Goater 	return &init_user_ns;
187acce292cSCedric Le Goater }
188acce292cSCedric Le Goater 
create_user_ns(struct cred * new)18918b6e041SSerge Hallyn static inline int create_user_ns(struct cred *new)
190acce292cSCedric Le Goater {
19118b6e041SSerge Hallyn 	return -EINVAL;
192acce292cSCedric Le Goater }
193acce292cSCedric Le Goater 
unshare_userns(unsigned long unshare_flags,struct cred ** new_cred)194b2e0d987SEric W. Biederman static inline int unshare_userns(unsigned long unshare_flags,
195b2e0d987SEric W. Biederman 				 struct cred **new_cred)
196b2e0d987SEric W. Biederman {
197b2e0d987SEric W. Biederman 	if (unshare_flags & CLONE_NEWUSER)
198b2e0d987SEric W. Biederman 		return -EINVAL;
199b2e0d987SEric W. Biederman 	return 0;
200b2e0d987SEric W. Biederman }
201b2e0d987SEric W. Biederman 
put_user_ns(struct user_namespace * ns)202acce292cSCedric Le Goater static inline void put_user_ns(struct user_namespace *ns)
203acce292cSCedric Le Goater {
204acce292cSCedric Le Goater }
205acce292cSCedric Le Goater 
userns_may_setgroups(const struct user_namespace * ns)206273d2c67SEric W. Biederman static inline bool userns_may_setgroups(const struct user_namespace *ns)
207273d2c67SEric W. Biederman {
208273d2c67SEric W. Biederman 	return true;
209273d2c67SEric W. Biederman }
210d07b846fSSeth Forshee 
in_userns(const struct user_namespace * ancestor,const struct user_namespace * child)211a2b42626SEric W. Biederman static inline bool in_userns(const struct user_namespace *ancestor,
212a2b42626SEric W. Biederman 			     const struct user_namespace *child)
213a2b42626SEric W. Biederman {
214a2b42626SEric W. Biederman 	return true;
215a2b42626SEric W. Biederman }
216a2b42626SEric W. Biederman 
current_in_userns(const struct user_namespace * target_ns)217d07b846fSSeth Forshee static inline bool current_in_userns(const struct user_namespace *target_ns)
218d07b846fSSeth Forshee {
219d07b846fSSeth Forshee 	return true;
220d07b846fSSeth Forshee }
221bcac25a5SAndrey Vagin 
ns_get_owner(struct ns_common * ns)222bcac25a5SAndrey Vagin static inline struct ns_common *ns_get_owner(struct ns_common *ns)
223bcac25a5SAndrey Vagin {
224bcac25a5SAndrey Vagin 	return ERR_PTR(-EPERM);
225bcac25a5SAndrey Vagin }
22622d917d8SEric W. Biederman #endif
22722d917d8SEric W. Biederman 
228acce292cSCedric Le Goater #endif /* _LINUX_USER_H */
229