1a793d79eSChristian Brauner /* SPDX-License-Identifier: GPL-2.0 */ 2a793d79eSChristian Brauner #ifndef _LINUX_MNT_IDMAPPING_H 3a793d79eSChristian Brauner #define _LINUX_MNT_IDMAPPING_H 4a793d79eSChristian Brauner 5a793d79eSChristian Brauner #include <linux/types.h> 6a793d79eSChristian Brauner #include <linux/uidgid.h> 7a793d79eSChristian Brauner 8a793d79eSChristian Brauner struct user_namespace; 91ac2a410SChristian Brauner /* 101ac2a410SChristian Brauner * Carries the initial idmapping of 0:0:4294967295 which is an identity 111ac2a410SChristian Brauner * mapping. This means that {g,u}id 0 is mapped to {g,u}id 0, {g,u}id 1 is 121ac2a410SChristian Brauner * mapped to {g,u}id 1, [...], {g,u}id 1000 to {g,u}id 1000, [...]. 131ac2a410SChristian Brauner */ 14a793d79eSChristian Brauner extern struct user_namespace init_user_ns; 15a793d79eSChristian Brauner 16*1e5267cdSChristian Brauner typedef struct { 17*1e5267cdSChristian Brauner uid_t val; 18*1e5267cdSChristian Brauner } vfsuid_t; 19*1e5267cdSChristian Brauner 20*1e5267cdSChristian Brauner typedef struct { 21*1e5267cdSChristian Brauner gid_t val; 22*1e5267cdSChristian Brauner } vfsgid_t; 23*1e5267cdSChristian Brauner 24*1e5267cdSChristian Brauner #ifdef CONFIG_MULTIUSER 25*1e5267cdSChristian Brauner static inline uid_t __vfsuid_val(vfsuid_t uid) 26*1e5267cdSChristian Brauner { 27*1e5267cdSChristian Brauner return uid.val; 28*1e5267cdSChristian Brauner } 29*1e5267cdSChristian Brauner 30*1e5267cdSChristian Brauner static inline gid_t __vfsgid_val(vfsgid_t gid) 31*1e5267cdSChristian Brauner { 32*1e5267cdSChristian Brauner return gid.val; 33*1e5267cdSChristian Brauner } 34*1e5267cdSChristian Brauner #else 35*1e5267cdSChristian Brauner static inline uid_t __vfsuid_val(vfsuid_t uid) 36*1e5267cdSChristian Brauner { 37*1e5267cdSChristian Brauner return 0; 38*1e5267cdSChristian Brauner } 39*1e5267cdSChristian Brauner 40*1e5267cdSChristian Brauner static inline gid_t __vfsgid_val(vfsgid_t gid) 41*1e5267cdSChristian Brauner { 42*1e5267cdSChristian Brauner return 0; 43*1e5267cdSChristian Brauner } 44*1e5267cdSChristian Brauner #endif 45*1e5267cdSChristian Brauner 46*1e5267cdSChristian Brauner static inline bool vfsuid_valid(vfsuid_t uid) 47*1e5267cdSChristian Brauner { 48*1e5267cdSChristian Brauner return __vfsuid_val(uid) != (uid_t)-1; 49*1e5267cdSChristian Brauner } 50*1e5267cdSChristian Brauner 51*1e5267cdSChristian Brauner static inline bool vfsgid_valid(vfsgid_t gid) 52*1e5267cdSChristian Brauner { 53*1e5267cdSChristian Brauner return __vfsgid_val(gid) != (gid_t)-1; 54*1e5267cdSChristian Brauner } 55*1e5267cdSChristian Brauner 56*1e5267cdSChristian Brauner static inline bool vfsuid_eq(vfsuid_t left, vfsuid_t right) 57*1e5267cdSChristian Brauner { 58*1e5267cdSChristian Brauner return __vfsuid_val(left) == __vfsuid_val(right); 59*1e5267cdSChristian Brauner } 60*1e5267cdSChristian Brauner 61*1e5267cdSChristian Brauner static inline bool vfsgid_eq(vfsgid_t left, vfsgid_t right) 62*1e5267cdSChristian Brauner { 63*1e5267cdSChristian Brauner return __vfsgid_val(left) == __vfsgid_val(right); 64*1e5267cdSChristian Brauner } 65*1e5267cdSChristian Brauner 66*1e5267cdSChristian Brauner /** 67*1e5267cdSChristian Brauner * vfsuid_eq_kuid - check whether kuid and vfsuid have the same value 68*1e5267cdSChristian Brauner * @kuid: the kuid to compare 69*1e5267cdSChristian Brauner * @vfsuid: the vfsuid to compare 70*1e5267cdSChristian Brauner * 71*1e5267cdSChristian Brauner * Check whether @kuid and @vfsuid have the same values. 72*1e5267cdSChristian Brauner * 73*1e5267cdSChristian Brauner * Return: true if @kuid and @vfsuid have the same value, false if not. 74*1e5267cdSChristian Brauner */ 75*1e5267cdSChristian Brauner static inline bool vfsuid_eq_kuid(vfsuid_t vfsuid, kuid_t kuid) 76*1e5267cdSChristian Brauner { 77*1e5267cdSChristian Brauner return __vfsuid_val(vfsuid) == __kuid_val(kuid); 78*1e5267cdSChristian Brauner } 79*1e5267cdSChristian Brauner 80*1e5267cdSChristian Brauner /** 81*1e5267cdSChristian Brauner * vfsgid_eq_kgid - check whether kgid and vfsgid have the same value 82*1e5267cdSChristian Brauner * @kgid: the kgid to compare 83*1e5267cdSChristian Brauner * @vfsgid: the vfsgid to compare 84*1e5267cdSChristian Brauner * 85*1e5267cdSChristian Brauner * Check whether @kgid and @vfsgid have the same values. 86*1e5267cdSChristian Brauner * 87*1e5267cdSChristian Brauner * Return: true if @kgid and @vfsgid have the same value, false if not. 88*1e5267cdSChristian Brauner */ 89*1e5267cdSChristian Brauner static inline bool vfsgid_eq_kgid(kgid_t kgid, vfsgid_t vfsgid) 90*1e5267cdSChristian Brauner { 91*1e5267cdSChristian Brauner return __vfsgid_val(vfsgid) == __kgid_val(kgid); 92*1e5267cdSChristian Brauner } 93*1e5267cdSChristian Brauner 94*1e5267cdSChristian Brauner /* 95*1e5267cdSChristian Brauner * vfs{g,u}ids are created from k{g,u}ids. 96*1e5267cdSChristian Brauner * We don't allow them to be created from regular {u,g}id. 97*1e5267cdSChristian Brauner */ 98*1e5267cdSChristian Brauner #define VFSUIDT_INIT(val) (vfsuid_t){ __kuid_val(val) } 99*1e5267cdSChristian Brauner #define VFSGIDT_INIT(val) (vfsgid_t){ __kgid_val(val) } 100*1e5267cdSChristian Brauner 101*1e5267cdSChristian Brauner #define INVALID_VFSUID VFSUIDT_INIT(INVALID_UID) 102*1e5267cdSChristian Brauner #define INVALID_VFSGID VFSGIDT_INIT(INVALID_GID) 103*1e5267cdSChristian Brauner 104*1e5267cdSChristian Brauner /* 105*1e5267cdSChristian Brauner * Allow a vfs{g,u}id to be used as a k{g,u}id where we want to compare 106*1e5267cdSChristian Brauner * whether the mapped value is identical to value of a k{g,u}id. 107*1e5267cdSChristian Brauner */ 108*1e5267cdSChristian Brauner #define AS_KUIDT(val) (kuid_t){ __vfsuid_val(val) } 109*1e5267cdSChristian Brauner #define AS_KGIDT(val) (kgid_t){ __vfsgid_val(val) } 110*1e5267cdSChristian Brauner 111*1e5267cdSChristian Brauner #ifdef CONFIG_MULTIUSER 112*1e5267cdSChristian Brauner /** 113*1e5267cdSChristian Brauner * vfsgid_in_group_p() - check whether a vfsuid matches the caller's groups 114*1e5267cdSChristian Brauner * @vfsgid: the mnt gid to match 115*1e5267cdSChristian Brauner * 116*1e5267cdSChristian Brauner * This function can be used to determine whether @vfsuid matches any of the 117*1e5267cdSChristian Brauner * caller's groups. 118*1e5267cdSChristian Brauner * 119*1e5267cdSChristian Brauner * Return: 1 if vfsuid matches caller's groups, 0 if not. 120*1e5267cdSChristian Brauner */ 121*1e5267cdSChristian Brauner static inline int vfsgid_in_group_p(vfsgid_t vfsgid) 122*1e5267cdSChristian Brauner { 123*1e5267cdSChristian Brauner return in_group_p(AS_KGIDT(vfsgid)); 124*1e5267cdSChristian Brauner } 125*1e5267cdSChristian Brauner #else 126*1e5267cdSChristian Brauner static inline int vfsgid_in_group_p(vfsgid_t vfsgid) 127*1e5267cdSChristian Brauner { 128*1e5267cdSChristian Brauner return 1; 129*1e5267cdSChristian Brauner } 130*1e5267cdSChristian Brauner #endif 131*1e5267cdSChristian Brauner 132a793d79eSChristian Brauner /** 1331ac2a410SChristian Brauner * initial_idmapping - check whether this is the initial mapping 1341ac2a410SChristian Brauner * @ns: idmapping to check 1351ac2a410SChristian Brauner * 1361ac2a410SChristian Brauner * Check whether this is the initial mapping, mapping 0 to 0, 1 to 1, 1371ac2a410SChristian Brauner * [...], 1000 to 1000 [...]. 1381ac2a410SChristian Brauner * 1391ac2a410SChristian Brauner * Return: true if this is the initial mapping, false if not. 1401ac2a410SChristian Brauner */ 1411ac2a410SChristian Brauner static inline bool initial_idmapping(const struct user_namespace *ns) 1421ac2a410SChristian Brauner { 1431ac2a410SChristian Brauner return ns == &init_user_ns; 1441ac2a410SChristian Brauner } 1451ac2a410SChristian Brauner 1461ac2a410SChristian Brauner /** 1471ac2a410SChristian Brauner * no_idmapping - check whether we can skip remapping a kuid/gid 1481ac2a410SChristian Brauner * @mnt_userns: the mount's idmapping 1491ac2a410SChristian Brauner * @fs_userns: the filesystem's idmapping 1501ac2a410SChristian Brauner * 1511ac2a410SChristian Brauner * This function can be used to check whether a remapping between two 1521ac2a410SChristian Brauner * idmappings is required. 1531ac2a410SChristian Brauner * An idmapped mount is a mount that has an idmapping attached to it that 1541ac2a410SChristian Brauner * is different from the filsystem's idmapping and the initial idmapping. 1551ac2a410SChristian Brauner * If the initial mapping is used or the idmapping of the mount and the 1561ac2a410SChristian Brauner * filesystem are identical no remapping is required. 1571ac2a410SChristian Brauner * 1581ac2a410SChristian Brauner * Return: true if remapping can be skipped, false if not. 1591ac2a410SChristian Brauner */ 1601ac2a410SChristian Brauner static inline bool no_idmapping(const struct user_namespace *mnt_userns, 1611ac2a410SChristian Brauner const struct user_namespace *fs_userns) 1621ac2a410SChristian Brauner { 1631ac2a410SChristian Brauner return initial_idmapping(mnt_userns) || mnt_userns == fs_userns; 1641ac2a410SChristian Brauner } 1651ac2a410SChristian Brauner 1661ac2a410SChristian Brauner /** 1671ac2a410SChristian Brauner * mapped_kuid_fs - map a filesystem kuid into a mnt_userns 1681ac2a410SChristian Brauner * @mnt_userns: the mount's idmapping 1691ac2a410SChristian Brauner * @fs_userns: the filesystem's idmapping 1701ac2a410SChristian Brauner * @kuid : kuid to be mapped 1711ac2a410SChristian Brauner * 1721ac2a410SChristian Brauner * Take a @kuid and remap it from @fs_userns into @mnt_userns. Use this 1731ac2a410SChristian Brauner * function when preparing a @kuid to be reported to userspace. 1741ac2a410SChristian Brauner * 1751ac2a410SChristian Brauner * If no_idmapping() determines that this is not an idmapped mount we can 1761ac2a410SChristian Brauner * simply return @kuid unchanged. 1771ac2a410SChristian Brauner * If initial_idmapping() tells us that the filesystem is not mounted with an 1781ac2a410SChristian Brauner * idmapping we know the value of @kuid won't change when calling 1791ac2a410SChristian Brauner * from_kuid() so we can simply retrieve the value via __kuid_val() 1801ac2a410SChristian Brauner * directly. 1811ac2a410SChristian Brauner * 1821ac2a410SChristian Brauner * Return: @kuid mapped according to @mnt_userns. 1831ac2a410SChristian Brauner * If @kuid has no mapping in either @mnt_userns or @fs_userns INVALID_UID is 1841ac2a410SChristian Brauner * returned. 1851ac2a410SChristian Brauner */ 186*1e5267cdSChristian Brauner 187*1e5267cdSChristian Brauner static inline vfsuid_t make_vfsuid(struct user_namespace *mnt_userns, 1881ac2a410SChristian Brauner struct user_namespace *fs_userns, 1891ac2a410SChristian Brauner kuid_t kuid) 1901ac2a410SChristian Brauner { 1911ac2a410SChristian Brauner uid_t uid; 1921ac2a410SChristian Brauner 1931ac2a410SChristian Brauner if (no_idmapping(mnt_userns, fs_userns)) 194*1e5267cdSChristian Brauner return VFSUIDT_INIT(kuid); 1951ac2a410SChristian Brauner if (initial_idmapping(fs_userns)) 1961ac2a410SChristian Brauner uid = __kuid_val(kuid); 1971ac2a410SChristian Brauner else 1981ac2a410SChristian Brauner uid = from_kuid(fs_userns, kuid); 1991ac2a410SChristian Brauner if (uid == (uid_t)-1) 200*1e5267cdSChristian Brauner return INVALID_VFSUID; 201*1e5267cdSChristian Brauner return VFSUIDT_INIT(make_kuid(mnt_userns, uid)); 202*1e5267cdSChristian Brauner } 203*1e5267cdSChristian Brauner 204*1e5267cdSChristian Brauner static inline kuid_t mapped_kuid_fs(struct user_namespace *mnt_userns, 205*1e5267cdSChristian Brauner struct user_namespace *fs_userns, 206*1e5267cdSChristian Brauner kuid_t kuid) 207*1e5267cdSChristian Brauner { 208*1e5267cdSChristian Brauner return AS_KUIDT(make_vfsuid(mnt_userns, fs_userns, kuid)); 2091ac2a410SChristian Brauner } 2101ac2a410SChristian Brauner 2111ac2a410SChristian Brauner /** 2121ac2a410SChristian Brauner * mapped_kgid_fs - map a filesystem kgid into a mnt_userns 2131ac2a410SChristian Brauner * @mnt_userns: the mount's idmapping 2141ac2a410SChristian Brauner * @fs_userns: the filesystem's idmapping 2151ac2a410SChristian Brauner * @kgid : kgid to be mapped 2161ac2a410SChristian Brauner * 2171ac2a410SChristian Brauner * Take a @kgid and remap it from @fs_userns into @mnt_userns. Use this 2181ac2a410SChristian Brauner * function when preparing a @kgid to be reported to userspace. 2191ac2a410SChristian Brauner * 2201ac2a410SChristian Brauner * If no_idmapping() determines that this is not an idmapped mount we can 2211ac2a410SChristian Brauner * simply return @kgid unchanged. 2221ac2a410SChristian Brauner * If initial_idmapping() tells us that the filesystem is not mounted with an 2231ac2a410SChristian Brauner * idmapping we know the value of @kgid won't change when calling 2241ac2a410SChristian Brauner * from_kgid() so we can simply retrieve the value via __kgid_val() 2251ac2a410SChristian Brauner * directly. 2261ac2a410SChristian Brauner * 2271ac2a410SChristian Brauner * Return: @kgid mapped according to @mnt_userns. 2281ac2a410SChristian Brauner * If @kgid has no mapping in either @mnt_userns or @fs_userns INVALID_GID is 2291ac2a410SChristian Brauner * returned. 2301ac2a410SChristian Brauner */ 231*1e5267cdSChristian Brauner 232*1e5267cdSChristian Brauner static inline vfsgid_t make_vfsgid(struct user_namespace *mnt_userns, 2331ac2a410SChristian Brauner struct user_namespace *fs_userns, 2341ac2a410SChristian Brauner kgid_t kgid) 2351ac2a410SChristian Brauner { 2361ac2a410SChristian Brauner gid_t gid; 2371ac2a410SChristian Brauner 2381ac2a410SChristian Brauner if (no_idmapping(mnt_userns, fs_userns)) 239*1e5267cdSChristian Brauner return VFSGIDT_INIT(kgid); 2401ac2a410SChristian Brauner if (initial_idmapping(fs_userns)) 2411ac2a410SChristian Brauner gid = __kgid_val(kgid); 2421ac2a410SChristian Brauner else 2431ac2a410SChristian Brauner gid = from_kgid(fs_userns, kgid); 2441ac2a410SChristian Brauner if (gid == (gid_t)-1) 245*1e5267cdSChristian Brauner return INVALID_VFSGID; 246*1e5267cdSChristian Brauner return VFSGIDT_INIT(make_kgid(mnt_userns, gid)); 247*1e5267cdSChristian Brauner } 248*1e5267cdSChristian Brauner 249*1e5267cdSChristian Brauner static inline kgid_t mapped_kgid_fs(struct user_namespace *mnt_userns, 250*1e5267cdSChristian Brauner struct user_namespace *fs_userns, 251*1e5267cdSChristian Brauner kgid_t kgid) 252*1e5267cdSChristian Brauner { 253*1e5267cdSChristian Brauner return AS_KGIDT(make_vfsgid(mnt_userns, fs_userns, kgid)); 254*1e5267cdSChristian Brauner } 255*1e5267cdSChristian Brauner 256*1e5267cdSChristian Brauner /** 257*1e5267cdSChristian Brauner * from_vfsuid - map a vfsuid into the filesystem idmapping 258*1e5267cdSChristian Brauner * @mnt_userns: the mount's idmapping 259*1e5267cdSChristian Brauner * @fs_userns: the filesystem's idmapping 260*1e5267cdSChristian Brauner * @vfsuid : vfsuid to be mapped 261*1e5267cdSChristian Brauner * 262*1e5267cdSChristian Brauner * Map @vfsuid into the filesystem idmapping. This function has to be used in 263*1e5267cdSChristian Brauner * order to e.g. write @vfsuid to inode->i_uid. 264*1e5267cdSChristian Brauner * 265*1e5267cdSChristian Brauner * Return: @vfsuid mapped into the filesystem idmapping 266*1e5267cdSChristian Brauner */ 267*1e5267cdSChristian Brauner static inline kuid_t from_vfsuid(struct user_namespace *mnt_userns, 268*1e5267cdSChristian Brauner struct user_namespace *fs_userns, 269*1e5267cdSChristian Brauner vfsuid_t vfsuid) 270*1e5267cdSChristian Brauner { 271*1e5267cdSChristian Brauner uid_t uid; 272*1e5267cdSChristian Brauner 273*1e5267cdSChristian Brauner if (no_idmapping(mnt_userns, fs_userns)) 274*1e5267cdSChristian Brauner return AS_KUIDT(vfsuid); 275*1e5267cdSChristian Brauner uid = from_kuid(mnt_userns, AS_KUIDT(vfsuid)); 276*1e5267cdSChristian Brauner if (uid == (uid_t)-1) 277*1e5267cdSChristian Brauner return INVALID_UID; 278*1e5267cdSChristian Brauner if (initial_idmapping(fs_userns)) 279*1e5267cdSChristian Brauner return KUIDT_INIT(uid); 280*1e5267cdSChristian Brauner return make_kuid(fs_userns, uid); 2811ac2a410SChristian Brauner } 2821ac2a410SChristian Brauner 2831ac2a410SChristian Brauner /** 2841ac2a410SChristian Brauner * mapped_kuid_user - map a user kuid into a mnt_userns 2851ac2a410SChristian Brauner * @mnt_userns: the mount's idmapping 2861ac2a410SChristian Brauner * @fs_userns: the filesystem's idmapping 2871ac2a410SChristian Brauner * @kuid : kuid to be mapped 2881ac2a410SChristian Brauner * 2891ac2a410SChristian Brauner * Use the idmapping of @mnt_userns to remap a @kuid into @fs_userns. Use this 2901ac2a410SChristian Brauner * function when preparing a @kuid to be written to disk or inode. 2911ac2a410SChristian Brauner * 2921ac2a410SChristian Brauner * If no_idmapping() determines that this is not an idmapped mount we can 2931ac2a410SChristian Brauner * simply return @kuid unchanged. 2941ac2a410SChristian Brauner * If initial_idmapping() tells us that the filesystem is not mounted with an 2951ac2a410SChristian Brauner * idmapping we know the value of @kuid won't change when calling 2961ac2a410SChristian Brauner * make_kuid() so we can simply retrieve the value via KUIDT_INIT() 2971ac2a410SChristian Brauner * directly. 2981ac2a410SChristian Brauner * 2991ac2a410SChristian Brauner * Return: @kuid mapped according to @mnt_userns. 3001ac2a410SChristian Brauner * If @kuid has no mapping in either @mnt_userns or @fs_userns INVALID_UID is 3011ac2a410SChristian Brauner * returned. 3021ac2a410SChristian Brauner */ 3031ac2a410SChristian Brauner static inline kuid_t mapped_kuid_user(struct user_namespace *mnt_userns, 3041ac2a410SChristian Brauner struct user_namespace *fs_userns, 3051ac2a410SChristian Brauner kuid_t kuid) 3061ac2a410SChristian Brauner { 307*1e5267cdSChristian Brauner return from_vfsuid(mnt_userns, fs_userns, VFSUIDT_INIT(kuid)); 308*1e5267cdSChristian Brauner } 309*1e5267cdSChristian Brauner 310*1e5267cdSChristian Brauner /** 311*1e5267cdSChristian Brauner * vfsuid_has_fsmapping - check whether a vfsuid maps into the filesystem 312*1e5267cdSChristian Brauner * @mnt_userns: the mount's idmapping 313*1e5267cdSChristian Brauner * @fs_userns: the filesystem's idmapping 314*1e5267cdSChristian Brauner * @vfsuid: vfsuid to be mapped 315*1e5267cdSChristian Brauner * 316*1e5267cdSChristian Brauner * Check whether @vfsuid has a mapping in the filesystem idmapping. Use this 317*1e5267cdSChristian Brauner * function to check whether the filesystem idmapping has a mapping for 318*1e5267cdSChristian Brauner * @vfsuid. 319*1e5267cdSChristian Brauner * 320*1e5267cdSChristian Brauner * Return: true if @vfsuid has a mapping in the filesystem, false if not. 321*1e5267cdSChristian Brauner */ 322*1e5267cdSChristian Brauner static inline bool vfsuid_has_fsmapping(struct user_namespace *mnt_userns, 323*1e5267cdSChristian Brauner struct user_namespace *fs_userns, 324*1e5267cdSChristian Brauner vfsuid_t vfsuid) 325*1e5267cdSChristian Brauner { 326*1e5267cdSChristian Brauner return uid_valid(from_vfsuid(mnt_userns, fs_userns, vfsuid)); 327*1e5267cdSChristian Brauner } 328*1e5267cdSChristian Brauner 329*1e5267cdSChristian Brauner /** 330*1e5267cdSChristian Brauner * from_vfsgid - map a vfsgid into the filesystem idmapping 331*1e5267cdSChristian Brauner * @mnt_userns: the mount's idmapping 332*1e5267cdSChristian Brauner * @fs_userns: the filesystem's idmapping 333*1e5267cdSChristian Brauner * @vfsgid : vfsgid to be mapped 334*1e5267cdSChristian Brauner * 335*1e5267cdSChristian Brauner * Map @vfsgid into the filesystem idmapping. This function has to be used in 336*1e5267cdSChristian Brauner * order to e.g. write @vfsgid to inode->i_gid. 337*1e5267cdSChristian Brauner * 338*1e5267cdSChristian Brauner * Return: @vfsgid mapped into the filesystem idmapping 339*1e5267cdSChristian Brauner */ 340*1e5267cdSChristian Brauner static inline kgid_t from_vfsgid(struct user_namespace *mnt_userns, 341*1e5267cdSChristian Brauner struct user_namespace *fs_userns, 342*1e5267cdSChristian Brauner vfsgid_t vfsgid) 343*1e5267cdSChristian Brauner { 344*1e5267cdSChristian Brauner gid_t gid; 3451ac2a410SChristian Brauner 3461ac2a410SChristian Brauner if (no_idmapping(mnt_userns, fs_userns)) 347*1e5267cdSChristian Brauner return AS_KGIDT(vfsgid); 348*1e5267cdSChristian Brauner gid = from_kgid(mnt_userns, AS_KGIDT(vfsgid)); 349*1e5267cdSChristian Brauner if (gid == (gid_t)-1) 350*1e5267cdSChristian Brauner return INVALID_GID; 3511ac2a410SChristian Brauner if (initial_idmapping(fs_userns)) 352*1e5267cdSChristian Brauner return KGIDT_INIT(gid); 353*1e5267cdSChristian Brauner return make_kgid(fs_userns, gid); 3541ac2a410SChristian Brauner } 3551ac2a410SChristian Brauner 3561ac2a410SChristian Brauner /** 3571ac2a410SChristian Brauner * mapped_kgid_user - map a user kgid into a mnt_userns 3581ac2a410SChristian Brauner * @mnt_userns: the mount's idmapping 3591ac2a410SChristian Brauner * @fs_userns: the filesystem's idmapping 3601ac2a410SChristian Brauner * @kgid : kgid to be mapped 3611ac2a410SChristian Brauner * 3621ac2a410SChristian Brauner * Use the idmapping of @mnt_userns to remap a @kgid into @fs_userns. Use this 3631ac2a410SChristian Brauner * function when preparing a @kgid to be written to disk or inode. 3641ac2a410SChristian Brauner * 3651ac2a410SChristian Brauner * If no_idmapping() determines that this is not an idmapped mount we can 3661ac2a410SChristian Brauner * simply return @kgid unchanged. 3671ac2a410SChristian Brauner * If initial_idmapping() tells us that the filesystem is not mounted with an 3681ac2a410SChristian Brauner * idmapping we know the value of @kgid won't change when calling 3691ac2a410SChristian Brauner * make_kgid() so we can simply retrieve the value via KGIDT_INIT() 3701ac2a410SChristian Brauner * directly. 3711ac2a410SChristian Brauner * 3721ac2a410SChristian Brauner * Return: @kgid mapped according to @mnt_userns. 3731ac2a410SChristian Brauner * If @kgid has no mapping in either @mnt_userns or @fs_userns INVALID_GID is 3741ac2a410SChristian Brauner * returned. 3751ac2a410SChristian Brauner */ 3761ac2a410SChristian Brauner static inline kgid_t mapped_kgid_user(struct user_namespace *mnt_userns, 3771ac2a410SChristian Brauner struct user_namespace *fs_userns, 3781ac2a410SChristian Brauner kgid_t kgid) 3791ac2a410SChristian Brauner { 380*1e5267cdSChristian Brauner return from_vfsgid(mnt_userns, fs_userns, VFSGIDT_INIT(kgid)); 381*1e5267cdSChristian Brauner } 3821ac2a410SChristian Brauner 383*1e5267cdSChristian Brauner /** 384*1e5267cdSChristian Brauner * vfsgid_has_fsmapping - check whether a vfsgid maps into the filesystem 385*1e5267cdSChristian Brauner * @mnt_userns: the mount's idmapping 386*1e5267cdSChristian Brauner * @fs_userns: the filesystem's idmapping 387*1e5267cdSChristian Brauner * @vfsgid: vfsgid to be mapped 388*1e5267cdSChristian Brauner * 389*1e5267cdSChristian Brauner * Check whether @vfsgid has a mapping in the filesystem idmapping. Use this 390*1e5267cdSChristian Brauner * function to check whether the filesystem idmapping has a mapping for 391*1e5267cdSChristian Brauner * @vfsgid. 392*1e5267cdSChristian Brauner * 393*1e5267cdSChristian Brauner * Return: true if @vfsgid has a mapping in the filesystem, false if not. 394*1e5267cdSChristian Brauner */ 395*1e5267cdSChristian Brauner static inline bool vfsgid_has_fsmapping(struct user_namespace *mnt_userns, 396*1e5267cdSChristian Brauner struct user_namespace *fs_userns, 397*1e5267cdSChristian Brauner vfsgid_t vfsgid) 398*1e5267cdSChristian Brauner { 399*1e5267cdSChristian Brauner return gid_valid(from_vfsgid(mnt_userns, fs_userns, vfsgid)); 4001ac2a410SChristian Brauner } 4011ac2a410SChristian Brauner 4021ac2a410SChristian Brauner /** 403a793d79eSChristian Brauner * mapped_fsuid - return caller's fsuid mapped up into a mnt_userns 4041ac2a410SChristian Brauner * @mnt_userns: the mount's idmapping 405209188ceSChristian Brauner * @fs_userns: the filesystem's idmapping 406a793d79eSChristian Brauner * 407a793d79eSChristian Brauner * Use this helper to initialize a new vfs or filesystem object based on 408a793d79eSChristian Brauner * the caller's fsuid. A common example is initializing the i_uid field of 409a793d79eSChristian Brauner * a newly allocated inode triggered by a creation event such as mkdir or 410a793d79eSChristian Brauner * O_CREAT. Other examples include the allocation of quotas for a specific 411a793d79eSChristian Brauner * user. 412a793d79eSChristian Brauner * 413a793d79eSChristian Brauner * Return: the caller's current fsuid mapped up according to @mnt_userns. 414a793d79eSChristian Brauner */ 415209188ceSChristian Brauner static inline kuid_t mapped_fsuid(struct user_namespace *mnt_userns, 416209188ceSChristian Brauner struct user_namespace *fs_userns) 417a793d79eSChristian Brauner { 418209188ceSChristian Brauner return mapped_kuid_user(mnt_userns, fs_userns, current_fsuid()); 419a793d79eSChristian Brauner } 420a793d79eSChristian Brauner 421a793d79eSChristian Brauner /** 422a793d79eSChristian Brauner * mapped_fsgid - return caller's fsgid mapped up into a mnt_userns 4231ac2a410SChristian Brauner * @mnt_userns: the mount's idmapping 424209188ceSChristian Brauner * @fs_userns: the filesystem's idmapping 425a793d79eSChristian Brauner * 426a793d79eSChristian Brauner * Use this helper to initialize a new vfs or filesystem object based on 427a793d79eSChristian Brauner * the caller's fsgid. A common example is initializing the i_gid field of 428a793d79eSChristian Brauner * a newly allocated inode triggered by a creation event such as mkdir or 429a793d79eSChristian Brauner * O_CREAT. Other examples include the allocation of quotas for a specific 430a793d79eSChristian Brauner * user. 431a793d79eSChristian Brauner * 432a793d79eSChristian Brauner * Return: the caller's current fsgid mapped up according to @mnt_userns. 433a793d79eSChristian Brauner */ 434209188ceSChristian Brauner static inline kgid_t mapped_fsgid(struct user_namespace *mnt_userns, 435209188ceSChristian Brauner struct user_namespace *fs_userns) 436a793d79eSChristian Brauner { 437209188ceSChristian Brauner return mapped_kgid_user(mnt_userns, fs_userns, current_fsgid()); 438a793d79eSChristian Brauner } 439a793d79eSChristian Brauner 440a793d79eSChristian Brauner #endif /* _LINUX_MNT_IDMAPPING_H */ 441