diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2019-05-12 19:18:42 +0200 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2019-05-25 23:59:55 +0200 |
commit | feb8ae43a7b33148028829b1b1691b28c874c952 (patch) | |
tree | 1670945a5204dba39d205c1c4c420025f159a035 /fs/super.c | |
parent | no need to protect against put_user_ns(NULL) (diff) | |
download | linux-feb8ae43a7b33148028829b1b1691b28c874c952.tar.xz linux-feb8ae43a7b33148028829b1b1691b28c874c952.zip |
start massaging the checks in sget_...(): move to sget_userns()
there are 3 remaining callers of sget_userns() - sget(), mount_ns()
and mount_pseudo_xattr(). Extra check in sget() is conditional
upon mount being neither KERNMOUNT nor SUBMOUNT, the identical one
in mount_ns() - upon being not KERNMOUNT; mount_pseudo_xattr()
has no such checks at all.
However, mount_ns() is never used with SUBMOUNT and mount_pseudo_xattr()
is used only for KERNMOUNT, so both would be fine with the same logics
as currently done in sget(), allowing to consolidate the entire thing
in sget_userns() itself.
That's not where these checks will end up in the long run, though -
the whole reason why they'd been done so deep in the bowels of
mount(2) was that there had been no way for a filesystem to specify
which userns to look at until it has entered ->mount().
Now there is a place where filesystem could override the defaults -
->init_fs_context(). Which allows to pull the checks out into
the callers of vfs_get_tree(). That'll take quite a bit of
massage, but that mess is possible to tease apart.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/super.c')
-rw-r--r-- | fs/super.c | 14 |
1 files changed, 4 insertions, 10 deletions
diff --git a/fs/super.c b/fs/super.c index 2739f57515f8..9c371a04e1b6 100644 --- a/fs/super.c +++ b/fs/super.c @@ -583,6 +583,10 @@ struct super_block *sget_userns(struct file_system_type *type, struct super_block *old; int err; + /* Ensure the requestor has permissions over the target filesystem */ + if (!(flags & (SB_KERNMOUNT|SB_SUBMOUNT)) && !ns_capable(user_ns, CAP_SYS_ADMIN)) + return ERR_PTR(-EPERM); + if (!(flags & (SB_KERNMOUNT|SB_SUBMOUNT)) && !(type->fs_flags & FS_USERNS_MOUNT) && !capable(CAP_SYS_ADMIN)) @@ -653,10 +657,6 @@ struct super_block *sget(struct file_system_type *type, if (flags & SB_SUBMOUNT) user_ns = &init_user_ns; - /* Ensure the requestor has permissions over the target filesystem */ - if (!(flags & (SB_KERNMOUNT|SB_SUBMOUNT)) && !ns_capable(user_ns, CAP_SYS_ADMIN)) - return ERR_PTR(-EPERM); - return sget_userns(type, test, set, flags, user_ns, data); } @@ -1164,12 +1164,6 @@ struct dentry *mount_ns(struct file_system_type *fs_type, { struct super_block *sb; - /* Don't allow mounting unless the caller has CAP_SYS_ADMIN - * over the namespace. - */ - if (!(flags & SB_KERNMOUNT) && !ns_capable(user_ns, CAP_SYS_ADMIN)) - return ERR_PTR(-EPERM); - sb = sget_userns(fs_type, ns_test_super, ns_set_super, flags, user_ns, ns); if (IS_ERR(sb)) |