summaryrefslogtreecommitdiffstats
path: root/include/linux/fs.h
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2016-05-24 10:29:01 -0400
committerEric W. Biederman <ebiederm@xmission.com>2016-06-23 16:41:55 -0400
commit6e4eab577a0cae15b3da9b888cff16fe57981b3e (patch)
treebb60b079a664429a42113aecdb05b3858460850f /include/linux/fs.h
parente94591d0d90c13166cb6eb54ce5f96ed13d81b55 (diff)
fs: Add user namespace member to struct super_block
Start marking filesystems with a user namespace owner, s_user_ns. In this change this is only used for permission checks of who may mount a filesystem. Ultimately s_user_ns will be used for translating ids and checking capabilities for filesystems mounted from user namespaces. The default policy for setting s_user_ns is implemented in sget(), which arranges for s_user_ns to be set to current_user_ns() and to ensure that the mounter of the filesystem has CAP_SYS_ADMIN in that user_ns. The guts of sget are split out into another function sget_userns(). The function sget_userns calls alloc_super with the specified user namespace or it verifies the existing superblock that was found has the expected user namespace, and fails with EBUSY when it is not. This failing prevents users with the wrong privileges mounting a filesystem. The reason for the split of sget_userns from sget is that in some cases such as mount_ns and kernfs_mount_ns a different policy for permission checking of mounts and setting s_user_ns is necessary, and the existence of sget_userns() allows those policies to be implemented. The helper mount_ns is expected to be used for filesystems such as proc and mqueuefs which present per namespace information. The function mount_ns is modified to call sget_userns instead of sget to ensure the user namespace owner of the namespace whose information is presented by the filesystem is used on the superblock. For sysfs and cgroup the appropriate permission checks are already in place, and kernfs_mount_ns is modified to call sget_userns so that the init_user_ns is the only user namespace used. For the cgroup filesystem cgroup namespace mounts are bind mounts of a subset of the full cgroup filesystem and as such s_user_ns must be the same for all of them as there is only a single superblock. Mounts of sysfs that vary based on the network namespace could in principle change s_user_ns but it keeps the analysis and implementation of kernfs simpler if that is not supported, and at present there appear to be no benefits from supporting a different s_user_ns on any sysfs mount. Getting the details of setting s_user_ns correct has been a long process. Thanks to Pavel Tikhorirorv who spotted a leak in sget_userns. Thanks to Seth Forshee who has kept the work alive. Thanks-to: Seth Forshee <seth.forshee@canonical.com> Thanks-to: Pavel Tikhomirov <ptikhomirov@virtuozzo.com> Acked-by: Seth Forshee <seth.forshee@canonical.com> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Diffstat (limited to 'include/linux/fs.h')
-rw-r--r--include/linux/fs.h12
1 files changed, 12 insertions, 0 deletions
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 1ce006a24f49..9eef64f23a75 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1433,6 +1433,13 @@ struct super_block {
1433 struct hlist_head s_pins; 1433 struct hlist_head s_pins;
1434 1434
1435 /* 1435 /*
1436 * Owning user namespace and default context in which to
1437 * interpret filesystem uids, gids, quotas, device nodes,
1438 * xattrs and security labels.
1439 */
1440 struct user_namespace *s_user_ns;
1441
1442 /*
1436 * Keep the lru lists last in the structure so they always sit on their 1443 * Keep the lru lists last in the structure so they always sit on their
1437 * own individual cachelines. 1444 * own individual cachelines.
1438 */ 1445 */
@@ -2056,6 +2063,11 @@ void deactivate_locked_super(struct super_block *sb);
2056int set_anon_super(struct super_block *s, void *data); 2063int set_anon_super(struct super_block *s, void *data);
2057int get_anon_bdev(dev_t *); 2064int get_anon_bdev(dev_t *);
2058void free_anon_bdev(dev_t); 2065void free_anon_bdev(dev_t);
2066struct super_block *sget_userns(struct file_system_type *type,
2067 int (*test)(struct super_block *,void *),
2068 int (*set)(struct super_block *,void *),
2069 int flags, struct user_namespace *user_ns,
2070 void *data);
2059struct super_block *sget(struct file_system_type *type, 2071struct super_block *sget(struct file_system_type *type,
2060 int (*test)(struct super_block *,void *), 2072 int (*test)(struct super_block *,void *),
2061 int (*set)(struct super_block *,void *), 2073 int (*set)(struct super_block *,void *),