summaryrefslogtreecommitdiffstats
path: root/fs/super.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2017-01-31 12:06:16 -0500
committerEric W. Biederman <ebiederm@xmission.com>2017-02-01 10:36:12 -0500
commit93faccbbfa958a9668d3ab4e30f38dd205cee8d8 (patch)
treef4a102b92d86d19a52a88a57bdde19ad25250ca1 /fs/super.c
parentc6c70f4455d1eda91065e93cc4f7eddf4499b105 (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.c13
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);