![]() |
|
|||
0001 /* SPDX-License-Identifier: GPL-2.0 */ 0002 #ifndef _LINUX_MNT_IDMAPPING_H 0003 #define _LINUX_MNT_IDMAPPING_H 0004 0005 #include <linux/types.h> 0006 #include <linux/uidgid.h> 0007 0008 struct user_namespace; 0009 /* 0010 * Carries the initial idmapping of 0:0:4294967295 which is an identity 0011 * mapping. This means that {g,u}id 0 is mapped to {g,u}id 0, {g,u}id 1 is 0012 * mapped to {g,u}id 1, [...], {g,u}id 1000 to {g,u}id 1000, [...]. 0013 */ 0014 extern struct user_namespace init_user_ns; 0015 0016 typedef struct { 0017 uid_t val; 0018 } vfsuid_t; 0019 0020 typedef struct { 0021 gid_t val; 0022 } vfsgid_t; 0023 0024 static_assert(sizeof(vfsuid_t) == sizeof(kuid_t)); 0025 static_assert(sizeof(vfsgid_t) == sizeof(kgid_t)); 0026 static_assert(offsetof(vfsuid_t, val) == offsetof(kuid_t, val)); 0027 static_assert(offsetof(vfsgid_t, val) == offsetof(kgid_t, val)); 0028 0029 #ifdef CONFIG_MULTIUSER 0030 static inline uid_t __vfsuid_val(vfsuid_t uid) 0031 { 0032 return uid.val; 0033 } 0034 0035 static inline gid_t __vfsgid_val(vfsgid_t gid) 0036 { 0037 return gid.val; 0038 } 0039 #else 0040 static inline uid_t __vfsuid_val(vfsuid_t uid) 0041 { 0042 return 0; 0043 } 0044 0045 static inline gid_t __vfsgid_val(vfsgid_t gid) 0046 { 0047 return 0; 0048 } 0049 #endif 0050 0051 static inline bool vfsuid_valid(vfsuid_t uid) 0052 { 0053 return __vfsuid_val(uid) != (uid_t)-1; 0054 } 0055 0056 static inline bool vfsgid_valid(vfsgid_t gid) 0057 { 0058 return __vfsgid_val(gid) != (gid_t)-1; 0059 } 0060 0061 static inline bool vfsuid_eq(vfsuid_t left, vfsuid_t right) 0062 { 0063 return vfsuid_valid(left) && __vfsuid_val(left) == __vfsuid_val(right); 0064 } 0065 0066 static inline bool vfsgid_eq(vfsgid_t left, vfsgid_t right) 0067 { 0068 return vfsgid_valid(left) && __vfsgid_val(left) == __vfsgid_val(right); 0069 } 0070 0071 /** 0072 * vfsuid_eq_kuid - check whether kuid and vfsuid have the same value 0073 * @vfsuid: the vfsuid to compare 0074 * @kuid: the kuid to compare 0075 * 0076 * Check whether @vfsuid and @kuid have the same values. 0077 * 0078 * Return: true if @vfsuid and @kuid have the same value, false if not. 0079 * Comparison between two invalid uids returns false. 0080 */ 0081 static inline bool vfsuid_eq_kuid(vfsuid_t vfsuid, kuid_t kuid) 0082 { 0083 return vfsuid_valid(vfsuid) && __vfsuid_val(vfsuid) == __kuid_val(kuid); 0084 } 0085 0086 /** 0087 * vfsgid_eq_kgid - check whether kgid and vfsgid have the same value 0088 * @vfsgid: the vfsgid to compare 0089 * @kgid: the kgid to compare 0090 * 0091 * Check whether @vfsgid and @kgid have the same values. 0092 * 0093 * Return: true if @vfsgid and @kgid have the same value, false if not. 0094 * Comparison between two invalid gids returns false. 0095 */ 0096 static inline bool vfsgid_eq_kgid(vfsgid_t vfsgid, kgid_t kgid) 0097 { 0098 return vfsgid_valid(vfsgid) && __vfsgid_val(vfsgid) == __kgid_val(kgid); 0099 } 0100 0101 /* 0102 * vfs{g,u}ids are created from k{g,u}ids. 0103 * We don't allow them to be created from regular {u,g}id. 0104 */ 0105 #define VFSUIDT_INIT(val) (vfsuid_t){ __kuid_val(val) } 0106 #define VFSGIDT_INIT(val) (vfsgid_t){ __kgid_val(val) } 0107 0108 #define INVALID_VFSUID VFSUIDT_INIT(INVALID_UID) 0109 #define INVALID_VFSGID VFSGIDT_INIT(INVALID_GID) 0110 0111 /* 0112 * Allow a vfs{g,u}id to be used as a k{g,u}id where we want to compare 0113 * whether the mapped value is identical to value of a k{g,u}id. 0114 */ 0115 #define AS_KUIDT(val) (kuid_t){ __vfsuid_val(val) } 0116 #define AS_KGIDT(val) (kgid_t){ __vfsgid_val(val) } 0117 0118 #ifdef CONFIG_MULTIUSER 0119 /** 0120 * vfsgid_in_group_p() - check whether a vfsuid matches the caller's groups 0121 * @vfsgid: the mnt gid to match 0122 * 0123 * This function can be used to determine whether @vfsuid matches any of the 0124 * caller's groups. 0125 * 0126 * Return: 1 if vfsuid matches caller's groups, 0 if not. 0127 */ 0128 static inline int vfsgid_in_group_p(vfsgid_t vfsgid) 0129 { 0130 return in_group_p(AS_KGIDT(vfsgid)); 0131 } 0132 #else 0133 static inline int vfsgid_in_group_p(vfsgid_t vfsgid) 0134 { 0135 return 1; 0136 } 0137 #endif 0138 0139 /** 0140 * initial_idmapping - check whether this is the initial mapping 0141 * @ns: idmapping to check 0142 * 0143 * Check whether this is the initial mapping, mapping 0 to 0, 1 to 1, 0144 * [...], 1000 to 1000 [...]. 0145 * 0146 * Return: true if this is the initial mapping, false if not. 0147 */ 0148 static inline bool initial_idmapping(const struct user_namespace *ns) 0149 { 0150 return ns == &init_user_ns; 0151 } 0152 0153 /** 0154 * no_idmapping - check whether we can skip remapping a kuid/gid 0155 * @mnt_userns: the mount's idmapping 0156 * @fs_userns: the filesystem's idmapping 0157 * 0158 * This function can be used to check whether a remapping between two 0159 * idmappings is required. 0160 * An idmapped mount is a mount that has an idmapping attached to it that 0161 * is different from the filsystem's idmapping and the initial idmapping. 0162 * If the initial mapping is used or the idmapping of the mount and the 0163 * filesystem are identical no remapping is required. 0164 * 0165 * Return: true if remapping can be skipped, false if not. 0166 */ 0167 static inline bool no_idmapping(const struct user_namespace *mnt_userns, 0168 const struct user_namespace *fs_userns) 0169 { 0170 return initial_idmapping(mnt_userns) || mnt_userns == fs_userns; 0171 } 0172 0173 /** 0174 * make_vfsuid - map a filesystem kuid into a mnt_userns 0175 * @mnt_userns: the mount's idmapping 0176 * @fs_userns: the filesystem's idmapping 0177 * @kuid : kuid to be mapped 0178 * 0179 * Take a @kuid and remap it from @fs_userns into @mnt_userns. Use this 0180 * function when preparing a @kuid to be reported to userspace. 0181 * 0182 * If no_idmapping() determines that this is not an idmapped mount we can 0183 * simply return @kuid unchanged. 0184 * If initial_idmapping() tells us that the filesystem is not mounted with an 0185 * idmapping we know the value of @kuid won't change when calling 0186 * from_kuid() so we can simply retrieve the value via __kuid_val() 0187 * directly. 0188 * 0189 * Return: @kuid mapped according to @mnt_userns. 0190 * If @kuid has no mapping in either @mnt_userns or @fs_userns INVALID_UID is 0191 * returned. 0192 */ 0193 0194 static inline vfsuid_t make_vfsuid(struct user_namespace *mnt_userns, 0195 struct user_namespace *fs_userns, 0196 kuid_t kuid) 0197 { 0198 uid_t uid; 0199 0200 if (no_idmapping(mnt_userns, fs_userns)) 0201 return VFSUIDT_INIT(kuid); 0202 if (initial_idmapping(fs_userns)) 0203 uid = __kuid_val(kuid); 0204 else 0205 uid = from_kuid(fs_userns, kuid); 0206 if (uid == (uid_t)-1) 0207 return INVALID_VFSUID; 0208 return VFSUIDT_INIT(make_kuid(mnt_userns, uid)); 0209 } 0210 0211 static inline kuid_t mapped_kuid_fs(struct user_namespace *mnt_userns, 0212 struct user_namespace *fs_userns, 0213 kuid_t kuid) 0214 { 0215 return AS_KUIDT(make_vfsuid(mnt_userns, fs_userns, kuid)); 0216 } 0217 0218 /** 0219 * make_vfsgid - map a filesystem kgid into a mnt_userns 0220 * @mnt_userns: the mount's idmapping 0221 * @fs_userns: the filesystem's idmapping 0222 * @kgid : kgid to be mapped 0223 * 0224 * Take a @kgid and remap it from @fs_userns into @mnt_userns. Use this 0225 * function when preparing a @kgid to be reported to userspace. 0226 * 0227 * If no_idmapping() determines that this is not an idmapped mount we can 0228 * simply return @kgid unchanged. 0229 * If initial_idmapping() tells us that the filesystem is not mounted with an 0230 * idmapping we know the value of @kgid won't change when calling 0231 * from_kgid() so we can simply retrieve the value via __kgid_val() 0232 * directly. 0233 * 0234 * Return: @kgid mapped according to @mnt_userns. 0235 * If @kgid has no mapping in either @mnt_userns or @fs_userns INVALID_GID is 0236 * returned. 0237 */ 0238 0239 static inline vfsgid_t make_vfsgid(struct user_namespace *mnt_userns, 0240 struct user_namespace *fs_userns, 0241 kgid_t kgid) 0242 { 0243 gid_t gid; 0244 0245 if (no_idmapping(mnt_userns, fs_userns)) 0246 return VFSGIDT_INIT(kgid); 0247 if (initial_idmapping(fs_userns)) 0248 gid = __kgid_val(kgid); 0249 else 0250 gid = from_kgid(fs_userns, kgid); 0251 if (gid == (gid_t)-1) 0252 return INVALID_VFSGID; 0253 return VFSGIDT_INIT(make_kgid(mnt_userns, gid)); 0254 } 0255 0256 static inline kgid_t mapped_kgid_fs(struct user_namespace *mnt_userns, 0257 struct user_namespace *fs_userns, 0258 kgid_t kgid) 0259 { 0260 return AS_KGIDT(make_vfsgid(mnt_userns, fs_userns, kgid)); 0261 } 0262 0263 /** 0264 * from_vfsuid - map a vfsuid into the filesystem idmapping 0265 * @mnt_userns: the mount's idmapping 0266 * @fs_userns: the filesystem's idmapping 0267 * @vfsuid : vfsuid to be mapped 0268 * 0269 * Map @vfsuid into the filesystem idmapping. This function has to be used in 0270 * order to e.g. write @vfsuid to inode->i_uid. 0271 * 0272 * Return: @vfsuid mapped into the filesystem idmapping 0273 */ 0274 static inline kuid_t from_vfsuid(struct user_namespace *mnt_userns, 0275 struct user_namespace *fs_userns, 0276 vfsuid_t vfsuid) 0277 { 0278 uid_t uid; 0279 0280 if (no_idmapping(mnt_userns, fs_userns)) 0281 return AS_KUIDT(vfsuid); 0282 uid = from_kuid(mnt_userns, AS_KUIDT(vfsuid)); 0283 if (uid == (uid_t)-1) 0284 return INVALID_UID; 0285 if (initial_idmapping(fs_userns)) 0286 return KUIDT_INIT(uid); 0287 return make_kuid(fs_userns, uid); 0288 } 0289 0290 /** 0291 * mapped_kuid_user - map a user kuid into a mnt_userns 0292 * @mnt_userns: the mount's idmapping 0293 * @fs_userns: the filesystem's idmapping 0294 * @kuid : kuid to be mapped 0295 * 0296 * Use the idmapping of @mnt_userns to remap a @kuid into @fs_userns. Use this 0297 * function when preparing a @kuid to be written to disk or inode. 0298 * 0299 * If no_idmapping() determines that this is not an idmapped mount we can 0300 * simply return @kuid unchanged. 0301 * If initial_idmapping() tells us that the filesystem is not mounted with an 0302 * idmapping we know the value of @kuid won't change when calling 0303 * make_kuid() so we can simply retrieve the value via KUIDT_INIT() 0304 * directly. 0305 * 0306 * Return: @kuid mapped according to @mnt_userns. 0307 * If @kuid has no mapping in either @mnt_userns or @fs_userns INVALID_UID is 0308 * returned. 0309 */ 0310 static inline kuid_t mapped_kuid_user(struct user_namespace *mnt_userns, 0311 struct user_namespace *fs_userns, 0312 kuid_t kuid) 0313 { 0314 return from_vfsuid(mnt_userns, fs_userns, VFSUIDT_INIT(kuid)); 0315 } 0316 0317 /** 0318 * vfsuid_has_fsmapping - check whether a vfsuid maps into the filesystem 0319 * @mnt_userns: the mount's idmapping 0320 * @fs_userns: the filesystem's idmapping 0321 * @vfsuid: vfsuid to be mapped 0322 * 0323 * Check whether @vfsuid has a mapping in the filesystem idmapping. Use this 0324 * function to check whether the filesystem idmapping has a mapping for 0325 * @vfsuid. 0326 * 0327 * Return: true if @vfsuid has a mapping in the filesystem, false if not. 0328 */ 0329 static inline bool vfsuid_has_fsmapping(struct user_namespace *mnt_userns, 0330 struct user_namespace *fs_userns, 0331 vfsuid_t vfsuid) 0332 { 0333 return uid_valid(from_vfsuid(mnt_userns, fs_userns, vfsuid)); 0334 } 0335 0336 /** 0337 * vfsuid_into_kuid - convert vfsuid into kuid 0338 * @vfsuid: the vfsuid to convert 0339 * 0340 * This can be used when a vfsuid is committed as a kuid. 0341 * 0342 * Return: a kuid with the value of @vfsuid 0343 */ 0344 static inline kuid_t vfsuid_into_kuid(vfsuid_t vfsuid) 0345 { 0346 return AS_KUIDT(vfsuid); 0347 } 0348 0349 /** 0350 * from_vfsgid - map a vfsgid into the filesystem idmapping 0351 * @mnt_userns: the mount's idmapping 0352 * @fs_userns: the filesystem's idmapping 0353 * @vfsgid : vfsgid to be mapped 0354 * 0355 * Map @vfsgid into the filesystem idmapping. This function has to be used in 0356 * order to e.g. write @vfsgid to inode->i_gid. 0357 * 0358 * Return: @vfsgid mapped into the filesystem idmapping 0359 */ 0360 static inline kgid_t from_vfsgid(struct user_namespace *mnt_userns, 0361 struct user_namespace *fs_userns, 0362 vfsgid_t vfsgid) 0363 { 0364 gid_t gid; 0365 0366 if (no_idmapping(mnt_userns, fs_userns)) 0367 return AS_KGIDT(vfsgid); 0368 gid = from_kgid(mnt_userns, AS_KGIDT(vfsgid)); 0369 if (gid == (gid_t)-1) 0370 return INVALID_GID; 0371 if (initial_idmapping(fs_userns)) 0372 return KGIDT_INIT(gid); 0373 return make_kgid(fs_userns, gid); 0374 } 0375 0376 /** 0377 * mapped_kgid_user - map a user kgid into a mnt_userns 0378 * @mnt_userns: the mount's idmapping 0379 * @fs_userns: the filesystem's idmapping 0380 * @kgid : kgid to be mapped 0381 * 0382 * Use the idmapping of @mnt_userns to remap a @kgid into @fs_userns. Use this 0383 * function when preparing a @kgid to be written to disk or inode. 0384 * 0385 * If no_idmapping() determines that this is not an idmapped mount we can 0386 * simply return @kgid unchanged. 0387 * If initial_idmapping() tells us that the filesystem is not mounted with an 0388 * idmapping we know the value of @kgid won't change when calling 0389 * make_kgid() so we can simply retrieve the value via KGIDT_INIT() 0390 * directly. 0391 * 0392 * Return: @kgid mapped according to @mnt_userns. 0393 * If @kgid has no mapping in either @mnt_userns or @fs_userns INVALID_GID is 0394 * returned. 0395 */ 0396 static inline kgid_t mapped_kgid_user(struct user_namespace *mnt_userns, 0397 struct user_namespace *fs_userns, 0398 kgid_t kgid) 0399 { 0400 return from_vfsgid(mnt_userns, fs_userns, VFSGIDT_INIT(kgid)); 0401 } 0402 0403 /** 0404 * vfsgid_has_fsmapping - check whether a vfsgid maps into the filesystem 0405 * @mnt_userns: the mount's idmapping 0406 * @fs_userns: the filesystem's idmapping 0407 * @vfsgid: vfsgid to be mapped 0408 * 0409 * Check whether @vfsgid has a mapping in the filesystem idmapping. Use this 0410 * function to check whether the filesystem idmapping has a mapping for 0411 * @vfsgid. 0412 * 0413 * Return: true if @vfsgid has a mapping in the filesystem, false if not. 0414 */ 0415 static inline bool vfsgid_has_fsmapping(struct user_namespace *mnt_userns, 0416 struct user_namespace *fs_userns, 0417 vfsgid_t vfsgid) 0418 { 0419 return gid_valid(from_vfsgid(mnt_userns, fs_userns, vfsgid)); 0420 } 0421 0422 /** 0423 * vfsgid_into_kgid - convert vfsgid into kgid 0424 * @vfsgid: the vfsgid to convert 0425 * 0426 * This can be used when a vfsgid is committed as a kgid. 0427 * 0428 * Return: a kgid with the value of @vfsgid 0429 */ 0430 static inline kgid_t vfsgid_into_kgid(vfsgid_t vfsgid) 0431 { 0432 return AS_KGIDT(vfsgid); 0433 } 0434 0435 /** 0436 * mapped_fsuid - return caller's fsuid mapped up into a mnt_userns 0437 * @mnt_userns: the mount's idmapping 0438 * @fs_userns: the filesystem's idmapping 0439 * 0440 * Use this helper to initialize a new vfs or filesystem object based on 0441 * the caller's fsuid. A common example is initializing the i_uid field of 0442 * a newly allocated inode triggered by a creation event such as mkdir or 0443 * O_CREAT. Other examples include the allocation of quotas for a specific 0444 * user. 0445 * 0446 * Return: the caller's current fsuid mapped up according to @mnt_userns. 0447 */ 0448 static inline kuid_t mapped_fsuid(struct user_namespace *mnt_userns, 0449 struct user_namespace *fs_userns) 0450 { 0451 return from_vfsuid(mnt_userns, fs_userns, 0452 VFSUIDT_INIT(current_fsuid())); 0453 } 0454 0455 /** 0456 * mapped_fsgid - return caller's fsgid mapped up into a mnt_userns 0457 * @mnt_userns: the mount's idmapping 0458 * @fs_userns: the filesystem's idmapping 0459 * 0460 * Use this helper to initialize a new vfs or filesystem object based on 0461 * the caller's fsgid. A common example is initializing the i_gid field of 0462 * a newly allocated inode triggered by a creation event such as mkdir or 0463 * O_CREAT. Other examples include the allocation of quotas for a specific 0464 * user. 0465 * 0466 * Return: the caller's current fsgid mapped up according to @mnt_userns. 0467 */ 0468 static inline kgid_t mapped_fsgid(struct user_namespace *mnt_userns, 0469 struct user_namespace *fs_userns) 0470 { 0471 return from_vfsgid(mnt_userns, fs_userns, 0472 VFSGIDT_INIT(current_fsgid())); 0473 } 0474 0475 #endif /* _LINUX_MNT_IDMAPPING_H */
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.1.0 LXR engine. The LXR team |
![]() ![]() |