Merge tag 'dlm-6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/linux-dlm
[linux-2.6-microblaze.git] / include / linux / mnt_idmapping.h
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         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         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         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 static inline bool vfsuid_gt_kuid(vfsuid_t vfsuid, kuid_t kuid)
100 {
101         return __vfsuid_val(vfsuid) > __kuid_val(kuid);
102 }
103
104 static inline bool vfsgid_gt_kgid(vfsgid_t vfsgid, kgid_t kgid)
105 {
106         return __vfsgid_val(vfsgid) > __kgid_val(kgid);
107 }
108
109 static inline bool vfsuid_lt_kuid(vfsuid_t vfsuid, kuid_t kuid)
110 {
111         return __vfsuid_val(vfsuid) < __kuid_val(kuid);
112 }
113
114 static inline bool vfsgid_lt_kgid(vfsgid_t vfsgid, kgid_t kgid)
115 {
116         return __vfsgid_val(vfsgid) < __kgid_val(kgid);
117 }
118
119 /*
120  * vfs{g,u}ids are created from k{g,u}ids.
121  * We don't allow them to be created from regular {u,g}id.
122  */
123 #define VFSUIDT_INIT(val) (vfsuid_t){ __kuid_val(val) }
124 #define VFSGIDT_INIT(val) (vfsgid_t){ __kgid_val(val) }
125
126 #define INVALID_VFSUID VFSUIDT_INIT(INVALID_UID)
127 #define INVALID_VFSGID VFSGIDT_INIT(INVALID_GID)
128
129 /*
130  * Allow a vfs{g,u}id to be used as a k{g,u}id where we want to compare
131  * whether the mapped value is identical to value of a k{g,u}id.
132  */
133 #define AS_KUIDT(val) (kuid_t){ __vfsuid_val(val) }
134 #define AS_KGIDT(val) (kgid_t){ __vfsgid_val(val) }
135
136 #ifdef CONFIG_MULTIUSER
137 /**
138  * vfsgid_in_group_p() - check whether a vfsuid matches the caller's groups
139  * @vfsgid: the mnt gid to match
140  *
141  * This function can be used to determine whether @vfsuid matches any of the
142  * caller's groups.
143  *
144  * Return: 1 if vfsuid matches caller's groups, 0 if not.
145  */
146 static inline int vfsgid_in_group_p(vfsgid_t vfsgid)
147 {
148         return in_group_p(AS_KGIDT(vfsgid));
149 }
150 #else
151 static inline int vfsgid_in_group_p(vfsgid_t vfsgid)
152 {
153         return 1;
154 }
155 #endif
156
157 /**
158  * initial_idmapping - check whether this is the initial mapping
159  * @ns: idmapping to check
160  *
161  * Check whether this is the initial mapping, mapping 0 to 0, 1 to 1,
162  * [...], 1000 to 1000 [...].
163  *
164  * Return: true if this is the initial mapping, false if not.
165  */
166 static inline bool initial_idmapping(const struct user_namespace *ns)
167 {
168         return ns == &init_user_ns;
169 }
170
171 /**
172  * no_idmapping - check whether we can skip remapping a kuid/gid
173  * @mnt_userns: the mount's idmapping
174  * @fs_userns: the filesystem's idmapping
175  *
176  * This function can be used to check whether a remapping between two
177  * idmappings is required.
178  * An idmapped mount is a mount that has an idmapping attached to it that
179  * is different from the filsystem's idmapping and the initial idmapping.
180  * If the initial mapping is used or the idmapping of the mount and the
181  * filesystem are identical no remapping is required.
182  *
183  * Return: true if remapping can be skipped, false if not.
184  */
185 static inline bool no_idmapping(const struct user_namespace *mnt_userns,
186                                 const struct user_namespace *fs_userns)
187 {
188         return initial_idmapping(mnt_userns) || mnt_userns == fs_userns;
189 }
190
191 /**
192  * make_vfsuid - map a filesystem kuid into a mnt_userns
193  * @mnt_userns: the mount's idmapping
194  * @fs_userns: the filesystem's idmapping
195  * @kuid : kuid to be mapped
196  *
197  * Take a @kuid and remap it from @fs_userns into @mnt_userns. Use this
198  * function when preparing a @kuid to be reported to userspace.
199  *
200  * If no_idmapping() determines that this is not an idmapped mount we can
201  * simply return @kuid unchanged.
202  * If initial_idmapping() tells us that the filesystem is not mounted with an
203  * idmapping we know the value of @kuid won't change when calling
204  * from_kuid() so we can simply retrieve the value via __kuid_val()
205  * directly.
206  *
207  * Return: @kuid mapped according to @mnt_userns.
208  * If @kuid has no mapping in either @mnt_userns or @fs_userns INVALID_UID is
209  * returned.
210  */
211
212 static inline vfsuid_t make_vfsuid(struct user_namespace *mnt_userns,
213                                    struct user_namespace *fs_userns,
214                                    kuid_t kuid)
215 {
216         uid_t uid;
217
218         if (no_idmapping(mnt_userns, fs_userns))
219                 return VFSUIDT_INIT(kuid);
220         if (initial_idmapping(fs_userns))
221                 uid = __kuid_val(kuid);
222         else
223                 uid = from_kuid(fs_userns, kuid);
224         if (uid == (uid_t)-1)
225                 return INVALID_VFSUID;
226         return VFSUIDT_INIT(make_kuid(mnt_userns, uid));
227 }
228
229 /**
230  * make_vfsgid - map a filesystem kgid into a mnt_userns
231  * @mnt_userns: the mount's idmapping
232  * @fs_userns: the filesystem's idmapping
233  * @kgid : kgid to be mapped
234  *
235  * Take a @kgid and remap it from @fs_userns into @mnt_userns. Use this
236  * function when preparing a @kgid to be reported to userspace.
237  *
238  * If no_idmapping() determines that this is not an idmapped mount we can
239  * simply return @kgid unchanged.
240  * If initial_idmapping() tells us that the filesystem is not mounted with an
241  * idmapping we know the value of @kgid won't change when calling
242  * from_kgid() so we can simply retrieve the value via __kgid_val()
243  * directly.
244  *
245  * Return: @kgid mapped according to @mnt_userns.
246  * If @kgid has no mapping in either @mnt_userns or @fs_userns INVALID_GID is
247  * returned.
248  */
249
250 static inline vfsgid_t make_vfsgid(struct user_namespace *mnt_userns,
251                                    struct user_namespace *fs_userns,
252                                    kgid_t kgid)
253 {
254         gid_t gid;
255
256         if (no_idmapping(mnt_userns, fs_userns))
257                 return VFSGIDT_INIT(kgid);
258         if (initial_idmapping(fs_userns))
259                 gid = __kgid_val(kgid);
260         else
261                 gid = from_kgid(fs_userns, kgid);
262         if (gid == (gid_t)-1)
263                 return INVALID_VFSGID;
264         return VFSGIDT_INIT(make_kgid(mnt_userns, gid));
265 }
266
267 /**
268  * from_vfsuid - map a vfsuid into the filesystem idmapping
269  * @mnt_userns: the mount's idmapping
270  * @fs_userns: the filesystem's idmapping
271  * @vfsuid : vfsuid to be mapped
272  *
273  * Map @vfsuid into the filesystem idmapping. This function has to be used in
274  * order to e.g. write @vfsuid to inode->i_uid.
275  *
276  * Return: @vfsuid mapped into the filesystem idmapping
277  */
278 static inline kuid_t from_vfsuid(struct user_namespace *mnt_userns,
279                                  struct user_namespace *fs_userns,
280                                  vfsuid_t vfsuid)
281 {
282         uid_t uid;
283
284         if (no_idmapping(mnt_userns, fs_userns))
285                 return AS_KUIDT(vfsuid);
286         uid = from_kuid(mnt_userns, AS_KUIDT(vfsuid));
287         if (uid == (uid_t)-1)
288                 return INVALID_UID;
289         if (initial_idmapping(fs_userns))
290                 return KUIDT_INIT(uid);
291         return make_kuid(fs_userns, uid);
292 }
293
294 /**
295  * vfsuid_has_fsmapping - check whether a vfsuid maps into the filesystem
296  * @mnt_userns: the mount's idmapping
297  * @fs_userns: the filesystem's idmapping
298  * @vfsuid: vfsuid to be mapped
299  *
300  * Check whether @vfsuid has a mapping in the filesystem idmapping. Use this
301  * function to check whether the filesystem idmapping has a mapping for
302  * @vfsuid.
303  *
304  * Return: true if @vfsuid has a mapping in the filesystem, false if not.
305  */
306 static inline bool vfsuid_has_fsmapping(struct user_namespace *mnt_userns,
307                                         struct user_namespace *fs_userns,
308                                         vfsuid_t vfsuid)
309 {
310         return uid_valid(from_vfsuid(mnt_userns, fs_userns, vfsuid));
311 }
312
313 static inline bool vfsuid_has_mapping(struct user_namespace *userns,
314                                       vfsuid_t vfsuid)
315 {
316         return from_kuid(userns, AS_KUIDT(vfsuid)) != (uid_t)-1;
317 }
318
319 /**
320  * vfsuid_into_kuid - convert vfsuid into kuid
321  * @vfsuid: the vfsuid to convert
322  *
323  * This can be used when a vfsuid is committed as a kuid.
324  *
325  * Return: a kuid with the value of @vfsuid
326  */
327 static inline kuid_t vfsuid_into_kuid(vfsuid_t vfsuid)
328 {
329         return AS_KUIDT(vfsuid);
330 }
331
332 /**
333  * from_vfsgid - map a vfsgid into the filesystem idmapping
334  * @mnt_userns: the mount's idmapping
335  * @fs_userns: the filesystem's idmapping
336  * @vfsgid : vfsgid to be mapped
337  *
338  * Map @vfsgid into the filesystem idmapping. This function has to be used in
339  * order to e.g. write @vfsgid to inode->i_gid.
340  *
341  * Return: @vfsgid mapped into the filesystem idmapping
342  */
343 static inline kgid_t from_vfsgid(struct user_namespace *mnt_userns,
344                                  struct user_namespace *fs_userns,
345                                  vfsgid_t vfsgid)
346 {
347         gid_t gid;
348
349         if (no_idmapping(mnt_userns, fs_userns))
350                 return AS_KGIDT(vfsgid);
351         gid = from_kgid(mnt_userns, AS_KGIDT(vfsgid));
352         if (gid == (gid_t)-1)
353                 return INVALID_GID;
354         if (initial_idmapping(fs_userns))
355                 return KGIDT_INIT(gid);
356         return make_kgid(fs_userns, gid);
357 }
358
359 /**
360  * vfsgid_has_fsmapping - check whether a vfsgid maps into the filesystem
361  * @mnt_userns: the mount's idmapping
362  * @fs_userns: the filesystem's idmapping
363  * @vfsgid: vfsgid to be mapped
364  *
365  * Check whether @vfsgid has a mapping in the filesystem idmapping. Use this
366  * function to check whether the filesystem idmapping has a mapping for
367  * @vfsgid.
368  *
369  * Return: true if @vfsgid has a mapping in the filesystem, false if not.
370  */
371 static inline bool vfsgid_has_fsmapping(struct user_namespace *mnt_userns,
372                                         struct user_namespace *fs_userns,
373                                         vfsgid_t vfsgid)
374 {
375         return gid_valid(from_vfsgid(mnt_userns, fs_userns, vfsgid));
376 }
377
378 static inline bool vfsgid_has_mapping(struct user_namespace *userns,
379                                       vfsgid_t vfsgid)
380 {
381         return from_kgid(userns, AS_KGIDT(vfsgid)) != (gid_t)-1;
382 }
383
384 /**
385  * vfsgid_into_kgid - convert vfsgid into kgid
386  * @vfsgid: the vfsgid to convert
387  *
388  * This can be used when a vfsgid is committed as a kgid.
389  *
390  * Return: a kgid with the value of @vfsgid
391  */
392 static inline kgid_t vfsgid_into_kgid(vfsgid_t vfsgid)
393 {
394         return AS_KGIDT(vfsgid);
395 }
396
397 /**
398  * mapped_fsuid - return caller's fsuid mapped up into a mnt_userns
399  * @mnt_userns: the mount's idmapping
400  * @fs_userns: the filesystem's idmapping
401  *
402  * Use this helper to initialize a new vfs or filesystem object based on
403  * the caller's fsuid. A common example is initializing the i_uid field of
404  * a newly allocated inode triggered by a creation event such as mkdir or
405  * O_CREAT. Other examples include the allocation of quotas for a specific
406  * user.
407  *
408  * Return: the caller's current fsuid mapped up according to @mnt_userns.
409  */
410 static inline kuid_t mapped_fsuid(struct user_namespace *mnt_userns,
411                                   struct user_namespace *fs_userns)
412 {
413         return from_vfsuid(mnt_userns, fs_userns,
414                            VFSUIDT_INIT(current_fsuid()));
415 }
416
417 /**
418  * mapped_fsgid - return caller's fsgid mapped up into a mnt_userns
419  * @mnt_userns: the mount's idmapping
420  * @fs_userns: the filesystem's idmapping
421  *
422  * Use this helper to initialize a new vfs or filesystem object based on
423  * the caller's fsgid. A common example is initializing the i_gid field of
424  * a newly allocated inode triggered by a creation event such as mkdir or
425  * O_CREAT. Other examples include the allocation of quotas for a specific
426  * user.
427  *
428  * Return: the caller's current fsgid mapped up according to @mnt_userns.
429  */
430 static inline kgid_t mapped_fsgid(struct user_namespace *mnt_userns,
431                                   struct user_namespace *fs_userns)
432 {
433         return from_vfsgid(mnt_userns, fs_userns,
434                            VFSGIDT_INIT(current_fsgid()));
435 }
436
437 #endif /* _LINUX_MNT_IDMAPPING_H */