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 * @kuid: the kuid to compare 74 * @vfsuid: the vfsuid to compare 75 * 76 * Check whether @kuid and @vfsuid have the same values. 77 * 78 * Return: true if @kuid and @vfsuid 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 * @kgid: the kgid to compare 89 * @vfsgid: the vfsgid to compare 90 * 91 * Check whether @kgid and @vfsgid have the same values. 92 * 93 * Return: true if @kgid and @vfsgid have the same value, false if not. 94 * Comparison between two invalid gids returns false. 95 */ 96 static inline bool vfsgid_eq_kgid(kgid_t kgid, vfsgid_t vfsgid) 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 * mapped_kuid_fs - 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 * mapped_kgid_fs - 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 * from_vfsgid - map a vfsgid into the filesystem idmapping 338 * @mnt_userns: the mount's idmapping 339 * @fs_userns: the filesystem's idmapping 340 * @vfsgid : vfsgid to be mapped 341 * 342 * Map @vfsgid into the filesystem idmapping. This function has to be used in 343 * order to e.g. write @vfsgid to inode->i_gid. 344 * 345 * Return: @vfsgid mapped into the filesystem idmapping 346 */ 347 static inline kgid_t from_vfsgid(struct user_namespace *mnt_userns, 348 struct user_namespace *fs_userns, 349 vfsgid_t vfsgid) 350 { 351 gid_t gid; 352 353 if (no_idmapping(mnt_userns, fs_userns)) 354 return AS_KGIDT(vfsgid); 355 gid = from_kgid(mnt_userns, AS_KGIDT(vfsgid)); 356 if (gid == (gid_t)-1) 357 return INVALID_GID; 358 if (initial_idmapping(fs_userns)) 359 return KGIDT_INIT(gid); 360 return make_kgid(fs_userns, gid); 361 } 362 363 /** 364 * mapped_kgid_user - map a user kgid into a mnt_userns 365 * @mnt_userns: the mount's idmapping 366 * @fs_userns: the filesystem's idmapping 367 * @kgid : kgid to be mapped 368 * 369 * Use the idmapping of @mnt_userns to remap a @kgid into @fs_userns. Use this 370 * function when preparing a @kgid to be written to disk or inode. 371 * 372 * If no_idmapping() determines that this is not an idmapped mount we can 373 * simply return @kgid unchanged. 374 * If initial_idmapping() tells us that the filesystem is not mounted with an 375 * idmapping we know the value of @kgid won't change when calling 376 * make_kgid() so we can simply retrieve the value via KGIDT_INIT() 377 * directly. 378 * 379 * Return: @kgid mapped according to @mnt_userns. 380 * If @kgid has no mapping in either @mnt_userns or @fs_userns INVALID_GID is 381 * returned. 382 */ 383 static inline kgid_t mapped_kgid_user(struct user_namespace *mnt_userns, 384 struct user_namespace *fs_userns, 385 kgid_t kgid) 386 { 387 return from_vfsgid(mnt_userns, fs_userns, VFSGIDT_INIT(kgid)); 388 } 389 390 /** 391 * vfsgid_has_fsmapping - check whether a vfsgid maps into the filesystem 392 * @mnt_userns: the mount's idmapping 393 * @fs_userns: the filesystem's idmapping 394 * @vfsgid: vfsgid to be mapped 395 * 396 * Check whether @vfsgid has a mapping in the filesystem idmapping. Use this 397 * function to check whether the filesystem idmapping has a mapping for 398 * @vfsgid. 399 * 400 * Return: true if @vfsgid has a mapping in the filesystem, false if not. 401 */ 402 static inline bool vfsgid_has_fsmapping(struct user_namespace *mnt_userns, 403 struct user_namespace *fs_userns, 404 vfsgid_t vfsgid) 405 { 406 return gid_valid(from_vfsgid(mnt_userns, fs_userns, vfsgid)); 407 } 408 409 /** 410 * mapped_fsuid - return caller's fsuid mapped up into a mnt_userns 411 * @mnt_userns: the mount's idmapping 412 * @fs_userns: the filesystem's idmapping 413 * 414 * Use this helper to initialize a new vfs or filesystem object based on 415 * the caller's fsuid. A common example is initializing the i_uid field of 416 * a newly allocated inode triggered by a creation event such as mkdir or 417 * O_CREAT. Other examples include the allocation of quotas for a specific 418 * user. 419 * 420 * Return: the caller's current fsuid mapped up according to @mnt_userns. 421 */ 422 static inline kuid_t mapped_fsuid(struct user_namespace *mnt_userns, 423 struct user_namespace *fs_userns) 424 { 425 return from_vfsuid(mnt_userns, fs_userns, 426 VFSUIDT_INIT(current_fsuid())); 427 } 428 429 /** 430 * mapped_fsgid - return caller's fsgid mapped up into a mnt_userns 431 * @mnt_userns: the mount's idmapping 432 * @fs_userns: the filesystem's idmapping 433 * 434 * Use this helper to initialize a new vfs or filesystem object based on 435 * the caller's fsgid. A common example is initializing the i_gid field of 436 * a newly allocated inode triggered by a creation event such as mkdir or 437 * O_CREAT. Other examples include the allocation of quotas for a specific 438 * user. 439 * 440 * Return: the caller's current fsgid mapped up according to @mnt_userns. 441 */ 442 static inline kgid_t mapped_fsgid(struct user_namespace *mnt_userns, 443 struct user_namespace *fs_userns) 444 { 445 return from_vfsgid(mnt_userns, fs_userns, 446 VFSGIDT_INIT(current_fsgid())); 447 } 448 449 #endif /* _LINUX_MNT_IDMAPPING_H */ 450