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