lkml.org 
[lkml]   [2008]   [Feb]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[patch 05/10] unprivileged mounts: allow unprivileged bind mounts
    From: Miklos Szeredi <mszeredi@suse.cz>

    Allow bind mounts to unprivileged users if the following conditions are met:

    - mountpoint is not a symlink
    - parent mount is owned by the user
    - the number of user mounts is below the maximum

    Unprivileged mounts imply MS_SETUSER, and will also have the "nosuid" and
    "nodev" mount flags set.

    In particular, if mounting process doesn't have CAP_SETUID capability,
    then the "nosuid" flag will be added, and if it doesn't have CAP_MKNOD
    capability, then the "nodev" flag will be added.

    Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
    Acked-by: Serge Hallyn <serue@us.ibm.com>
    ---

    Index: linux/fs/namespace.c
    ===================================================================
    --- linux.orig/fs/namespace.c 2008-02-04 23:47:58.000000000 +0100
    +++ linux/fs/namespace.c 2008-02-04 23:48:00.000000000 +0100
    @@ -545,6 +545,11 @@ static void __set_mnt_user(struct vfsmou
    WARN_ON(mnt->mnt_flags & MNT_USER);
    mnt->mnt_uid = current->fsuid;
    mnt->mnt_flags |= MNT_USER;
    +
    + if (!capable(CAP_SETUID))
    + mnt->mnt_flags |= MNT_NOSUID;
    + if (!capable(CAP_MKNOD))
    + mnt->mnt_flags |= MNT_NODEV;
    }

    static void set_mnt_user(struct vfsmount *mnt)
    @@ -1160,22 +1165,26 @@ asmlinkage long sys_oldumount(char __use

    #endif

    -static int mount_is_safe(struct nameidata *nd)
    +/*
    + * Conditions for unprivileged mounts are:
    + * - mountpoint is not a symlink
    + * - mountpoint is in a mount owned by the user
    + */
    +static bool permit_mount(struct nameidata *nd, int *flags)
    {
    + struct inode *inode = nd->path.dentry->d_inode;
    +
    if (capable(CAP_SYS_ADMIN))
    - return 0;
    - return -EPERM;
    -#ifdef notyet
    - if (S_ISLNK(nd->path.dentry->d_inode->i_mode))
    - return -EPERM;
    - if (nd->path.dentry->d_inode->i_mode & S_ISVTX) {
    - if (current->uid != nd->path.dentry->d_inode->i_uid)
    - return -EPERM;
    - }
    - if (vfs_permission(nd, MAY_WRITE))
    - return -EPERM;
    - return 0;
    -#endif
    + return true;
    +
    + if (S_ISLNK(inode->i_mode))
    + return false;
    +
    + if (!is_mount_owner(nd->path.mnt, current->fsuid))
    + return false;
    +
    + *flags |= MS_SETUSER;
    + return true;
    }

    static int lives_below_in_same_fs(struct dentry *d, struct dentry *dentry)
    @@ -1419,9 +1428,10 @@ static int do_loopback(struct nameidata
    int clone_fl;
    struct nameidata old_nd;
    struct vfsmount *mnt = NULL;
    - int err = mount_is_safe(nd);
    - if (err)
    - return err;
    + int err;
    +
    + if (!permit_mount(nd, &flags))
    + return -EPERM;
    if (!old_name || !*old_name)
    return -EINVAL;
    err = path_lookup(old_name, LOOKUP_FOLLOW, &old_nd);
    --


    \
     
     \ /
      Last update: 2008-02-05 22:41    [W:0.024 / U:59.660 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site