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 /include | |
| 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 'include')
| -rw-r--r-- | include/linux/debugfs.h | 3 | ||||
| -rw-r--r-- | include/linux/mount.h | 3 | ||||
| -rw-r--r-- | include/uapi/linux/fs.h | 1 |
3 files changed, 6 insertions, 1 deletions
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h index 014cc564d1c4..233006be30aa 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h | |||
| @@ -97,9 +97,10 @@ struct dentry *debugfs_create_dir(const char *name, struct dentry *parent); | |||
| 97 | struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent, | 97 | struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent, |
| 98 | const char *dest); | 98 | const char *dest); |
| 99 | 99 | ||
| 100 | typedef struct vfsmount *(*debugfs_automount_t)(struct dentry *, void *); | ||
| 100 | struct dentry *debugfs_create_automount(const char *name, | 101 | struct dentry *debugfs_create_automount(const char *name, |
| 101 | struct dentry *parent, | 102 | struct dentry *parent, |
| 102 | struct vfsmount *(*f)(void *), | 103 | debugfs_automount_t f, |
| 103 | void *data); | 104 | void *data); |
| 104 | 105 | ||
| 105 | void debugfs_remove(struct dentry *dentry); | 106 | void debugfs_remove(struct dentry *dentry); |
diff --git a/include/linux/mount.h b/include/linux/mount.h index c6f55158d5e5..8e0352af06b7 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h | |||
| @@ -90,6 +90,9 @@ struct file_system_type; | |||
| 90 | extern struct vfsmount *vfs_kern_mount(struct file_system_type *type, | 90 | extern struct vfsmount *vfs_kern_mount(struct file_system_type *type, |
| 91 | int flags, const char *name, | 91 | int flags, const char *name, |
| 92 | void *data); | 92 | void *data); |
| 93 | extern struct vfsmount *vfs_submount(const struct dentry *mountpoint, | ||
| 94 | struct file_system_type *type, | ||
| 95 | const char *name, void *data); | ||
| 93 | 96 | ||
| 94 | extern void mnt_set_expiry(struct vfsmount *mnt, struct list_head *expiry_list); | 97 | extern void mnt_set_expiry(struct vfsmount *mnt, struct list_head *expiry_list); |
| 95 | extern void mark_mounts_for_expiry(struct list_head *mounts); | 98 | extern void mark_mounts_for_expiry(struct list_head *mounts); |
diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h index 36da93fbf188..048a85e9f017 100644 --- a/include/uapi/linux/fs.h +++ b/include/uapi/linux/fs.h | |||
| @@ -132,6 +132,7 @@ struct inodes_stat_t { | |||
| 132 | #define MS_LAZYTIME (1<<25) /* Update the on-disk [acm]times lazily */ | 132 | #define MS_LAZYTIME (1<<25) /* Update the on-disk [acm]times lazily */ |
| 133 | 133 | ||
| 134 | /* These sb flags are internal to the kernel */ | 134 | /* These sb flags are internal to the kernel */ |
| 135 | #define MS_SUBMOUNT (1<<26) | ||
| 135 | #define MS_NOREMOTELOCK (1<<27) | 136 | #define MS_NOREMOTELOCK (1<<27) |
| 136 | #define MS_NOSEC (1<<28) | 137 | #define MS_NOSEC (1<<28) |
| 137 | #define MS_BORN (1<<29) | 138 | #define MS_BORN (1<<29) |
