History

Merge tag 'vfs-6.15-rc1.mount' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull vfs mount updates from Christian Brauner: - Mount notifications The day has come where we finally provide a new api to listen for mount topology changes outside of /proc/<pid>/mountinfo. A mount namespace file descriptor can be supplied and registered with fanotify to listen for mount topology changes. Currently notifications for mount, umount and moving mounts are generated. The generated notification record contains the unique mount id of the mount. The listmount() and statmount() api can be used to query detailed information about the mount using the received unique mount id. This allows userspace to figure out exactly how the mount topology changed without having to generating diffs of /proc/<pid>/mountinfo in userspace. - Support O_PATH file descriptors with FSCONFIG_SET_FD in the new mount api - Support detached mounts in overlayfs Since last cycle we support specifying overlayfs layers via file descriptors. However, we don't allow detached mounts which means userspace cannot user file descriptors received via open_tree(OPEN_TREE_CLONE) and fsmount() directly. They have to attach them to a mount namespace via move_mount() first. This is cumbersome and means they have to undo mounts via umount(). Allow them to directly use detached mounts. - Allow to retrieve idmappings with statmount Currently it isn't possible to figure out what idmapping has been attached to an idmapped mount. Add an extension to statmount() which allows to read the idmapping from the mount. - Allow creating idmapped mounts from mounts that are already idmapped So far it isn't possible to allow the creation of idmapped mounts from already idmapped mounts as this has significant lifetime implications. Make the creation of idmapped mounts atomic by allow to pass struct mount_attr together with the open_tree_attr() system call allowing to solve these issues without complicating VFS lookup in any way. The system call has in general the benefit that creating a detached mount and applying mount attributes to it becomes an atomic operation for userspace. - Add a way to query statmount() for supported options Allow userspace to query which mount information can be retrieved through statmount(). - Allow superblock owners to force unmount * tag 'vfs-6.15-rc1.mount' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: (21 commits) umount: Allow superblock owners to force umount selftests: add tests for mount notification selinux: add FILE__WATCH_MOUNTNS samples/vfs: fix printf format string for size_t fs: allow changing idmappings fs: add kflags member to struct mount_kattr fs: add open_tree_attr() fs: add copy_mount_setattr() helper fs: add vfs_open_tree() helper statmount: add a new supported_mask field samples/vfs: add STATMOUNT_MNT_{G,U}IDMAP selftests: add tests for using detached mount with overlayfs samples/vfs: check whether flag was raised statmount: allow to retrieve idmappings uidgid: add map_id_range_up() fs: allow detached mounts in clone_private_mount() selftests/overlayfs: test specifying layers as O_PATH file descriptors fs: support O_PATH fds with FSCONFIG_SET_FD vfs: add notifications for mount attach and detach fanotify: notify on mount attach and detach ...

Linus Torvalds committed 1 year ago

Commit fd101da2 parents a79a09a e1ff7aa52 files · +1567 −175Browse files

Unified · Split

52 files
  1. arch/alpha/kernel/syscalls/syscall.tbl +1 −0
  2. arch/arm/tools/syscall.tbl +1 −0
  3. arch/arm64/tools/syscall_32.tbl +1 −0
  4. arch/m68k/kernel/syscalls/syscall.tbl +1 −0
  5. arch/microblaze/kernel/syscalls/syscall.tbl +1 −0
  6. arch/mips/kernel/syscalls/syscall_n32.tbl +1 −0
  7. arch/mips/kernel/syscalls/syscall_n64.tbl +1 −0
  8. arch/mips/kernel/syscalls/syscall_o32.tbl +1 −0
  9. arch/parisc/kernel/syscalls/syscall.tbl +1 −0
  10. arch/powerpc/kernel/syscalls/syscall.tbl +1 −0
  11. arch/s390/kernel/syscalls/syscall.tbl +1 −0
  12. arch/sh/kernel/syscalls/syscall.tbl +1 −0
  13. arch/sparc/kernel/syscalls/syscall.tbl +1 −0
  14. arch/x86/entry/syscalls/syscall_32.tbl +1 −0
  15. arch/x86/entry/syscalls/syscall_64.tbl +1 −0
  16. arch/xtensa/kernel/syscalls/syscall.tbl +1 −0
  17. fs/autofs/autofs_i.h +2 −0
  18. fs/fsopen.c +1 −1
  19. fs/internal.h +1 −0
  20. fs/mnt_idmapping.c +51 −0
  21. fs/mount.h +26 −0
  22. fs/namespace.c +363 −122
  23. fs/notify/fanotify/fanotify.c +35 −3
  24. fs/notify/fanotify/fanotify.h +18 −0
  25. fs/notify/fanotify/fanotify_user.c +75 −14
  26. fs/notify/fdinfo.c +5 −0
  27. fs/notify/fsnotify.c +40 −7
  28. fs/notify/fsnotify.h +11 −0
  29. fs/notify/mark.c +11 −3
  30. fs/pnode.c +3 −1
  31. include/linux/fanotify.h +8 −4
  32. include/linux/fsnotify.h +20 −0
  33. include/linux/fsnotify_backend.h +42 −0
  34. include/linux/mnt_idmapping.h +5 −0
  35. include/linux/syscalls.h +4 −0
  36. include/linux/uidgid.h +6 −0
  37. include/uapi/asm-generic/unistd.h +3 −1
  38. include/uapi/linux/fanotify.h +10 −0
  39. include/uapi/linux/mount.h +9 −1
  40. kernel/user_namespace.c +17 −9
  41. samples/vfs/samples-vfs.h +13 −1
  42. samples/vfs/test-list-all-mounts.c +29 −6
  43. scripts/syscall.tbl +1 −0
  44. security/selinux/hooks.c +3 −0
  45. security/selinux/include/classmap.h +1 −1
  46. tools/testing/selftests/Makefile +1 −0
  47. tools/testing/selftests/filesystems/mount-notify/.gitignore +2 −0
  48. tools/testing/selftests/filesystems/mount-notify/Makefile +6 −0
  49. tools/testing/selftests/filesystems/mount-notify/mount-notify_test.c +516 −0
  50. tools/testing/selftests/filesystems/overlayfs/set_layers_via_fds.c +195 −0
  51. tools/testing/selftests/filesystems/overlayfs/wrappers.h +17 −0
  52. tools/testing/selftests/filesystems/statmount/statmount.h +1 −1
arch/alpha/kernel/syscalls/syscall.tbl+1−0
@@ -506,3 +506,4 @@ · 505 unmodified lines
506506 574 common getxattrat sys_getxattrat
507507 575 common listxattrat sys_listxattrat
508508 576 common removexattrat sys_removexattrat
509+577 common open_tree_attr sys_open_tree_attr
arch/arm/tools/syscall.tbl+1−0
@@ -481,3 +481,4 @@ · 480 unmodified lines
481481 464 common getxattrat sys_getxattrat
482482 465 common listxattrat sys_listxattrat
483483 466 common removexattrat sys_removexattrat
484+467 common open_tree_attr sys_open_tree_attr
arch/arm64/tools/syscall_32.tbl+1−0
@@ -478,3 +478,4 @@ · 477 unmodified lines
478478 464 common getxattrat sys_getxattrat
479479 465 common listxattrat sys_listxattrat
480480 466 common removexattrat sys_removexattrat
481+467 common open_tree_attr sys_open_tree_attr
arch/m68k/kernel/syscalls/syscall.tbl+1−0
@@ -466,3 +466,4 @@ · 465 unmodified lines
466466 464 common getxattrat sys_getxattrat
467467 465 common listxattrat sys_listxattrat
468468 466 common removexattrat sys_removexattrat
469+467 common open_tree_attr sys_open_tree_attr
arch/microblaze/kernel/syscalls/syscall.tbl+1−0
@@ -472,3 +472,4 @@ · 471 unmodified lines
472472 464 common getxattrat sys_getxattrat
473473 465 common listxattrat sys_listxattrat
474474 466 common removexattrat sys_removexattrat
475+467 common open_tree_attr sys_open_tree_attr
arch/mips/kernel/syscalls/syscall_n32.tbl+1−0
@@ -405,3 +405,4 @@ · 404 unmodified lines
405405 464 n32 getxattrat sys_getxattrat
406406 465 n32 listxattrat sys_listxattrat
407407 466 n32 removexattrat sys_removexattrat
408+467 n32 open_tree_attr sys_open_tree_attr
arch/mips/kernel/syscalls/syscall_n64.tbl+1−0
@@ -381,3 +381,4 @@ · 380 unmodified lines
381381 464 n64 getxattrat sys_getxattrat
382382 465 n64 listxattrat sys_listxattrat
383383 466 n64 removexattrat sys_removexattrat
384+467 n64 open_tree_attr sys_open_tree_attr
arch/mips/kernel/syscalls/syscall_o32.tbl+1−0
@@ -454,3 +454,4 @@ · 453 unmodified lines
454454 464 o32 getxattrat sys_getxattrat
455455 465 o32 listxattrat sys_listxattrat
456456 466 o32 removexattrat sys_removexattrat
457+467 o32 open_tree_attr sys_open_tree_attr
arch/parisc/kernel/syscalls/syscall.tbl+1−0
@@ -465,3 +465,4 @@ · 464 unmodified lines
465465 464 common getxattrat sys_getxattrat
466466 465 common listxattrat sys_listxattrat
467467 466 common removexattrat sys_removexattrat
468+467 common open_tree_attr sys_open_tree_attr
arch/powerpc/kernel/syscalls/syscall.tbl+1−0
@@ -557,3 +557,4 @@ · 556 unmodified lines
557557 464 common getxattrat sys_getxattrat
558558 465 common listxattrat sys_listxattrat
559559 466 common removexattrat sys_removexattrat
560+467 common open_tree_attr sys_open_tree_attr
arch/s390/kernel/syscalls/syscall.tbl+1−0
@@ -469,3 +469,4 @@ · 468 unmodified lines
469469 464 common getxattrat sys_getxattrat sys_getxattrat
470470 465 common listxattrat sys_listxattrat sys_listxattrat
471471 466 common removexattrat sys_removexattrat sys_removexattrat
472+467 common open_tree_attr sys_open_tree_attr sys_open_tree_attr
arch/sh/kernel/syscalls/syscall.tbl+1−0
@@ -470,3 +470,4 @@ · 469 unmodified lines
470470 464 common getxattrat sys_getxattrat
471471 465 common listxattrat sys_listxattrat
472472 466 common removexattrat sys_removexattrat
473+467 common open_tree_attr sys_open_tree_attr
arch/sparc/kernel/syscalls/syscall.tbl+1−0
@@ -512,3 +512,4 @@ · 511 unmodified lines
512512 464 common getxattrat sys_getxattrat
513513 465 common listxattrat sys_listxattrat
514514 466 common removexattrat sys_removexattrat
515+467 common open_tree_attr sys_open_tree_attr
arch/x86/entry/syscalls/syscall_32.tbl+1−0
@@ -472,3 +472,4 @@ · 471 unmodified lines
472472 464 i386 getxattrat sys_getxattrat
473473 465 i386 listxattrat sys_listxattrat
474474 466 i386 removexattrat sys_removexattrat
475+467 i386 open_tree_attr sys_open_tree_attr
arch/x86/entry/syscalls/syscall_64.tbl+1−0
@@ -390,6 +390,7 @@ · 389 unmodified lines
390390 464 common getxattrat sys_getxattrat
391391 465 common listxattrat sys_listxattrat
392392 466 common removexattrat sys_removexattrat
393+467 common open_tree_attr sys_open_tree_attr
393394
394395 #
395396 # Due to a historical design error, certain syscalls are numbered differently
arch/xtensa/kernel/syscalls/syscall.tbl+1−0
@@ -437,3 +437,4 @@ · 436 unmodified lines
437437 464 common getxattrat sys_getxattrat
438438 465 common listxattrat sys_listxattrat
439439 466 common removexattrat sys_removexattrat
440+467 common open_tree_attr sys_open_tree_attr
fs/autofs/autofs_i.h+2−0
@@ -218,6 +218,8 @@ void autofs_clean_ino(struct autofs_info *); · 217 unmodified lines
218218
219219 static inline int autofs_check_pipe(struct file *pipe)
220220 {
221+ if (pipe->f_mode & FMODE_PATH)
222+ return -EINVAL;
221223 if (!(pipe->f_mode & FMODE_CAN_WRITE))
222224 return -EINVAL;
223225 if (!S_ISFIFO(file_inode(pipe)->i_mode))
fs/fsopen.c+1−1
@@ -453,7 +453,7 @@ SYSCALL_DEFINE5(fsconfig, · 452 unmodified lines
453453 case FSCONFIG_SET_FD:
454454 param.type = fs_value_is_file;
455455 ret = -EBADF;
456− param.file = fget(aux);
456+ param.file = fget_raw(aux);
457457 if (!param.file)
458458 goto out_key;
459459 param.dirfd = aux;
fs/internal.h+1−0
@@ -338,3 +338,4 @@ static inline bool path_mounted(const struct path *path) · 337 unmodified lines
338338 }
339339 void file_f_owner_release(struct file *file);
340340 bool file_seek_cur_needs_f_lock(struct file *file);
341+int statmount_mnt_idmap(struct mnt_idmap *idmap, struct seq_file *seq, bool uid_map);
fs/mnt_idmapping.c+51−0
@@ -6,6 +6,7 @@ · 5 unmodified lines
66 #include <linux/mnt_idmapping.h>
77 #include <linux/slab.h>
88 #include <linux/user_namespace.h>
9+#include <linux/seq_file.h>
910
1011 #include "internal.h"
1112
@@ -334,3 +335,53 @@ void mnt_idmap_put(struct mnt_idmap *idmap) · 322 unmodified lines
334335 free_mnt_idmap(idmap);
335336 }
336337 EXPORT_SYMBOL_GPL(mnt_idmap_put);
338+
339+int statmount_mnt_idmap(struct mnt_idmap *idmap, struct seq_file *seq, bool uid_map)
340+{
341+ struct uid_gid_map *map, *map_up;
342+ u32 idx, nr_mappings;
343+
344+ if (!is_valid_mnt_idmap(idmap))
345+ return 0;
346+
347+ /*
348+ * Idmappings are shown relative to the caller's idmapping.
349+ * This is both the most intuitive and most useful solution.
350+ */
351+ if (uid_map) {
352+ map = &idmap->uid_map;
353+ map_up = &current_user_ns()->uid_map;
354+ } else {
355+ map = &idmap->gid_map;
356+ map_up = &current_user_ns()->gid_map;
357+ }
358+
359+ for (idx = 0, nr_mappings = 0; idx < map->nr_extents; idx++) {
360+ uid_t lower;
361+ struct uid_gid_extent *extent;
362+
363+ if (map->nr_extents <= UID_GID_MAP_MAX_BASE_EXTENTS)
364+ extent = &map->extent[idx];
365+ else
366+ extent = &map->forward[idx];
367+
368+ /*
369+ * Verify that the whole range of the mapping can be
370+ * resolved in the caller's idmapping. If it cannot be
371+ * resolved skip the mapping.
372+ */
373+ lower = map_id_range_up(map_up, extent->lower_first, extent->count);
374+ if (lower == (uid_t) -1)
375+ continue;
376+
377+ seq_printf(seq, "%u %u %u", extent->first, lower, extent->count);
378+
379+ seq->count++; /* mappings are separated by \0 */
380+ if (seq_has_overflowed(seq))
381+ return -EAGAIN;
382+
383+ nr_mappings++;
384+ }
385+
386+ return nr_mappings;
387+}
fs/mount.h+26−0
@@ -5,6 +5,8 @@ · 4 unmodified lines
55 #include <linux/ns_common.h>
66 #include <linux/fs_pin.h>
77
8+extern struct list_head notify_list;
9+
810 struct mnt_namespace {
911 struct ns_common ns;
1012 struct mount * root;
@@ -21,6 +23,10 @@ struct mnt_namespace { · 10 unmodified lines
2123 struct rcu_head mnt_ns_rcu;
2224 };
2325 u64 event;
26+#ifdef CONFIG_FSNOTIFY
27+ __u32 n_fsnotify_mask;
28+ struct fsnotify_mark_connector __rcu *n_fsnotify_marks;
29+#endif
2430 unsigned int nr_mounts; /* # of mounts in the namespace */
2531 unsigned int pending_mounts;
2632 struct rb_node mnt_ns_tree_node; /* node in the mnt_ns_tree */
@@ -76,6 +82,8 @@ struct mount { · 49 unmodified lines
7682 #ifdef CONFIG_FSNOTIFY
7783 struct fsnotify_mark_connector __rcu *mnt_fsnotify_marks;
7884 __u32 mnt_fsnotify_mask;
85+ struct list_head to_notify; /* need to queue notification */
86+ struct mnt_namespace *prev_ns; /* previous namespace (NULL if none) */
7987 #endif
8088 int mnt_id; /* mount identifier, reused */
8189 u64 mnt_id_unique; /* mount ID unique until reboot */
@@ -177,3 +185,21 @@ static inline struct mnt_namespace *to_mnt_ns(struct ns_common *ns) · 95 unmodified lines
177185 {
178186 return container_of(ns, struct mnt_namespace, ns);
179187 }
188+
189+#ifdef CONFIG_FSNOTIFY
190+static inline void mnt_notify_add(struct mount *m)
191+{
192+ /* Optimize the case where there are no watches */
193+ if ((m->mnt_ns && m->mnt_ns->n_fsnotify_marks) ||
194+ (m->prev_ns && m->prev_ns->n_fsnotify_marks))
195+ list_add_tail(&m->to_notify, &notify_list);
196+ else
197+ m->prev_ns = m->mnt_ns;
198+}
199+#else
200+static inline void mnt_notify_add(struct mount *m)
201+{
202+}
203+#endif
204+
205+struct mnt_namespace *mnt_ns_from_dentry(struct dentry *dentry);
fs/namespace.c+363−122
@@ -81,15 +81,23 @@ static HLIST_HEAD(unmounted); /* protected by namespace_sem */ · 80 unmodified lines
8181 static LIST_HEAD(ex_mountpoints); /* protected by namespace_sem */
8282 static DEFINE_SEQLOCK(mnt_ns_tree_lock);
8383
84+#ifdef CONFIG_FSNOTIFY
85+LIST_HEAD(notify_list); /* protected by namespace_sem */
86+#endif
8487 static struct rb_root mnt_ns_tree = RB_ROOT; /* protected by mnt_ns_tree_lock */
8588 static LIST_HEAD(mnt_ns_list); /* protected by mnt_ns_tree_lock */
8689
90+enum mount_kattr_flags_t {
91+ MOUNT_KATTR_RECURSE = (1 << 0),
92+ MOUNT_KATTR_IDMAP_REPLACE = (1 << 1),
93+};
94+
8795 struct mount_kattr {
8896 unsigned int attr_set;
8997 unsigned int attr_clr;
9098 unsigned int propagation;
9199 unsigned int lookup_flags;
92− bool recurse;
100+ enum mount_kattr_flags_t kflags;
93101 struct user_namespace *mnt_userns;
94102 struct mnt_idmap *mnt_idmap;
95103 };
@@ -163,6 +171,7 @@ static void mnt_ns_release(struct mnt_namespace *ns) · 67 unmodified lines
163171 {
164172 /* keep alive for {list,stat}mount() */
165173 if (refcount_dec_and_test(&ns->passive)) {
174+ fsnotify_mntns_delete(ns);
166175 put_user_ns(ns->user_ns);
167176 kfree(ns);
168177 }
@@ -1176,6 +1185,8 @@ static void mnt_add_to_ns(struct mnt_namespace *ns, struct mount *mnt) · 1007 unmodified lines
11761185 ns->mnt_first_node = &mnt->mnt_node;
11771186 rb_link_node(&mnt->mnt_node, parent, link);
11781187 rb_insert_color(&mnt->mnt_node, &ns->mounts);
1188+
1189+ mnt_notify_add(mnt);
11791190 }
11801191
11811192 /*
@@ -1723,6 +1734,50 @@ int may_umount(struct vfsmount *mnt) · 541 unmodified lines
17231734
17241735 EXPORT_SYMBOL(may_umount);
17251736
1737+#ifdef CONFIG_FSNOTIFY
1738+static void mnt_notify(struct mount *p)
1739+{
1740+ if (!p->prev_ns && p->mnt_ns) {
1741+ fsnotify_mnt_attach(p->mnt_ns, &p->mnt);
1742+ } else if (p->prev_ns && !p->mnt_ns) {
1743+ fsnotify_mnt_detach(p->prev_ns, &p->mnt);
1744+ } else if (p->prev_ns == p->mnt_ns) {
1745+ fsnotify_mnt_move(p->mnt_ns, &p->mnt);
1746+ } else {
1747+ fsnotify_mnt_detach(p->prev_ns, &p->mnt);
1748+ fsnotify_mnt_attach(p->mnt_ns, &p->mnt);
1749+ }
1750+ p->prev_ns = p->mnt_ns;
1751+}
1752+
1753+static void notify_mnt_list(void)
1754+{
1755+ struct mount *m, *tmp;
1756+ /*
1757+ * Notify about mounts that were added/reparented/detached/remain
1758+ * connected after unmount.
1759+ */
1760+ list_for_each_entry_safe(m, tmp, &notify_list, to_notify) {
1761+ mnt_notify(m);
1762+ list_del_init(&m->to_notify);
1763+ }
1764+}
1765+
1766+static bool need_notify_mnt_list(void)
1767+{
1768+ return !list_empty(&notify_list);
1769+}
1770+#else
1771+static void notify_mnt_list(void)
1772+{
1773+}
1774+
1775+static bool need_notify_mnt_list(void)
1776+{
1777+ return false;
1778+}
1779+#endif
1780+
17261781 static void namespace_unlock(void)
17271782 {
17281783 struct hlist_head head;
@@ -1733,7 +1788,18 @@ static void namespace_unlock(void) · 4 unmodified lines
17331788 hlist_move_list(&unmounted, &head);
17341789 list_splice_init(&ex_mountpoints, &list);
17351790
1736− up_write(&namespace_sem);
1791+ if (need_notify_mnt_list()) {
1792+ /*
1793+ * No point blocking out concurrent readers while notifications
1794+ * are sent. This will also allow statmount()/listmount() to run
1795+ * concurrently.
1796+ */
1797+ downgrade_write(&namespace_sem);
1798+ notify_mnt_list();
1799+ up_read(&namespace_sem);
1800+ } else {
1801+ up_write(&namespace_sem);
1802+ }
17371803
17381804 shrink_dentry_list(&list);
17391805
@@ -1846,6 +1912,19 @@ static void umount_tree(struct mount *mnt, enum umount_tree_flags how) · 106 unmodified lines
18461912 change_mnt_propagation(p, MS_PRIVATE);
18471913 if (disconnect)
18481914 hlist_add_head(&p->mnt_umount, &unmounted);
1915+
1916+ /*
1917+ * At this point p->mnt_ns is NULL, notification will be queued
1918+ * only if
1919+ *
1920+ * - p->prev_ns is non-NULL *and*
1921+ * - p->prev_ns->n_fsnotify_marks is non-NULL
1922+ *
1923+ * This will preclude queuing the mount if this is a cleanup
1924+ * after a failed copy_tree() or destruction of an anonymous
1925+ * namespace, etc.
1926+ */
1927+ mnt_notify_add(p);
18491928 }
18501929 }
18511930
@@ -2026,6 +2105,7 @@ static void warn_mandlock(void) · 174 unmodified lines
20262105 static int can_umount(const struct path *path, int flags)
20272106 {
20282107 struct mount *mnt = real_mount(path->mnt);
2108+ struct super_block *sb = path->dentry->d_sb;
20292109
20302110 if (!may_mount())
20312111 return -EPERM;
@@ -2035,7 +2115,7 @@ static int can_umount(const struct path *path, int flags) · 3 unmodified lines
20352115 return -EINVAL;
20362116 if (mnt->mnt.mnt_flags & MNT_LOCKED) /* Check optimistically */
20372117 return -EINVAL;
2038− if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN))
2118+ if (flags & MNT_FORCE && !ns_capable(sb->s_user_ns, CAP_SYS_ADMIN))
20392119 return -EPERM;
20402120 return 0;
20412121 }
@@ -2145,16 +2225,24 @@ struct mnt_namespace *get_sequential_mnt_ns(struct mnt_namespace *mntns, bool pr · 103 unmodified lines
21452225 }
21462226 }
21472227
2228+struct mnt_namespace *mnt_ns_from_dentry(struct dentry *dentry)
2229+{
2230+ if (!is_mnt_ns_file(dentry))
2231+ return NULL;
2232+
2233+ return to_mnt_ns(get_proc_ns(dentry->d_inode));
2234+}
2235+
21482236 static bool mnt_ns_loop(struct dentry *dentry)
21492237 {
21502238 /* Could bind mounting the mount namespace inode cause a
21512239 * mount namespace loop?
21522240 */
2153− struct mnt_namespace *mnt_ns;
2154− if (!is_mnt_ns_file(dentry))
2241+ struct mnt_namespace *mnt_ns = mnt_ns_from_dentry(dentry);
2242+
2243+ if (!mnt_ns)
21552244 return false;
21562245
2157− mnt_ns = to_mnt_ns(get_proc_ns(dentry->d_inode));
21582246 return current->nsproxy->mnt_ns->seq >= mnt_ns->seq;
21592247 }
21602248
@@ -2287,6 +2375,28 @@ bool has_locked_children(struct mount *mnt, struct dentry *dentry) · 126 unmodified lines
22872375 return false;
22882376 }
22892377
2378+/*
2379+ * Check that there aren't references to earlier/same mount namespaces in the
2380+ * specified subtree. Such references can act as pins for mount namespaces
2381+ * that aren't checked by the mount-cycle checking code, thereby allowing
2382+ * cycles to be made.
2383+ */
2384+static bool check_for_nsfs_mounts(struct mount *subtree)
2385+{
2386+ struct mount *p;
2387+ bool ret = false;
2388+
2389+ lock_mount_hash();
2390+ for (p = subtree; p; p = next_mnt(p, subtree))
2391+ if (mnt_ns_loop(p->mnt.mnt_root))
2392+ goto out;
2393+
2394+ ret = true;
2395+out:
2396+ unlock_mount_hash();
2397+ return ret;
2398+}
2399+
22902400 /**
22912401 * clone_private_mount - create a private clone of a path
22922402 * @path: path to clone
@@ -2295,6 +2405,8 @@ bool has_locked_children(struct mount *mnt, struct dentry *dentry) · 2 unmodified lines
22952405 * will not be attached anywhere in the namespace and will be private (i.e.
22962406 * changes to the originating mount won't be propagated into this).
22972407 *
2408+ * This assumes caller has called or done the equivalent of may_mount().
2409+ *
22982410 * Release with mntput().
22992411 */
23002412 struct vfsmount *clone_private_mount(const struct path *path)
@@ -2302,30 +2414,36 @@ struct vfsmount *clone_private_mount(const struct path *path) · 1 unmodified line
23022414 struct mount *old_mnt = real_mount(path->mnt);
23032415 struct mount *new_mnt;
23042416
2305− down_read(&namespace_sem);
2417+ scoped_guard(rwsem_read, &namespace_sem)
23062418 if (IS_MNT_UNBINDABLE(old_mnt))
2307− goto invalid;
2419+ return ERR_PTR(-EINVAL);
2420+
2421+ if (mnt_has_parent(old_mnt)) {
2422+ if (!check_mnt(old_mnt))
2423+ return ERR_PTR(-EINVAL);
2424+ } else {
2425+ if (!is_mounted(&old_mnt->mnt))
2426+ return ERR_PTR(-EINVAL);
23082427
2309− if (!check_mnt(old_mnt))
2310− goto invalid;
2428+ /* Make sure this isn't something purely kernel internal. */
2429+ if (!is_anon_ns(old_mnt->mnt_ns))
2430+ return ERR_PTR(-EINVAL);
2431+
2432+ /* Make sure we don't create mount namespace loops. */
2433+ if (!check_for_nsfs_mounts(old_mnt))
2434+ return ERR_PTR(-EINVAL);
2435+ }
23112436
23122437 if (has_locked_children(old_mnt, path->dentry))
2313− goto invalid;
2438+ return ERR_PTR(-EINVAL);
23142439
23152440 new_mnt = clone_mnt(old_mnt, path->dentry, CL_PRIVATE);
2316− up_read(&namespace_sem);
2317−
23182441 if (IS_ERR(new_mnt))
2319− return ERR_CAST(new_mnt);
2442+ return ERR_PTR(-EINVAL);
23202443
23212444 /* Longterm mount to be removed by kern_unmount*() */
23222445 new_mnt->mnt_ns = MNT_NS_INTERNAL;
2323−
23242446 return &new_mnt->mnt;
2325−
2326−invalid:
2327− up_read(&namespace_sem);
2328− return ERR_PTR(-EINVAL);
23292447 }
23302448 EXPORT_SYMBOL_GPL(clone_private_mount);
23312449
@@ -2547,6 +2665,7 @@ static int attach_recursive_mnt(struct mount *source_mnt, · 215 unmodified lines
25472665 dest_mp = smp;
25482666 unhash_mnt(source_mnt);
25492667 attach_mnt(source_mnt, top_mnt, dest_mp, beneath);
2668+ mnt_notify_add(source_mnt);
25502669 touch_mnt_namespace(source_mnt->mnt_ns);
25512670 } else {
25522671 if (source_mnt->mnt_ns) {
@@ -2889,24 +3008,22 @@ static struct file *open_detached_copy(struct path *path, bool recursive) · 336 unmodified lines
28893008 return file;
28903009 }
28913010
2892−SYSCALL_DEFINE3(open_tree, int, dfd, const char __user *, filename, unsigned, flags)
3011+static struct file *vfs_open_tree(int dfd, const char __user *filename, unsigned int flags)
28933012 {
2894− struct file *file;
2895− struct path path;
3013+ int ret;
3014+ struct path path __free(path_put) = {};
28963015 int lookup_flags = LOOKUP_AUTOMOUNT | LOOKUP_FOLLOW;
28973016 bool detached = flags & OPEN_TREE_CLONE;
2898− int error;
2899− int fd;
29003017
29013018 BUILD_BUG_ON(OPEN_TREE_CLOEXEC != O_CLOEXEC);
29023019
29033020 if (flags & ~(AT_EMPTY_PATH | AT_NO_AUTOMOUNT | AT_RECURSIVE |
29043021 AT_SYMLINK_NOFOLLOW | OPEN_TREE_CLONE |
29053022 OPEN_TREE_CLOEXEC))
2906− return -EINVAL;
3023+ return ERR_PTR(-EINVAL);
29073024
29083025 if ((flags & (AT_RECURSIVE | OPEN_TREE_CLONE)) == AT_RECURSIVE)
2909− return -EINVAL;
3026+ return ERR_PTR(-EINVAL);
29103027
29113028 if (flags & AT_NO_AUTOMOUNT)
29123029 lookup_flags &= ~LOOKUP_AUTOMOUNT;
@@ -2916,27 +3033,32 @@ SYSCALL_DEFINE3(open_tree, int, dfd, const char __user *, filename, unsigned, fl · 3 unmodified lines
29163033 lookup_flags |= LOOKUP_EMPTY;
29173034
29183035 if (detached && !may_mount())
2919− return -EPERM;
3036+ return ERR_PTR(-EPERM);
3037+
3038+ ret = user_path_at(dfd, filename, lookup_flags, &path);
3039+ if (unlikely(ret))
3040+ return ERR_PTR(ret);
3041+
3042+ if (detached)
3043+ return open_detached_copy(&path, flags & AT_RECURSIVE);
3044+
3045+ return dentry_open(&path, O_PATH, current_cred());
3046+}
3047+
3048+SYSCALL_DEFINE3(open_tree, int, dfd, const char __user *, filename, unsigned, flags)
3049+{
3050+ int fd;
3051+ struct file *file __free(fput) = NULL;
3052+
3053+ file = vfs_open_tree(dfd, filename, flags);
3054+ if (IS_ERR(file))
3055+ return PTR_ERR(file);
29203056
29213057 fd = get_unused_fd_flags(flags & O_CLOEXEC);
29223058 if (fd < 0)
29233059 return fd;
29243060
2925− error = user_path_at(dfd, filename, lookup_flags, &path);
2926− if (unlikely(error)) {
2927− file = ERR_PTR(error);
2928− } else {
2929− if (detached)
2930− file = open_detached_copy(&path, flags & AT_RECURSIVE);
2931− else
2932− file = dentry_open(&path, O_PATH, current_cred());
2933− path_put(&path);
2934− }
2935− if (IS_ERR(file)) {
2936− put_unused_fd(fd);
2937− return PTR_ERR(file);
2938− }
2939− fd_install(fd, file);
3061+ fd_install(fd, no_free_ptr(file));
29403062 return fd;
29413063 }
29423064
@@ -3123,28 +3245,6 @@ static inline int tree_contains_unbindable(struct mount *mnt) · 180 unmodified lines
31233245 return 0;
31243246 }
31253247
3126−/*
3127− * Check that there aren't references to earlier/same mount namespaces in the
3128− * specified subtree. Such references can act as pins for mount namespaces
3129− * that aren't checked by the mount-cycle checking code, thereby allowing
3130− * cycles to be made.
3131− */
3132−static bool check_for_nsfs_mounts(struct mount *subtree)
3133−{
3134− struct mount *p;
3135− bool ret = false;
3136−
3137− lock_mount_hash();
3138− for (p = subtree; p; p = next_mnt(p, subtree))
3139− if (mnt_ns_loop(p->mnt.mnt_root))
3140− goto out;
3141−
3142− ret = true;
3143−out:
3144− unlock_mount_hash();
3145− return ret;
3146−}
3147−
31483248 static int do_set_group(struct path *from_path, struct path *to_path)
31493249 {
31503250 struct mount *from, *to;
@@ -4468,6 +4568,8 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, · 1317 unmodified lines
44684568 list_del_init(&new_mnt->mnt_expire);
44694569 put_mountpoint(root_mp);
44704570 unlock_mount_hash();
4571+ mnt_notify_add(root_mnt);
4572+ mnt_notify_add(new_mnt);
44714573 chroot_fs_refs(&root, &new);
44724574 error = 0;
44734575 out4:
@@ -4512,11 +4614,10 @@ static int can_idmap_mount(const struct mount_kattr *kattr, struct mount *mnt) · 38 unmodified lines
45124614 return -EINVAL;
45134615
45144616 /*
4515− * Once a mount has been idmapped we don't allow it to change its
4516− * mapping. It makes things simpler and callers can just create
4517− * another bind-mount they can idmap if they want to.
4617+ * We only allow an mount to change it's idmapping if it has
4618+ * never been accessible to userspace.
45184619 */
4519− if (is_idmapped_mnt(m))
4620+ if (!(kattr->kflags & MOUNT_KATTR_IDMAP_REPLACE) && is_idmapped_mnt(m))
45204621 return -EPERM;
45214622
45224623 /* The underlying filesystem doesn't support idmapped mounts yet. */
@@ -4576,7 +4677,7 @@ static int mount_setattr_prepare(struct mount_kattr *kattr, struct mount *mnt) · 53 unmodified lines
45764677 break;
45774678 }
45784679
4579− if (!kattr->recurse)
4680+ if (!(kattr->kflags & MOUNT_KATTR_RECURSE))
45804681 return 0;
45814682 }
45824683
@@ -4606,18 +4707,16 @@ static int mount_setattr_prepare(struct mount_kattr *kattr, struct mount *mnt) · 23 unmodified lines
46064707
46074708 static void do_idmap_mount(const struct mount_kattr *kattr, struct mount *mnt)
46084709 {
4710+ struct mnt_idmap *old_idmap;
4711+
46094712 if (!kattr->mnt_idmap)
46104713 return;
46114714
4612− /*
4613− * Pairs with smp_load_acquire() in mnt_idmap().
4614− *
4615− * Since we only allow a mount to change the idmapping once and
4616− * verified this in can_idmap_mount() we know that the mount has
4617− * @nop_mnt_idmap attached to it. So there's no need to drop any
4618− * references.
4619− */
4715+ old_idmap = mnt_idmap(&mnt->mnt);
4716+
4717+ /* Pairs with smp_load_acquire() in mnt_idmap(). */
46204718 smp_store_release(&mnt->mnt.mnt_idmap, mnt_idmap_get(kattr->mnt_idmap));
4719+ mnt_idmap_put(old_idmap);
46214720 }
46224721
46234722 static void mount_setattr_commit(struct mount_kattr *kattr, struct mount *mnt)
@@ -4637,7 +4736,7 @@ static void mount_setattr_commit(struct mount_kattr *kattr, struct mount *mnt) · 13 unmodified lines
46374736
46384737 if (kattr->propagation)
46394738 change_mnt_propagation(m, kattr->propagation);
4640− if (!kattr->recurse)
4739+ if (!(kattr->kflags & MOUNT_KATTR_RECURSE))
46414740 break;
46424741 }
46434742 touch_mnt_namespace(mnt->mnt_ns);
@@ -4667,7 +4766,7 @@ static int do_mount_setattr(struct path *path, struct mount_kattr *kattr) · 23 unmodified lines
46674766 */
46684767 namespace_lock();
46694768 if (kattr->propagation == MS_SHARED) {
4670− err = invent_group_ids(mnt, kattr->recurse);
4769+ err = invent_group_ids(mnt, kattr->kflags & MOUNT_KATTR_RECURSE);
46714770 if (err) {
46724771 namespace_unlock();
46734772 return err;
@@ -4718,7 +4817,7 @@ out: · 44 unmodified lines
47184817 }
47194818
47204819 static int build_mount_idmapped(const struct mount_attr *attr, size_t usize,
4721− struct mount_kattr *kattr, unsigned int flags)
4820+ struct mount_kattr *kattr)
47224821 {
47234822 struct ns_common *ns;
47244823 struct user_namespace *mnt_userns;
@@ -4726,13 +4825,23 @@ static int build_mount_idmapped(const struct mount_attr *attr, size_t usize, · 1 unmodified line
47264825 if (!((attr->attr_set | attr->attr_clr) & MOUNT_ATTR_IDMAP))
47274826 return 0;
47284827
4729− /*
4730− * We currently do not support clearing an idmapped mount. If this ever
4731− * is a use-case we can revisit this but for now let's keep it simple
4732− * and not allow it.
4733− */
4734− if (attr->attr_clr & MOUNT_ATTR_IDMAP)
4735− return -EINVAL;
4828+ if (attr->attr_clr & MOUNT_ATTR_IDMAP) {
4829+ /*
4830+ * We can only remove an idmapping if it's never been
4831+ * exposed to userspace.
4832+ */
4833+ if (!(kattr->kflags & MOUNT_KATTR_IDMAP_REPLACE))
4834+ return -EINVAL;
4835+
4836+ /*
4837+ * Removal of idmappings is equivalent to setting
4838+ * nop_mnt_idmap.
4839+ */
4840+ if (!(attr->attr_set & MOUNT_ATTR_IDMAP)) {
4841+ kattr->mnt_idmap = &nop_mnt_idmap;
4842+ return 0;
4843+ }
4844+ }
47364845
47374846 if (attr->userns_fd > INT_MAX)
47384847 return -EINVAL;
@@ -4769,22 +4878,8 @@ static int build_mount_idmapped(const struct mount_attr *attr, size_t usize, · 30 unmodified lines
47694878 }
47704879
47714880 static int build_mount_kattr(const struct mount_attr *attr, size_t usize,
4772− struct mount_kattr *kattr, unsigned int flags)
4881+ struct mount_kattr *kattr)
47734882 {
4774− unsigned int lookup_flags = LOOKUP_AUTOMOUNT | LOOKUP_FOLLOW;
4775−
4776− if (flags & AT_NO_AUTOMOUNT)
4777− lookup_flags &= ~LOOKUP_AUTOMOUNT;
4778− if (flags & AT_SYMLINK_NOFOLLOW)
4779− lookup_flags &= ~LOOKUP_FOLLOW;
4780− if (flags & AT_EMPTY_PATH)
4781− lookup_flags |= LOOKUP_EMPTY;
4782−
4783− *kattr = (struct mount_kattr) {
4784− .lookup_flags = lookup_flags,
4785− .recurse = !!(flags & AT_RECURSIVE),
4786− };
4787−
47884883 if (attr->propagation & ~MOUNT_SETATTR_PROPAGATION_FLAGS)
47894884 return -EINVAL;
47904885 if (hweight32(attr->propagation & MOUNT_SETATTR_PROPAGATION_FLAGS) > 1)
@@ -4832,35 +4927,28 @@ static int build_mount_kattr(const struct mount_attr *attr, size_t usize, · 41 unmodified lines
48324927 return -EINVAL;
48334928 }
48344929
4835− return build_mount_idmapped(attr, usize, kattr, flags);
4930+ return build_mount_idmapped(attr, usize, kattr);
48364931 }
48374932
48384933 static void finish_mount_kattr(struct mount_kattr *kattr)
48394934 {
4840− put_user_ns(kattr->mnt_userns);
4841− kattr->mnt_userns = NULL;
4935+ if (kattr->mnt_userns) {
4936+ put_user_ns(kattr->mnt_userns);
4937+ kattr->mnt_userns = NULL;
4938+ }
48424939
48434940 if (kattr->mnt_idmap)
48444941 mnt_idmap_put(kattr->mnt_idmap);
48454942 }
48464943
4847−SYSCALL_DEFINE5(mount_setattr, int, dfd, const char __user *, path,
4848− unsigned int, flags, struct mount_attr __user *, uattr,
4849− size_t, usize)
4944+static int copy_mount_setattr(struct mount_attr __user *uattr, size_t usize,
4945+ struct mount_kattr *kattr)
48504946 {
4851− int err;
4852− struct path target;
4947+ int ret;
48534948 struct mount_attr attr;
4854− struct mount_kattr kattr;
48554949
48564950 BUILD_BUG_ON(sizeof(struct mount_attr) != MOUNT_ATTR_SIZE_VER0);
48574951
4858− if (flags & ~(AT_EMPTY_PATH |
4859− AT_RECURSIVE |
4860− AT_SYMLINK_NOFOLLOW |
4861− AT_NO_AUTOMOUNT))
4862− return -EINVAL;
4863−
48644952 if (unlikely(usize > PAGE_SIZE))
48654953 return -E2BIG;
48664954 if (unlikely(usize < MOUNT_ATTR_SIZE_VER0))
@@ -4869,9 +4957,9 @@ SYSCALL_DEFINE5(mount_setattr, int, dfd, const char __user *, path, · 2 unmodified lines
48694957 if (!may_mount())
48704958 return -EPERM;
48714959
4872− err = copy_struct_from_user(&attr, sizeof(attr), uattr, usize);
4873− if (err)
4874− return err;
4960+ ret = copy_struct_from_user(&attr, sizeof(attr), uattr, usize);
4961+ if (ret)
4962+ return ret;
48754963
48764964 /* Don't bother walking through the mounts if this is a nop. */
48774965 if (attr.attr_set == 0 &&
@@ -4879,7 +4967,39 @@ SYSCALL_DEFINE5(mount_setattr, int, dfd, const char __user *, path, · 1 unmodified line
48794967 attr.propagation == 0)
48804968 return 0;
48814969
4882− err = build_mount_kattr(&attr, usize, &kattr, flags);
4970+ return build_mount_kattr(&attr, usize, kattr);
4971+}
4972+
4973+SYSCALL_DEFINE5(mount_setattr, int, dfd, const char __user *, path,
4974+ unsigned int, flags, struct mount_attr __user *, uattr,
4975+ size_t, usize)
4976+{
4977+ int err;
4978+ struct path target;
4979+ struct mount_kattr kattr;
4980+ unsigned int lookup_flags = LOOKUP_AUTOMOUNT | LOOKUP_FOLLOW;
4981+
4982+ if (flags & ~(AT_EMPTY_PATH |
4983+ AT_RECURSIVE |
4984+ AT_SYMLINK_NOFOLLOW |
4985+ AT_NO_AUTOMOUNT))
4986+ return -EINVAL;
4987+
4988+ if (flags & AT_NO_AUTOMOUNT)
4989+ lookup_flags &= ~LOOKUP_AUTOMOUNT;
4990+ if (flags & AT_SYMLINK_NOFOLLOW)
4991+ lookup_flags &= ~LOOKUP_FOLLOW;
4992+ if (flags & AT_EMPTY_PATH)
4993+ lookup_flags |= LOOKUP_EMPTY;
4994+
4995+ kattr = (struct mount_kattr) {
4996+ .lookup_flags = lookup_flags,
4997+ };
4998+
4999+ if (flags & AT_RECURSIVE)
5000+ kattr.kflags |= MOUNT_KATTR_RECURSE;
5001+
5002+ err = copy_mount_setattr(uattr, usize, &kattr);
48835003 if (err)
48845004 return err;
48855005
@@ -4892,6 +5012,47 @@ SYSCALL_DEFINE5(mount_setattr, int, dfd, const char __user *, path, · 6 unmodified lines
48925012 return err;
48935013 }
48945014
5015+SYSCALL_DEFINE5(open_tree_attr, int, dfd, const char __user *, filename,
5016+ unsigned, flags, struct mount_attr __user *, uattr,
5017+ size_t, usize)
5018+{
5019+ struct file __free(fput) *file = NULL;
5020+ int fd;
5021+
5022+ if (!uattr && usize)
5023+ return -EINVAL;
5024+
5025+ file = vfs_open_tree(dfd, filename, flags);
5026+ if (IS_ERR(file))
5027+ return PTR_ERR(file);
5028+
5029+ if (uattr) {
5030+ int ret;
5031+ struct mount_kattr kattr = {};
5032+
5033+ kattr.kflags = MOUNT_KATTR_IDMAP_REPLACE;
5034+ if (flags & AT_RECURSIVE)
5035+ kattr.kflags |= MOUNT_KATTR_RECURSE;
5036+
5037+ ret = copy_mount_setattr(uattr, usize, &kattr);
5038+ if (ret)
5039+ return ret;
5040+
5041+ ret = do_mount_setattr(&file->f_path, &kattr);
5042+ if (ret)
5043+ return ret;
5044+
5045+ finish_mount_kattr(&kattr);
5046+ }
5047+
5048+ fd = get_unused_fd_flags(flags & O_CLOEXEC);
5049+ if (fd < 0)
5050+ return fd;
5051+
5052+ fd_install(fd, no_free_ptr(file));
5053+ return fd;
5054+}
5055+
48955056 int show_path(struct seq_file *m, struct dentry *root)
48965057 {
48975058 if (root->d_sb->s_op->show_path)
@@ -4915,6 +5076,7 @@ struct kstatmount { · 17 unmodified lines
49155076 struct statmount __user *buf;
49165077 size_t bufsize;
49175078 struct vfsmount *mnt;
5079+ struct mnt_idmap *idmap;
49185080 u64 mask;
49195081 struct path root;
49205082 struct statmount sm;
@@ -5184,6 +5346,46 @@ static int statmount_opt_sec_array(struct kstatmount *s, struct seq_file *seq) · 263 unmodified lines
51845346 return 0;
51855347 }
51865348
5349+static inline int statmount_mnt_uidmap(struct kstatmount *s, struct seq_file *seq)
5350+{
5351+ int ret;
5352+
5353+ ret = statmount_mnt_idmap(s->idmap, seq, true);
5354+ if (ret < 0)
5355+ return ret;
5356+
5357+ s->sm.mnt_uidmap_num = ret;
5358+ /*
5359+ * Always raise STATMOUNT_MNT_UIDMAP even if there are no valid
5360+ * mappings. This allows userspace to distinguish between a
5361+ * non-idmapped mount and an idmapped mount where none of the
5362+ * individual mappings are valid in the caller's idmapping.
5363+ */
5364+ if (is_valid_mnt_idmap(s->idmap))
5365+ s->sm.mask |= STATMOUNT_MNT_UIDMAP;
5366+ return 0;
5367+}
5368+
5369+static inline int statmount_mnt_gidmap(struct kstatmount *s, struct seq_file *seq)
5370+{
5371+ int ret;
5372+
5373+ ret = statmount_mnt_idmap(s->idmap, seq, false);
5374+ if (ret < 0)
5375+ return ret;
5376+
5377+ s->sm.mnt_gidmap_num = ret;
5378+ /*
5379+ * Always raise STATMOUNT_MNT_GIDMAP even if there are no valid
5380+ * mappings. This allows userspace to distinguish between a
5381+ * non-idmapped mount and an idmapped mount where none of the
5382+ * individual mappings are valid in the caller's idmapping.
5383+ */
5384+ if (is_valid_mnt_idmap(s->idmap))
5385+ s->sm.mask |= STATMOUNT_MNT_GIDMAP;
5386+ return 0;
5387+}
5388+
51875389 static int statmount_string(struct kstatmount *s, u64 flag)
51885390 {
51895391 int ret = 0;
@@ -5231,6 +5433,14 @@ static int statmount_string(struct kstatmount *s, u64 flag) · 41 unmodified lines
52315433 offp = &sm->sb_source;
52325434 ret = statmount_sb_source(s, seq);
52335435 break;
5436+ case STATMOUNT_MNT_UIDMAP:
5437+ sm->mnt_uidmap = start;
5438+ ret = statmount_mnt_uidmap(s, seq);
5439+ break;
5440+ case STATMOUNT_MNT_GIDMAP:
5441+ sm->mnt_gidmap = start;
5442+ ret = statmount_mnt_gidmap(s, seq);
5443+ break;
52345444 default:
52355445 WARN_ON_ONCE(true);
52365446 return -EINVAL;
@@ -5323,6 +5533,21 @@ static int grab_requested_root(struct mnt_namespace *ns, struct path *root) · 86 unmodified lines
53235533 return 0;
53245534 }
53255535
5536+/* This must be updated whenever a new flag is added */
5537+#define STATMOUNT_SUPPORTED (STATMOUNT_SB_BASIC | \
5538+ STATMOUNT_MNT_BASIC | \
5539+ STATMOUNT_PROPAGATE_FROM | \
5540+ STATMOUNT_MNT_ROOT | \
5541+ STATMOUNT_MNT_POINT | \
5542+ STATMOUNT_FS_TYPE | \
5543+ STATMOUNT_MNT_NS_ID | \
5544+ STATMOUNT_MNT_OPTS | \
5545+ STATMOUNT_FS_SUBTYPE | \
5546+ STATMOUNT_SB_SOURCE | \
5547+ STATMOUNT_OPT_ARRAY | \
5548+ STATMOUNT_OPT_SEC_ARRAY | \
5549+ STATMOUNT_SUPPORTED_MASK)
5550+
53265551 static int do_statmount(struct kstatmount *s, u64 mnt_id, u64 mnt_ns_id,
53275552 struct mnt_namespace *ns)
53285553 {
@@ -5356,6 +5581,7 @@ static int do_statmount(struct kstatmount *s, u64 mnt_id, u64 mnt_ns_id, · 27 unmodified lines
53565581 return err;
53575582
53585583 s->root = root;
5584+ s->idmap = mnt_idmap(s->mnt);
53595585 if (s->mask & STATMOUNT_SB_BASIC)
53605586 statmount_sb_basic(s);
53615587
@@ -5389,12 +5615,26 @@ static int do_statmount(struct kstatmount *s, u64 mnt_id, u64 mnt_ns_id, · 27 unmodified lines
53895615 if (!err && s->mask & STATMOUNT_SB_SOURCE)
53905616 err = statmount_string(s, STATMOUNT_SB_SOURCE);
53915617
5618+ if (!err && s->mask & STATMOUNT_MNT_UIDMAP)
5619+ err = statmount_string(s, STATMOUNT_MNT_UIDMAP);
5620+
5621+ if (!err && s->mask & STATMOUNT_MNT_GIDMAP)
5622+ err = statmount_string(s, STATMOUNT_MNT_GIDMAP);
5623+
53925624 if (!err && s->mask & STATMOUNT_MNT_NS_ID)
53935625 statmount_mnt_ns_id(s, ns);
53945626
5627+ if (!err && s->mask & STATMOUNT_SUPPORTED_MASK) {
5628+ s->sm.mask |= STATMOUNT_SUPPORTED_MASK;
5629+ s->sm.supported_mask = STATMOUNT_SUPPORTED;
5630+ }
5631+
53955632 if (err)
53965633 return err;
53975634
5635+ /* Are there bits in the return mask not present in STATMOUNT_SUPPORTED? */
5636+ WARN_ON_ONCE(~STATMOUNT_SUPPORTED & s->sm.mask);
5637+
53985638 return 0;
53995639 }
54005640
@@ -5412,7 +5652,8 @@ static inline bool retry_statmount(const long ret, size_t *seq_size) · 11 unmodified lines
54125652 #define STATMOUNT_STRING_REQ (STATMOUNT_MNT_ROOT | STATMOUNT_MNT_POINT | \
54135653 STATMOUNT_FS_TYPE | STATMOUNT_MNT_OPTS | \
54145654 STATMOUNT_FS_SUBTYPE | STATMOUNT_SB_SOURCE | \
5415− STATMOUNT_OPT_ARRAY | STATMOUNT_OPT_SEC_ARRAY)
5655+ STATMOUNT_OPT_ARRAY | STATMOUNT_OPT_SEC_ARRAY | \
5656+ STATMOUNT_MNT_UIDMAP | STATMOUNT_MNT_GIDMAP)
54165657
54175658 static int prepare_kstatmount(struct kstatmount *ks, struct mnt_id_req *kreq,
54185659 struct statmount __user *buf, size_t bufsize,
fs/notify/fanotify/fanotify.c+35−3
@@ -166,6 +166,8 @@ static bool fanotify_should_merge(struct fanotify_event *old, · 165 unmodified lines
166166 case FANOTIFY_EVENT_TYPE_FS_ERROR:
167167 return fanotify_error_event_equal(FANOTIFY_EE(old),
168168 FANOTIFY_EE(new));
169+ case FANOTIFY_EVENT_TYPE_MNT:
170+ return false;
169171 default:
170172 WARN_ON_ONCE(1);
171173 }
@@ -312,7 +314,10 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group, · 140 unmodified lines
312314 pr_debug("%s: report_mask=%x mask=%x data=%p data_type=%d\n",
313315 __func__, iter_info->report_mask, event_mask, data, data_type);
314316
315− if (!fid_mode) {
317+ if (FAN_GROUP_FLAG(group, FAN_REPORT_MNT)) {
318+ if (data_type != FSNOTIFY_EVENT_MNT)
319+ return 0;
320+ } else if (!fid_mode) {
316321 /* Do we have path to open a file descriptor? */
317322 if (!path)
318323 return 0;
@@ -557,6 +562,20 @@ static struct fanotify_event *fanotify_alloc_path_event(const struct path *path, · 238 unmodified lines
557562 return &pevent->fae;
558563 }
559564
565+static struct fanotify_event *fanotify_alloc_mnt_event(u64 mnt_id, gfp_t gfp)
566+{
567+ struct fanotify_mnt_event *pevent;
568+
569+ pevent = kmem_cache_alloc(fanotify_mnt_event_cachep, gfp);
570+ if (!pevent)
571+ return NULL;
572+
573+ pevent->fae.type = FANOTIFY_EVENT_TYPE_MNT;
574+ pevent->mnt_id = mnt_id;
575+
576+ return &pevent->fae;
577+}
578+
560579 static struct fanotify_event *fanotify_alloc_perm_event(const void *data,
561580 int data_type,
562581 gfp_t gfp)
@@ -731,6 +750,7 @@ static struct fanotify_event *fanotify_alloc_event( · 168 unmodified lines
731750 fid_mode);
732751 struct inode *dirid = fanotify_dfid_inode(mask, data, data_type, dir);
733752 const struct path *path = fsnotify_data_path(data, data_type);
753+ u64 mnt_id = fsnotify_data_mnt_id(data, data_type);
734754 struct mem_cgroup *old_memcg;
735755 struct dentry *moved = NULL;
736756 struct inode *child = NULL;
@@ -826,8 +846,12 @@ static struct fanotify_event *fanotify_alloc_event( · 89 unmodified lines
826846 moved, &hash, gfp);
827847 } else if (fid_mode) {
828848 event = fanotify_alloc_fid_event(id, fsid, &hash, gfp);
829− } else {
849+ } else if (path) {
830850 event = fanotify_alloc_path_event(path, &hash, gfp);
851+ } else if (mnt_id) {
852+ event = fanotify_alloc_mnt_event(mnt_id, gfp);
853+ } else {
854+ WARN_ON_ONCE(1);
831855 }
832856
833857 if (!event)
@@ -927,7 +951,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask, · 93 unmodified lines
927951 BUILD_BUG_ON(FAN_RENAME != FS_RENAME);
928952 BUILD_BUG_ON(FAN_PRE_ACCESS != FS_PRE_ACCESS);
929953
930− BUILD_BUG_ON(HWEIGHT32(ALL_FANOTIFY_EVENT_BITS) != 22);
954+ BUILD_BUG_ON(HWEIGHT32(ALL_FANOTIFY_EVENT_BITS) != 24);
931955
932956 mask = fanotify_group_event_mask(group, iter_info, &match_mask,
933957 mask, data, data_type, dir);
@@ -1028,6 +1052,11 @@ static void fanotify_free_error_event(struct fsnotify_group *group, · 94 unmodified lines
10281052 mempool_free(fee, &group->fanotify_data.error_events_pool);
10291053 }
10301054
1055+static void fanotify_free_mnt_event(struct fanotify_event *event)
1056+{
1057+ kmem_cache_free(fanotify_mnt_event_cachep, FANOTIFY_ME(event));
1058+}
1059+
10311060 static void fanotify_free_event(struct fsnotify_group *group,
10321061 struct fsnotify_event *fsn_event)
10331062 {
@@ -1054,6 +1083,9 @@ static void fanotify_free_event(struct fsnotify_group *group, · 20 unmodified lines
10541083 case FANOTIFY_EVENT_TYPE_FS_ERROR:
10551084 fanotify_free_error_event(group, event);
10561085 break;
1086+ case FANOTIFY_EVENT_TYPE_MNT:
1087+ fanotify_free_mnt_event(event);
1088+ break;
10571089 default:
10581090 WARN_ON_ONCE(1);
10591091 }
fs/notify/fanotify/fanotify.h+18−0
@@ -9,6 +9,7 @@ extern struct kmem_cache *fanotify_mark_cache; · 8 unmodified lines
99 extern struct kmem_cache *fanotify_fid_event_cachep;
1010 extern struct kmem_cache *fanotify_path_event_cachep;
1111 extern struct kmem_cache *fanotify_perm_event_cachep;
12+extern struct kmem_cache *fanotify_mnt_event_cachep;
1213
1314 /* Possible states of the permission event */
1415 enum {
@@ -244,6 +245,7 @@ enum fanotify_event_type { · 229 unmodified lines
244245 FANOTIFY_EVENT_TYPE_PATH_PERM,
245246 FANOTIFY_EVENT_TYPE_OVERFLOW, /* struct fanotify_event */
246247 FANOTIFY_EVENT_TYPE_FS_ERROR, /* struct fanotify_error_event */
248+ FANOTIFY_EVENT_TYPE_MNT,
247249 __FANOTIFY_EVENT_TYPE_NUM
248250 };
249251
@@ -409,12 +411,23 @@ struct fanotify_path_event { · 159 unmodified lines
409411 struct path path;
410412 };
411413
414+struct fanotify_mnt_event {
415+ struct fanotify_event fae;
416+ u64 mnt_id;
417+};
418+
412419 static inline struct fanotify_path_event *
413420 FANOTIFY_PE(struct fanotify_event *event)
414421 {
415422 return container_of(event, struct fanotify_path_event, fae);
416423 }
417424
425+static inline struct fanotify_mnt_event *
426+FANOTIFY_ME(struct fanotify_event *event)
427+{
428+ return container_of(event, struct fanotify_mnt_event, fae);
429+}
430+
418431 /*
419432 * Structure for permission fanotify events. It gets allocated and freed in
420433 * fanotify_handle_event() since we wait there for user response. When the
@@ -466,6 +479,11 @@ static inline bool fanotify_is_error_event(u32 mask) · 45 unmodified lines
466479 return mask & FAN_FS_ERROR;
467480 }
468481
482+static inline bool fanotify_is_mnt_event(u32 mask)
483+{
484+ return mask & (FAN_MNT_ATTACH | FAN_MNT_DETACH);
485+}
486+
469487 static inline const struct path *fanotify_event_path(struct fanotify_event *event)
470488 {
471489 if (event->type == FANOTIFY_EVENT_TYPE_PATH)
fs/notify/fanotify/fanotify_user.c+75−14
@@ -113,6 +113,7 @@ struct kmem_cache *fanotify_mark_cache __ro_after_init; · 112 unmodified lines
113113 struct kmem_cache *fanotify_fid_event_cachep __ro_after_init;
114114 struct kmem_cache *fanotify_path_event_cachep __ro_after_init;
115115 struct kmem_cache *fanotify_perm_event_cachep __ro_after_init;
116+struct kmem_cache *fanotify_mnt_event_cachep __ro_after_init;
116117
117118 #define FANOTIFY_EVENT_ALIGN 4
118119 #define FANOTIFY_FID_INFO_HDR_LEN \
@@ -123,6 +124,8 @@ struct kmem_cache *fanotify_perm_event_cachep __ro_after_init; · 4 unmodified lines
123124 (sizeof(struct fanotify_event_info_error))
124125 #define FANOTIFY_RANGE_INFO_LEN \
125126 (sizeof(struct fanotify_event_info_range))
127+#define FANOTIFY_MNT_INFO_LEN \
128+ (sizeof(struct fanotify_event_info_mnt))
126129
127130 static int fanotify_fid_info_len(int fh_len, int name_len)
128131 {
@@ -178,6 +181,8 @@ static size_t fanotify_event_len(unsigned int info_mode, · 49 unmodified lines
178181 fh_len = fanotify_event_object_fh_len(event);
179182 event_len += fanotify_fid_info_len(fh_len, dot_len);
180183 }
184+ if (fanotify_is_mnt_event(event->mask))
185+ event_len += FANOTIFY_MNT_INFO_LEN;
181186
182187 if (info_mode & FAN_REPORT_PIDFD)
183188 event_len += FANOTIFY_PIDFD_INFO_LEN;
@@ -405,6 +410,25 @@ static int process_access_response(struct fsnotify_group *group, · 221 unmodified lines
405410 return -ENOENT;
406411 }
407412
413+static size_t copy_mnt_info_to_user(struct fanotify_event *event,
414+ char __user *buf, int count)
415+{
416+ struct fanotify_event_info_mnt info = { };
417+
418+ info.hdr.info_type = FAN_EVENT_INFO_TYPE_MNT;
419+ info.hdr.len = FANOTIFY_MNT_INFO_LEN;
420+
421+ if (WARN_ON(count < info.hdr.len))
422+ return -EFAULT;
423+
424+ info.mnt_id = FANOTIFY_ME(event)->mnt_id;
425+
426+ if (copy_to_user(buf, &info, sizeof(info)))
427+ return -EFAULT;
428+
429+ return info.hdr.len;
430+}
431+
408432 static size_t copy_error_info_to_user(struct fanotify_event *event,
409433 char __user *buf, int count)
410434 {
@@ -700,6 +724,15 @@ static int copy_info_records_to_user(struct fanotify_event *event, · 289 unmodified lines
700724 total_bytes += ret;
701725 }
702726
727+ if (fanotify_is_mnt_event(event->mask)) {
728+ ret = copy_mnt_info_to_user(event, buf, count);
729+ if (ret < 0)
730+ return ret;
731+ buf += ret;
732+ count -= ret;
733+ total_bytes += ret;
734+ }
735+
703736 return total_bytes;
704737 }
705738
@@ -1508,6 +1541,14 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags) · 802 unmodified lines
15081541 if ((flags & FAN_REPORT_PIDFD) && (flags & FAN_REPORT_TID))
15091542 return -EINVAL;
15101543
1544+ /* Don't allow mixing mnt events with inode events for now */
1545+ if (flags & FAN_REPORT_MNT) {
1546+ if (class != FAN_CLASS_NOTIF)
1547+ return -EINVAL;
1548+ if (flags & (FANOTIFY_FID_BITS | FAN_REPORT_FD_ERROR))
1549+ return -EINVAL;
1550+ }
1551+
15111552 if (event_f_flags & ~FANOTIFY_INIT_ALL_EVENT_F_BITS)
15121553 return -EINVAL;
15131554
@@ -1767,7 +1808,6 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, · 253 unmodified lines
17671808 int dfd, const char __user *pathname)
17681809 {
17691810 struct inode *inode = NULL;
1770− struct vfsmount *mnt = NULL;
17711811 struct fsnotify_group *group;
17721812 struct path path;
17731813 struct fan_fsid __fsid, *fsid = NULL;
@@ -1776,7 +1816,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, · 2 unmodified lines
17761816 unsigned int mark_cmd = flags & FANOTIFY_MARK_CMD_BITS;
17771817 unsigned int ignore = flags & FANOTIFY_MARK_IGNORE_BITS;
17781818 unsigned int obj_type, fid_mode;
1779− void *obj;
1819+ void *obj = NULL;
17801820 u32 umask = 0;
17811821 int ret;
17821822
@@ -1800,6 +1840,9 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, · 17 unmodified lines
18001840 case FAN_MARK_FILESYSTEM:
18011841 obj_type = FSNOTIFY_OBJ_TYPE_SB;
18021842 break;
1843+ case FAN_MARK_MNTNS:
1844+ obj_type = FSNOTIFY_OBJ_TYPE_MNTNS;
1845+ break;
18031846 default:
18041847 return -EINVAL;
18051848 }
@@ -1847,6 +1890,19 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, · 41 unmodified lines
18471890 return -EINVAL;
18481891 group = fd_file(f)->private_data;
18491892
1893+ /* Only report mount events on mnt namespace */
1894+ if (FAN_GROUP_FLAG(group, FAN_REPORT_MNT)) {
1895+ if (mask & ~FANOTIFY_MOUNT_EVENTS)
1896+ return -EINVAL;
1897+ if (mark_type != FAN_MARK_MNTNS)
1898+ return -EINVAL;
1899+ } else {
1900+ if (mask & FANOTIFY_MOUNT_EVENTS)
1901+ return -EINVAL;
1902+ if (mark_type == FAN_MARK_MNTNS)
1903+ return -EINVAL;
1904+ }
1905+
18501906 /*
18511907 * An unprivileged user is not allowed to setup mount nor filesystem
18521908 * marks. This also includes setting up such marks by a group that
@@ -1888,7 +1944,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, · 35 unmodified lines
18881944 * point.
18891945 */
18901946 fid_mode = FAN_GROUP_FLAG(group, FANOTIFY_FID_BITS);
1891− if (mask & ~(FANOTIFY_FD_EVENTS|FANOTIFY_EVENT_FLAGS) &&
1947+ if (mask & ~(FANOTIFY_FD_EVENTS|FANOTIFY_MOUNT_EVENTS|FANOTIFY_EVENT_FLAGS) &&
18921948 (!fid_mode || mark_type == FAN_MARK_MOUNT))
18931949 return -EINVAL;
18941950
@@ -1938,17 +1994,21 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, · 43 unmodified lines
19381994 }
19391995
19401996 /* inode held in place by reference to path; group by fget on fd */
1941− if (mark_type == FAN_MARK_INODE) {
1997+ if (obj_type == FSNOTIFY_OBJ_TYPE_INODE) {
19421998 inode = path.dentry->d_inode;
19431999 obj = inode;
1944− } else {
1945− mnt = path.mnt;
1946− if (mark_type == FAN_MARK_MOUNT)
1947− obj = mnt;
1948− else
1949− obj = mnt->mnt_sb;
2000+ } else if (obj_type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) {
2001+ obj = path.mnt;
2002+ } else if (obj_type == FSNOTIFY_OBJ_TYPE_SB) {
2003+ obj = path.mnt->mnt_sb;
2004+ } else if (obj_type == FSNOTIFY_OBJ_TYPE_MNTNS) {
2005+ obj = mnt_ns_from_dentry(path.dentry);
19502006 }
19512007
2008+ ret = -EINVAL;
2009+ if (!obj)
2010+ goto path_put_and_out;
2011+
19522012 /*
19532013 * If some other task has this inode open for write we should not add
19542014 * an ignore mask, unless that ignore mask is supposed to survive
@@ -1956,10 +2016,10 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, · 1 unmodified line
19562016 */
19572017 if (mark_cmd == FAN_MARK_ADD && (flags & FANOTIFY_MARK_IGNORE_BITS) &&
19582018 !(flags & FAN_MARK_IGNORED_SURV_MODIFY)) {
1959− ret = mnt ? -EINVAL : -EISDIR;
2019+ ret = !inode ? -EINVAL : -EISDIR;
19602020 /* FAN_MARK_IGNORE requires SURV_MODIFY for sb/mount/dir marks */
19612021 if (ignore == FAN_MARK_IGNORE &&
1962− (mnt || S_ISDIR(inode->i_mode)))
2022+ (!inode || S_ISDIR(inode->i_mode)))
19632023 goto path_put_and_out;
19642024
19652025 ret = 0;
@@ -1968,7 +2028,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, · 2 unmodified lines
19682028 }
19692029
19702030 /* Mask out FAN_EVENT_ON_CHILD flag for sb/mount/non-dir marks */
1971− if (mnt || !S_ISDIR(inode->i_mode)) {
2031+ if (!inode || !S_ISDIR(inode->i_mode)) {
19722032 mask &= ~FAN_EVENT_ON_CHILD;
19732033 umask = FAN_EVENT_ON_CHILD;
19742034 /*
@@ -2042,7 +2102,7 @@ static int __init fanotify_user_setup(void) · 67 unmodified lines
20422102 FANOTIFY_DEFAULT_MAX_USER_MARKS);
20432103
20442104 BUILD_BUG_ON(FANOTIFY_INIT_FLAGS & FANOTIFY_INTERNAL_GROUP_FLAGS);
2045− BUILD_BUG_ON(HWEIGHT32(FANOTIFY_INIT_FLAGS) != 13);
2105+ BUILD_BUG_ON(HWEIGHT32(FANOTIFY_INIT_FLAGS) != 14);
20462106 BUILD_BUG_ON(HWEIGHT32(FANOTIFY_MARK_FLAGS) != 11);
20472107
20482108 fanotify_mark_cache = KMEM_CACHE(fanotify_mark,
@@ -2055,6 +2115,7 @@ static int __init fanotify_user_setup(void) · 6 unmodified lines
20552115 fanotify_perm_event_cachep =
20562116 KMEM_CACHE(fanotify_perm_event, SLAB_PANIC);
20572117 }
2118+ fanotify_mnt_event_cachep = KMEM_CACHE(fanotify_mnt_event, SLAB_PANIC);
20582119
20592120 fanotify_max_queued_events = FANOTIFY_DEFAULT_MAX_EVENTS;
20602121 init_user_ns.ucount_max[UCOUNT_FANOTIFY_GROUPS] =
fs/notify/fdinfo.c+5−0
@@ -121,6 +121,11 @@ static void fanotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark) · 120 unmodified lines
121121
122122 seq_printf(m, "fanotify sdev:%x mflags:%x mask:%x ignored_mask:%x\n",
123123 sb->s_dev, mflags, mark->mask, mark->ignore_mask);
124+ } else if (mark->connector->type == FSNOTIFY_OBJ_TYPE_MNTNS) {
125+ struct mnt_namespace *mnt_ns = fsnotify_conn_mntns(mark->connector);
126+
127+ seq_printf(m, "fanotify mnt_ns:%u mflags:%x mask:%x ignored_mask:%x\n",
128+ mnt_ns->ns.inum, mflags, mark->mask, mark->ignore_mask);
124129 }
125130 }
126131
fs/notify/fsnotify.c+40−7
@@ -28,6 +28,11 @@ void __fsnotify_vfsmount_delete(struct vfsmount *mnt) · 27 unmodified lines
2828 fsnotify_clear_marks_by_mount(mnt);
2929 }
3030
31+void __fsnotify_mntns_delete(struct mnt_namespace *mntns)
32+{
33+ fsnotify_clear_marks_by_mntns(mntns);
34+}
35+
3136 /**
3237 * fsnotify_unmount_inodes - an sb is unmounting. handle any watched inodes.
3338 * @sb: superblock being unmounted.
@@ -420,7 +425,7 @@ static int send_to_group(__u32 mask, const void *data, int data_type, · 386 unmodified lines
420425 file_name, cookie, iter_info);
421426 }
422427
423−static struct fsnotify_mark *fsnotify_first_mark(struct fsnotify_mark_connector **connp)
428+static struct fsnotify_mark *fsnotify_first_mark(struct fsnotify_mark_connector *const *connp)
424429 {
425430 struct fsnotify_mark_connector *conn;
426431 struct hlist_node *node = NULL;
@@ -538,14 +543,15 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir, · 111 unmodified lines
538543 {
539544 const struct path *path = fsnotify_data_path(data, data_type);
540545 struct super_block *sb = fsnotify_data_sb(data, data_type);
541− struct fsnotify_sb_info *sbinfo = fsnotify_sb_info(sb);
546+ const struct fsnotify_mnt *mnt_data = fsnotify_data_mnt(data, data_type);
547+ struct fsnotify_sb_info *sbinfo = sb ? fsnotify_sb_info(sb) : NULL;
542548 struct fsnotify_iter_info iter_info = {};
543549 struct mount *mnt = NULL;
544550 struct inode *inode2 = NULL;
545551 struct dentry *moved;
546552 int inode2_type;
547553 int ret = 0;
548− __u32 test_mask, marks_mask;
554+ __u32 test_mask, marks_mask = 0;
549555
550556 if (path)
551557 mnt = real_mount(path->mnt);
@@ -578,17 +584,20 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir, · 26 unmodified lines
578584 if ((!sbinfo || !sbinfo->sb_marks) &&
579585 (!mnt || !mnt->mnt_fsnotify_marks) &&
580586 (!inode || !inode->i_fsnotify_marks) &&
581− (!inode2 || !inode2->i_fsnotify_marks))
587+ (!inode2 || !inode2->i_fsnotify_marks) &&
588+ (!mnt_data || !mnt_data->ns->n_fsnotify_marks))
582589 return 0;
583590
584− marks_mask = READ_ONCE(sb->s_fsnotify_mask);
591+ if (sb)
592+ marks_mask |= READ_ONCE(sb->s_fsnotify_mask);
585593 if (mnt)
586594 marks_mask |= READ_ONCE(mnt->mnt_fsnotify_mask);
587595 if (inode)
588596 marks_mask |= READ_ONCE(inode->i_fsnotify_mask);
589597 if (inode2)
590598 marks_mask |= READ_ONCE(inode2->i_fsnotify_mask);
591−
599+ if (mnt_data)
600+ marks_mask |= READ_ONCE(mnt_data->ns->n_fsnotify_mask);
592601
593602 /*
594603 * If this is a modify event we may need to clear some ignore masks.
@@ -618,6 +627,10 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir, · 23 unmodified lines
618627 iter_info.marks[inode2_type] =
619628 fsnotify_first_mark(&inode2->i_fsnotify_marks);
620629 }
630+ if (mnt_data) {
631+ iter_info.marks[FSNOTIFY_ITER_TYPE_MNTNS] =
632+ fsnotify_first_mark(&mnt_data->ns->n_fsnotify_marks);
633+ }
621634
622635 /*
623636 * We need to merge inode/vfsmount/sb mark lists so that e.g. inode mark
@@ -708,11 +721,31 @@ void file_set_fsnotify_mode_from_watchers(struct file *file) · 84 unmodified lines
708721 }
709722 #endif
710723
724+void fsnotify_mnt(__u32 mask, struct mnt_namespace *ns, struct vfsmount *mnt)
725+{
726+ struct fsnotify_mnt data = {
727+ .ns = ns,
728+ .mnt_id = real_mount(mnt)->mnt_id_unique,
729+ };
730+
731+ if (WARN_ON_ONCE(!ns))
732+ return;
733+
734+ /*
735+ * This is an optimization as well as making sure fsnotify_init() has
736+ * been called.
737+ */
738+ if (!ns->n_fsnotify_marks)
739+ return;
740+
741+ fsnotify(mask, &data, FSNOTIFY_EVENT_MNT, NULL, NULL, NULL, 0);
742+}
743+
711744 static __init int fsnotify_init(void)
712745 {
713746 int ret;
714747
715− BUILD_BUG_ON(HWEIGHT32(ALL_FSNOTIFY_BITS) != 24);
748+ BUILD_BUG_ON(HWEIGHT32(ALL_FSNOTIFY_BITS) != 26);
716749
717750 ret = init_srcu_struct(&fsnotify_mark_srcu);
718751 if (ret)
fs/notify/fsnotify.h+11−0
@@ -33,6 +33,12 @@ static inline struct super_block *fsnotify_conn_sb( · 32 unmodified lines
3333 return conn->obj;
3434 }
3535
36+static inline struct mnt_namespace *fsnotify_conn_mntns(
37+ struct fsnotify_mark_connector *conn)
38+{
39+ return conn->obj;
40+}
41+
3642 static inline struct super_block *fsnotify_object_sb(void *obj,
3743 enum fsnotify_obj_type obj_type)
3844 {
@@ -89,6 +95,11 @@ static inline void fsnotify_clear_marks_by_sb(struct super_block *sb) · 50 unmodified lines
8995 fsnotify_destroy_marks(fsnotify_sb_marks(sb));
9096 }
9197
98+static inline void fsnotify_clear_marks_by_mntns(struct mnt_namespace *mntns)
99+{
100+ fsnotify_destroy_marks(&mntns->n_fsnotify_marks);
101+}
102+
92103 /*
93104 * update the dentry->d_flags of all of inode's children to indicate if inode cares
94105 * about events that happen to its children.
fs/notify/mark.c+11−3
@@ -107,6 +107,8 @@ static fsnotify_connp_t *fsnotify_object_connp(void *obj, · 106 unmodified lines
107107 return &real_mount(obj)->mnt_fsnotify_marks;
108108 case FSNOTIFY_OBJ_TYPE_SB:
109109 return fsnotify_sb_marks(obj);
110+ case FSNOTIFY_OBJ_TYPE_MNTNS:
111+ return &((struct mnt_namespace *)obj)->n_fsnotify_marks;
110112 default:
111113 return NULL;
112114 }
@@ -120,6 +122,8 @@ static __u32 *fsnotify_conn_mask_p(struct fsnotify_mark_connector *conn) · 7 unmodified lines
120122 return &fsnotify_conn_mount(conn)->mnt_fsnotify_mask;
121123 else if (conn->type == FSNOTIFY_OBJ_TYPE_SB)
122124 return &fsnotify_conn_sb(conn)->s_fsnotify_mask;
125+ else if (conn->type == FSNOTIFY_OBJ_TYPE_MNTNS)
126+ return &fsnotify_conn_mntns(conn)->n_fsnotify_mask;
123127 return NULL;
124128 }
125129
@@ -346,12 +350,15 @@ static void *fsnotify_detach_connector_from_object( · 220 unmodified lines
346350 fsnotify_conn_mount(conn)->mnt_fsnotify_mask = 0;
347351 } else if (conn->type == FSNOTIFY_OBJ_TYPE_SB) {
348352 fsnotify_conn_sb(conn)->s_fsnotify_mask = 0;
353+ } else if (conn->type == FSNOTIFY_OBJ_TYPE_MNTNS) {
354+ fsnotify_conn_mntns(conn)->n_fsnotify_mask = 0;
349355 }
350356
351357 rcu_assign_pointer(*connp, NULL);
352358 conn->obj = NULL;
353359 conn->type = FSNOTIFY_OBJ_TYPE_DETACHED;
354− fsnotify_update_sb_watchers(sb, conn);
360+ if (sb)
361+ fsnotify_update_sb_watchers(sb, conn);
355362
356363 return inode;
357364 }
@@ -724,7 +731,7 @@ static int fsnotify_add_mark_list(struct fsnotify_mark *mark, void *obj, · 366 unmodified lines
724731 * Attach the sb info before attaching a connector to any object on sb.
725732 * The sb info will remain attached as long as sb lives.
726733 */
727− if (!fsnotify_sb_info(sb)) {
734+ if (sb && !fsnotify_sb_info(sb)) {
728735 err = fsnotify_attach_info_to_sb(sb);
729736 if (err)
730737 return err;
@@ -770,7 +777,8 @@ restart: · 39 unmodified lines
770777 /* mark should be the last entry. last is the current last entry */
771778 hlist_add_behind_rcu(&mark->obj_list, &last->obj_list);
772779 added:
773− fsnotify_update_sb_watchers(sb, conn);
780+ if (sb)
781+ fsnotify_update_sb_watchers(sb, conn);
774782 /*
775783 * Since connector is attached to object using cmpxchg() we are
776784 * guaranteed that connector initialization is fully visible by anyone
fs/pnode.c+3−1
@@ -549,8 +549,10 @@ static void restore_mounts(struct list_head *to_restore) · 548 unmodified lines
549549 mp = parent->mnt_mp;
550550 parent = parent->mnt_parent;
551551 }
552− if (parent != mnt->mnt_parent)
552+ if (parent != mnt->mnt_parent) {
553553 mnt_change_mountpoint(parent, mp, mnt);
554+ mnt_notify_add(mnt);
555+ }
554556 }
555557 }
556558
include/linux/fanotify.h+8−4
@@ -25,7 +25,7 @@ · 24 unmodified lines
2525
2626 #define FANOTIFY_FID_BITS (FAN_REPORT_DFID_NAME_TARGET)
2727
28−#define FANOTIFY_INFO_MODES (FANOTIFY_FID_BITS | FAN_REPORT_PIDFD)
28+#define FANOTIFY_INFO_MODES (FANOTIFY_FID_BITS | FAN_REPORT_PIDFD | FAN_REPORT_MNT)
2929
3030 /*
3131 * fanotify_init() flags that require CAP_SYS_ADMIN.
@@ -38,7 +38,8 @@ · 6 unmodified lines
3838 FAN_REPORT_PIDFD | \
3939 FAN_REPORT_FD_ERROR | \
4040 FAN_UNLIMITED_QUEUE | \
41− FAN_UNLIMITED_MARKS)
41+ FAN_UNLIMITED_MARKS | \
42+ FAN_REPORT_MNT)
4243
4344 /*
4445 * fanotify_init() flags that are allowed for user without CAP_SYS_ADMIN.
@@ -58,7 +59,7 @@ · 13 unmodified lines
5859 #define FANOTIFY_INTERNAL_GROUP_FLAGS (FANOTIFY_UNPRIV)
5960
6061 #define FANOTIFY_MARK_TYPE_BITS (FAN_MARK_INODE | FAN_MARK_MOUNT | \
61− FAN_MARK_FILESYSTEM)
62+ FAN_MARK_FILESYSTEM | FAN_MARK_MNTNS)
6263
6364 #define FANOTIFY_MARK_CMD_BITS (FAN_MARK_ADD | FAN_MARK_REMOVE | \
6465 FAN_MARK_FLUSH)
@@ -109,10 +110,13 @@ · 44 unmodified lines
109110 /* Events that can only be reported with data type FSNOTIFY_EVENT_ERROR */
110111 #define FANOTIFY_ERROR_EVENTS (FAN_FS_ERROR)
111112
113+#define FANOTIFY_MOUNT_EVENTS (FAN_MNT_ATTACH | FAN_MNT_DETACH)
114+
112115 /* Events that user can request to be notified on */
113116 #define FANOTIFY_EVENTS (FANOTIFY_PATH_EVENTS | \
114117 FANOTIFY_INODE_EVENTS | \
115− FANOTIFY_ERROR_EVENTS)
118+ FANOTIFY_ERROR_EVENTS | \
119+ FANOTIFY_MOUNT_EVENTS)
116120
117121 /* Extra flags that may be reported with event or control handling of events */
118122 #define FANOTIFY_EVENT_FLAGS (FAN_EVENT_ON_CHILD | FAN_ONDIR)
include/linux/fsnotify.h+20−0
@@ -320,6 +320,11 @@ static inline void fsnotify_vfsmount_delete(struct vfsmount *mnt) · 319 unmodified lines
320320 __fsnotify_vfsmount_delete(mnt);
321321 }
322322
323+static inline void fsnotify_mntns_delete(struct mnt_namespace *mntns)
324+{
325+ __fsnotify_mntns_delete(mntns);
326+}
327+
323328 /*
324329 * fsnotify_inoderemove - an inode is going away
325330 */
@@ -528,4 +533,19 @@ static inline int fsnotify_sb_error(struct super_block *sb, struct inode *inode, · 202 unmodified lines
528533 NULL, NULL, NULL, 0);
529534 }
530535
536+static inline void fsnotify_mnt_attach(struct mnt_namespace *ns, struct vfsmount *mnt)
537+{
538+ fsnotify_mnt(FS_MNT_ATTACH, ns, mnt);
539+}
540+
541+static inline void fsnotify_mnt_detach(struct mnt_namespace *ns, struct vfsmount *mnt)
542+{
543+ fsnotify_mnt(FS_MNT_DETACH, ns, mnt);
544+}
545+
546+static inline void fsnotify_mnt_move(struct mnt_namespace *ns, struct vfsmount *mnt)
547+{
548+ fsnotify_mnt(FS_MNT_MOVE, ns, mnt);
549+}
550+
531551 #endif /* _LINUX_FS_NOTIFY_H */
include/linux/fsnotify_backend.h+42−0
@@ -59,6 +59,10 @@ · 58 unmodified lines
5959
6060 #define FS_PRE_ACCESS 0x00100000 /* Pre-content access hook */
6161
62+#define FS_MNT_ATTACH 0x01000000 /* Mount was attached */
63+#define FS_MNT_DETACH 0x02000000 /* Mount was detached */
64+#define FS_MNT_MOVE (FS_MNT_ATTACH | FS_MNT_DETACH)
65+
6266 /*
6367 * Set on inode mark that cares about things that happen to its children.
6468 * Always set for dnotify and inotify.
@@ -80,6 +84,9 @@ · 15 unmodified lines
8084 */
8185 #define ALL_FSNOTIFY_DIRENT_EVENTS (FS_CREATE | FS_DELETE | FS_MOVE | FS_RENAME)
8286
87+/* Mount namespace events */
88+#define FSNOTIFY_MNT_EVENTS (FS_MNT_ATTACH | FS_MNT_DETACH)
89+
8390 /* Content events can be used to inspect file content */
8491 #define FSNOTIFY_CONTENT_PERM_EVENTS (FS_OPEN_PERM | FS_OPEN_EXEC_PERM | \
8592 FS_ACCESS_PERM)
@@ -108,6 +115,7 @@ · 22 unmodified lines
108115
109116 /* Events that can be reported to backends */
110117 #define ALL_FSNOTIFY_EVENTS (ALL_FSNOTIFY_DIRENT_EVENTS | \
118+ FSNOTIFY_MNT_EVENTS | \
111119 FS_EVENTS_POSS_ON_CHILD | \
112120 FS_DELETE_SELF | FS_MOVE_SELF | \
113121 FS_UNMOUNT | FS_Q_OVERFLOW | FS_IN_IGNORED | \
@@ -298,6 +306,7 @@ enum fsnotify_data_type { · 184 unmodified lines
298306 FSNOTIFY_EVENT_PATH,
299307 FSNOTIFY_EVENT_INODE,
300308 FSNOTIFY_EVENT_DENTRY,
309+ FSNOTIFY_EVENT_MNT,
301310 FSNOTIFY_EVENT_ERROR,
302311 };
303312
@@ -318,6 +327,11 @@ static inline const struct path *file_range_path(const struct file_range *range) · 14 unmodified lines
318327 return range->path;
319328 }
320329
330+struct fsnotify_mnt {
331+ const struct mnt_namespace *ns;
332+ u64 mnt_id;
333+};
334+
321335 static inline struct inode *fsnotify_data_inode(const void *data, int data_type)
322336 {
323337 switch (data_type) {
@@ -383,6 +397,24 @@ static inline struct super_block *fsnotify_data_sb(const void *data, · 59 unmodified lines
383397 }
384398 }
385399
400+static inline const struct fsnotify_mnt *fsnotify_data_mnt(const void *data,
401+ int data_type)
402+{
403+ switch (data_type) {
404+ case FSNOTIFY_EVENT_MNT:
405+ return data;
406+ default:
407+ return NULL;
408+ }
409+}
410+
411+static inline u64 fsnotify_data_mnt_id(const void *data, int data_type)
412+{
413+ const struct fsnotify_mnt *mnt_data = fsnotify_data_mnt(data, data_type);
414+
415+ return mnt_data ? mnt_data->mnt_id : 0;
416+}
417+
386418 static inline struct fs_error_report *fsnotify_data_error_report(
387419 const void *data,
388420 int data_type)
@@ -420,6 +452,7 @@ enum fsnotify_iter_type { · 31 unmodified lines
420452 FSNOTIFY_ITER_TYPE_SB,
421453 FSNOTIFY_ITER_TYPE_PARENT,
422454 FSNOTIFY_ITER_TYPE_INODE2,
455+ FSNOTIFY_ITER_TYPE_MNTNS,
423456 FSNOTIFY_ITER_TYPE_COUNT
424457 };
425458
@@ -429,6 +462,7 @@ enum fsnotify_obj_type { · 3 unmodified lines
429462 FSNOTIFY_OBJ_TYPE_INODE,
430463 FSNOTIFY_OBJ_TYPE_VFSMOUNT,
431464 FSNOTIFY_OBJ_TYPE_SB,
465+ FSNOTIFY_OBJ_TYPE_MNTNS,
432466 FSNOTIFY_OBJ_TYPE_COUNT,
433467 FSNOTIFY_OBJ_TYPE_DETACHED = FSNOTIFY_OBJ_TYPE_COUNT
434468 };
@@ -613,8 +647,10 @@ extern int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data · 178 unmodified lines
613647 extern void __fsnotify_inode_delete(struct inode *inode);
614648 extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt);
615649 extern void fsnotify_sb_delete(struct super_block *sb);
650+extern void __fsnotify_mntns_delete(struct mnt_namespace *mntns);
616651 extern void fsnotify_sb_free(struct super_block *sb);
617652 extern u32 fsnotify_get_cookie(void);
653+extern void fsnotify_mnt(__u32 mask, struct mnt_namespace *ns, struct vfsmount *mnt);
618654
619655 static inline __u32 fsnotify_parent_needed_mask(__u32 mask)
620656 {
@@ -928,6 +964,9 @@ static inline void __fsnotify_vfsmount_delete(struct vfsmount *mnt) · 307 unmodified lines
928964 static inline void fsnotify_sb_delete(struct super_block *sb)
929965 {}
930966
967+static inline void __fsnotify_mntns_delete(struct mnt_namespace *mntns)
968+{}
969+
931970 static inline void fsnotify_sb_free(struct super_block *sb)
932971 {}
933972
@@ -942,6 +981,9 @@ static inline u32 fsnotify_get_cookie(void) · 8 unmodified lines
942981 static inline void fsnotify_unmount_inodes(struct super_block *sb)
943982 {}
944983
984+static inline void fsnotify_mnt(__u32 mask, struct mnt_namespace *ns, struct vfsmount *mnt)
985+{}
986+
945987 #endif /* CONFIG_FSNOTIFY */
946988
947989 #endif /* __KERNEL __ */
include/linux/mnt_idmapping.h+5−0
@@ -25,6 +25,11 @@ static_assert(sizeof(vfsgid_t) == sizeof(kgid_t)); · 24 unmodified lines
2525 static_assert(offsetof(vfsuid_t, val) == offsetof(kuid_t, val));
2626 static_assert(offsetof(vfsgid_t, val) == offsetof(kgid_t, val));
2727
28+static inline bool is_valid_mnt_idmap(const struct mnt_idmap *idmap)
29+{
30+ return idmap != &nop_mnt_idmap && idmap != &invalid_mnt_idmap;
31+}
32+
2833 #ifdef CONFIG_MULTIUSER
2934 static inline uid_t __vfsuid_val(vfsuid_t uid)
3035 {
include/linux/syscalls.h+4−0
@@ -951,6 +951,10 @@ asmlinkage long sys_statx(int dfd, const char __user *path, unsigned flags, · 950 unmodified lines
951951 asmlinkage long sys_rseq(struct rseq __user *rseq, uint32_t rseq_len,
952952 int flags, uint32_t sig);
953953 asmlinkage long sys_open_tree(int dfd, const char __user *path, unsigned flags);
954+asmlinkage long sys_open_tree_attr(int dfd, const char __user *path,
955+ unsigned flags,
956+ struct mount_attr __user *uattr,
957+ size_t usize);
954958 asmlinkage long sys_move_mount(int from_dfd, const char __user *from_path,
955959 int to_dfd, const char __user *to_path,
956960 unsigned int ms_flags);
include/linux/uidgid.h+6−0
@@ -132,6 +132,7 @@ static inline bool kgid_has_mapping(struct user_namespace *ns, kgid_t gid) · 131 unmodified lines
132132
133133 u32 map_id_down(struct uid_gid_map *map, u32 id);
134134 u32 map_id_up(struct uid_gid_map *map, u32 id);
135+u32 map_id_range_up(struct uid_gid_map *map, u32 id, u32 count);
135136
136137 #else
137138
@@ -186,6 +187,11 @@ static inline u32 map_id_down(struct uid_gid_map *map, u32 id) · 48 unmodified lines
186187 return id;
187188 }
188189
190+static inline u32 map_id_range_up(struct uid_gid_map *map, u32 id, u32 count)
191+{
192+ return id;
193+}
194+
189195 static inline u32 map_id_up(struct uid_gid_map *map, u32 id)
190196 {
191197 return id;
include/uapi/asm-generic/unistd.h+3−1
@@ -849,9 +849,11 @@ __SYSCALL(__NR_getxattrat, sys_getxattrat) · 848 unmodified lines
849849 __SYSCALL(__NR_listxattrat, sys_listxattrat)
850850 #define __NR_removexattrat 466
851851 __SYSCALL(__NR_removexattrat, sys_removexattrat)
852+#define __NR_open_tree_attr 467
853+__SYSCALL(__NR_open_tree_attr, sys_open_tree_attr)
852854
853855 #undef __NR_syscalls
854−#define __NR_syscalls 467
856+#define __NR_syscalls 468
855857
856858 /*
857859 * 32 bit systems traditionally used different
include/uapi/linux/fanotify.h+10−0
@@ -28,6 +28,8 @@ · 27 unmodified lines
2828 /* #define FAN_DIR_MODIFY 0x00080000 */ /* Deprecated (reserved) */
2929
3030 #define FAN_PRE_ACCESS 0x00100000 /* Pre-content access hook */
31+#define FAN_MNT_ATTACH 0x01000000 /* Mount was attached */
32+#define FAN_MNT_DETACH 0x02000000 /* Mount was detached */
3133
3234 #define FAN_EVENT_ON_CHILD 0x08000000 /* Interested in child events */
3335
@@ -64,6 +66,7 @@ · 30 unmodified lines
6466 #define FAN_REPORT_NAME 0x00000800 /* Report events with name */
6567 #define FAN_REPORT_TARGET_FID 0x00001000 /* Report dirent target id */
6668 #define FAN_REPORT_FD_ERROR 0x00002000 /* event->fd can report error */
69+#define FAN_REPORT_MNT 0x00004000 /* Report mount events */
6770
6871 /* Convenience macro - FAN_REPORT_NAME requires FAN_REPORT_DIR_FID */
6972 #define FAN_REPORT_DFID_NAME (FAN_REPORT_DIR_FID | FAN_REPORT_NAME)
@@ -94,6 +97,7 @@ · 24 unmodified lines
9497 #define FAN_MARK_INODE 0x00000000
9598 #define FAN_MARK_MOUNT 0x00000010
9699 #define FAN_MARK_FILESYSTEM 0x00000100
100+#define FAN_MARK_MNTNS 0x00000110
97101
98102 /*
99103 * Convenience macro - FAN_MARK_IGNORE requires FAN_MARK_IGNORED_SURV_MODIFY
@@ -147,6 +151,7 @@ struct fanotify_event_metadata { · 47 unmodified lines
147151 #define FAN_EVENT_INFO_TYPE_PIDFD 4
148152 #define FAN_EVENT_INFO_TYPE_ERROR 5
149153 #define FAN_EVENT_INFO_TYPE_RANGE 6
154+#define FAN_EVENT_INFO_TYPE_MNT 7
150155
151156 /* Special info types for FAN_RENAME */
152157 #define FAN_EVENT_INFO_TYPE_OLD_DFID_NAME 10
@@ -200,6 +205,11 @@ struct fanotify_event_info_range { · 47 unmodified lines
200205 __u64 count;
201206 };
202207
208+struct fanotify_event_info_mnt {
209+ struct fanotify_event_info_header hdr;
210+ __u64 mnt_id;
211+};
212+
203213 /*
204214 * User space may need to record additional information about its decision.
205215 * The extra information type records what kind of information is included.
include/uapi/linux/mount.h+9−1
@@ -179,7 +179,12 @@ struct statmount { · 178 unmodified lines
179179 __u32 opt_array; /* [str] Array of nul terminated fs options */
180180 __u32 opt_sec_num; /* Number of security options */
181181 __u32 opt_sec_array; /* [str] Array of nul terminated security options */
182− __u64 __spare2[46];
182+ __u64 supported_mask; /* Mask flags that this kernel supports */
183+ __u32 mnt_uidmap_num; /* Number of uid mappings */
184+ __u32 mnt_uidmap; /* [str] Array of uid mappings (as seen from callers namespace) */
185+ __u32 mnt_gidmap_num; /* Number of gid mappings */
186+ __u32 mnt_gidmap; /* [str] Array of gid mappings (as seen from callers namespace) */
187+ __u64 __spare2[43];
183188 char str[]; /* Variable size part containing strings */
184189 };
185190
@@ -217,6 +222,9 @@ struct mnt_id_req { · 31 unmodified lines
217222 #define STATMOUNT_SB_SOURCE 0x00000200U /* Want/got sb_source */
218223 #define STATMOUNT_OPT_ARRAY 0x00000400U /* Want/got opt_... */
219224 #define STATMOUNT_OPT_SEC_ARRAY 0x00000800U /* Want/got opt_sec... */
225+#define STATMOUNT_SUPPORTED_MASK 0x00001000U /* Want/got supported mask flags */
226+#define STATMOUNT_MNT_UIDMAP 0x00002000U /* Want/got uidmap... */
227+#define STATMOUNT_MNT_GIDMAP 0x00004000U /* Want/got gidmap... */
220228
221229 /*
222230 * Special @mnt_id values that can be passed to listmount
kernel/user_namespace.c+17−9
@@ -238,7 +238,7 @@ EXPORT_SYMBOL(__put_user_ns); · 237 unmodified lines
238238 struct idmap_key {
239239 bool map_up; /* true -> id from kid; false -> kid from id */
240240 u32 id; /* id to find */
241− u32 count; /* == 0 unless used with map_id_range_down() */
241+ u32 count;
242242 };
243243
244244 /*
@@ -343,16 +343,19 @@ u32 map_id_down(struct uid_gid_map *map, u32 id) · 98 unmodified lines
343343 * UID_GID_MAP_MAX_BASE_EXTENTS.
344344 */
345345 static struct uid_gid_extent *
346−map_id_up_base(unsigned extents, struct uid_gid_map *map, u32 id)
346+map_id_range_up_base(unsigned extents, struct uid_gid_map *map, u32 id, u32 count)
347347 {
348348 unsigned idx;
349− u32 first, last;
349+ u32 first, last, id2;
350+
351+ id2 = id + count - 1;
350352
351353 /* Find the matching extent */
352354 for (idx = 0; idx < extents; idx++) {
353355 first = map->extent[idx].lower_first;
354356 last = first + map->extent[idx].count - 1;
355− if (id >= first && id <= last)
357+ if (id >= first && id <= last &&
358+ (id2 >= first && id2 <= last))
356359 return &map->extent[idx];
357360 }
358361 return NULL;
@@ -363,28 +366,28 @@ map_id_up_base(unsigned extents, struct uid_gid_map *map, u32 id) · 4 unmodified lines
363366 * Can only be called if number of mappings exceeds UID_GID_MAP_MAX_BASE_EXTENTS.
364367 */
365368 static struct uid_gid_extent *
366−map_id_up_max(unsigned extents, struct uid_gid_map *map, u32 id)
369+map_id_range_up_max(unsigned extents, struct uid_gid_map *map, u32 id, u32 count)
367370 {
368371 struct idmap_key key;
369372
370373 key.map_up = true;
371− key.count = 1;
374+ key.count = count;
372375 key.id = id;
373376
374377 return bsearch(&key, map->reverse, extents,
375378 sizeof(struct uid_gid_extent), cmp_map_id);
376379 }
377380
378−u32 map_id_up(struct uid_gid_map *map, u32 id)
381+u32 map_id_range_up(struct uid_gid_map *map, u32 id, u32 count)
379382 {
380383 struct uid_gid_extent *extent;
381384 unsigned extents = map->nr_extents;
382385 smp_rmb();
383386
384387 if (extents <= UID_GID_MAP_MAX_BASE_EXTENTS)
385− extent = map_id_up_base(extents, map, id);
388+ extent = map_id_range_up_base(extents, map, id, count);
386389 else
387− extent = map_id_up_max(extents, map, id);
390+ extent = map_id_range_up_max(extents, map, id, count);
388391
389392 /* Map the id or note failure */
390393 if (extent)
@@ -395,6 +398,11 @@ u32 map_id_up(struct uid_gid_map *map, u32 id) · 4 unmodified lines
395398 return id;
396399 }
397400
401+u32 map_id_up(struct uid_gid_map *map, u32 id)
402+{
403+ return map_id_range_up(map, id, 1);
404+}
405+
398406 /**
399407 * make_kuid - Map a user-namespace uid pair into a kuid.
400408 * @ns: User namespace that the uid is in
samples/vfs/samples-vfs.h+13−1
@@ -42,7 +42,11 @@ struct statmount { · 41 unmodified lines
4242 __u32 opt_array; /* [str] Array of nul terminated fs options */
4343 __u32 opt_sec_num; /* Number of security options */
4444 __u32 opt_sec_array; /* [str] Array of nul terminated security options */
45− __u64 __spare2[46];
45+ __u32 mnt_uidmap_num; /* Number of uid mappings */
46+ __u32 mnt_uidmap; /* [str] Array of uid mappings */
47+ __u32 mnt_gidmap_num; /* Number of gid mappings */
48+ __u32 mnt_gidmap; /* [str] Array of gid mappings */
49+ __u64 __spare2[44];
4650 char str[]; /* Variable size part containing strings */
4751 };
4852
@@ -158,6 +162,14 @@ struct mnt_ns_info { · 109 unmodified lines
158162 #define STATX_MNT_ID_UNIQUE 0x00004000U /* Want/got extended stx_mount_id */
159163 #endif
160164
165+#ifndef STATMOUNT_MNT_UIDMAP
166+#define STATMOUNT_MNT_UIDMAP 0x00002000U /* Want/got uidmap... */
167+#endif
168+
169+#ifndef STATMOUNT_MNT_GIDMAP
170+#define STATMOUNT_MNT_GIDMAP 0x00004000U /* Want/got gidmap... */
171+#endif
172+
161173 #ifndef MOUNT_ATTR_RDONLY
162174 #define MOUNT_ATTR_RDONLY 0x00000001 /* Mount read-only */
163175 #endif
samples/vfs/test-list-all-mounts.c+29−6
@@ -128,20 +128,43 @@ next: · 127 unmodified lines
128128 STATMOUNT_MNT_POINT |
129129 STATMOUNT_MNT_NS_ID |
130130 STATMOUNT_MNT_OPTS |
131− STATMOUNT_FS_TYPE, 0);
131+ STATMOUNT_FS_TYPE |
132+ STATMOUNT_MNT_UIDMAP |
133+ STATMOUNT_MNT_GIDMAP, 0);
132134 if (!stmnt) {
133135 printf("Failed to statmount(%" PRIu64 ") in mount namespace(%" PRIu64 ")\n",
134136 (uint64_t)last_mnt_id, (uint64_t)info.mnt_ns_id);
135137 continue;
136138 }
137139
138− printf("mnt_id:\t\t%" PRIu64 "\nmnt_parent_id:\t%" PRIu64 "\nfs_type:\t%s\nmnt_root:\t%s\nmnt_point:\t%s\nmnt_opts:\t%s\n\n",
140+ printf("mnt_id:\t\t%" PRIu64 "\nmnt_parent_id:\t%" PRIu64 "\nfs_type:\t%s\nmnt_root:\t%s\nmnt_point:\t%s\nmnt_opts:\t%s\n",
139141 (uint64_t)stmnt->mnt_id,
140142 (uint64_t)stmnt->mnt_parent_id,
141− stmnt->str + stmnt->fs_type,
142− stmnt->str + stmnt->mnt_root,
143− stmnt->str + stmnt->mnt_point,
144− stmnt->str + stmnt->mnt_opts);
143+ (stmnt->mask & STATMOUNT_FS_TYPE) ? stmnt->str + stmnt->fs_type : "",
144+ (stmnt->mask & STATMOUNT_MNT_ROOT) ? stmnt->str + stmnt->mnt_root : "",
145+ (stmnt->mask & STATMOUNT_MNT_POINT) ? stmnt->str + stmnt->mnt_point : "",
146+ (stmnt->mask & STATMOUNT_MNT_OPTS) ? stmnt->str + stmnt->mnt_opts : "");
147+
148+ if (stmnt->mask & STATMOUNT_MNT_UIDMAP) {
149+ const char *idmap = stmnt->str + stmnt->mnt_uidmap;
150+
151+ for (size_t idx = 0; idx < stmnt->mnt_uidmap_num; idx++) {
152+ printf("mnt_uidmap[%zu]:\t%s\n", idx, idmap);
153+ idmap += strlen(idmap) + 1;
154+ }
155+ }
156+
157+ if (stmnt->mask & STATMOUNT_MNT_GIDMAP) {
158+ const char *idmap = stmnt->str + stmnt->mnt_gidmap;
159+
160+ for (size_t idx = 0; idx < stmnt->mnt_gidmap_num; idx++) {
161+ printf("mnt_gidmap[%zu]:\t%s\n", idx, idmap);
162+ idmap += strlen(idmap) + 1;
163+ }
164+ }
165+
166+ printf("\n");
167+
145168 free(stmnt);
146169 }
147170 }
scripts/syscall.tbl+1−0
@@ -407,3 +407,4 @@ · 406 unmodified lines
407407 464 common getxattrat sys_getxattrat
408408 465 common listxattrat sys_listxattrat
409409 466 common removexattrat sys_removexattrat
410+467 common open_tree_attr sys_open_tree_attr
security/selinux/hooks.c+3−0
@@ -3395,6 +3395,9 @@ static int selinux_path_notify(const struct path *path, u64 mask, · 3394 unmodified lines
33953395 case FSNOTIFY_OBJ_TYPE_INODE:
33963396 perm = FILE__WATCH;
33973397 break;
3398+ case FSNOTIFY_OBJ_TYPE_MNTNS:
3399+ perm = FILE__WATCH_MOUNTNS;
3400+ break;
33983401 default:
33993402 return -EINVAL;
34003403 }
security/selinux/include/classmap.h+1−1
@@ -8,7 +8,7 @@ · 7 unmodified lines
88 COMMON_FILE_SOCK_PERMS, "unlink", "link", "rename", "execute", \
99 "quotaon", "mounton", "audit_access", "open", "execmod", \
1010 "watch", "watch_mount", "watch_sb", "watch_with_perm", \
11− "watch_reads"
11+ "watch_reads", "watch_mountns"
1212
1313 #define COMMON_SOCK_PERMS \
1414 COMMON_FILE_SOCK_PERMS, "bind", "connect", "listen", "accept", \
tools/testing/selftests/Makefile+1−0
@@ -35,6 +35,7 @@ TARGETS += filesystems/epoll · 34 unmodified lines
3535 TARGETS += filesystems/fat
3636 TARGETS += filesystems/overlayfs
3737 TARGETS += filesystems/statmount
38+TARGETS += filesystems/mount-notify
3839 TARGETS += firmware
3940 TARGETS += fpu
4041 TARGETS += ftrace
tools/testing/selftests/filesystems/mount-notify/.gitignore+2−0
@@ -0,0 +1,2 @@
1+# SPDX-License-Identifier: GPL-2.0-only
2+/*_test
tools/testing/selftests/filesystems/mount-notify/Makefile+6−0
@@ -0,0 +1,6 @@
1+# SPDX-License-Identifier: GPL-2.0-or-later
2+
3+CFLAGS += -Wall -O2 -g $(KHDR_INCLUDES)
4+TEST_GEN_PROGS := mount-notify_test
5+
6+include ../../lib.mk
tools/testing/selftests/filesystems/mount-notify/mount-notify_test.c+516−0
@@ -0,0 +1,516 @@
1+// SPDX-License-Identifier: GPL-2.0-or-later
2+// Copyright (c) 2025 Miklos Szeredi <miklos@szeredi.hu>
3+
4+#define _GNU_SOURCE
5+#include <fcntl.h>
6+#include <sched.h>
7+#include <stdio.h>
8+#include <string.h>
9+#include <sys/stat.h>
10+#include <sys/mount.h>
11+#include <linux/fanotify.h>
12+#include <unistd.h>
13+#include <sys/fanotify.h>
14+#include <sys/syscall.h>
15+
16+#include "../../kselftest_harness.h"
17+#include "../statmount/statmount.h"
18+
19+#ifndef FAN_MNT_ATTACH
20+struct fanotify_event_info_mnt {
21+ struct fanotify_event_info_header hdr;
22+ __u64 mnt_id;
23+};
24+#define FAN_MNT_ATTACH 0x01000000 /* Mount was attached */
25+#endif
26+
27+#ifndef FAN_MNT_DETACH
28+#define FAN_MNT_DETACH 0x02000000 /* Mount was detached */
29+#endif
30+
31+#ifndef FAN_REPORT_MNT
32+#define FAN_REPORT_MNT 0x00004000 /* Report mount events */
33+#endif
34+
35+#ifndef FAN_MARK_MNTNS
36+#define FAN_MARK_MNTNS 0x00000110
37+#endif
38+
39+static uint64_t get_mnt_id(struct __test_metadata *const _metadata,
40+ const char *path)
41+{
42+ struct statx sx;
43+
44+ ASSERT_EQ(statx(AT_FDCWD, path, 0, STATX_MNT_ID_UNIQUE, &sx), 0);
45+ ASSERT_TRUE(!!(sx.stx_mask & STATX_MNT_ID_UNIQUE));
46+ return sx.stx_mnt_id;
47+}
48+
49+static const char root_mntpoint_templ[] = "/tmp/mount-notify_test_root.XXXXXX";
50+
51+FIXTURE(fanotify) {
52+ int fan_fd;
53+ char buf[256];
54+ unsigned int rem;
55+ void *next;
56+ char root_mntpoint[sizeof(root_mntpoint_templ)];
57+ int orig_root;
58+ int ns_fd;
59+ uint64_t root_id;
60+};
61+
62+FIXTURE_SETUP(fanotify)
63+{
64+ int ret;
65+
66+ ASSERT_EQ(unshare(CLONE_NEWNS), 0);
67+
68+ self->ns_fd = open("/proc/self/ns/mnt", O_RDONLY);
69+ ASSERT_GE(self->ns_fd, 0);
70+
71+ ASSERT_EQ(mount("", "/", NULL, MS_REC|MS_PRIVATE, NULL), 0);
72+
73+ strcpy(self->root_mntpoint, root_mntpoint_templ);
74+ ASSERT_NE(mkdtemp(self->root_mntpoint), NULL);
75+
76+ self->orig_root = open("/", O_PATH | O_CLOEXEC);
77+ ASSERT_GE(self->orig_root, 0);
78+
79+ ASSERT_EQ(mount("tmpfs", self->root_mntpoint, "tmpfs", 0, NULL), 0);
80+
81+ ASSERT_EQ(chroot(self->root_mntpoint), 0);
82+
83+ ASSERT_EQ(chdir("/"), 0);
84+
85+ ASSERT_EQ(mkdir("a", 0700), 0);
86+
87+ ASSERT_EQ(mkdir("b", 0700), 0);
88+
89+ self->root_id = get_mnt_id(_metadata, "/");
90+ ASSERT_NE(self->root_id, 0);
91+
92+ self->fan_fd = fanotify_init(FAN_REPORT_MNT, 0);
93+ ASSERT_GE(self->fan_fd, 0);
94+
95+ ret = fanotify_mark(self->fan_fd, FAN_MARK_ADD | FAN_MARK_MNTNS,
96+ FAN_MNT_ATTACH | FAN_MNT_DETACH, self->ns_fd, NULL);
97+ ASSERT_EQ(ret, 0);
98+
99+ self->rem = 0;
100+}
101+
102+FIXTURE_TEARDOWN(fanotify)
103+{
104+ ASSERT_EQ(self->rem, 0);
105+ close(self->fan_fd);
106+
107+ ASSERT_EQ(fchdir(self->orig_root), 0);
108+
109+ ASSERT_EQ(chroot("."), 0);
110+
111+ EXPECT_EQ(umount2(self->root_mntpoint, MNT_DETACH), 0);
112+ EXPECT_EQ(chdir(self->root_mntpoint), 0);
113+ EXPECT_EQ(chdir("/"), 0);
114+ EXPECT_EQ(rmdir(self->root_mntpoint), 0);
115+}
116+
117+static uint64_t expect_notify(struct __test_metadata *const _metadata,
118+ FIXTURE_DATA(fanotify) *self,
119+ uint64_t *mask)
120+{
121+ struct fanotify_event_metadata *meta;
122+ struct fanotify_event_info_mnt *mnt;
123+ unsigned int thislen;
124+
125+ if (!self->rem) {
126+ ssize_t len = read(self->fan_fd, self->buf, sizeof(self->buf));
127+ ASSERT_GT(len, 0);
128+
129+ self->rem = len;
130+ self->next = (void *) self->buf;
131+ }
132+
133+ meta = self->next;
134+ ASSERT_TRUE(FAN_EVENT_OK(meta, self->rem));
135+
136+ thislen = meta->event_len;
137+ self->rem -= thislen;
138+ self->next += thislen;
139+
140+ *mask = meta->mask;
141+ thislen -= sizeof(*meta);
142+
143+ mnt = ((void *) meta) + meta->event_len - thislen;
144+
145+ ASSERT_EQ(thislen, sizeof(*mnt));
146+
147+ return mnt->mnt_id;
148+}
149+
150+static void expect_notify_n(struct __test_metadata *const _metadata,
151+ FIXTURE_DATA(fanotify) *self,
152+ unsigned int n, uint64_t mask[], uint64_t mnts[])
153+{
154+ unsigned int i;
155+
156+ for (i = 0; i < n; i++)
157+ mnts[i] = expect_notify(_metadata, self, &mask[i]);
158+}
159+
160+static uint64_t expect_notify_mask(struct __test_metadata *const _metadata,
161+ FIXTURE_DATA(fanotify) *self,
162+ uint64_t expect_mask)
163+{
164+ uint64_t mntid, mask;
165+
166+ mntid = expect_notify(_metadata, self, &mask);
167+ ASSERT_EQ(expect_mask, mask);
168+
169+ return mntid;
170+}
171+
172+
173+static void expect_notify_mask_n(struct __test_metadata *const _metadata,
174+ FIXTURE_DATA(fanotify) *self,
175+ uint64_t mask, unsigned int n, uint64_t mnts[])
176+{
177+ unsigned int i;
178+
179+ for (i = 0; i < n; i++)
180+ mnts[i] = expect_notify_mask(_metadata, self, mask);
181+}
182+
183+static void verify_mount_ids(struct __test_metadata *const _metadata,
184+ const uint64_t list1[], const uint64_t list2[],
185+ size_t num)
186+{
187+ unsigned int i, j;
188+
189+ // Check that neither list has any duplicates
190+ for (i = 0; i < num; i++) {
191+ for (j = 0; j < num; j++) {
192+ if (i != j) {
193+ ASSERT_NE(list1[i], list1[j]);
194+ ASSERT_NE(list2[i], list2[j]);
195+ }
196+ }
197+ }
198+ // Check that all list1 memebers can be found in list2. Together with
199+ // the above it means that the list1 and list2 represent the same sets.
200+ for (i = 0; i < num; i++) {
201+ for (j = 0; j < num; j++) {
202+ if (list1[i] == list2[j])
203+ break;
204+ }
205+ ASSERT_NE(j, num);
206+ }
207+}
208+
209+static void check_mounted(struct __test_metadata *const _metadata,
210+ const uint64_t mnts[], size_t num)
211+{
212+ ssize_t ret;
213+ uint64_t *list;
214+
215+ list = malloc((num + 1) * sizeof(list[0]));
216+ ASSERT_NE(list, NULL);
217+
218+ ret = listmount(LSMT_ROOT, 0, 0, list, num + 1, 0);
219+ ASSERT_EQ(ret, num);
220+
221+ verify_mount_ids(_metadata, mnts, list, num);
222+
223+ free(list);
224+}
225+
226+static void setup_mount_tree(struct __test_metadata *const _metadata,
227+ int log2_num)
228+{
229+ int ret, i;
230+
231+ ret = mount("", "/", NULL, MS_SHARED, NULL);
232+ ASSERT_EQ(ret, 0);
233+
234+ for (i = 0; i < log2_num; i++) {
235+ ret = mount("/", "/", NULL, MS_BIND, NULL);
236+ ASSERT_EQ(ret, 0);
237+ }
238+}
239+
240+TEST_F(fanotify, bind)
241+{
242+ int ret;
243+ uint64_t mnts[2] = { self->root_id };
244+
245+ ret = mount("/", "/", NULL, MS_BIND, NULL);
246+ ASSERT_EQ(ret, 0);
247+
248+ mnts[1] = expect_notify_mask(_metadata, self, FAN_MNT_ATTACH);
249+ ASSERT_NE(mnts[0], mnts[1]);
250+
251+ check_mounted(_metadata, mnts, 2);
252+
253+ // Cleanup
254+ uint64_t detach_id;
255+ ret = umount("/");
256+ ASSERT_EQ(ret, 0);
257+
258+ detach_id = expect_notify_mask(_metadata, self, FAN_MNT_DETACH);
259+ ASSERT_EQ(detach_id, mnts[1]);
260+
261+ check_mounted(_metadata, mnts, 1);
262+}
263+
264+TEST_F(fanotify, move)
265+{
266+ int ret;
267+ uint64_t mnts[2] = { self->root_id };
268+ uint64_t move_id;
269+
270+ ret = mount("/", "/a", NULL, MS_BIND, NULL);
271+ ASSERT_EQ(ret, 0);
272+
273+ mnts[1] = expect_notify_mask(_metadata, self, FAN_MNT_ATTACH);
274+ ASSERT_NE(mnts[0], mnts[1]);
275+
276+ check_mounted(_metadata, mnts, 2);
277+
278+ ret = move_mount(AT_FDCWD, "/a", AT_FDCWD, "/b", 0);
279+ ASSERT_EQ(ret, 0);
280+
281+ move_id = expect_notify_mask(_metadata, self, FAN_MNT_ATTACH | FAN_MNT_DETACH);
282+ ASSERT_EQ(move_id, mnts[1]);
283+
284+ // Cleanup
285+ ret = umount("/b");
286+ ASSERT_EQ(ret, 0);
287+
288+ check_mounted(_metadata, mnts, 1);
289+}
290+
291+TEST_F(fanotify, propagate)
292+{
293+ const unsigned int log2_num = 4;
294+ const unsigned int num = (1 << log2_num);
295+ uint64_t mnts[num];
296+
297+ setup_mount_tree(_metadata, log2_num);
298+
299+ expect_notify_mask_n(_metadata, self, FAN_MNT_ATTACH, num - 1, mnts + 1);
300+
301+ mnts[0] = self->root_id;
302+ check_mounted(_metadata, mnts, num);
303+
304+ // Cleanup
305+ int ret;
306+ uint64_t mnts2[num];
307+ ret = umount2("/", MNT_DETACH);
308+ ASSERT_EQ(ret, 0);
309+
310+ ret = mount("", "/", NULL, MS_PRIVATE, NULL);
311+ ASSERT_EQ(ret, 0);
312+
313+ mnts2[0] = self->root_id;
314+ expect_notify_mask_n(_metadata, self, FAN_MNT_DETACH, num - 1, mnts2 + 1);
315+ verify_mount_ids(_metadata, mnts, mnts2, num);
316+
317+ check_mounted(_metadata, mnts, 1);
318+}
319+
320+TEST_F(fanotify, fsmount)
321+{
322+ int ret, fs, mnt;
323+ uint64_t mnts[2] = { self->root_id };
324+
325+ fs = fsopen("tmpfs", 0);
326+ ASSERT_GE(fs, 0);
327+
328+ ret = fsconfig(fs, FSCONFIG_CMD_CREATE, 0, 0, 0);
329+ ASSERT_EQ(ret, 0);
330+
331+ mnt = fsmount(fs, 0, 0);
332+ ASSERT_GE(mnt, 0);
333+
334+ close(fs);
335+
336+ ret = move_mount(mnt, "", AT_FDCWD, "/a", MOVE_MOUNT_F_EMPTY_PATH);
337+ ASSERT_EQ(ret, 0);
338+
339+ close(mnt);
340+
341+ mnts[1] = expect_notify_mask(_metadata, self, FAN_MNT_ATTACH);
342+ ASSERT_NE(mnts[0], mnts[1]);
343+
344+ check_mounted(_metadata, mnts, 2);
345+
346+ // Cleanup
347+ uint64_t detach_id;
348+ ret = umount("/a");
349+ ASSERT_EQ(ret, 0);
350+
351+ detach_id = expect_notify_mask(_metadata, self, FAN_MNT_DETACH);
352+ ASSERT_EQ(detach_id, mnts[1]);
353+
354+ check_mounted(_metadata, mnts, 1);
355+}
356+
357+TEST_F(fanotify, reparent)
358+{
359+ uint64_t mnts[6] = { self->root_id };
360+ uint64_t dmnts[3];
361+ uint64_t masks[3];
362+ unsigned int i;
363+ int ret;
364+
365+ // Create setup with a[1] -> b[2] propagation
366+ ret = mount("/", "/a", NULL, MS_BIND, NULL);
367+ ASSERT_EQ(ret, 0);
368+
369+ ret = mount("", "/a", NULL, MS_SHARED, NULL);
370+ ASSERT_EQ(ret, 0);
371+
372+ ret = mount("/a", "/b", NULL, MS_BIND, NULL);
373+ ASSERT_EQ(ret, 0);
374+
375+ ret = mount("", "/b", NULL, MS_SLAVE, NULL);
376+ ASSERT_EQ(ret, 0);
377+
378+ expect_notify_mask_n(_metadata, self, FAN_MNT_ATTACH, 2, mnts + 1);
379+
380+ check_mounted(_metadata, mnts, 3);
381+
382+ // Mount on a[3], which is propagated to b[4]
383+ ret = mount("/", "/a", NULL, MS_BIND, NULL);
384+ ASSERT_EQ(ret, 0);
385+
386+ expect_notify_mask_n(_metadata, self, FAN_MNT_ATTACH, 2, mnts + 3);
387+
388+ check_mounted(_metadata, mnts, 5);
389+
390+ // Mount on b[5], not propagated
391+ ret = mount("/", "/b", NULL, MS_BIND, NULL);
392+ ASSERT_EQ(ret, 0);
393+
394+ mnts[5] = expect_notify_mask(_metadata, self, FAN_MNT_ATTACH);
395+
396+ check_mounted(_metadata, mnts, 6);
397+
398+ // Umount a[3], which is propagated to b[4], but not b[5]
399+ // This will result in b[5] "falling" on b[2]
400+ ret = umount("/a");
401+ ASSERT_EQ(ret, 0);
402+
403+ expect_notify_n(_metadata, self, 3, masks, dmnts);
404+ verify_mount_ids(_metadata, mnts + 3, dmnts, 3);
405+
406+ for (i = 0; i < 3; i++) {
407+ if (dmnts[i] == mnts[5]) {
408+ ASSERT_EQ(masks[i], FAN_MNT_ATTACH | FAN_MNT_DETACH);
409+ } else {
410+ ASSERT_EQ(masks[i], FAN_MNT_DETACH);
411+ }
412+ }
413+
414+ mnts[3] = mnts[5];
415+ check_mounted(_metadata, mnts, 4);
416+
417+ // Cleanup
418+ ret = umount("/b");
419+ ASSERT_EQ(ret, 0);
420+
421+ ret = umount("/a");
422+ ASSERT_EQ(ret, 0);
423+
424+ ret = umount("/b");
425+ ASSERT_EQ(ret, 0);
426+
427+ expect_notify_mask_n(_metadata, self, FAN_MNT_DETACH, 3, dmnts);
428+ verify_mount_ids(_metadata, mnts + 1, dmnts, 3);
429+
430+ check_mounted(_metadata, mnts, 1);
431+}
432+
433+TEST_F(fanotify, rmdir)
434+{
435+ uint64_t mnts[3] = { self->root_id };
436+ int ret;
437+
438+ ret = mount("/", "/a", NULL, MS_BIND, NULL);
439+ ASSERT_EQ(ret, 0);
440+
441+ ret = mount("/", "/a/b", NULL, MS_BIND, NULL);
442+ ASSERT_EQ(ret, 0);
443+
444+ expect_notify_mask_n(_metadata, self, FAN_MNT_ATTACH, 2, mnts + 1);
445+
446+ check_mounted(_metadata, mnts, 3);
447+
448+ ret = chdir("/a");
449+ ASSERT_EQ(ret, 0);
450+
451+ ret = fork();
452+ ASSERT_GE(ret, 0);
453+
454+ if (ret == 0) {
455+ chdir("/");
456+ unshare(CLONE_NEWNS);
457+ mount("", "/", NULL, MS_REC|MS_PRIVATE, NULL);
458+ umount2("/a", MNT_DETACH);
459+ // This triggers a detach in the other namespace
460+ rmdir("/a");
461+ exit(0);
462+ }
463+ wait(NULL);
464+
465+ expect_notify_mask_n(_metadata, self, FAN_MNT_DETACH, 2, mnts + 1);
466+ check_mounted(_metadata, mnts, 1);
467+
468+ // Cleanup
469+ ret = chdir("/");
470+ ASSERT_EQ(ret, 0);
471+}
472+
473+TEST_F(fanotify, pivot_root)
474+{
475+ uint64_t mnts[3] = { self->root_id };
476+ uint64_t mnts2[3];
477+ int ret;
478+
479+ ret = mount("tmpfs", "/a", "tmpfs", 0, NULL);
480+ ASSERT_EQ(ret, 0);
481+
482+ mnts[2] = expect_notify_mask(_metadata, self, FAN_MNT_ATTACH);
483+
484+ ret = mkdir("/a/new", 0700);
485+ ASSERT_EQ(ret, 0);
486+
487+ ret = mkdir("/a/old", 0700);
488+ ASSERT_EQ(ret, 0);
489+
490+ ret = mount("/a", "/a/new", NULL, MS_BIND, NULL);
491+ ASSERT_EQ(ret, 0);
492+
493+ mnts[1] = expect_notify_mask(_metadata, self, FAN_MNT_ATTACH);
494+ check_mounted(_metadata, mnts, 3);
495+
496+ ret = syscall(SYS_pivot_root, "/a/new", "/a/new/old");
497+ ASSERT_EQ(ret, 0);
498+
499+ expect_notify_mask_n(_metadata, self, FAN_MNT_ATTACH | FAN_MNT_DETACH, 2, mnts2);
500+ verify_mount_ids(_metadata, mnts, mnts2, 2);
501+ check_mounted(_metadata, mnts, 3);
502+
503+ // Cleanup
504+ ret = syscall(SYS_pivot_root, "/old", "/old/a/new");
505+ ASSERT_EQ(ret, 0);
506+
507+ ret = umount("/a/new");
508+ ASSERT_EQ(ret, 0);
509+
510+ ret = umount("/a");
511+ ASSERT_EQ(ret, 0);
512+
513+ check_mounted(_metadata, mnts, 1);
514+}
515+
516+TEST_HARNESS_MAIN
tools/testing/selftests/filesystems/overlayfs/set_layers_via_fds.c+195−0
@@ -20,12 +20,16 @@ FIXTURE(set_layers_via_fds) { · 19 unmodified lines
2020 FIXTURE_SETUP(set_layers_via_fds)
2121 {
2222 ASSERT_EQ(mkdir("/set_layers_via_fds", 0755), 0);
23+ ASSERT_EQ(mkdir("/set_layers_via_fds_tmpfs", 0755), 0);
2324 }
2425
2526 FIXTURE_TEARDOWN(set_layers_via_fds)
2627 {
2728 umount2("/set_layers_via_fds", 0);
2829 ASSERT_EQ(rmdir("/set_layers_via_fds"), 0);
30+
31+ umount2("/set_layers_via_fds_tmpfs", 0);
32+ ASSERT_EQ(rmdir("/set_layers_via_fds_tmpfs"), 0);
2933 }
3034
3135 TEST_F(set_layers_via_fds, set_layers_via_fds)
@@ -214,4 +218,195 @@ TEST_F(set_layers_via_fds, set_500_layers_via_fds) · 182 unmodified lines
214218 ASSERT_EQ(close(fd_overlay), 0);
215219 }
216220
221+TEST_F(set_layers_via_fds, set_500_layers_via_opath_fds)
222+{
223+ int fd_context, fd_tmpfs, fd_overlay, fd_work, fd_upper, fd_lower;
224+ int layer_fds[500] = { [0 ... 499] = -EBADF };
225+
226+ ASSERT_EQ(unshare(CLONE_NEWNS), 0);
227+ ASSERT_EQ(sys_mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL), 0);
228+
229+ fd_context = sys_fsopen("tmpfs", 0);
230+ ASSERT_GE(fd_context, 0);
231+
232+ ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0), 0);
233+ fd_tmpfs = sys_fsmount(fd_context, 0, 0);
234+ ASSERT_GE(fd_tmpfs, 0);
235+ ASSERT_EQ(close(fd_context), 0);
236+
237+ for (int i = 0; i < ARRAY_SIZE(layer_fds); i++) {
238+ char path[100];
239+
240+ sprintf(path, "l%d", i);
241+ ASSERT_EQ(mkdirat(fd_tmpfs, path, 0755), 0);
242+ layer_fds[i] = openat(fd_tmpfs, path, O_DIRECTORY | O_PATH);
243+ ASSERT_GE(layer_fds[i], 0);
244+ }
245+
246+ ASSERT_EQ(mkdirat(fd_tmpfs, "w", 0755), 0);
247+ fd_work = openat(fd_tmpfs, "w", O_DIRECTORY | O_PATH);
248+ ASSERT_GE(fd_work, 0);
249+
250+ ASSERT_EQ(mkdirat(fd_tmpfs, "u", 0755), 0);
251+ fd_upper = openat(fd_tmpfs, "u", O_DIRECTORY | O_PATH);
252+ ASSERT_GE(fd_upper, 0);
253+
254+ ASSERT_EQ(mkdirat(fd_tmpfs, "l501", 0755), 0);
255+ fd_lower = openat(fd_tmpfs, "l501", O_DIRECTORY | O_PATH);
256+ ASSERT_GE(fd_lower, 0);
257+
258+ ASSERT_EQ(sys_move_mount(fd_tmpfs, "", -EBADF, "/tmp", MOVE_MOUNT_F_EMPTY_PATH), 0);
259+ ASSERT_EQ(close(fd_tmpfs), 0);
260+
261+ fd_context = sys_fsopen("overlay", 0);
262+ ASSERT_GE(fd_context, 0);
263+
264+ ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "workdir", NULL, fd_work), 0);
265+ ASSERT_EQ(close(fd_work), 0);
266+
267+ ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "upperdir", NULL, fd_upper), 0);
268+ ASSERT_EQ(close(fd_upper), 0);
269+
270+ for (int i = 0; i < ARRAY_SIZE(layer_fds); i++) {
271+ ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, layer_fds[i]), 0);
272+ ASSERT_EQ(close(layer_fds[i]), 0);
273+ }
274+
275+ ASSERT_NE(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, fd_lower), 0);
276+ ASSERT_EQ(close(fd_lower), 0);
277+
278+ ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0), 0);
279+
280+ fd_overlay = sys_fsmount(fd_context, 0, 0);
281+ ASSERT_GE(fd_overlay, 0);
282+ ASSERT_EQ(close(fd_context), 0);
283+ ASSERT_EQ(close(fd_overlay), 0);
284+}
285+
286+TEST_F(set_layers_via_fds, set_layers_via_detached_mount_fds)
287+{
288+ int fd_context, fd_tmpfs, fd_overlay, fd_tmp;
289+ int layer_fds[] = { [0 ... 8] = -EBADF };
290+ bool layers_found[] = { [0 ... 8] = false };
291+ size_t len = 0;
292+ char *line = NULL;
293+ FILE *f_mountinfo;
294+
295+ ASSERT_EQ(unshare(CLONE_NEWNS), 0);
296+ ASSERT_EQ(sys_mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL), 0);
297+
298+ fd_context = sys_fsopen("tmpfs", 0);
299+ ASSERT_GE(fd_context, 0);
300+
301+ ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0), 0);
302+ fd_tmpfs = sys_fsmount(fd_context, 0, 0);
303+ ASSERT_GE(fd_tmpfs, 0);
304+ ASSERT_EQ(close(fd_context), 0);
305+
306+ ASSERT_EQ(mkdirat(fd_tmpfs, "u", 0755), 0);
307+ ASSERT_EQ(mkdirat(fd_tmpfs, "u/upper", 0755), 0);
308+ ASSERT_EQ(mkdirat(fd_tmpfs, "u/work", 0755), 0);
309+ ASSERT_EQ(mkdirat(fd_tmpfs, "l1", 0755), 0);
310+ ASSERT_EQ(mkdirat(fd_tmpfs, "l2", 0755), 0);
311+ ASSERT_EQ(mkdirat(fd_tmpfs, "l3", 0755), 0);
312+ ASSERT_EQ(mkdirat(fd_tmpfs, "l4", 0755), 0);
313+ ASSERT_EQ(mkdirat(fd_tmpfs, "d1", 0755), 0);
314+ ASSERT_EQ(mkdirat(fd_tmpfs, "d2", 0755), 0);
315+ ASSERT_EQ(mkdirat(fd_tmpfs, "d3", 0755), 0);
316+
317+ ASSERT_EQ(sys_move_mount(fd_tmpfs, "", -EBADF, "/set_layers_via_fds_tmpfs", MOVE_MOUNT_F_EMPTY_PATH), 0);
318+
319+ fd_tmp = open_tree(fd_tmpfs, "u", OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC);
320+ ASSERT_GE(fd_tmp, 0);
321+
322+ layer_fds[0] = openat(fd_tmp, "upper", O_CLOEXEC | O_DIRECTORY | O_PATH);
323+ ASSERT_GE(layer_fds[0], 0);
324+
325+ layer_fds[1] = openat(fd_tmp, "work", O_CLOEXEC | O_DIRECTORY | O_PATH);
326+ ASSERT_GE(layer_fds[1], 0);
327+
328+ layer_fds[2] = open_tree(fd_tmpfs, "l1", OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC);
329+ ASSERT_GE(layer_fds[2], 0);
330+
331+ layer_fds[3] = open_tree(fd_tmpfs, "l2", OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC);
332+ ASSERT_GE(layer_fds[3], 0);
333+
334+ layer_fds[4] = open_tree(fd_tmpfs, "l3", OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC);
335+ ASSERT_GE(layer_fds[4], 0);
336+
337+ layer_fds[5] = open_tree(fd_tmpfs, "l4", OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC);
338+ ASSERT_GE(layer_fds[5], 0);
339+
340+ layer_fds[6] = open_tree(fd_tmpfs, "d1", OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC);
341+ ASSERT_GE(layer_fds[6], 0);
342+
343+ layer_fds[7] = open_tree(fd_tmpfs, "d2", OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC);
344+ ASSERT_GE(layer_fds[7], 0);
345+
346+ layer_fds[8] = open_tree(fd_tmpfs, "d3", OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC);
347+ ASSERT_GE(layer_fds[8], 0);
348+
349+ ASSERT_EQ(close(fd_tmpfs), 0);
350+
351+ fd_context = sys_fsopen("overlay", 0);
352+ ASSERT_GE(fd_context, 0);
353+
354+ ASSERT_NE(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir", NULL, layer_fds[2]), 0);
355+
356+ ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "upperdir", NULL, layer_fds[0]), 0);
357+ ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "workdir", NULL, layer_fds[1]), 0);
358+ ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, layer_fds[2]), 0);
359+ ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, layer_fds[3]), 0);
360+ ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, layer_fds[4]), 0);
361+ ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir+", NULL, layer_fds[5]), 0);
362+ ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "datadir+", NULL, layer_fds[6]), 0);
363+ ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "datadir+", NULL, layer_fds[7]), 0);
364+ ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "datadir+", NULL, layer_fds[8]), 0);
365+
366+ ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_STRING, "metacopy", "on", 0), 0);
367+
368+ ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0), 0);
369+
370+ fd_overlay = sys_fsmount(fd_context, 0, 0);
371+ ASSERT_GE(fd_overlay, 0);
372+
373+ ASSERT_EQ(sys_move_mount(fd_overlay, "", -EBADF, "/set_layers_via_fds", MOVE_MOUNT_F_EMPTY_PATH), 0);
374+
375+ f_mountinfo = fopen("/proc/self/mountinfo", "r");
376+ ASSERT_NE(f_mountinfo, NULL);
377+
378+ while (getline(&line, &len, f_mountinfo) != -1) {
379+ char *haystack = line;
380+
381+ if (strstr(haystack, "workdir=/tmp/w"))
382+ layers_found[0] = true;
383+ if (strstr(haystack, "upperdir=/tmp/u"))
384+ layers_found[1] = true;
385+ if (strstr(haystack, "lowerdir+=/tmp/l1"))
386+ layers_found[2] = true;
387+ if (strstr(haystack, "lowerdir+=/tmp/l2"))
388+ layers_found[3] = true;
389+ if (strstr(haystack, "lowerdir+=/tmp/l3"))
390+ layers_found[4] = true;
391+ if (strstr(haystack, "lowerdir+=/tmp/l4"))
392+ layers_found[5] = true;
393+ if (strstr(haystack, "datadir+=/tmp/d1"))
394+ layers_found[6] = true;
395+ if (strstr(haystack, "datadir+=/tmp/d2"))
396+ layers_found[7] = true;
397+ if (strstr(haystack, "datadir+=/tmp/d3"))
398+ layers_found[8] = true;
399+ }
400+ free(line);
401+
402+ for (int i = 0; i < ARRAY_SIZE(layer_fds); i++) {
403+ ASSERT_EQ(layers_found[i], true);
404+ ASSERT_EQ(close(layer_fds[i]), 0);
405+ }
406+
407+ ASSERT_EQ(close(fd_context), 0);
408+ ASSERT_EQ(close(fd_overlay), 0);
409+ ASSERT_EQ(fclose(f_mountinfo), 0);
410+}
411+
217412 TEST_HARNESS_MAIN
tools/testing/selftests/filesystems/overlayfs/wrappers.h+17−0
@@ -44,4 +44,21 @@ static inline int sys_move_mount(int from_dfd, const char *from_pathname, · 43 unmodified lines
4444 to_pathname, flags);
4545 }
4646
47+#ifndef OPEN_TREE_CLONE
48+#define OPEN_TREE_CLONE 1
49+#endif
50+
51+#ifndef OPEN_TREE_CLOEXEC
52+#define OPEN_TREE_CLOEXEC O_CLOEXEC
53+#endif
54+
55+#ifndef AT_RECURSIVE
56+#define AT_RECURSIVE 0x8000
57+#endif
58+
59+static inline int sys_open_tree(int dfd, const char *filename, unsigned int flags)
60+{
61+ return syscall(__NR_open_tree, dfd, filename, flags);
62+}
63+
4764 #endif
tools/testing/selftests/filesystems/statmount/statmount.h+1−1
@@ -25,7 +25,7 @@ static inline int statmount(uint64_t mnt_id, uint64_t mnt_ns_id, uint64_t mask, · 24 unmodified lines
2525 return syscall(__NR_statmount, &req, buf, bufsize, flags);
2626 }
2727
28−static ssize_t listmount(uint64_t mnt_id, uint64_t mnt_ns_id,
28+static inline ssize_t listmount(uint64_t mnt_id, uint64_t mnt_ns_id,
2929 uint64_t last_mnt_id, uint64_t list[], size_t num,
3030 unsigned int flags)
3131 {