mnt_idmapping.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Copyright (c) 2022 Christian Brauner <brauner@kernel.org> */
  3. #include <linux/cred.h>
  4. #include <linux/fs.h>
  5. #include <linux/mnt_idmapping.h>
  6. #include <linux/slab.h>
  7. #include <linux/user_namespace.h>
  8. #include <linux/seq_file.h>
  9. #include "internal.h"
  10. /*
  11. * Outside of this file vfs{g,u}id_t are always created from k{g,u}id_t,
  12. * never from raw values. These are just internal helpers.
  13. */
  14. #define VFSUIDT_INIT_RAW(val) (vfsuid_t){ val }
  15. #define VFSGIDT_INIT_RAW(val) (vfsgid_t){ val }
  16. struct mnt_idmap {
  17. struct uid_gid_map uid_map;
  18. struct uid_gid_map gid_map;
  19. refcount_t count;
  20. };
  21. /*
  22. * Carries the initial idmapping of 0:0:4294967295 which is an identity
  23. * mapping. This means that {g,u}id 0 is mapped to {g,u}id 0, {g,u}id 1 is
  24. * mapped to {g,u}id 1, [...], {g,u}id 1000 to {g,u}id 1000, [...].
  25. */
  26. struct mnt_idmap nop_mnt_idmap = {
  27. .count = REFCOUNT_INIT(1),
  28. };
  29. EXPORT_SYMBOL_GPL(nop_mnt_idmap);
  30. /*
  31. * Carries the invalid idmapping of a full 0-4294967295 {g,u}id range.
  32. * This means that all {g,u}ids are mapped to INVALID_VFS{G,U}ID.
  33. */
  34. struct mnt_idmap invalid_mnt_idmap = {
  35. .count = REFCOUNT_INIT(1),
  36. };
  37. EXPORT_SYMBOL_GPL(invalid_mnt_idmap);
  38. /**
  39. * initial_idmapping - check whether this is the initial mapping
  40. * @ns: idmapping to check
  41. *
  42. * Check whether this is the initial mapping, mapping 0 to 0, 1 to 1,
  43. * [...], 1000 to 1000 [...].
  44. *
  45. * Return: true if this is the initial mapping, false if not.
  46. */
  47. static inline bool initial_idmapping(const struct user_namespace *ns)
  48. {
  49. return ns == &init_user_ns;
  50. }
  51. /**
  52. * make_vfsuid - map a filesystem kuid according to an idmapping
  53. * @idmap: the mount's idmapping
  54. * @fs_userns: the filesystem's idmapping
  55. * @kuid : kuid to be mapped
  56. *
  57. * Take a @kuid and remap it from @fs_userns into @idmap. Use this
  58. * function when preparing a @kuid to be reported to userspace.
  59. *
  60. * If initial_idmapping() determines that this is not an idmapped mount
  61. * we can simply return @kuid unchanged.
  62. * If initial_idmapping() tells us that the filesystem is not mounted with an
  63. * idmapping we know the value of @kuid won't change when calling
  64. * from_kuid() so we can simply retrieve the value via __kuid_val()
  65. * directly.
  66. *
  67. * Return: @kuid mapped according to @idmap.
  68. * If @kuid has no mapping in either @idmap or @fs_userns INVALID_UID is
  69. * returned.
  70. */
  71. vfsuid_t make_vfsuid(struct mnt_idmap *idmap,
  72. struct user_namespace *fs_userns,
  73. kuid_t kuid)
  74. {
  75. uid_t uid;
  76. if (idmap == &nop_mnt_idmap)
  77. return VFSUIDT_INIT(kuid);
  78. if (idmap == &invalid_mnt_idmap)
  79. return INVALID_VFSUID;
  80. if (initial_idmapping(fs_userns))
  81. uid = __kuid_val(kuid);
  82. else
  83. uid = from_kuid(fs_userns, kuid);
  84. if (uid == (uid_t)-1)
  85. return INVALID_VFSUID;
  86. return VFSUIDT_INIT_RAW(map_id_down(&idmap->uid_map, uid));
  87. }
  88. EXPORT_SYMBOL_GPL(make_vfsuid);
  89. /**
  90. * make_vfsgid - map a filesystem kgid according to an idmapping
  91. * @idmap: the mount's idmapping
  92. * @fs_userns: the filesystem's idmapping
  93. * @kgid : kgid to be mapped
  94. *
  95. * Take a @kgid and remap it from @fs_userns into @idmap. Use this
  96. * function when preparing a @kgid to be reported to userspace.
  97. *
  98. * If initial_idmapping() determines that this is not an idmapped mount
  99. * we can simply return @kgid unchanged.
  100. * If initial_idmapping() tells us that the filesystem is not mounted with an
  101. * idmapping we know the value of @kgid won't change when calling
  102. * from_kgid() so we can simply retrieve the value via __kgid_val()
  103. * directly.
  104. *
  105. * Return: @kgid mapped according to @idmap.
  106. * If @kgid has no mapping in either @idmap or @fs_userns INVALID_GID is
  107. * returned.
  108. */
  109. vfsgid_t make_vfsgid(struct mnt_idmap *idmap,
  110. struct user_namespace *fs_userns, kgid_t kgid)
  111. {
  112. gid_t gid;
  113. if (idmap == &nop_mnt_idmap)
  114. return VFSGIDT_INIT(kgid);
  115. if (idmap == &invalid_mnt_idmap)
  116. return INVALID_VFSGID;
  117. if (initial_idmapping(fs_userns))
  118. gid = __kgid_val(kgid);
  119. else
  120. gid = from_kgid(fs_userns, kgid);
  121. if (gid == (gid_t)-1)
  122. return INVALID_VFSGID;
  123. return VFSGIDT_INIT_RAW(map_id_down(&idmap->gid_map, gid));
  124. }
  125. EXPORT_SYMBOL_GPL(make_vfsgid);
  126. /**
  127. * from_vfsuid - map a vfsuid into the filesystem idmapping
  128. * @idmap: the mount's idmapping
  129. * @fs_userns: the filesystem's idmapping
  130. * @vfsuid : vfsuid to be mapped
  131. *
  132. * Map @vfsuid into the filesystem idmapping. This function has to be used in
  133. * order to e.g. write @vfsuid to inode->i_uid.
  134. *
  135. * Return: @vfsuid mapped into the filesystem idmapping
  136. */
  137. kuid_t from_vfsuid(struct mnt_idmap *idmap,
  138. struct user_namespace *fs_userns, vfsuid_t vfsuid)
  139. {
  140. uid_t uid;
  141. if (idmap == &nop_mnt_idmap)
  142. return AS_KUIDT(vfsuid);
  143. if (idmap == &invalid_mnt_idmap)
  144. return INVALID_UID;
  145. uid = map_id_up(&idmap->uid_map, __vfsuid_val(vfsuid));
  146. if (uid == (uid_t)-1)
  147. return INVALID_UID;
  148. if (initial_idmapping(fs_userns))
  149. return KUIDT_INIT(uid);
  150. return make_kuid(fs_userns, uid);
  151. }
  152. EXPORT_SYMBOL_GPL(from_vfsuid);
  153. /**
  154. * from_vfsgid - map a vfsgid into the filesystem idmapping
  155. * @idmap: the mount's idmapping
  156. * @fs_userns: the filesystem's idmapping
  157. * @vfsgid : vfsgid to be mapped
  158. *
  159. * Map @vfsgid into the filesystem idmapping. This function has to be used in
  160. * order to e.g. write @vfsgid to inode->i_gid.
  161. *
  162. * Return: @vfsgid mapped into the filesystem idmapping
  163. */
  164. kgid_t from_vfsgid(struct mnt_idmap *idmap,
  165. struct user_namespace *fs_userns, vfsgid_t vfsgid)
  166. {
  167. gid_t gid;
  168. if (idmap == &nop_mnt_idmap)
  169. return AS_KGIDT(vfsgid);
  170. if (idmap == &invalid_mnt_idmap)
  171. return INVALID_GID;
  172. gid = map_id_up(&idmap->gid_map, __vfsgid_val(vfsgid));
  173. if (gid == (gid_t)-1)
  174. return INVALID_GID;
  175. if (initial_idmapping(fs_userns))
  176. return KGIDT_INIT(gid);
  177. return make_kgid(fs_userns, gid);
  178. }
  179. EXPORT_SYMBOL_GPL(from_vfsgid);
  180. #ifdef CONFIG_MULTIUSER
  181. /**
  182. * vfsgid_in_group_p() - check whether a vfsuid matches the caller's groups
  183. * @vfsgid: the mnt gid to match
  184. *
  185. * This function can be used to determine whether @vfsuid matches any of the
  186. * caller's groups.
  187. *
  188. * Return: 1 if vfsuid matches caller's groups, 0 if not.
  189. */
  190. int vfsgid_in_group_p(vfsgid_t vfsgid)
  191. {
  192. return in_group_p(AS_KGIDT(vfsgid));
  193. }
  194. #else
  195. int vfsgid_in_group_p(vfsgid_t vfsgid)
  196. {
  197. return 1;
  198. }
  199. #endif
  200. EXPORT_SYMBOL_GPL(vfsgid_in_group_p);
  201. static int copy_mnt_idmap(struct uid_gid_map *map_from,
  202. struct uid_gid_map *map_to)
  203. {
  204. struct uid_gid_extent *forward, *reverse;
  205. u32 nr_extents = READ_ONCE(map_from->nr_extents);
  206. /* Pairs with smp_wmb() when writing the idmapping. */
  207. smp_rmb();
  208. /*
  209. * Don't blindly copy @map_to into @map_from if nr_extents is
  210. * smaller or equal to UID_GID_MAP_MAX_BASE_EXTENTS. Since we
  211. * read @nr_extents someone could have written an idmapping and
  212. * then we might end up with inconsistent data. So just don't do
  213. * anything at all.
  214. */
  215. if (nr_extents == 0)
  216. return -EINVAL;
  217. /*
  218. * Here we know that nr_extents is greater than zero which means
  219. * a map has been written. Since idmappings can't be changed
  220. * once they have been written we know that we can safely copy
  221. * from @map_to into @map_from.
  222. */
  223. if (nr_extents <= UID_GID_MAP_MAX_BASE_EXTENTS) {
  224. *map_to = *map_from;
  225. return 0;
  226. }
  227. forward = kmemdup_array(map_from->forward, nr_extents,
  228. sizeof(struct uid_gid_extent),
  229. GFP_KERNEL_ACCOUNT);
  230. if (!forward)
  231. return -ENOMEM;
  232. reverse = kmemdup_array(map_from->reverse, nr_extents,
  233. sizeof(struct uid_gid_extent),
  234. GFP_KERNEL_ACCOUNT);
  235. if (!reverse) {
  236. kfree(forward);
  237. return -ENOMEM;
  238. }
  239. /*
  240. * The idmapping isn't exposed anywhere so we don't need to care
  241. * about ordering between extent pointers and @nr_extents
  242. * initialization.
  243. */
  244. map_to->forward = forward;
  245. map_to->reverse = reverse;
  246. map_to->nr_extents = nr_extents;
  247. return 0;
  248. }
  249. static void free_mnt_idmap(struct mnt_idmap *idmap)
  250. {
  251. if (idmap->uid_map.nr_extents > UID_GID_MAP_MAX_BASE_EXTENTS) {
  252. kfree(idmap->uid_map.forward);
  253. kfree(idmap->uid_map.reverse);
  254. }
  255. if (idmap->gid_map.nr_extents > UID_GID_MAP_MAX_BASE_EXTENTS) {
  256. kfree(idmap->gid_map.forward);
  257. kfree(idmap->gid_map.reverse);
  258. }
  259. kfree(idmap);
  260. }
  261. struct mnt_idmap *alloc_mnt_idmap(struct user_namespace *mnt_userns)
  262. {
  263. struct mnt_idmap *idmap;
  264. int ret;
  265. idmap = kzalloc_obj(struct mnt_idmap, GFP_KERNEL_ACCOUNT);
  266. if (!idmap)
  267. return ERR_PTR(-ENOMEM);
  268. refcount_set(&idmap->count, 1);
  269. ret = copy_mnt_idmap(&mnt_userns->uid_map, &idmap->uid_map);
  270. if (!ret)
  271. ret = copy_mnt_idmap(&mnt_userns->gid_map, &idmap->gid_map);
  272. if (ret) {
  273. free_mnt_idmap(idmap);
  274. idmap = ERR_PTR(ret);
  275. }
  276. return idmap;
  277. }
  278. /**
  279. * mnt_idmap_get - get a reference to an idmapping
  280. * @idmap: the idmap to bump the reference on
  281. *
  282. * If @idmap is not the @nop_mnt_idmap bump the reference count.
  283. *
  284. * Return: @idmap with reference count bumped if @not_mnt_idmap isn't passed.
  285. */
  286. struct mnt_idmap *mnt_idmap_get(struct mnt_idmap *idmap)
  287. {
  288. if (idmap != &nop_mnt_idmap && idmap != &invalid_mnt_idmap)
  289. refcount_inc(&idmap->count);
  290. return idmap;
  291. }
  292. EXPORT_SYMBOL_GPL(mnt_idmap_get);
  293. /**
  294. * mnt_idmap_put - put a reference to an idmapping
  295. * @idmap: the idmap to put the reference on
  296. *
  297. * If this is a non-initial idmapping, put the reference count when a mount is
  298. * released and free it if we're the last user.
  299. */
  300. void mnt_idmap_put(struct mnt_idmap *idmap)
  301. {
  302. if (idmap != &nop_mnt_idmap && idmap != &invalid_mnt_idmap &&
  303. refcount_dec_and_test(&idmap->count))
  304. free_mnt_idmap(idmap);
  305. }
  306. EXPORT_SYMBOL_GPL(mnt_idmap_put);
  307. int statmount_mnt_idmap(struct mnt_idmap *idmap, struct seq_file *seq, bool uid_map)
  308. {
  309. struct uid_gid_map *map, *map_up;
  310. u32 idx, nr_mappings;
  311. if (!is_valid_mnt_idmap(idmap))
  312. return 0;
  313. /*
  314. * Idmappings are shown relative to the caller's idmapping.
  315. * This is both the most intuitive and most useful solution.
  316. */
  317. if (uid_map) {
  318. map = &idmap->uid_map;
  319. map_up = &current_user_ns()->uid_map;
  320. } else {
  321. map = &idmap->gid_map;
  322. map_up = &current_user_ns()->gid_map;
  323. }
  324. for (idx = 0, nr_mappings = 0; idx < map->nr_extents; idx++) {
  325. uid_t lower;
  326. struct uid_gid_extent *extent;
  327. if (map->nr_extents <= UID_GID_MAP_MAX_BASE_EXTENTS)
  328. extent = &map->extent[idx];
  329. else
  330. extent = &map->forward[idx];
  331. /*
  332. * Verify that the whole range of the mapping can be
  333. * resolved in the caller's idmapping. If it cannot be
  334. * resolved skip the mapping.
  335. */
  336. lower = map_id_range_up(map_up, extent->lower_first, extent->count);
  337. if (lower == (uid_t) -1)
  338. continue;
  339. seq_printf(seq, "%u %u %u", extent->first, lower, extent->count);
  340. seq->count++; /* mappings are separated by \0 */
  341. if (seq_has_overflowed(seq))
  342. return -EAGAIN;
  343. nr_mappings++;
  344. }
  345. return nr_mappings;
  346. }