Line data Source code
1 : /* SPDX-License-Identifier: GPL-2.0 */
2 : #ifndef _LINUX_MNT_IDMAPPING_H
3 : #define _LINUX_MNT_IDMAPPING_H
4 :
5 : #include <linux/types.h>
6 : #include <linux/uidgid.h>
7 :
8 : struct mnt_idmap;
9 : struct user_namespace;
10 :
11 : extern struct mnt_idmap nop_mnt_idmap;
12 : extern struct user_namespace init_user_ns;
13 :
14 : typedef struct {
15 : uid_t val;
16 : } vfsuid_t;
17 :
18 : typedef struct {
19 : gid_t val;
20 : } vfsgid_t;
21 :
22 : static_assert(sizeof(vfsuid_t) == sizeof(kuid_t));
23 : static_assert(sizeof(vfsgid_t) == sizeof(kgid_t));
24 : static_assert(offsetof(vfsuid_t, val) == offsetof(kuid_t, val));
25 : static_assert(offsetof(vfsgid_t, val) == offsetof(kgid_t, val));
26 :
27 : #ifdef CONFIG_MULTIUSER
28 : static inline uid_t __vfsuid_val(vfsuid_t uid)
29 : {
30 : return uid.val;
31 : }
32 :
33 : static inline gid_t __vfsgid_val(vfsgid_t gid)
34 : {
35 : return gid.val;
36 : }
37 : #else
38 : static inline uid_t __vfsuid_val(vfsuid_t uid)
39 : {
40 : return 0;
41 : }
42 :
43 : static inline gid_t __vfsgid_val(vfsgid_t gid)
44 : {
45 : return 0;
46 : }
47 : #endif
48 :
49 : static inline bool vfsuid_valid(vfsuid_t uid)
50 : {
51 : return __vfsuid_val(uid) != (uid_t)-1;
52 : }
53 :
54 : static inline bool vfsgid_valid(vfsgid_t gid)
55 : {
56 : return __vfsgid_val(gid) != (gid_t)-1;
57 : }
58 :
59 : static inline bool vfsuid_eq(vfsuid_t left, vfsuid_t right)
60 : {
61 0 : return vfsuid_valid(left) && __vfsuid_val(left) == __vfsuid_val(right);
62 : }
63 :
64 : static inline bool vfsgid_eq(vfsgid_t left, vfsgid_t right)
65 : {
66 0 : return vfsgid_valid(left) && __vfsgid_val(left) == __vfsgid_val(right);
67 : }
68 :
69 : /**
70 : * vfsuid_eq_kuid - check whether kuid and vfsuid have the same value
71 : * @vfsuid: the vfsuid to compare
72 : * @kuid: the kuid to compare
73 : *
74 : * Check whether @vfsuid and @kuid have the same values.
75 : *
76 : * Return: true if @vfsuid and @kuid have the same value, false if not.
77 : * Comparison between two invalid uids returns false.
78 : */
79 : static inline bool vfsuid_eq_kuid(vfsuid_t vfsuid, kuid_t kuid)
80 : {
81 7 : return vfsuid_valid(vfsuid) && __vfsuid_val(vfsuid) == __kuid_val(kuid);
82 : }
83 :
84 : /**
85 : * vfsgid_eq_kgid - check whether kgid and vfsgid have the same value
86 : * @vfsgid: the vfsgid to compare
87 : * @kgid: the kgid to compare
88 : *
89 : * Check whether @vfsgid and @kgid have the same values.
90 : *
91 : * Return: true if @vfsgid and @kgid have the same value, false if not.
92 : * Comparison between two invalid gids returns false.
93 : */
94 : static inline bool vfsgid_eq_kgid(vfsgid_t vfsgid, kgid_t kgid)
95 : {
96 : return vfsgid_valid(vfsgid) && __vfsgid_val(vfsgid) == __kgid_val(kgid);
97 : }
98 :
99 : /*
100 : * vfs{g,u}ids are created from k{g,u}ids.
101 : * We don't allow them to be created from regular {u,g}id.
102 : */
103 : #define VFSUIDT_INIT(val) (vfsuid_t){ __kuid_val(val) }
104 : #define VFSGIDT_INIT(val) (vfsgid_t){ __kgid_val(val) }
105 :
106 : #define INVALID_VFSUID VFSUIDT_INIT(INVALID_UID)
107 : #define INVALID_VFSGID VFSGIDT_INIT(INVALID_GID)
108 :
109 : /*
110 : * Allow a vfs{g,u}id to be used as a k{g,u}id where we want to compare
111 : * whether the mapped value is identical to value of a k{g,u}id.
112 : */
113 : #define AS_KUIDT(val) (kuid_t){ __vfsuid_val(val) }
114 : #define AS_KGIDT(val) (kgid_t){ __vfsgid_val(val) }
115 :
116 : int vfsgid_in_group_p(vfsgid_t vfsgid);
117 :
118 : vfsuid_t make_vfsuid(struct mnt_idmap *idmap,
119 : struct user_namespace *fs_userns, kuid_t kuid);
120 :
121 : vfsgid_t make_vfsgid(struct mnt_idmap *idmap,
122 : struct user_namespace *fs_userns, kgid_t kgid);
123 :
124 : kuid_t from_vfsuid(struct mnt_idmap *idmap,
125 : struct user_namespace *fs_userns, vfsuid_t vfsuid);
126 :
127 : kgid_t from_vfsgid(struct mnt_idmap *idmap,
128 : struct user_namespace *fs_userns, vfsgid_t vfsgid);
129 :
130 : /**
131 : * vfsuid_has_fsmapping - check whether a vfsuid maps into the filesystem
132 : * @idmap: the mount's idmapping
133 : * @fs_userns: the filesystem's idmapping
134 : * @vfsuid: vfsuid to be mapped
135 : *
136 : * Check whether @vfsuid has a mapping in the filesystem idmapping. Use this
137 : * function to check whether the filesystem idmapping has a mapping for
138 : * @vfsuid.
139 : *
140 : * Return: true if @vfsuid has a mapping in the filesystem, false if not.
141 : */
142 : static inline bool vfsuid_has_fsmapping(struct mnt_idmap *idmap,
143 : struct user_namespace *fs_userns,
144 : vfsuid_t vfsuid)
145 : {
146 0 : return uid_valid(from_vfsuid(idmap, fs_userns, vfsuid));
147 : }
148 :
149 : static inline bool vfsuid_has_mapping(struct user_namespace *userns,
150 : vfsuid_t vfsuid)
151 : {
152 0 : return from_kuid(userns, AS_KUIDT(vfsuid)) != (uid_t)-1;
153 : }
154 :
155 : /**
156 : * vfsuid_into_kuid - convert vfsuid into kuid
157 : * @vfsuid: the vfsuid to convert
158 : *
159 : * This can be used when a vfsuid is committed as a kuid.
160 : *
161 : * Return: a kuid with the value of @vfsuid
162 : */
163 : static inline kuid_t vfsuid_into_kuid(vfsuid_t vfsuid)
164 : {
165 : return AS_KUIDT(vfsuid);
166 : }
167 :
168 : /**
169 : * vfsgid_has_fsmapping - check whether a vfsgid maps into the filesystem
170 : * @idmap: the mount's idmapping
171 : * @fs_userns: the filesystem's idmapping
172 : * @vfsgid: vfsgid to be mapped
173 : *
174 : * Check whether @vfsgid has a mapping in the filesystem idmapping. Use this
175 : * function to check whether the filesystem idmapping has a mapping for
176 : * @vfsgid.
177 : *
178 : * Return: true if @vfsgid has a mapping in the filesystem, false if not.
179 : */
180 : static inline bool vfsgid_has_fsmapping(struct mnt_idmap *idmap,
181 : struct user_namespace *fs_userns,
182 : vfsgid_t vfsgid)
183 : {
184 0 : return gid_valid(from_vfsgid(idmap, fs_userns, vfsgid));
185 : }
186 :
187 : static inline bool vfsgid_has_mapping(struct user_namespace *userns,
188 : vfsgid_t vfsgid)
189 : {
190 0 : return from_kgid(userns, AS_KGIDT(vfsgid)) != (gid_t)-1;
191 : }
192 :
193 : /**
194 : * vfsgid_into_kgid - convert vfsgid into kgid
195 : * @vfsgid: the vfsgid to convert
196 : *
197 : * This can be used when a vfsgid is committed as a kgid.
198 : *
199 : * Return: a kgid with the value of @vfsgid
200 : */
201 : static inline kgid_t vfsgid_into_kgid(vfsgid_t vfsgid)
202 : {
203 : return AS_KGIDT(vfsgid);
204 : }
205 :
206 : /**
207 : * mapped_fsuid - return caller's fsuid mapped according to an idmapping
208 : * @idmap: the mount's idmapping
209 : * @fs_userns: the filesystem's idmapping
210 : *
211 : * Use this helper to initialize a new vfs or filesystem object based on
212 : * the caller's fsuid. A common example is initializing the i_uid field of
213 : * a newly allocated inode triggered by a creation event such as mkdir or
214 : * O_CREAT. Other examples include the allocation of quotas for a specific
215 : * user.
216 : *
217 : * Return: the caller's current fsuid mapped up according to @idmap.
218 : */
219 : static inline kuid_t mapped_fsuid(struct mnt_idmap *idmap,
220 : struct user_namespace *fs_userns)
221 : {
222 8 : return from_vfsuid(idmap, fs_userns, VFSUIDT_INIT(current_fsuid()));
223 : }
224 :
225 : /**
226 : * mapped_fsgid - return caller's fsgid mapped according to an idmapping
227 : * @idmap: the mount's idmapping
228 : * @fs_userns: the filesystem's idmapping
229 : *
230 : * Use this helper to initialize a new vfs or filesystem object based on
231 : * the caller's fsgid. A common example is initializing the i_gid field of
232 : * a newly allocated inode triggered by a creation event such as mkdir or
233 : * O_CREAT. Other examples include the allocation of quotas for a specific
234 : * user.
235 : *
236 : * Return: the caller's current fsgid mapped up according to @idmap.
237 : */
238 : static inline kgid_t mapped_fsgid(struct mnt_idmap *idmap,
239 : struct user_namespace *fs_userns)
240 : {
241 8 : return from_vfsgid(idmap, fs_userns, VFSGIDT_INIT(current_fsgid()));
242 : }
243 :
244 : bool check_fsmapping(const struct mnt_idmap *idmap,
245 : const struct super_block *sb);
246 :
247 : #endif /* _LINUX_MNT_IDMAPPING_H */
|