]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
fs: add mount_setattr()
authorChristian Brauner <christian.brauner@ubuntu.com>
Thu, 21 Jan 2021 13:19:53 +0000 (14:19 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Sun, 24 Jan 2021 13:42:45 +0000 (14:42 +0100)
This implements the missing mount_setattr() syscall. While the new mount
api allows to change the properties of a superblock there is currently
no way to change the properties of a mount or a mount tree using file
descriptors which the new mount api is based on. In addition the old
mount api has the restriction that mount options cannot be applied
recursively. This hasn't changed since changing mount options on a
per-mount basis was implemented in [1] and has been a frequent request
not just for convenience but also for security reasons. The legacy
mount syscall is unable to accommodate this behavior without introducing
a whole new set of flags because MS_REC | MS_REMOUNT | MS_BIND |
MS_RDONLY | MS_NOEXEC | [...] only apply the mount option to the topmost
mount. Changing MS_REC to apply to the whole mount tree would mean
introducing a significant uapi change and would likely cause significant
regressions.

The new mount_setattr() syscall allows to recursively clear and set
mount options in one shot. Multiple calls to change mount options
requesting the same changes are idempotent:

int mount_setattr(int dfd, const char *path, unsigned flags,
                  struct mount_attr *uattr, size_t usize);

Flags to modify path resolution behavior are specified in the @flags
argument. Currently, AT_EMPTY_PATH, AT_RECURSIVE, AT_SYMLINK_NOFOLLOW,
and AT_NO_AUTOMOUNT are supported. If useful, additional lookup flags to
restrict path resolution as introduced with openat2() might be supported
in the future.

The mount_setattr() syscall can be expected to grow over time and is
designed with extensibility in mind. It follows the extensible syscall
pattern we have used with other syscalls such as openat2(), clone3(),
sched_{set,get}attr(), and others.
The set of mount options is passed in the uapi struct mount_attr which
currently has the following layout:

struct mount_attr {
__u64 attr_set;
__u64 attr_clr;
__u64 propagation;
__u64 userns_fd;
};

The @attr_set and @attr_clr members are used to clear and set mount
options. This way a user can e.g. request that a set of flags is to be
raised such as turning mounts readonly by raising MOUNT_ATTR_RDONLY in
@attr_set while at the same time requesting that another set of flags is
to be lowered such as removing noexec from a mount tree by specifying
MOUNT_ATTR_NOEXEC in @attr_clr.

Note, since the MOUNT_ATTR_<atime> values are an enum starting from 0,
not a bitmap, users wanting to transition to a different atime setting
cannot simply specify the atime setting in @attr_set, but must also
specify MOUNT_ATTR__ATIME in the @attr_clr field. So we ensure that
MOUNT_ATTR__ATIME can't be partially set in @attr_clr and that @attr_set
can't have any atime bits set if MOUNT_ATTR__ATIME isn't set in
@attr_clr.

The @propagation field lets callers specify the propagation type of a
mount tree. Propagation is a single property that has four different
settings and as such is not really a flag argument but an enum.
Specifically, it would be unclear what setting and clearing propagation
settings in combination would amount to. The legacy mount() syscall thus
forbids the combination of multiple propagation settings too. The goal
is to keep the semantics of mount propagation somewhat simple as they
are overly complex as it is.

The @userns_fd field lets user specify a user namespace whose idmapping
becomes the idmapping of the mount. This is implemented and explained in
detail in the next patch.

[1]: commit 2e4b7fcd9260 ("[PATCH] r/o bind mounts: honor mount writer counts at remount")

Link: https://lore.kernel.org/r/20210121131959.646623-35-christian.brauner@ubuntu.com
Cc: David Howells <dhowells@redhat.com>
Cc: Aleksa Sarai <cyphar@cyphar.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: linux-fsdevel@vger.kernel.org
Cc: linux-api@vger.kernel.org
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
23 files changed:
arch/alpha/kernel/syscalls/syscall.tbl
arch/arm/tools/syscall.tbl
arch/arm64/include/asm/unistd.h
arch/arm64/include/asm/unistd32.h
arch/ia64/kernel/syscalls/syscall.tbl
arch/m68k/kernel/syscalls/syscall.tbl
arch/microblaze/kernel/syscalls/syscall.tbl
arch/mips/kernel/syscalls/syscall_n32.tbl
arch/mips/kernel/syscalls/syscall_n64.tbl
arch/mips/kernel/syscalls/syscall_o32.tbl
arch/parisc/kernel/syscalls/syscall.tbl
arch/powerpc/kernel/syscalls/syscall.tbl
arch/s390/kernel/syscalls/syscall.tbl
arch/sh/kernel/syscalls/syscall.tbl
arch/sparc/kernel/syscalls/syscall.tbl
arch/x86/entry/syscalls/syscall_32.tbl
arch/x86/entry/syscalls/syscall_64.tbl
arch/xtensa/kernel/syscalls/syscall.tbl
fs/namespace.c
include/linux/syscalls.h
include/uapi/asm-generic/unistd.h
include/uapi/linux/mount.h
tools/include/uapi/asm-generic/unistd.h

index a6617067dbe6457a9d8cae8f60823e10813344ce..02f0244e005c67f5544dc09e2a7a71d67fc916d0 100644 (file)
 549    common  faccessat2                      sys_faccessat2
 550    common  process_madvise                 sys_process_madvise
 551    common  epoll_pwait2                    sys_epoll_pwait2
+552    common  mount_setattr                   sys_mount_setattr
index 20e1170e2e0aaeb52ea10f1802c637164ea79b5e..dcc1191291a225509693b769ecee3be417403a34 100644 (file)
 439    common  faccessat2                      sys_faccessat2
 440    common  process_madvise                 sys_process_madvise
 441    common  epoll_pwait2                    sys_epoll_pwait2
+442    common  mount_setattr                   sys_mount_setattr
index 86a9d7b3eabe9ee254df4abd7f4fd008176d1cf5..949788f5ba4007049d0e92b55895ef738c1949fa 100644 (file)
@@ -38,7 +38,7 @@
 #define __ARM_NR_compat_set_tls                (__ARM_NR_COMPAT_BASE + 5)
 #define __ARM_NR_COMPAT_END            (__ARM_NR_COMPAT_BASE + 0x800)
 
-#define __NR_compat_syscalls           442
+#define __NR_compat_syscalls           443
 #endif
 
 #define __ARCH_WANT_SYS_CLONE
index cccfbbefbf952e2c37d3cb39e046a3877df40638..3d874f624056b15b7e948d4c6821261f3907d4f5 100644 (file)
@@ -891,6 +891,8 @@ __SYSCALL(__NR_faccessat2, sys_faccessat2)
 __SYSCALL(__NR_process_madvise, sys_process_madvise)
 #define __NR_epoll_pwait2 441
 __SYSCALL(__NR_epoll_pwait2, compat_sys_epoll_pwait2)
+#define __NR_mount_setattr 442
+__SYSCALL(__NR_mount_setattr, sys_mount_setattr)
 
 /*
  * Please add new compat syscalls above this comment and update
index bfc00f2bd437236823e16abf22f68ca1bc6bebdb..d89231166e19efbdae049f28da2194e34969da58 100644 (file)
 439    common  faccessat2                      sys_faccessat2
 440    common  process_madvise                 sys_process_madvise
 441    common  epoll_pwait2                    sys_epoll_pwait2
+442    common  mount_setattr                   sys_mount_setattr
index 7fe4e45c864c4f36ca7cdd6f410590541f5e6429..72bde6707dd33c311b5f239542279cc554bccb2b 100644 (file)
 439    common  faccessat2                      sys_faccessat2
 440    common  process_madvise                 sys_process_madvise
 441    common  epoll_pwait2                    sys_epoll_pwait2
+442    common  mount_setattr                   sys_mount_setattr
index a522adf194abe3a3cd982a92888b58365d3858f7..d603a5ec933865b1876267e6e1bf5e57e0044137 100644 (file)
 439    common  faccessat2                      sys_faccessat2
 440    common  process_madvise                 sys_process_madvise
 441    common  epoll_pwait2                    sys_epoll_pwait2
+442    common  mount_setattr                   sys_mount_setattr
index 0f03ad223f332cfe755c019fada0fbbaf958149c..8fd8c1790941c66048d8f90763dc29f9bdd74571 100644 (file)
 439    n32     faccessat2                      sys_faccessat2
 440    n32     process_madvise                 sys_process_madvise
 441    n32     epoll_pwait2                    compat_sys_epoll_pwait2
+442    n32     mount_setattr                   sys_mount_setattr
index 91649690b52f1b25ac229ad4e224366861ab66b9..169f21438065b58d0722445fb1f4afe16ff16a27 100644 (file)
 439    n64     faccessat2                      sys_faccessat2
 440    n64     process_madvise                 sys_process_madvise
 441    n64     epoll_pwait2                    sys_epoll_pwait2
+442    n64     mount_setattr                   sys_mount_setattr
index 4bad0c40aed6bcfa46294cd0be3d3566137085e0..090d29ca80ff8fefb7ef4f962f69371189c3ae61 100644 (file)
 439    o32     faccessat2                      sys_faccessat2
 440    o32     process_madvise                 sys_process_madvise
 441    o32     epoll_pwait2                    sys_epoll_pwait2                compat_sys_epoll_pwait2
+442    o32     mount_setattr                   sys_mount_setattr
index 6bcc31966b4460b28a863384f97ea5c97d7b027c..271a9251968345de67e53a2f2f9ad1ba5aa855dd 100644 (file)
 439    common  faccessat2                      sys_faccessat2
 440    common  process_madvise                 sys_process_madvise
 441    common  epoll_pwait2                    sys_epoll_pwait2                compat_sys_epoll_pwait2
+442    common  mount_setattr                   sys_mount_setattr
index f744eb5cba887d398e150e9ef9fbb1293d5fe08f..72e5aa67ab8ad1ac9341f221881fdedd2bb8082b 100644 (file)
 439    common  faccessat2                      sys_faccessat2
 440    common  process_madvise                 sys_process_madvise
 441    common  epoll_pwait2                    sys_epoll_pwait2                compat_sys_epoll_pwait2
+442    common  mount_setattr                   sys_mount_setattr
index d443423495e565e49a8e57527f00dfdd4ffbea17..3abef2144dac79b69b25852ce28ffb2e5b284afe 100644 (file)
 439  common    faccessat2              sys_faccessat2                  sys_faccessat2
 440  common    process_madvise         sys_process_madvise             sys_process_madvise
 441  common    epoll_pwait2            sys_epoll_pwait2                compat_sys_epoll_pwait2
+442  common    mount_setattr           sys_mount_setattr               sys_mount_setattr
index 9df40ac0ebc05f584b43dc23777f027cddeff6b3..d08eebad6b7f394cf3bd10a469a179edd14368e3 100644 (file)
 439    common  faccessat2                      sys_faccessat2
 440    common  process_madvise                 sys_process_madvise
 441    common  epoll_pwait2                    sys_epoll_pwait2
+442    common  mount_setattr                   sys_mount_setattr
index 40d8c7cd82984b44ddf9f95074835961114547eb..84403a99039c819c1c43b3600105b5b7cd87a49f 100644 (file)
 439    common  faccessat2                      sys_faccessat2
 440    common  process_madvise                 sys_process_madvise
 441    common  epoll_pwait2                    sys_epoll_pwait2                compat_sys_epoll_pwait2
+442    common  mount_setattr                   sys_mount_setattr
index 874aeacde2dd157cd1d8f41e34f74598a4ef3f5a..a1c9f496fca6a2bfb44e761b2c5a18199b57d1c7 100644 (file)
 439    i386    faccessat2              sys_faccessat2
 440    i386    process_madvise         sys_process_madvise
 441    i386    epoll_pwait2            sys_epoll_pwait2                compat_sys_epoll_pwait2
+442    i386    mount_setattr           sys_mount_setattr
index 78672124d28be0da465300ee9a301bab59c1ac1d..7bf01cbe582f03bc26adb4092bb9023384ec217f 100644 (file)
 439    common  faccessat2              sys_faccessat2
 440    common  process_madvise         sys_process_madvise
 441    common  epoll_pwait2            sys_epoll_pwait2
+442    common  mount_setattr           sys_mount_setattr
 
 #
 # Due to a historical design error, certain syscalls are numbered differently
index 46116a28eeed3bd0b250ab06874f6238103720a4..365a9b84922482f194962e6744be37a9a82990bd 100644 (file)
 439    common  faccessat2                      sys_faccessat2
 440    common  process_madvise                 sys_process_madvise
 441    common  epoll_pwait2                    sys_epoll_pwait2
+442    common  mount_setattr                   sys_mount_setattr
index 00ed0d6cb2ee08d41a77bb0137610f3eebe77cbb..726a51c8c46ef7fe3394c4720b4dea1958414844 100644 (file)
@@ -73,6 +73,14 @@ static DECLARE_RWSEM(namespace_sem);
 static HLIST_HEAD(unmounted);  /* protected by namespace_sem */
 static LIST_HEAD(ex_mountpoints); /* protected by namespace_sem */
 
+struct mount_kattr {
+       unsigned int attr_set;
+       unsigned int attr_clr;
+       unsigned int propagation;
+       unsigned int lookup_flags;
+       bool recurse;
+};
+
 /* /sys/fs */
 struct kobject *fs_kobj;
 EXPORT_SYMBOL_GPL(fs_kobj);
@@ -3469,6 +3477,11 @@ out_type:
        (MOUNT_ATTR_RDONLY | MOUNT_ATTR_NOSUID | MOUNT_ATTR_NODEV | \
         MOUNT_ATTR_NOEXEC | MOUNT_ATTR__ATIME | MOUNT_ATTR_NODIRATIME)
 
+#define MOUNT_SETATTR_VALID_FLAGS FSMOUNT_VALID_FLAGS
+
+#define MOUNT_SETATTR_PROPAGATION_FLAGS \
+       (MS_UNBINDABLE | MS_PRIVATE | MS_SLAVE | MS_SHARED)
+
 static unsigned int attr_flags_to_mnt_flags(u64 attr_flags)
 {
        unsigned int mnt_flags = 0;
@@ -3820,6 +3833,256 @@ out0:
        return error;
 }
 
+static unsigned int recalc_flags(struct mount_kattr *kattr, struct mount *mnt)
+{
+       unsigned int flags = mnt->mnt.mnt_flags;
+
+       /*  flags to clear */
+       flags &= ~kattr->attr_clr;
+       /* flags to raise */
+       flags |= kattr->attr_set;
+
+       return flags;
+}
+
+static struct mount *mount_setattr_prepare(struct mount_kattr *kattr,
+                                          struct mount *mnt, int *err)
+{
+       struct mount *m = mnt, *last = NULL;
+
+       if (!is_mounted(&m->mnt)) {
+               *err = -EINVAL;
+               goto out;
+       }
+
+       if (!(mnt_has_parent(m) ? check_mnt(m) : is_anon_ns(m->mnt_ns))) {
+               *err = -EINVAL;
+               goto out;
+       }
+
+       do {
+               unsigned int flags;
+
+               flags = recalc_flags(kattr, m);
+               if (!can_change_locked_flags(m, flags)) {
+                       *err = -EPERM;
+                       goto out;
+               }
+
+               last = m;
+
+               if ((kattr->attr_set & MNT_READONLY) &&
+                   !(m->mnt.mnt_flags & MNT_READONLY)) {
+                       *err = mnt_hold_writers(m);
+                       if (*err)
+                               goto out;
+               }
+       } while (kattr->recurse && (m = next_mnt(m, mnt)));
+
+out:
+       return last;
+}
+
+static void mount_setattr_commit(struct mount_kattr *kattr,
+                                struct mount *mnt, struct mount *last,
+                                int err)
+{
+       struct mount *m = mnt;
+
+       do {
+               if (!err) {
+                       unsigned int flags;
+
+                       flags = recalc_flags(kattr, m);
+                       WRITE_ONCE(m->mnt.mnt_flags, flags);
+               }
+
+               /*
+                * We either set MNT_READONLY above so make it visible
+                * before ~MNT_WRITE_HOLD or we failed to recursively
+                * apply mount options.
+                */
+               if ((kattr->attr_set & MNT_READONLY) &&
+                   (m->mnt.mnt_flags & MNT_WRITE_HOLD))
+                       mnt_unhold_writers(m);
+
+               if (!err && kattr->propagation)
+                       change_mnt_propagation(m, kattr->propagation);
+
+               /*
+                * On failure, only cleanup until we found the first mount
+                * we failed to handle.
+                */
+               if (err && m == last)
+                       break;
+       } while (kattr->recurse && (m = next_mnt(m, mnt)));
+
+       if (!err)
+               touch_mnt_namespace(mnt->mnt_ns);
+}
+
+static int do_mount_setattr(struct path *path, struct mount_kattr *kattr)
+{
+       struct mount *mnt = real_mount(path->mnt), *last = NULL;
+       int err = 0;
+
+       if (path->dentry != mnt->mnt.mnt_root)
+               return -EINVAL;
+
+       if (kattr->propagation) {
+               /*
+                * Only take namespace_lock() if we're actually changing
+                * propagation.
+                */
+               namespace_lock();
+               if (kattr->propagation == MS_SHARED) {
+                       err = invent_group_ids(mnt, kattr->recurse);
+                       if (err) {
+                               namespace_unlock();
+                               return err;
+                       }
+               }
+       }
+
+       lock_mount_hash();
+
+       /*
+        * Get the mount tree in a shape where we can change mount
+        * properties without failure.
+        */
+       last = mount_setattr_prepare(kattr, mnt, &err);
+       if (last) /* Commit all changes or revert to the old state. */
+               mount_setattr_commit(kattr, mnt, last, err);
+
+       unlock_mount_hash();
+
+       if (kattr->propagation) {
+               namespace_unlock();
+               if (err)
+                       cleanup_group_ids(mnt, NULL);
+       }
+
+       return err;
+}
+
+static int build_mount_kattr(const struct mount_attr *attr,
+                            struct mount_kattr *kattr, unsigned int flags)
+{
+       unsigned int lookup_flags = LOOKUP_AUTOMOUNT | LOOKUP_FOLLOW;
+
+       if (flags & AT_NO_AUTOMOUNT)
+               lookup_flags &= ~LOOKUP_AUTOMOUNT;
+       if (flags & AT_SYMLINK_NOFOLLOW)
+               lookup_flags &= ~LOOKUP_FOLLOW;
+       if (flags & AT_EMPTY_PATH)
+               lookup_flags |= LOOKUP_EMPTY;
+
+       *kattr = (struct mount_kattr) {
+               .lookup_flags   = lookup_flags,
+               .recurse        = !!(flags & AT_RECURSIVE),
+       };
+
+       if (attr->propagation & ~MOUNT_SETATTR_PROPAGATION_FLAGS)
+               return -EINVAL;
+       if (hweight32(attr->propagation & MOUNT_SETATTR_PROPAGATION_FLAGS) > 1)
+               return -EINVAL;
+       kattr->propagation = attr->propagation;
+
+       if ((attr->attr_set | attr->attr_clr) & ~MOUNT_SETATTR_VALID_FLAGS)
+               return -EINVAL;
+
+       if (attr->userns_fd)
+               return -EINVAL;
+
+       kattr->attr_set = attr_flags_to_mnt_flags(attr->attr_set);
+       kattr->attr_clr = attr_flags_to_mnt_flags(attr->attr_clr);
+
+       /*
+        * Since the MOUNT_ATTR_<atime> values are an enum, not a bitmap,
+        * users wanting to transition to a different atime setting cannot
+        * simply specify the atime setting in @attr_set, but must also
+        * specify MOUNT_ATTR__ATIME in the @attr_clr field.
+        * So ensure that MOUNT_ATTR__ATIME can't be partially set in
+        * @attr_clr and that @attr_set can't have any atime bits set if
+        * MOUNT_ATTR__ATIME isn't set in @attr_clr.
+        */
+       if (attr->attr_clr & MOUNT_ATTR__ATIME) {
+               if ((attr->attr_clr & MOUNT_ATTR__ATIME) != MOUNT_ATTR__ATIME)
+                       return -EINVAL;
+
+               /*
+                * Clear all previous time settings as they are mutually
+                * exclusive.
+                */
+               kattr->attr_clr |= MNT_RELATIME | MNT_NOATIME;
+               switch (attr->attr_set & MOUNT_ATTR__ATIME) {
+               case MOUNT_ATTR_RELATIME:
+                       kattr->attr_set |= MNT_RELATIME;
+                       break;
+               case MOUNT_ATTR_NOATIME:
+                       kattr->attr_set |= MNT_NOATIME;
+                       break;
+               case MOUNT_ATTR_STRICTATIME:
+                       break;
+               default:
+                       return -EINVAL;
+               }
+       } else {
+               if (attr->attr_set & MOUNT_ATTR__ATIME)
+                       return -EINVAL;
+       }
+
+       return 0;
+}
+
+SYSCALL_DEFINE5(mount_setattr, int, dfd, const char __user *, path,
+               unsigned int, flags, struct mount_attr __user *, uattr,
+               size_t, usize)
+{
+       int err;
+       struct path target;
+       struct mount_attr attr;
+       struct mount_kattr kattr;
+
+       BUILD_BUG_ON(sizeof(struct mount_attr) != MOUNT_ATTR_SIZE_VER0);
+
+       if (flags & ~(AT_EMPTY_PATH |
+                     AT_RECURSIVE |
+                     AT_SYMLINK_NOFOLLOW |
+                     AT_NO_AUTOMOUNT))
+               return -EINVAL;
+
+       if (unlikely(usize > PAGE_SIZE))
+               return -E2BIG;
+       if (unlikely(usize < MOUNT_ATTR_SIZE_VER0))
+               return -EINVAL;
+
+       if (!may_mount())
+               return -EPERM;
+
+       err = copy_struct_from_user(&attr, sizeof(attr), uattr, usize);
+       if (err)
+               return err;
+
+       /* Don't bother walking through the mounts if this is a nop. */
+       if (attr.attr_set == 0 &&
+           attr.attr_clr == 0 &&
+           attr.propagation == 0)
+               return 0;
+
+       err = build_mount_kattr(&attr, &kattr, flags);
+       if (err)
+               return err;
+
+       err = user_path_at(dfd, path, kattr.lookup_flags, &target);
+       if (err)
+               return err;
+
+       err = do_mount_setattr(&target, &kattr);
+       path_put(&target);
+       return err;
+}
+
 static void __init init_mount_tree(void)
 {
        struct vfsmount *mnt;
index 7688bc983de54a0c8e75ea585f5cea1749523b02..cd7b5c817ba2c3e7baf1b89f66fd70e675837b7b 100644 (file)
@@ -68,6 +68,7 @@ union bpf_attr;
 struct io_uring_params;
 struct clone_args;
 struct open_how;
+struct mount_attr;
 
 #include <linux/types.h>
 #include <linux/aio_abi.h>
@@ -1028,6 +1029,9 @@ asmlinkage long sys_open_tree(int dfd, const char __user *path, unsigned flags);
 asmlinkage long sys_move_mount(int from_dfd, const char __user *from_path,
                               int to_dfd, const char __user *to_path,
                               unsigned int ms_flags);
+asmlinkage long sys_mount_setattr(int dfd, const char __user *path,
+                                 unsigned int flags,
+                                 struct mount_attr __user *uattr, size_t usize);
 asmlinkage long sys_fsopen(const char __user *fs_name, unsigned int flags);
 asmlinkage long sys_fsconfig(int fs_fd, unsigned int cmd, const char __user *key,
                             const void __user *value, int aux);
index 728752917785efe99cc6a325edbb488a58ff4674..ce58cff99b66530a02e2bc85c7264b236f5b343d 100644 (file)
@@ -861,9 +861,11 @@ __SYSCALL(__NR_faccessat2, sys_faccessat2)
 __SYSCALL(__NR_process_madvise, sys_process_madvise)
 #define __NR_epoll_pwait2 441
 __SC_COMP(__NR_epoll_pwait2, sys_epoll_pwait2, compat_sys_epoll_pwait2)
+#define __NR_mount_setattr 442
+__SYSCALL(__NR_mount_setattr, sys_mount_setattr)
 
 #undef __NR_syscalls
-#define __NR_syscalls 442
+#define __NR_syscalls 443
 
 /*
  * 32 bit systems traditionally used different
index dd8306ea336c19b695fa9a748c14f5ad92fe3e63..d3bcefdfa73d3868f15b145cd22d5947c4dcdaa6 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _UAPI_LINUX_MOUNT_H
 #define _UAPI_LINUX_MOUNT_H
 
+#include <linux/types.h>
+
 /*
  * These are the fs-independent mount-flags: up to 32 flags are supported
  *
@@ -118,4 +120,17 @@ enum fsconfig_command {
 #define MOUNT_ATTR_STRICTATIME 0x00000020 /* - Always perform atime updates */
 #define MOUNT_ATTR_NODIRATIME  0x00000080 /* Do not update directory access times */
 
+/*
+ * mount_setattr()
+ */
+struct mount_attr {
+       __u64 attr_set;
+       __u64 attr_clr;
+       __u64 propagation;
+       __u64 userns_fd;
+};
+
+/* List of all mount_attr versions. */
+#define MOUNT_ATTR_SIZE_VER0   32 /* sizeof first published struct */
+
 #endif /* _UAPI_LINUX_MOUNT_H */
index 728752917785efe99cc6a325edbb488a58ff4674..ce58cff99b66530a02e2bc85c7264b236f5b343d 100644 (file)
@@ -861,9 +861,11 @@ __SYSCALL(__NR_faccessat2, sys_faccessat2)
 __SYSCALL(__NR_process_madvise, sys_process_madvise)
 #define __NR_epoll_pwait2 441
 __SC_COMP(__NR_epoll_pwait2, sys_epoll_pwait2, compat_sys_epoll_pwait2)
+#define __NR_mount_setattr 442
+__SYSCALL(__NR_mount_setattr, sys_mount_setattr)
 
 #undef __NR_syscalls
-#define __NR_syscalls 442
+#define __NR_syscalls 443
 
 /*
  * 32 bit systems traditionally used different