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 161e5267cdSChristian Brauner typedef struct { 171e5267cdSChristian Brauner uid_t val; 181e5267cdSChristian Brauner } vfsuid_t; 191e5267cdSChristian Brauner 201e5267cdSChristian Brauner typedef struct { 211e5267cdSChristian Brauner gid_t val; 221e5267cdSChristian Brauner } vfsgid_t; 231e5267cdSChristian Brauner 2445c31150SChristian Brauner static_assert(sizeof(vfsuid_t) == sizeof(kuid_t)); 2545c31150SChristian Brauner static_assert(sizeof(vfsgid_t) == sizeof(kgid_t)); 2645c31150SChristian Brauner static_assert(offsetof(vfsuid_t, val) == offsetof(kuid_t, val)); 2745c31150SChristian Brauner static_assert(offsetof(vfsgid_t, val) == offsetof(kgid_t, val)); 2845c31150SChristian Brauner 291e5267cdSChristian Brauner #ifdef CONFIG_MULTIUSER 301e5267cdSChristian Brauner static inline uid_t __vfsuid_val(vfsuid_t uid) 311e5267cdSChristian Brauner { 321e5267cdSChristian Brauner return uid.val; 331e5267cdSChristian Brauner } 341e5267cdSChristian Brauner 351e5267cdSChristian Brauner static inline gid_t __vfsgid_val(vfsgid_t gid) 361e5267cdSChristian Brauner { 371e5267cdSChristian Brauner return gid.val; 381e5267cdSChristian Brauner } 391e5267cdSChristian Brauner #else 401e5267cdSChristian Brauner static inline uid_t __vfsuid_val(vfsuid_t uid) 411e5267cdSChristian Brauner { 421e5267cdSChristian Brauner return 0; 431e5267cdSChristian Brauner } 441e5267cdSChristian Brauner 451e5267cdSChristian Brauner static inline gid_t __vfsgid_val(vfsgid_t gid) 461e5267cdSChristian Brauner { 471e5267cdSChristian Brauner return 0; 481e5267cdSChristian Brauner } 491e5267cdSChristian Brauner #endif 501e5267cdSChristian Brauner 511e5267cdSChristian Brauner static inline bool vfsuid_valid(vfsuid_t uid) 521e5267cdSChristian Brauner { 531e5267cdSChristian Brauner return __vfsuid_val(uid) != (uid_t)-1; 541e5267cdSChristian Brauner } 551e5267cdSChristian Brauner 561e5267cdSChristian Brauner static inline bool vfsgid_valid(vfsgid_t gid) 571e5267cdSChristian Brauner { 581e5267cdSChristian Brauner return __vfsgid_val(gid) != (gid_t)-1; 591e5267cdSChristian Brauner } 601e5267cdSChristian Brauner 611e5267cdSChristian Brauner static inline bool vfsuid_eq(vfsuid_t left, vfsuid_t right) 621e5267cdSChristian Brauner { 634d0548a7SSeth Forshee return vfsuid_valid(left) && __vfsuid_val(left) == __vfsuid_val(right); 641e5267cdSChristian Brauner } 651e5267cdSChristian Brauner 661e5267cdSChristian Brauner static inline bool vfsgid_eq(vfsgid_t left, vfsgid_t right) 671e5267cdSChristian Brauner { 684d0548a7SSeth Forshee return vfsgid_valid(left) && __vfsgid_val(left) == __vfsgid_val(right); 691e5267cdSChristian Brauner } 701e5267cdSChristian Brauner 711e5267cdSChristian Brauner /** 721e5267cdSChristian Brauner * vfsuid_eq_kuid - check whether kuid and vfsuid have the same value 731e5267cdSChristian Brauner * @vfsuid: the vfsuid to compare 7477940f0dSChristian Brauner * @kuid: the kuid to compare 751e5267cdSChristian Brauner * 7677940f0dSChristian Brauner * Check whether @vfsuid and @kuid have the same values. 771e5267cdSChristian Brauner * 7877940f0dSChristian Brauner * Return: true if @vfsuid and @kuid have the same value, false if not. 794d0548a7SSeth Forshee * Comparison between two invalid uids returns false. 801e5267cdSChristian Brauner */ 811e5267cdSChristian Brauner static inline bool vfsuid_eq_kuid(vfsuid_t vfsuid, kuid_t kuid) 821e5267cdSChristian Brauner { 834d0548a7SSeth Forshee return vfsuid_valid(vfsuid) && __vfsuid_val(vfsuid) == __kuid_val(kuid); 841e5267cdSChristian Brauner } 851e5267cdSChristian Brauner 861e5267cdSChristian Brauner /** 871e5267cdSChristian Brauner * vfsgid_eq_kgid - check whether kgid and vfsgid have the same value 881e5267cdSChristian Brauner * @vfsgid: the vfsgid to compare 8977940f0dSChristian Brauner * @kgid: the kgid to compare 901e5267cdSChristian Brauner * 9177940f0dSChristian Brauner * Check whether @vfsgid and @kgid have the same values. 921e5267cdSChristian Brauner * 9377940f0dSChristian Brauner * Return: true if @vfsgid and @kgid have the same value, false if not. 944d0548a7SSeth Forshee * Comparison between two invalid gids returns false. 951e5267cdSChristian Brauner */ 9677940f0dSChristian Brauner static inline bool vfsgid_eq_kgid(vfsgid_t vfsgid, kgid_t kgid) 971e5267cdSChristian Brauner { 984d0548a7SSeth Forshee return vfsgid_valid(vfsgid) && __vfsgid_val(vfsgid) == __kgid_val(kgid); 991e5267cdSChristian Brauner } 1001e5267cdSChristian Brauner 1011e5267cdSChristian Brauner /* 1021e5267cdSChristian Brauner * vfs{g,u}ids are created from k{g,u}ids. 1031e5267cdSChristian Brauner * We don't allow them to be created from regular {u,g}id. 1041e5267cdSChristian Brauner */ 1051e5267cdSChristian Brauner #define VFSUIDT_INIT(val) (vfsuid_t){ __kuid_val(val) } 1061e5267cdSChristian Brauner #define VFSGIDT_INIT(val) (vfsgid_t){ __kgid_val(val) } 1071e5267cdSChristian Brauner 1081e5267cdSChristian Brauner #define INVALID_VFSUID VFSUIDT_INIT(INVALID_UID) 1091e5267cdSChristian Brauner #define INVALID_VFSGID VFSGIDT_INIT(INVALID_GID) 1101e5267cdSChristian Brauner 1111e5267cdSChristian Brauner /* 1121e5267cdSChristian Brauner * Allow a vfs{g,u}id to be used as a k{g,u}id where we want to compare 1131e5267cdSChristian Brauner * whether the mapped value is identical to value of a k{g,u}id. 1141e5267cdSChristian Brauner */ 1151e5267cdSChristian Brauner #define AS_KUIDT(val) (kuid_t){ __vfsuid_val(val) } 1161e5267cdSChristian Brauner #define AS_KGIDT(val) (kgid_t){ __vfsgid_val(val) } 1171e5267cdSChristian Brauner 1181e5267cdSChristian Brauner #ifdef CONFIG_MULTIUSER 1191e5267cdSChristian Brauner /** 1201e5267cdSChristian Brauner * vfsgid_in_group_p() - check whether a vfsuid matches the caller's groups 1211e5267cdSChristian Brauner * @vfsgid: the mnt gid to match 1221e5267cdSChristian Brauner * 1231e5267cdSChristian Brauner * This function can be used to determine whether @vfsuid matches any of the 1241e5267cdSChristian Brauner * caller's groups. 1251e5267cdSChristian Brauner * 1261e5267cdSChristian Brauner * Return: 1 if vfsuid matches caller's groups, 0 if not. 1271e5267cdSChristian Brauner */ 1281e5267cdSChristian Brauner static inline int vfsgid_in_group_p(vfsgid_t vfsgid) 1291e5267cdSChristian Brauner { 1301e5267cdSChristian Brauner return in_group_p(AS_KGIDT(vfsgid)); 1311e5267cdSChristian Brauner } 1321e5267cdSChristian Brauner #else 1331e5267cdSChristian Brauner static inline int vfsgid_in_group_p(vfsgid_t vfsgid) 1341e5267cdSChristian Brauner { 1351e5267cdSChristian Brauner return 1; 1361e5267cdSChristian Brauner } 1371e5267cdSChristian Brauner #endif 1381e5267cdSChristian Brauner 139a793d79eSChristian Brauner /** 1401ac2a410SChristian Brauner * initial_idmapping - check whether this is the initial mapping 1411ac2a410SChristian Brauner * @ns: idmapping to check 1421ac2a410SChristian Brauner * 1431ac2a410SChristian Brauner * Check whether this is the initial mapping, mapping 0 to 0, 1 to 1, 1441ac2a410SChristian Brauner * [...], 1000 to 1000 [...]. 1451ac2a410SChristian Brauner * 1461ac2a410SChristian Brauner * Return: true if this is the initial mapping, false if not. 1471ac2a410SChristian Brauner */ 1481ac2a410SChristian Brauner static inline bool initial_idmapping(const struct user_namespace *ns) 1491ac2a410SChristian Brauner { 1501ac2a410SChristian Brauner return ns == &init_user_ns; 1511ac2a410SChristian Brauner } 1521ac2a410SChristian Brauner 1531ac2a410SChristian Brauner /** 1541ac2a410SChristian Brauner * no_idmapping - check whether we can skip remapping a kuid/gid 1551ac2a410SChristian Brauner * @mnt_userns: the mount's idmapping 1561ac2a410SChristian Brauner * @fs_userns: the filesystem's idmapping 1571ac2a410SChristian Brauner * 1581ac2a410SChristian Brauner * This function can be used to check whether a remapping between two 1591ac2a410SChristian Brauner * idmappings is required. 1601ac2a410SChristian Brauner * An idmapped mount is a mount that has an idmapping attached to it that 1611ac2a410SChristian Brauner * is different from the filsystem's idmapping and the initial idmapping. 1621ac2a410SChristian Brauner * If the initial mapping is used or the idmapping of the mount and the 1631ac2a410SChristian Brauner * filesystem are identical no remapping is required. 1641ac2a410SChristian Brauner * 1651ac2a410SChristian Brauner * Return: true if remapping can be skipped, false if not. 1661ac2a410SChristian Brauner */ 1671ac2a410SChristian Brauner static inline bool no_idmapping(const struct user_namespace *mnt_userns, 1681ac2a410SChristian Brauner const struct user_namespace *fs_userns) 1691ac2a410SChristian Brauner { 1701ac2a410SChristian Brauner return initial_idmapping(mnt_userns) || mnt_userns == fs_userns; 1711ac2a410SChristian Brauner } 1721ac2a410SChristian Brauner 1731ac2a410SChristian Brauner /** 17477940f0dSChristian Brauner * make_vfsuid - map a filesystem kuid into a mnt_userns 1751ac2a410SChristian Brauner * @mnt_userns: the mount's idmapping 1761ac2a410SChristian Brauner * @fs_userns: the filesystem's idmapping 1771ac2a410SChristian Brauner * @kuid : kuid to be mapped 1781ac2a410SChristian Brauner * 1791ac2a410SChristian Brauner * Take a @kuid and remap it from @fs_userns into @mnt_userns. Use this 1801ac2a410SChristian Brauner * function when preparing a @kuid to be reported to userspace. 1811ac2a410SChristian Brauner * 1821ac2a410SChristian Brauner * If no_idmapping() determines that this is not an idmapped mount we can 1831ac2a410SChristian Brauner * simply return @kuid unchanged. 1841ac2a410SChristian Brauner * If initial_idmapping() tells us that the filesystem is not mounted with an 1851ac2a410SChristian Brauner * idmapping we know the value of @kuid won't change when calling 1861ac2a410SChristian Brauner * from_kuid() so we can simply retrieve the value via __kuid_val() 1871ac2a410SChristian Brauner * directly. 1881ac2a410SChristian Brauner * 1891ac2a410SChristian Brauner * Return: @kuid mapped according to @mnt_userns. 1901ac2a410SChristian Brauner * If @kuid has no mapping in either @mnt_userns or @fs_userns INVALID_UID is 1911ac2a410SChristian Brauner * returned. 1921ac2a410SChristian Brauner */ 1931e5267cdSChristian Brauner 1941e5267cdSChristian Brauner static inline vfsuid_t make_vfsuid(struct user_namespace *mnt_userns, 1951ac2a410SChristian Brauner struct user_namespace *fs_userns, 1961ac2a410SChristian Brauner kuid_t kuid) 1971ac2a410SChristian Brauner { 1981ac2a410SChristian Brauner uid_t uid; 1991ac2a410SChristian Brauner 2001ac2a410SChristian Brauner if (no_idmapping(mnt_userns, fs_userns)) 2011e5267cdSChristian Brauner return VFSUIDT_INIT(kuid); 2021ac2a410SChristian Brauner if (initial_idmapping(fs_userns)) 2031ac2a410SChristian Brauner uid = __kuid_val(kuid); 2041ac2a410SChristian Brauner else 2051ac2a410SChristian Brauner uid = from_kuid(fs_userns, kuid); 2061ac2a410SChristian Brauner if (uid == (uid_t)-1) 2071e5267cdSChristian Brauner return INVALID_VFSUID; 2081e5267cdSChristian Brauner return VFSUIDT_INIT(make_kuid(mnt_userns, uid)); 2091e5267cdSChristian Brauner } 2101e5267cdSChristian Brauner 2111e5267cdSChristian Brauner static inline kuid_t mapped_kuid_fs(struct user_namespace *mnt_userns, 2121e5267cdSChristian Brauner struct user_namespace *fs_userns, 2131e5267cdSChristian Brauner kuid_t kuid) 2141e5267cdSChristian Brauner { 2151e5267cdSChristian Brauner return AS_KUIDT(make_vfsuid(mnt_userns, fs_userns, kuid)); 2161ac2a410SChristian Brauner } 2171ac2a410SChristian Brauner 2181ac2a410SChristian Brauner /** 21977940f0dSChristian Brauner * make_vfsgid - map a filesystem kgid into a mnt_userns 2201ac2a410SChristian Brauner * @mnt_userns: the mount's idmapping 2211ac2a410SChristian Brauner * @fs_userns: the filesystem's idmapping 2221ac2a410SChristian Brauner * @kgid : kgid to be mapped 2231ac2a410SChristian Brauner * 2241ac2a410SChristian Brauner * Take a @kgid and remap it from @fs_userns into @mnt_userns. Use this 2251ac2a410SChristian Brauner * function when preparing a @kgid to be reported to userspace. 2261ac2a410SChristian Brauner * 2271ac2a410SChristian Brauner * If no_idmapping() determines that this is not an idmapped mount we can 2281ac2a410SChristian Brauner * simply return @kgid unchanged. 2291ac2a410SChristian Brauner * If initial_idmapping() tells us that the filesystem is not mounted with an 2301ac2a410SChristian Brauner * idmapping we know the value of @kgid won't change when calling 2311ac2a410SChristian Brauner * from_kgid() so we can simply retrieve the value via __kgid_val() 2321ac2a410SChristian Brauner * directly. 2331ac2a410SChristian Brauner * 2341ac2a410SChristian Brauner * Return: @kgid mapped according to @mnt_userns. 2351ac2a410SChristian Brauner * If @kgid has no mapping in either @mnt_userns or @fs_userns INVALID_GID is 2361ac2a410SChristian Brauner * returned. 2371ac2a410SChristian Brauner */ 2381e5267cdSChristian Brauner 2391e5267cdSChristian Brauner static inline vfsgid_t make_vfsgid(struct user_namespace *mnt_userns, 2401ac2a410SChristian Brauner struct user_namespace *fs_userns, 2411ac2a410SChristian Brauner kgid_t kgid) 2421ac2a410SChristian Brauner { 2431ac2a410SChristian Brauner gid_t gid; 2441ac2a410SChristian Brauner 2451ac2a410SChristian Brauner if (no_idmapping(mnt_userns, fs_userns)) 2461e5267cdSChristian Brauner return VFSGIDT_INIT(kgid); 2471ac2a410SChristian Brauner if (initial_idmapping(fs_userns)) 2481ac2a410SChristian Brauner gid = __kgid_val(kgid); 2491ac2a410SChristian Brauner else 2501ac2a410SChristian Brauner gid = from_kgid(fs_userns, kgid); 2511ac2a410SChristian Brauner if (gid == (gid_t)-1) 2521e5267cdSChristian Brauner return INVALID_VFSGID; 2531e5267cdSChristian Brauner return VFSGIDT_INIT(make_kgid(mnt_userns, gid)); 2541e5267cdSChristian Brauner } 2551e5267cdSChristian Brauner 2561e5267cdSChristian Brauner static inline kgid_t mapped_kgid_fs(struct user_namespace *mnt_userns, 2571e5267cdSChristian Brauner struct user_namespace *fs_userns, 2581e5267cdSChristian Brauner kgid_t kgid) 2591e5267cdSChristian Brauner { 2601e5267cdSChristian Brauner return AS_KGIDT(make_vfsgid(mnt_userns, fs_userns, kgid)); 2611e5267cdSChristian Brauner } 2621e5267cdSChristian Brauner 2631e5267cdSChristian Brauner /** 2641e5267cdSChristian Brauner * from_vfsuid - map a vfsuid into the filesystem idmapping 2651e5267cdSChristian Brauner * @mnt_userns: the mount's idmapping 2661e5267cdSChristian Brauner * @fs_userns: the filesystem's idmapping 2671e5267cdSChristian Brauner * @vfsuid : vfsuid to be mapped 2681e5267cdSChristian Brauner * 2691e5267cdSChristian Brauner * Map @vfsuid into the filesystem idmapping. This function has to be used in 2701e5267cdSChristian Brauner * order to e.g. write @vfsuid to inode->i_uid. 2711e5267cdSChristian Brauner * 2721e5267cdSChristian Brauner * Return: @vfsuid mapped into the filesystem idmapping 2731e5267cdSChristian Brauner */ 2741e5267cdSChristian Brauner static inline kuid_t from_vfsuid(struct user_namespace *mnt_userns, 2751e5267cdSChristian Brauner struct user_namespace *fs_userns, 2761e5267cdSChristian Brauner vfsuid_t vfsuid) 2771e5267cdSChristian Brauner { 2781e5267cdSChristian Brauner uid_t uid; 2791e5267cdSChristian Brauner 2801e5267cdSChristian Brauner if (no_idmapping(mnt_userns, fs_userns)) 2811e5267cdSChristian Brauner return AS_KUIDT(vfsuid); 2821e5267cdSChristian Brauner uid = from_kuid(mnt_userns, AS_KUIDT(vfsuid)); 2831e5267cdSChristian Brauner if (uid == (uid_t)-1) 2841e5267cdSChristian Brauner return INVALID_UID; 2851e5267cdSChristian Brauner if (initial_idmapping(fs_userns)) 2861e5267cdSChristian Brauner return KUIDT_INIT(uid); 2871e5267cdSChristian Brauner return make_kuid(fs_userns, uid); 2881ac2a410SChristian Brauner } 2891ac2a410SChristian Brauner 2901ac2a410SChristian Brauner /** 2911ac2a410SChristian Brauner * mapped_kuid_user - map a user kuid into a mnt_userns 2921ac2a410SChristian Brauner * @mnt_userns: the mount's idmapping 2931ac2a410SChristian Brauner * @fs_userns: the filesystem's idmapping 2941ac2a410SChristian Brauner * @kuid : kuid to be mapped 2951ac2a410SChristian Brauner * 2961ac2a410SChristian Brauner * Use the idmapping of @mnt_userns to remap a @kuid into @fs_userns. Use this 2971ac2a410SChristian Brauner * function when preparing a @kuid to be written to disk or inode. 2981ac2a410SChristian Brauner * 2991ac2a410SChristian Brauner * If no_idmapping() determines that this is not an idmapped mount we can 3001ac2a410SChristian Brauner * simply return @kuid unchanged. 3011ac2a410SChristian Brauner * If initial_idmapping() tells us that the filesystem is not mounted with an 3021ac2a410SChristian Brauner * idmapping we know the value of @kuid won't change when calling 3031ac2a410SChristian Brauner * make_kuid() so we can simply retrieve the value via KUIDT_INIT() 3041ac2a410SChristian Brauner * directly. 3051ac2a410SChristian Brauner * 3061ac2a410SChristian Brauner * Return: @kuid mapped according to @mnt_userns. 3071ac2a410SChristian Brauner * If @kuid has no mapping in either @mnt_userns or @fs_userns INVALID_UID is 3081ac2a410SChristian Brauner * returned. 3091ac2a410SChristian Brauner */ 3101ac2a410SChristian Brauner static inline kuid_t mapped_kuid_user(struct user_namespace *mnt_userns, 3111ac2a410SChristian Brauner struct user_namespace *fs_userns, 3121ac2a410SChristian Brauner kuid_t kuid) 3131ac2a410SChristian Brauner { 3141e5267cdSChristian Brauner return from_vfsuid(mnt_userns, fs_userns, VFSUIDT_INIT(kuid)); 3151e5267cdSChristian Brauner } 3161e5267cdSChristian Brauner 3171e5267cdSChristian Brauner /** 3181e5267cdSChristian Brauner * vfsuid_has_fsmapping - check whether a vfsuid maps into the filesystem 3191e5267cdSChristian Brauner * @mnt_userns: the mount's idmapping 3201e5267cdSChristian Brauner * @fs_userns: the filesystem's idmapping 3211e5267cdSChristian Brauner * @vfsuid: vfsuid to be mapped 3221e5267cdSChristian Brauner * 3231e5267cdSChristian Brauner * Check whether @vfsuid has a mapping in the filesystem idmapping. Use this 3241e5267cdSChristian Brauner * function to check whether the filesystem idmapping has a mapping for 3251e5267cdSChristian Brauner * @vfsuid. 3261e5267cdSChristian Brauner * 3271e5267cdSChristian Brauner * Return: true if @vfsuid has a mapping in the filesystem, false if not. 3281e5267cdSChristian Brauner */ 3291e5267cdSChristian Brauner static inline bool vfsuid_has_fsmapping(struct user_namespace *mnt_userns, 3301e5267cdSChristian Brauner struct user_namespace *fs_userns, 3311e5267cdSChristian Brauner vfsuid_t vfsuid) 3321e5267cdSChristian Brauner { 3331e5267cdSChristian Brauner return uid_valid(from_vfsuid(mnt_userns, fs_userns, vfsuid)); 3341e5267cdSChristian Brauner } 3351e5267cdSChristian Brauner 3361e5267cdSChristian Brauner /** 337*c9fa2b07SChristian Brauner * vfsuid_into_kuid - convert vfsuid into kuid 338*c9fa2b07SChristian Brauner * @vfsuid: the vfsuid to convert 339*c9fa2b07SChristian Brauner * 340*c9fa2b07SChristian Brauner * This can be used when a vfsuid is committed as a kuid. 341*c9fa2b07SChristian Brauner * 342*c9fa2b07SChristian Brauner * Return: a kuid with the value of @vfsuid 343*c9fa2b07SChristian Brauner */ 344*c9fa2b07SChristian Brauner static inline kuid_t vfsuid_into_kuid(vfsuid_t vfsuid) 345*c9fa2b07SChristian Brauner { 346*c9fa2b07SChristian Brauner return AS_KUIDT(vfsuid); 347*c9fa2b07SChristian Brauner } 348*c9fa2b07SChristian Brauner 349*c9fa2b07SChristian Brauner /** 3501e5267cdSChristian Brauner * from_vfsgid - map a vfsgid into the filesystem idmapping 3511e5267cdSChristian Brauner * @mnt_userns: the mount's idmapping 3521e5267cdSChristian Brauner * @fs_userns: the filesystem's idmapping 3531e5267cdSChristian Brauner * @vfsgid : vfsgid to be mapped 3541e5267cdSChristian Brauner * 3551e5267cdSChristian Brauner * Map @vfsgid into the filesystem idmapping. This function has to be used in 3561e5267cdSChristian Brauner * order to e.g. write @vfsgid to inode->i_gid. 3571e5267cdSChristian Brauner * 3581e5267cdSChristian Brauner * Return: @vfsgid mapped into the filesystem idmapping 3591e5267cdSChristian Brauner */ 3601e5267cdSChristian Brauner static inline kgid_t from_vfsgid(struct user_namespace *mnt_userns, 3611e5267cdSChristian Brauner struct user_namespace *fs_userns, 3621e5267cdSChristian Brauner vfsgid_t vfsgid) 3631e5267cdSChristian Brauner { 3641e5267cdSChristian Brauner gid_t gid; 3651ac2a410SChristian Brauner 3661ac2a410SChristian Brauner if (no_idmapping(mnt_userns, fs_userns)) 3671e5267cdSChristian Brauner return AS_KGIDT(vfsgid); 3681e5267cdSChristian Brauner gid = from_kgid(mnt_userns, AS_KGIDT(vfsgid)); 3691e5267cdSChristian Brauner if (gid == (gid_t)-1) 3701e5267cdSChristian Brauner return INVALID_GID; 3711ac2a410SChristian Brauner if (initial_idmapping(fs_userns)) 3721e5267cdSChristian Brauner return KGIDT_INIT(gid); 3731e5267cdSChristian Brauner return make_kgid(fs_userns, gid); 3741ac2a410SChristian Brauner } 3751ac2a410SChristian Brauner 3761ac2a410SChristian Brauner /** 3771ac2a410SChristian Brauner * mapped_kgid_user - map a user kgid into a mnt_userns 3781ac2a410SChristian Brauner * @mnt_userns: the mount's idmapping 3791ac2a410SChristian Brauner * @fs_userns: the filesystem's idmapping 3801ac2a410SChristian Brauner * @kgid : kgid to be mapped 3811ac2a410SChristian Brauner * 3821ac2a410SChristian Brauner * Use the idmapping of @mnt_userns to remap a @kgid into @fs_userns. Use this 3831ac2a410SChristian Brauner * function when preparing a @kgid to be written to disk or inode. 3841ac2a410SChristian Brauner * 3851ac2a410SChristian Brauner * If no_idmapping() determines that this is not an idmapped mount we can 3861ac2a410SChristian Brauner * simply return @kgid unchanged. 3871ac2a410SChristian Brauner * If initial_idmapping() tells us that the filesystem is not mounted with an 3881ac2a410SChristian Brauner * idmapping we know the value of @kgid won't change when calling 3891ac2a410SChristian Brauner * make_kgid() so we can simply retrieve the value via KGIDT_INIT() 3901ac2a410SChristian Brauner * directly. 3911ac2a410SChristian Brauner * 3921ac2a410SChristian Brauner * Return: @kgid mapped according to @mnt_userns. 3931ac2a410SChristian Brauner * If @kgid has no mapping in either @mnt_userns or @fs_userns INVALID_GID is 3941ac2a410SChristian Brauner * returned. 3951ac2a410SChristian Brauner */ 3961ac2a410SChristian Brauner static inline kgid_t mapped_kgid_user(struct user_namespace *mnt_userns, 3971ac2a410SChristian Brauner struct user_namespace *fs_userns, 3981ac2a410SChristian Brauner kgid_t kgid) 3991ac2a410SChristian Brauner { 4001e5267cdSChristian Brauner return from_vfsgid(mnt_userns, fs_userns, VFSGIDT_INIT(kgid)); 4011e5267cdSChristian Brauner } 4021ac2a410SChristian Brauner 4031e5267cdSChristian Brauner /** 4041e5267cdSChristian Brauner * vfsgid_has_fsmapping - check whether a vfsgid maps into the filesystem 4051e5267cdSChristian Brauner * @mnt_userns: the mount's idmapping 4061e5267cdSChristian Brauner * @fs_userns: the filesystem's idmapping 4071e5267cdSChristian Brauner * @vfsgid: vfsgid to be mapped 4081e5267cdSChristian Brauner * 4091e5267cdSChristian Brauner * Check whether @vfsgid has a mapping in the filesystem idmapping. Use this 4101e5267cdSChristian Brauner * function to check whether the filesystem idmapping has a mapping for 4111e5267cdSChristian Brauner * @vfsgid. 4121e5267cdSChristian Brauner * 4131e5267cdSChristian Brauner * Return: true if @vfsgid has a mapping in the filesystem, false if not. 4141e5267cdSChristian Brauner */ 4151e5267cdSChristian Brauner static inline bool vfsgid_has_fsmapping(struct user_namespace *mnt_userns, 4161e5267cdSChristian Brauner struct user_namespace *fs_userns, 4171e5267cdSChristian Brauner vfsgid_t vfsgid) 4181e5267cdSChristian Brauner { 4191e5267cdSChristian Brauner return gid_valid(from_vfsgid(mnt_userns, fs_userns, vfsgid)); 4201ac2a410SChristian Brauner } 4211ac2a410SChristian Brauner 4221ac2a410SChristian Brauner /** 423*c9fa2b07SChristian Brauner * vfsgid_into_kgid - convert vfsgid into kgid 424*c9fa2b07SChristian Brauner * @vfsgid: the vfsgid to convert 425*c9fa2b07SChristian Brauner * 426*c9fa2b07SChristian Brauner * This can be used when a vfsgid is committed as a kgid. 427*c9fa2b07SChristian Brauner * 428*c9fa2b07SChristian Brauner * Return: a kgid with the value of @vfsgid 429*c9fa2b07SChristian Brauner */ 430*c9fa2b07SChristian Brauner static inline kgid_t vfsgid_into_kgid(vfsgid_t vfsgid) 431*c9fa2b07SChristian Brauner { 432*c9fa2b07SChristian Brauner return AS_KGIDT(vfsgid); 433*c9fa2b07SChristian Brauner } 434*c9fa2b07SChristian Brauner 435*c9fa2b07SChristian Brauner /** 436a793d79eSChristian Brauner * mapped_fsuid - return caller's fsuid mapped up into a mnt_userns 4371ac2a410SChristian Brauner * @mnt_userns: the mount's idmapping 438209188ceSChristian Brauner * @fs_userns: the filesystem's idmapping 439a793d79eSChristian Brauner * 440a793d79eSChristian Brauner * Use this helper to initialize a new vfs or filesystem object based on 441a793d79eSChristian Brauner * the caller's fsuid. A common example is initializing the i_uid field of 442a793d79eSChristian Brauner * a newly allocated inode triggered by a creation event such as mkdir or 443a793d79eSChristian Brauner * O_CREAT. Other examples include the allocation of quotas for a specific 444a793d79eSChristian Brauner * user. 445a793d79eSChristian Brauner * 446a793d79eSChristian Brauner * Return: the caller's current fsuid mapped up according to @mnt_userns. 447a793d79eSChristian Brauner */ 448209188ceSChristian Brauner static inline kuid_t mapped_fsuid(struct user_namespace *mnt_userns, 449209188ceSChristian Brauner struct user_namespace *fs_userns) 450a793d79eSChristian Brauner { 451fc04dafdSChristian Brauner return from_vfsuid(mnt_userns, fs_userns, 452fc04dafdSChristian Brauner VFSUIDT_INIT(current_fsuid())); 453a793d79eSChristian Brauner } 454a793d79eSChristian Brauner 455a793d79eSChristian Brauner /** 456a793d79eSChristian Brauner * mapped_fsgid - return caller's fsgid mapped up into a mnt_userns 4571ac2a410SChristian Brauner * @mnt_userns: the mount's idmapping 458209188ceSChristian Brauner * @fs_userns: the filesystem's idmapping 459a793d79eSChristian Brauner * 460a793d79eSChristian Brauner * Use this helper to initialize a new vfs or filesystem object based on 461a793d79eSChristian Brauner * the caller's fsgid. A common example is initializing the i_gid field of 462a793d79eSChristian Brauner * a newly allocated inode triggered by a creation event such as mkdir or 463a793d79eSChristian Brauner * O_CREAT. Other examples include the allocation of quotas for a specific 464a793d79eSChristian Brauner * user. 465a793d79eSChristian Brauner * 466a793d79eSChristian Brauner * Return: the caller's current fsgid mapped up according to @mnt_userns. 467a793d79eSChristian Brauner */ 468209188ceSChristian Brauner static inline kgid_t mapped_fsgid(struct user_namespace *mnt_userns, 469209188ceSChristian Brauner struct user_namespace *fs_userns) 470a793d79eSChristian Brauner { 471fc04dafdSChristian Brauner return from_vfsgid(mnt_userns, fs_userns, 472fc04dafdSChristian Brauner VFSGIDT_INIT(current_fsgid())); 473a793d79eSChristian Brauner } 474a793d79eSChristian Brauner 475a793d79eSChristian Brauner #endif /* _LINUX_MNT_IDMAPPING_H */ 476