From 90832ed56f0444b06c3b16c3f5e144c16f34c1a7 Mon Sep 17 00:00:00 2001 From: xenxynon Date: Fri, 31 Jan 2025 04:55:46 +0000 Subject: [PATCH] backport path unmount Signed-off-by: xenxynon --- fs/internal.h | 1 + fs/namespace.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/fs/internal.h b/fs/internal.h index 377f984e9226..9badc3b8cc11 100644 --- a/fs/internal.h +++ b/fs/internal.h @@ -85,6 +85,7 @@ extern int finish_automount(struct vfsmount *, struct path *); extern int sb_prepare_remount_readonly(struct super_block *); extern void __init mnt_init(void); +int path_umount(struct path *path, int flags); extern int __mnt_want_write_file(struct file *); extern void __mnt_drop_write_file(struct file *); diff --git a/fs/namespace.c b/fs/namespace.c index 7955b65334e8..52804361aaff 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1750,6 +1750,36 @@ SYSCALL_DEFINE1(oldumount, char __user *, name) #endif +static int can_umount(const struct path *path, int flags) + { + struct mount *mnt = real_mount(path->mnt); + if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW)) + return -EINVAL; + if (!may_mount()) + return -EPERM; + if (path->dentry != path->mnt->mnt_root) + return -EINVAL; + if (!check_mnt(mnt)) + return -EINVAL; + if (mnt->mnt.mnt_flags & MNT_LOCKED) + return -EINVAL; + if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN)) + return -EPERM; + return 0; + } + +int path_umount(struct path *path, int flags) + { + struct mount *mnt = real_mount(path->mnt); + int ret; + ret = can_umount(path, flags); + if (!ret) + ret = do_umount(mnt, flags); + dput(path->dentry); + mntput_no_expire(mnt); + return ret; + } + static bool is_mnt_ns_file(struct dentry *dentry) { /* Is this a proxy for a mount namespace? */