lkml.org 
[lkml]   [2020]   [Jul]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 02/24] fs: add a do_kern_mount helper
    Date
    Like do_mount, but takes a kernel pointer for the destination path.
    Switch over the mounts in the init code and devtmpfs to it, which
    just happen to work due to the implicit set_fs(KERNEL_DS) during early
    init right now.

    Signed-off-by: Christoph Hellwig <hch@lst.de>
    ---
    drivers/base/devtmpfs.c | 4 +-
    fs/namespace.c | 81 +++++++++++++++++++++++++----------------
    include/linux/fs.h | 2 +
    init/do_mounts.c | 8 ++--
    init/do_mounts_initrd.c | 6 +--
    5 files changed, 60 insertions(+), 41 deletions(-)

    diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c
    index c9017e0584c003..03221ca708c91c 100644
    --- a/drivers/base/devtmpfs.c
    +++ b/drivers/base/devtmpfs.c
    @@ -359,7 +359,7 @@ int __init devtmpfs_mount(void)
    if (!thread)
    return 0;

    - err = do_mount("devtmpfs", "dev", "devtmpfs", MS_SILENT, NULL);
    + err = do_kern_mount("devtmpfs", "dev", "devtmpfs", MS_SILENT, NULL);
    if (err)
    printk(KERN_INFO "devtmpfs: error mounting %i\n", err);
    else
    @@ -385,7 +385,7 @@ static int devtmpfs_setup(void *p)
    err = ksys_unshare(CLONE_NEWNS);
    if (err)
    goto out;
    - err = do_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, NULL);
    + err = do_kern_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, NULL);
    if (err)
    goto out;
    ksys_chdir("/.."); /* will traverse into overmounted root */
    diff --git a/fs/namespace.c b/fs/namespace.c
    index f30ed401cc6d7a..d208a389aac3c0 100644
    --- a/fs/namespace.c
    +++ b/fs/namespace.c
    @@ -3115,12 +3115,11 @@ char *copy_mount_string(const void __user *data)
    * Therefore, if this magic number is present, it carries no information
    * and must be discarded.
    */
    -long do_mount(const char *dev_name, const char __user *dir_name,
    +static int path_mount(const char *dev_name, struct path *path,
    const char *type_page, unsigned long flags, void *data_page)
    {
    - struct path path;
    unsigned int mnt_flags = 0, sb_flags;
    - int retval = 0;
    + int ret = 0;

    /* Discard magic */
    if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
    @@ -3133,19 +3132,13 @@ long do_mount(const char *dev_name, const char __user *dir_name,
    if (flags & MS_NOUSER)
    return -EINVAL;

    - /* ... and get the mountpoint */
    - retval = user_path_at(AT_FDCWD, dir_name, LOOKUP_FOLLOW, &path);
    - if (retval)
    - return retval;
    -
    - retval = security_sb_mount(dev_name, &path,
    - type_page, flags, data_page);
    - if (!retval && !may_mount())
    - retval = -EPERM;
    - if (!retval && (flags & SB_MANDLOCK) && !may_mandlock())
    - retval = -EPERM;
    - if (retval)
    - goto dput_out;
    + ret = security_sb_mount(dev_name, path, type_page, flags, data_page);
    + if (ret)
    + return ret;
    + if (!may_mount())
    + return -EPERM;
    + if ((flags & SB_MANDLOCK) && !may_mandlock())
    + return -EPERM;

    /* Default to relatime unless overriden */
    if (!(flags & MS_NOATIME))
    @@ -3172,7 +3165,7 @@ long do_mount(const char *dev_name, const char __user *dir_name,
    ((flags & (MS_NOATIME | MS_NODIRATIME | MS_RELATIME |
    MS_STRICTATIME)) == 0)) {
    mnt_flags &= ~MNT_ATIME_MASK;
    - mnt_flags |= path.mnt->mnt_flags & MNT_ATIME_MASK;
    + mnt_flags |= path->mnt->mnt_flags & MNT_ATIME_MASK;
    }

    sb_flags = flags & (SB_RDONLY |
    @@ -3185,22 +3178,46 @@ long do_mount(const char *dev_name, const char __user *dir_name,
    SB_I_VERSION);

    if ((flags & (MS_REMOUNT | MS_BIND)) == (MS_REMOUNT | MS_BIND))
    - retval = do_reconfigure_mnt(&path, mnt_flags);
    - else if (flags & MS_REMOUNT)
    - retval = do_remount(&path, flags, sb_flags, mnt_flags,
    - data_page);
    - else if (flags & MS_BIND)
    - retval = do_loopback(&path, dev_name, flags & MS_REC);
    - else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
    - retval = do_change_type(&path, flags);
    - else if (flags & MS_MOVE)
    - retval = do_move_mount_old(&path, dev_name);
    - else
    - retval = do_new_mount(&path, type_page, sb_flags, mnt_flags,
    - dev_name, data_page);
    -dput_out:
    + return do_reconfigure_mnt(path, mnt_flags);
    + if (flags & MS_REMOUNT)
    + return do_remount(path, flags, sb_flags, mnt_flags, data_page);
    + if (flags & MS_BIND)
    + return do_loopback(path, dev_name, flags & MS_REC);
    + if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
    + return do_change_type(path, flags);
    + if (flags & MS_MOVE)
    + return do_move_mount_old(path, dev_name);
    +
    + return do_new_mount(path, type_page, sb_flags, mnt_flags, dev_name,
    + data_page);
    +}
    +
    +long do_mount(const char *dev_name, const char __user *dir_name,
    + const char *type_page, unsigned long flags, void *data_page)
    +{
    + struct path path;
    + int ret;
    +
    + ret = user_path_at(AT_FDCWD, dir_name, LOOKUP_FOLLOW, &path);
    + if (ret)
    + return ret;
    + ret = path_mount(dev_name, &path, type_page, flags, data_page);
    path_put(&path);
    - return retval;
    + return ret;
    +}
    +
    +int do_kern_mount(const char *dev_name, const char *dir_name,
    + const char *type_page, unsigned long flags, void *data_page)
    +{
    + struct path path;
    + int ret;
    +
    + ret = kern_path(dir_name, LOOKUP_FOLLOW, &path);
    + if (ret)
    + return ret;
    + ret = path_mount(dev_name, &path, type_page, flags, data_page);
    + path_put(&path);
    + return ret;
    }

    static struct ucounts *inc_mnt_namespaces(struct user_namespace *ns)
    diff --git a/include/linux/fs.h b/include/linux/fs.h
    index a1d2685a487868..8f628f9868711d 100644
    --- a/include/linux/fs.h
    +++ b/include/linux/fs.h
    @@ -2337,6 +2337,8 @@ extern int may_umount_tree(struct vfsmount *);
    extern int may_umount(struct vfsmount *);
    extern long do_mount(const char *, const char __user *,
    const char *, unsigned long, void *);
    +int do_kern_mount(const char *dev_name, const char *dir_name,
    + const char *type_page, unsigned long flags, void *data_page);
    extern struct vfsmount *collect_mounts(const struct path *);
    extern void drop_collected_mounts(struct vfsmount *);
    extern int iterate_mounts(int (*)(struct vfsmount *, void *), void *,
    diff --git a/init/do_mounts.c b/init/do_mounts.c
    index 4f4ceb35805503..2fef92a8ed3c15 100644
    --- a/init/do_mounts.c
    +++ b/init/do_mounts.c
    @@ -395,16 +395,16 @@ static int __init do_mount_root(const char *name, const char *fs,
    int ret;

    if (data) {
    - /* do_mount() requires a full page as fifth argument */
    + /* do_kern_mount() requires a full page as fifth argument */
    p = alloc_page(GFP_KERNEL);
    if (!p)
    return -ENOMEM;
    data_page = page_address(p);
    - /* zero-pad. do_mount() will make sure it's terminated */
    + /* zero-pad. do_kern_mount() will make sure it's terminated */
    strncpy(data_page, data, PAGE_SIZE);
    }

    - ret = do_mount(name, "/root", fs, flags, data_page);
    + ret = do_kern_mount(name, "/root", fs, flags, data_page);
    if (ret)
    goto out;

    @@ -628,7 +628,7 @@ void __init prepare_namespace(void)
    mount_root();
    out:
    devtmpfs_mount();
    - do_mount(".", "/", NULL, MS_MOVE, NULL);
    + do_kern_mount(".", "/", NULL, MS_MOVE, NULL);
    ksys_chroot(".");
    }

    diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c
    index e08669187d63be..604ce78af9acfa 100644
    --- a/init/do_mounts_initrd.c
    +++ b/init/do_mounts_initrd.c
    @@ -62,7 +62,7 @@ static int __init init_linuxrc(struct subprocess_info *info, struct cred *new)
    console_on_rootfs();
    /* move initrd over / and chdir/chroot in initrd root */
    ksys_chdir("/root");
    - do_mount(".", "/", NULL, MS_MOVE, NULL);
    + do_kern_mount(".", "/", NULL, MS_MOVE, NULL);
    ksys_chroot(".");
    ksys_setsid();
    return 0;
    @@ -99,7 +99,7 @@ static void __init handle_initrd(void)
    current->flags &= ~PF_FREEZER_SKIP;

    /* move initrd to rootfs' /old */
    - do_mount("..", ".", NULL, MS_MOVE, NULL);
    + do_kern_mount("..", ".", NULL, MS_MOVE, NULL);
    /* switch root and cwd back to / of rootfs */
    ksys_chroot("..");

    @@ -113,7 +113,7 @@ static void __init handle_initrd(void)
    mount_root();

    printk(KERN_NOTICE "Trying to move old root to /initrd ... ");
    - error = do_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL);
    + error = do_kern_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL);
    if (!error)
    printk("okay\n");
    else {
    --
    2.27.0
    \
     
     \ /
      Last update: 2020-07-20 18:40    [W:7.287 / U:0.020 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site