diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2017-01-31 12:06:16 -0500 |
---|---|---|
committer | Eric W. Biederman <ebiederm@xmission.com> | 2017-02-01 10:36:12 -0500 |
commit | 93faccbbfa958a9668d3ab4e30f38dd205cee8d8 (patch) | |
tree | f4a102b92d86d19a52a88a57bdde19ad25250ca1 /fs/super.c | |
parent | c6c70f4455d1eda91065e93cc4f7eddf4499b105 (diff) |
fs: Better permission checking for submounts
To support unprivileged users mounting filesystems two permission
checks have to be performed: a test to see if the user allowed to
create a mount in the mount namespace, and a test to see if
the user is allowed to access the specified filesystem.
The automount case is special in that mounting the original filesystem
grants permission to mount the sub-filesystems, to any user who
happens to stumble across the their mountpoint and satisfies the
ordinary filesystem permission checks.
Attempting to handle the automount case by using override_creds
almost works. It preserves the idea that permission to mount
the original filesystem is permission to mount the sub-filesystem.
Unfortunately using override_creds messes up the filesystems
ordinary permission checks.
Solve this by being explicit that a mount is a submount by introducing
vfs_submount, and using it where appropriate.
vfs_submount uses a new mount internal mount flags MS_SUBMOUNT, to let
sget and friends know that a mount is a submount so they can take appropriate
action.
sget and sget_userns are modified to not perform any permission checks
on submounts.
follow_automount is modified to stop using override_creds as that
has proven problemantic.
do_mount is modified to always remove the new MS_SUBMOUNT flag so
that we know userspace will never by able to specify it.
autofs4 is modified to stop using current_real_cred that was put in
there to handle the previous version of submount permission checking.
cifs is modified to pass the mountpoint all of the way down to vfs_submount.
debugfs is modified to pass the mountpoint all of the way down to
trace_automount by adding a new parameter. To make this change easier
a new typedef debugfs_automount_t is introduced to capture the type of
the debugfs automount function.
Cc: stable@vger.kernel.org
Fixes: 069d5ac9ae0d ("autofs: Fix automounts by using current_real_cred()->uid")
Fixes: aeaa4a79ff6a ("fs: Call d_automount with the filesystems creds")
Reviewed-by: Trond Myklebust <trond.myklebust@primarydata.com>
Reviewed-by: Seth Forshee <seth.forshee@canonical.com>
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Diffstat (limited to 'fs/super.c')
-rw-r--r-- | fs/super.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/fs/super.c b/fs/super.c index 1709ed029a2c..4185844f7a12 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -469,7 +469,7 @@ struct super_block *sget_userns(struct file_system_type *type, | |||
469 | struct super_block *old; | 469 | struct super_block *old; |
470 | int err; | 470 | int err; |
471 | 471 | ||
472 | if (!(flags & MS_KERNMOUNT) && | 472 | if (!(flags & (MS_KERNMOUNT|MS_SUBMOUNT)) && |
473 | !(type->fs_flags & FS_USERNS_MOUNT) && | 473 | !(type->fs_flags & FS_USERNS_MOUNT) && |
474 | !capable(CAP_SYS_ADMIN)) | 474 | !capable(CAP_SYS_ADMIN)) |
475 | return ERR_PTR(-EPERM); | 475 | return ERR_PTR(-EPERM); |
@@ -499,7 +499,7 @@ retry: | |||
499 | } | 499 | } |
500 | if (!s) { | 500 | if (!s) { |
501 | spin_unlock(&sb_lock); | 501 | spin_unlock(&sb_lock); |
502 | s = alloc_super(type, flags, user_ns); | 502 | s = alloc_super(type, (flags & ~MS_SUBMOUNT), user_ns); |
503 | if (!s) | 503 | if (!s) |
504 | return ERR_PTR(-ENOMEM); | 504 | return ERR_PTR(-ENOMEM); |
505 | goto retry; | 505 | goto retry; |
@@ -540,8 +540,15 @@ struct super_block *sget(struct file_system_type *type, | |||
540 | { | 540 | { |
541 | struct user_namespace *user_ns = current_user_ns(); | 541 | struct user_namespace *user_ns = current_user_ns(); |
542 | 542 | ||
543 | /* We don't yet pass the user namespace of the parent | ||
544 | * mount through to here so always use &init_user_ns | ||
545 | * until that changes. | ||
546 | */ | ||
547 | if (flags & MS_SUBMOUNT) | ||
548 | user_ns = &init_user_ns; | ||
549 | |||
543 | /* Ensure the requestor has permissions over the target filesystem */ | 550 | /* Ensure the requestor has permissions over the target filesystem */ |
544 | if (!(flags & MS_KERNMOUNT) && !ns_capable(user_ns, CAP_SYS_ADMIN)) | 551 | if (!(flags & (MS_KERNMOUNT|MS_SUBMOUNT)) && !ns_capable(user_ns, CAP_SYS_ADMIN)) |
545 | return ERR_PTR(-EPERM); | 552 | return ERR_PTR(-EPERM); |
546 | 553 | ||
547 | return sget_userns(type, test, set, flags, user_ns, data); | 554 | return sget_userns(type, test, set, flags, user_ns, data); |