mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-03-30 19:15:14 +00:00
new helper: do_new_mount_fc()
Create an fs_context-aware version of do_new_mount(). This takes an fs_context with a superblock already attached to it. Make do_new_mount() use do_new_mount_fc() rather than do_new_mount(); this allows the consolidation of the mount creation, check and add steps. To make this work, mount_too_revealing() is changed to take a superblock rather than a mount (which the fs_context doesn't have available), allowing this check to be done before the mount object is created. Signed-off-by: David Howells <dhowells@redhat.com> Co-developed-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
a0c9a8b8fd
commit
132e460848
1 changed files with 39 additions and 26 deletions
|
@ -2523,7 +2523,37 @@ unlock:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mount_too_revealing(struct vfsmount *mnt, int *new_mnt_flags);
|
static bool mount_too_revealing(const struct super_block *sb, int *new_mnt_flags);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a new mount using a superblock configuration and request it
|
||||||
|
* be added to the namespace tree.
|
||||||
|
*/
|
||||||
|
static int do_new_mount_fc(struct fs_context *fc, struct path *mountpoint,
|
||||||
|
unsigned int mnt_flags)
|
||||||
|
{
|
||||||
|
struct vfsmount *mnt;
|
||||||
|
struct super_block *sb = fc->root->d_sb;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
if (mount_too_revealing(sb, &mnt_flags)) {
|
||||||
|
dput(fc->root);
|
||||||
|
fc->root = NULL;
|
||||||
|
deactivate_locked_super(sb);
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
|
|
||||||
|
up_write(&sb->s_umount);
|
||||||
|
|
||||||
|
mnt = vfs_create_mount(fc);
|
||||||
|
if (IS_ERR(mnt))
|
||||||
|
return PTR_ERR(mnt);
|
||||||
|
|
||||||
|
error = do_add_mount(real_mount(mnt), mountpoint, mnt_flags);
|
||||||
|
if (error < 0)
|
||||||
|
mntput(mnt);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* create a new mount for userspace and request it to be added into the
|
* create a new mount for userspace and request it to be added into the
|
||||||
|
@ -2533,7 +2563,6 @@ static int do_new_mount(struct path *path, const char *fstype, int sb_flags,
|
||||||
int mnt_flags, const char *name, void *data)
|
int mnt_flags, const char *name, void *data)
|
||||||
{
|
{
|
||||||
struct file_system_type *type;
|
struct file_system_type *type;
|
||||||
struct vfsmount *mnt;
|
|
||||||
struct fs_context *fc;
|
struct fs_context *fc;
|
||||||
const char *subtype = NULL;
|
const char *subtype = NULL;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
@ -2577,26 +2606,9 @@ static int do_new_mount(struct path *path, const char *fstype, int sb_flags,
|
||||||
err = parse_monolithic_mount_data(fc, data);
|
err = parse_monolithic_mount_data(fc, data);
|
||||||
if (!err)
|
if (!err)
|
||||||
err = vfs_get_tree(fc);
|
err = vfs_get_tree(fc);
|
||||||
if (err)
|
if (!err)
|
||||||
goto out;
|
err = do_new_mount_fc(fc, path, mnt_flags);
|
||||||
|
|
||||||
up_write(&fc->root->d_sb->s_umount);
|
|
||||||
mnt = vfs_create_mount(fc);
|
|
||||||
if (IS_ERR(mnt)) {
|
|
||||||
err = PTR_ERR(mnt);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mount_too_revealing(mnt, &mnt_flags)) {
|
|
||||||
mntput(mnt);
|
|
||||||
err = -EPERM;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = do_add_mount(real_mount(mnt), path, mnt_flags);
|
|
||||||
if (err)
|
|
||||||
mntput(mnt);
|
|
||||||
out:
|
|
||||||
put_fs_context(fc);
|
put_fs_context(fc);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -3421,7 +3433,8 @@ bool current_chrooted(void)
|
||||||
return chrooted;
|
return chrooted;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mnt_already_visible(struct mnt_namespace *ns, struct vfsmount *new,
|
static bool mnt_already_visible(struct mnt_namespace *ns,
|
||||||
|
const struct super_block *sb,
|
||||||
int *new_mnt_flags)
|
int *new_mnt_flags)
|
||||||
{
|
{
|
||||||
int new_flags = *new_mnt_flags;
|
int new_flags = *new_mnt_flags;
|
||||||
|
@ -3433,7 +3446,7 @@ static bool mnt_already_visible(struct mnt_namespace *ns, struct vfsmount *new,
|
||||||
struct mount *child;
|
struct mount *child;
|
||||||
int mnt_flags;
|
int mnt_flags;
|
||||||
|
|
||||||
if (mnt->mnt.mnt_sb->s_type != new->mnt_sb->s_type)
|
if (mnt->mnt.mnt_sb->s_type != sb->s_type)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* This mount is not fully visible if it's root directory
|
/* This mount is not fully visible if it's root directory
|
||||||
|
@ -3484,7 +3497,7 @@ found:
|
||||||
return visible;
|
return visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mount_too_revealing(struct vfsmount *mnt, int *new_mnt_flags)
|
static bool mount_too_revealing(const struct super_block *sb, int *new_mnt_flags)
|
||||||
{
|
{
|
||||||
const unsigned long required_iflags = SB_I_NOEXEC | SB_I_NODEV;
|
const unsigned long required_iflags = SB_I_NOEXEC | SB_I_NODEV;
|
||||||
struct mnt_namespace *ns = current->nsproxy->mnt_ns;
|
struct mnt_namespace *ns = current->nsproxy->mnt_ns;
|
||||||
|
@ -3494,7 +3507,7 @@ static bool mount_too_revealing(struct vfsmount *mnt, int *new_mnt_flags)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Can this filesystem be too revealing? */
|
/* Can this filesystem be too revealing? */
|
||||||
s_iflags = mnt->mnt_sb->s_iflags;
|
s_iflags = sb->s_iflags;
|
||||||
if (!(s_iflags & SB_I_USERNS_VISIBLE))
|
if (!(s_iflags & SB_I_USERNS_VISIBLE))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -3504,7 +3517,7 @@ static bool mount_too_revealing(struct vfsmount *mnt, int *new_mnt_flags)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return !mnt_already_visible(ns, mnt, new_mnt_flags);
|
return !mnt_already_visible(ns, sb, new_mnt_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mnt_may_suid(struct vfsmount *mnt)
|
bool mnt_may_suid(struct vfsmount *mnt)
|
||||||
|
|
Loading…
Add table
Reference in a new issue