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 user_namespace; 9 /* 10 * Carries the initial idmapping of 0:0:4294967295 which is an identity 11 * mapping. This means that {g,u}id 0 is mapped to {g,u}id 0, {g,u}id 1 is 12 * mapped to {g,u}id 1, [...], {g,u}id 1000 to {g,u}id 1000, [...]. 13 */ 14 extern struct user_namespace init_user_ns; 15 16 typedef struct { 17 uid_t val; 18 } vfsuid_t; 19 20 typedef struct { 21 gid_t val; 22 } vfsgid_t; 23 24 static_assert(sizeof(vfsuid_t) == sizeof(kuid_t)); 25 static_assert(sizeof(vfsgid_t) == sizeof(kgid_t)); 26 static_assert(offsetof(vfsuid_t, val) == offsetof(kuid_t, val)); 27 static_assert(offsetof(vfsgid_t, val) == offsetof(kgid_t, val)); 28 29 #ifdef CONFIG_MULTIUSER 30 static inline uid_t __vfsuid_val(vfsuid_t uid) 31 { 32 return uid.val; 33 } 34 35 static inline gid_t __vfsgid_val(vfsgid_t gid) 36 { 37 return gid.val; 38 } 39 #else 40 static inline uid_t __vfsuid_val(vfsuid_t uid) 41 { 42 return 0; 43 } 44 45 static inline gid_t __vfsgid_val(vfsgid_t gid) 46 { 47 return 0; 48 } 49 #endif 50 51 static inline bool vfsuid_valid(vfsuid_t uid) 52 { 53 return __vfsuid_val(uid) != (uid_t)-1; 54 } 55 56 static inline bool vfsgid_valid(vfsgid_t gid) 57 { 58 return __vfsgid_val(gid) != (gid_t)-1; 59 } 60 61 static inline bool vfsuid_eq(vfsuid_t left, vfsuid_t right) 62 { 63 return vfsuid_valid(left) && __vfsuid_val(left) == __vfsuid_val(right); 64 } 65 66 static inline bool vfsgid_eq(vfsgid_t left, vfsgid_t right) 67 { 68 return vfsgid_valid(left) && __vfsgid_val(left) == __vfsgid_val(right); 69 } 70 71 /** 72 * vfsuid_eq_kuid - check whether kuid and vfsuid have the same value 73 * @vfsuid: the vfsuid to compare 74 * @kuid: the kuid to compare 75 * 76 * Check whether @vfsuid and @kuid have the same values. 77 * 78 * Return: true if @vfsuid and @kuid have the same value, false if not. 79 * Comparison between two invalid uids returns false. 80 */ 81 static inline bool vfsuid_eq_kuid(vfsuid_t vfsuid, kuid_t kuid) 82 { 83 return vfsuid_valid(vfsuid) && __vfsuid_val(vfsuid) == __kuid_val(kuid); 84 } 85 86 /** 87 * vfsgid_eq_kgid - check whether kgid and vfsgid have the same value 88 * @vfsgid: the vfsgid to compare 89 * @kgid: the kgid to compare 90 * 91 * Check whether @vfsgid and @kgid have the same values. 92 * 93 * Return: true if @vfsgid and @kgid have the same value, false if not. 94 * Comparison between two invalid gids returns false. 95 */ 96 static inline bool vfsgid_eq_kgid(vfsgid_t vfsgid, kgid_t kgid) 97 { 98 return vfsgid_valid(vfsgid) && __vfsgid_val(vfsgid) == __kgid_val(kgid); 99 } 100 101 /* 102 * vfs{g,u}ids are created from k{g,u}ids. 103 * We don't allow them to be created from regular {u,g}id. 104 */ 105 #define VFSUIDT_INIT(val) (vfsuid_t){ __kuid_val(val) } 106 #define VFSGIDT_INIT(val) (vfsgid_t){ __kgid_val(val) } 107 108 #define INVALID_VFSUID VFSUIDT_INIT(INVALID_UID) 109 #define INVALID_VFSGID VFSGIDT_INIT(INVALID_GID) 110 111 /* 112 * Allow a vfs{g,u}id to be used as a k{g,u}id where we want to compare 113 * whether the mapped value is identical to value of a k{g,u}id. 114 */ 115 #define AS_KUIDT(val) (kuid_t){ __vfsuid_val(val) } 116 #define AS_KGIDT(val) (kgid_t){ __vfsgid_val(val) } 117 118 #ifdef CONFIG_MULTIUSER 119 /** 120 * vfsgid_in_group_p() - check whether a vfsuid matches the caller's groups 121 * @vfsgid: the mnt gid to match 122 * 123 * This function can be used to determine whether @vfsuid matches any of the 124 * caller's groups. 125 * 126 * Return: 1 if vfsuid matches caller's groups, 0 if not. 127 */ 128 static inline int vfsgid_in_group_p(vfsgid_t vfsgid) 129 { 130 return in_group_p(AS_KGIDT(vfsgid)); 131 } 132 #else 133 static inline int vfsgid_in_group_p(vfsgid_t vfsgid) 134 { 135 return 1; 136 } 137 #endif 138 139 /** 140 * initial_idmapping - check whether this is the initial mapping 141 * @ns: idmapping to check 142 * 143 * Check whether this is the initial mapping, mapping 0 to 0, 1 to 1, 144 * [...], 1000 to 1000 [...]. 145 * 146 * Return: true if this is the initial mapping, false if not. 147 */ 148 static inline bool initial_idmapping(const struct user_namespace *ns) 149 { 150 return ns == &init_user_ns; 151 } 152 153 /** 154 * no_idmapping - check whether we can skip remapping a kuid/gid 155 * @mnt_userns: the mount's idmapping 156 * @fs_userns: the filesystem's idmapping 157 * 158 * This function can be used to check whether a remapping between two 159 * idmappings is required. 160 * An idmapped mount is a mount that has an idmapping attached to it that 161 * is different from the filsystem's idmapping and the initial idmapping. 162 * If the initial mapping is used or the idmapping of the mount and the 163 * filesystem are identical no remapping is required. 164 * 165 * Return: true if remapping can be skipped, false if not. 166 */ 167 static inline bool no_idmapping(const struct user_namespace *mnt_userns, 168 const struct user_namespace *fs_userns) 169 { 170 return initial_idmapping(mnt_userns) || mnt_userns == fs_userns; 171 } 172 173 /** 174 * make_vfsuid - map a filesystem kuid into a mnt_userns 175 * @mnt_userns: the mount's idmapping 176 * @fs_userns: the filesystem's idmapping 177 * @kuid : kuid to be mapped 178 * 179 * Take a @kuid and remap it from @fs_userns into @mnt_userns. Use this 180 * function when preparing a @kuid to be reported to userspace. 181 * 182 * If no_idmapping() determines that this is not an idmapped mount we can 183 * simply return @kuid unchanged. 184 * If initial_idmapping() tells us that the filesystem is not mounted with an 185 * idmapping we know the value of @kuid won't change when calling 186 * from_kuid() so we can simply retrieve the value via __kuid_val() 187 * directly. 188 * 189 * Return: @kuid mapped according to @mnt_userns. 190 * If @kuid has no mapping in either @mnt_userns or @fs_userns INVALID_UID is 191 * returned. 192 */ 193 194 static inline vfsuid_t make_vfsuid(struct user_namespace *mnt_userns, 195 struct user_namespace *fs_userns, 196 kuid_t kuid) 197 { 198 uid_t uid; 199 200 if (no_idmapping(mnt_userns, fs_userns)) 201 return VFSUIDT_INIT(kuid); 202 if (initial_idmapping(fs_userns)) 203 uid = __kuid_val(kuid); 204 else 205 uid = from_kuid(fs_userns, kuid); 206 if (uid == (uid_t)-1) 207 return INVALID_VFSUID; 208 return VFSUIDT_INIT(make_kuid(mnt_userns, uid)); 209 } 210 211 static inline kuid_t mapped_kuid_fs(struct user_namespace *mnt_userns, 212 struct user_namespace *fs_userns, 213 kuid_t kuid) 214 { 215 return AS_KUIDT(make_vfsuid(mnt_userns, fs_userns, kuid)); 216 } 217 218 /** 219 * make_vfsgid - map a filesystem kgid into a mnt_userns 220 * @mnt_userns: the mount's idmapping 221 * @fs_userns: the filesystem's idmapping 222 * @kgid : kgid to be mapped 223 * 224 * Take a @kgid and remap it from @fs_userns into @mnt_userns. Use this 225 * function when preparing a @kgid to be reported to userspace. 226 * 227 * If no_idmapping() determines that this is not an idmapped mount we can 228 * simply return @kgid unchanged. 229 * If initial_idmapping() tells us that the filesystem is not mounted with an 230 * idmapping we know the value of @kgid won't change when calling 231 * from_kgid() so we can simply retrieve the value via __kgid_val() 232 * directly. 233 * 234 * Return: @kgid mapped according to @mnt_userns. 235 * If @kgid has no mapping in either @mnt_userns or @fs_userns INVALID_GID is 236 * returned. 237 */ 238 239 static inline vfsgid_t make_vfsgid(struct user_namespace *mnt_userns, 240 struct user_namespace *fs_userns, 241 kgid_t kgid) 242 { 243 gid_t gid; 244 245 if (no_idmapping(mnt_userns, fs_userns)) 246 return VFSGIDT_INIT(kgid); 247 if (initial_idmapping(fs_userns)) 248 gid = __kgid_val(kgid); 249 else 250 gid = from_kgid(fs_userns, kgid); 251 if (gid == (gid_t)-1) 252 return INVALID_VFSGID; 253 return VFSGIDT_INIT(make_kgid(mnt_userns, gid)); 254 } 255 256 static inline kgid_t mapped_kgid_fs(struct user_namespace *mnt_userns, 257 struct user_namespace *fs_userns, 258 kgid_t kgid) 259 { 260 return AS_KGIDT(make_vfsgid(mnt_userns, fs_userns, kgid)); 261 } 262 263 /** 264 * from_vfsuid - map a vfsuid into the filesystem idmapping 265 * @mnt_userns: the mount's idmapping 266 * @fs_userns: the filesystem's idmapping 267 * @vfsuid : vfsuid to be mapped 268 * 269 * Map @vfsuid into the filesystem idmapping. This function has to be used in 270 * order to e.g. write @vfsuid to inode->i_uid. 271 * 272 * Return: @vfsuid mapped into the filesystem idmapping 273 */ 274 static inline kuid_t from_vfsuid(struct user_namespace *mnt_userns, 275 struct user_namespace *fs_userns, 276 vfsuid_t vfsuid) 277 { 278 uid_t uid; 279 280 if (no_idmapping(mnt_userns, fs_userns)) 281 return AS_KUIDT(vfsuid); 282 uid = from_kuid(mnt_userns, AS_KUIDT(vfsuid)); 283 if (uid == (uid_t)-1) 284 return INVALID_UID; 285 if (initial_idmapping(fs_userns)) 286 return KUIDT_INIT(uid); 287 return make_kuid(fs_userns, uid); 288 } 289 290 /** 291 * mapped_kuid_user - map a user kuid into a mnt_userns 292 * @mnt_userns: the mount's idmapping 293 * @fs_userns: the filesystem's idmapping 294 * @kuid : kuid to be mapped 295 * 296 * Use the idmapping of @mnt_userns to remap a @kuid into @fs_userns. Use this 297 * function when preparing a @kuid to be written to disk or inode. 298 * 299 * If no_idmapping() determines that this is not an idmapped mount we can 300 * simply return @kuid unchanged. 301 * If initial_idmapping() tells us that the filesystem is not mounted with an 302 * idmapping we know the value of @kuid won't change when calling 303 * make_kuid() so we can simply retrieve the value via KUIDT_INIT() 304 * directly. 305 * 306 * Return: @kuid mapped according to @mnt_userns. 307 * If @kuid has no mapping in either @mnt_userns or @fs_userns INVALID_UID is 308 * returned. 309 */ 310 static inline kuid_t mapped_kuid_user(struct user_namespace *mnt_userns, 311 struct user_namespace *fs_userns, 312 kuid_t kuid) 313 { 314 return from_vfsuid(mnt_userns, fs_userns, VFSUIDT_INIT(kuid)); 315 } 316 317 /** 318 * vfsuid_has_fsmapping - check whether a vfsuid maps into the filesystem 319 * @mnt_userns: the mount's idmapping 320 * @fs_userns: the filesystem's idmapping 321 * @vfsuid: vfsuid to be mapped 322 * 323 * Check whether @vfsuid has a mapping in the filesystem idmapping. Use this 324 * function to check whether the filesystem idmapping has a mapping for 325 * @vfsuid. 326 * 327 * Return: true if @vfsuid has a mapping in the filesystem, false if not. 328 */ 329 static inline bool vfsuid_has_fsmapping(struct user_namespace *mnt_userns, 330 struct user_namespace *fs_userns, 331 vfsuid_t vfsuid) 332 { 333 return uid_valid(from_vfsuid(mnt_userns, fs_userns, vfsuid)); 334 } 335 336 /** 337 * vfsuid_into_kuid - convert vfsuid into kuid 338 * @vfsuid: the vfsuid to convert 339 * 340 * This can be used when a vfsuid is committed as a kuid. 341 * 342 * Return: a kuid with the value of @vfsuid 343 */ 344 static inline kuid_t vfsuid_into_kuid(vfsuid_t vfsuid) 345 { 346 return AS_KUIDT(vfsuid); 347 } 348 349 /** 350 * from_vfsgid - map a vfsgid into the filesystem idmapping 351 * @mnt_userns: the mount's idmapping 352 * @fs_userns: the filesystem's idmapping 353 * @vfsgid : vfsgid to be mapped 354 * 355 * Map @vfsgid into the filesystem idmapping. This function has to be used in 356 * order to e.g. write @vfsgid to inode->i_gid. 357 * 358 * Return: @vfsgid mapped into the filesystem idmapping 359 */ 360 static inline kgid_t from_vfsgid(struct user_namespace *mnt_userns, 361 struct user_namespace *fs_userns, 362 vfsgid_t vfsgid) 363 { 364 gid_t gid; 365 366 if (no_idmapping(mnt_userns, fs_userns)) 367 return AS_KGIDT(vfsgid); 368 gid = from_kgid(mnt_userns, AS_KGIDT(vfsgid)); 369 if (gid == (gid_t)-1) 370 return INVALID_GID; 371 if (initial_idmapping(fs_userns)) 372 return KGIDT_INIT(gid); 373 return make_kgid(fs_userns, gid); 374 } 375 376 /** 377 * mapped_kgid_user - map a user kgid into a mnt_userns 378 * @mnt_userns: the mount's idmapping 379 * @fs_userns: the filesystem's idmapping 380 * @kgid : kgid to be mapped 381 * 382 * Use the idmapping of @mnt_userns to remap a @kgid into @fs_userns. Use this 383 * function when preparing a @kgid to be written to disk or inode. 384 * 385 * If no_idmapping() determines that this is not an idmapped mount we can 386 * simply return @kgid unchanged. 387 * If initial_idmapping() tells us that the filesystem is not mounted with an 388 * idmapping we know the value of @kgid won't change when calling 389 * make_kgid() so we can simply retrieve the value via KGIDT_INIT() 390 * directly. 391 * 392 * Return: @kgid mapped according to @mnt_userns. 393 * If @kgid has no mapping in either @mnt_userns or @fs_userns INVALID_GID is 394 * returned. 395 */ 396 static inline kgid_t mapped_kgid_user(struct user_namespace *mnt_userns, 397 struct user_namespace *fs_userns, 398 kgid_t kgid) 399 { 400 return from_vfsgid(mnt_userns, fs_userns, VFSGIDT_INIT(kgid)); 401 } 402 403 /** 404 * vfsgid_has_fsmapping - check whether a vfsgid maps into the filesystem 405 * @mnt_userns: the mount's idmapping 406 * @fs_userns: the filesystem's idmapping 407 * @vfsgid: vfsgid to be mapped 408 * 409 * Check whether @vfsgid has a mapping in the filesystem idmapping. Use this 410 * function to check whether the filesystem idmapping has a mapping for 411 * @vfsgid. 412 * 413 * Return: true if @vfsgid has a mapping in the filesystem, false if not. 414 */ 415 static inline bool vfsgid_has_fsmapping(struct user_namespace *mnt_userns, 416 struct user_namespace *fs_userns, 417 vfsgid_t vfsgid) 418 { 419 return gid_valid(from_vfsgid(mnt_userns, fs_userns, vfsgid)); 420 } 421 422 /** 423 * vfsgid_into_kgid - convert vfsgid into kgid 424 * @vfsgid: the vfsgid to convert 425 * 426 * This can be used when a vfsgid is committed as a kgid. 427 * 428 * Return: a kgid with the value of @vfsgid 429 */ 430 static inline kgid_t vfsgid_into_kgid(vfsgid_t vfsgid) 431 { 432 return AS_KGIDT(vfsgid); 433 } 434 435 /** 436 * mapped_fsuid - return caller's fsuid mapped up into a mnt_userns 437 * @mnt_userns: the mount's idmapping 438 * @fs_userns: the filesystem's idmapping 439 * 440 * Use this helper to initialize a new vfs or filesystem object based on 441 * the caller's fsuid. A common example is initializing the i_uid field of 442 * a newly allocated inode triggered by a creation event such as mkdir or 443 * O_CREAT. Other examples include the allocation of quotas for a specific 444 * user. 445 * 446 * Return: the caller's current fsuid mapped up according to @mnt_userns. 447 */ 448 static inline kuid_t mapped_fsuid(struct user_namespace *mnt_userns, 449 struct user_namespace *fs_userns) 450 { 451 return from_vfsuid(mnt_userns, fs_userns, 452 VFSUIDT_INIT(current_fsuid())); 453 } 454 455 /** 456 * mapped_fsgid - return caller's fsgid mapped up into a mnt_userns 457 * @mnt_userns: the mount's idmapping 458 * @fs_userns: the filesystem's idmapping 459 * 460 * Use this helper to initialize a new vfs or filesystem object based on 461 * the caller's fsgid. A common example is initializing the i_gid field of 462 * a newly allocated inode triggered by a creation event such as mkdir or 463 * O_CREAT. Other examples include the allocation of quotas for a specific 464 * user. 465 * 466 * Return: the caller's current fsgid mapped up according to @mnt_userns. 467 */ 468 static inline kgid_t mapped_fsgid(struct user_namespace *mnt_userns, 469 struct user_namespace *fs_userns) 470 { 471 return from_vfsgid(mnt_userns, fs_userns, 472 VFSGIDT_INIT(current_fsgid())); 473 } 474 475 #endif /* _LINUX_MNT_IDMAPPING_H */ 476