aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHannes Reinecke <hare@suse.de>2021-06-10 09:12:44 +0200
committerHannes Reinecke <hare@suse.de>2021-06-10 09:12:44 +0200
commiteddd528a51cc0838c23fd1436b6d880ccc66ac45 (patch)
treec608d9fc964aca545c5bfa0107ddaf3437ddf67c
parent147e14e30cde27157d6794c149aa0eb10f578ff1 (diff)
downloadscsi-devel-eddd528a51cc0838c23fd1436b6d880ccc66ac45.tar.gz
block: user namespace support
Add initial support for user namespace tagging of struct gendisk. Signed-off-by: Hannes Reinecke <hare@suse.de>
-rw-r--r--block/Kconfig7
-rw-r--r--block/genhd.c85
-rw-r--r--include/linux/genhd.h3
3 files changed, 95 insertions, 0 deletions
diff --git a/block/Kconfig b/block/Kconfig
index a2297edfdde88..984cdd91e8c08 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -114,6 +114,13 @@ config BLK_DEV_THROTTLING_LOW
Note, this is an experimental interface and could be changed someday.
+config BLK_DEV_USER_NS
+ bool "Block user namespace support (EXPERIMENTAL)"
+ help
+ Make block devices namespace-aware.
+
+ This is an experimental feature; functionality may be limited.
+
config BLK_CMDLINE_PARSER
bool "Block device command line partition parser"
help
diff --git a/block/genhd.c b/block/genhd.c
index 9f8cb7beaad11..6c8f09532113d 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -864,11 +864,87 @@ static const struct seq_operations partitions_op = {
};
#endif
+#ifdef CONFIG_BLK_USER_NS
+static void *user_grab_current_ns(void)
+{
+ struct user_namespace *ns = current_user_ns();
+ return get_user_ns(ns);
+}
+
+static const void *user_initial_ns(void)
+{
+ return &init_user_ns;
+}
+
+static void user_put_ns(void *p)
+{
+ struct user_namespace *ns = p;
+ put_user_ns(ns);
+}
+
+static bool user_current_may_mount(void)
+{
+ return ns_capable(current_user_ns(), CAP_SYS_ADMIN);
+}
+
+static bool user_initial_ns_propagates(void)
+{
+ return true;
+}
+
+const struct kobj_ns_type_operations user_ns_type_operations = {
+ .type = KOBJ_NS_TYPE_USER,
+ .current_may_mount = user_current_may_mount,
+ .grab_current_ns = user_grab_current_ns,
+ .initial_ns = user_initial_ns,
+ .drop_ns = user_put_ns,
+ .initial_ns_propagates = user_initial_ns_propagates,
+};
+
+static const void *block_class_user_namespace(struct device *dev)
+{
+ struct gendisk *disk;
+
+ if (dev->type == &part_type)
+ disk = part_to_disk(dev_to_part(dev));
+ else
+ disk = dev_to_disk(dev);
+
+ return disk->user_ns;
+}
+
+static void block_class_get_ownership(struct device *dev, kuid_t *uid, kgid_t *gid)
+{
+ struct gendisk *disk;
+ struct user_namespace *ns;
+
+ if (dev->type == &part_type)
+ disk = part_to_disk(dev_to_part(dev));
+ else
+ disk = dev_to_disk(dev);
+
+ ns = disk->user_ns;
+ if (ns && ns != &init_user_ns) {
+ kuid_t ns_root_uid = make_kuid(ns, 0);
+ kgid_t ns_root_gid = make_kgid(ns, 0);
+
+ if (uid_valid(ns_root_uid))
+ *uid = ns_root_uid;
+
+ if (gid_valid(ns_root_gid))
+ *gid = ns_root_gid;
+ }
+}
+#endif /* CONFIG_BLK_DEV_USER_NS */
+
static int __init genhd_device_init(void)
{
int error;
block_class.dev_kobj = sysfs_dev_block_kobj;
+#ifdef CONFIG_BLK_DEV_USER_NS
+ kobj_ns_type_register(&user_ns_type_operations);
+#endif
error = class_register(&block_class);
if (unlikely(error))
return error;
@@ -1129,8 +1205,14 @@ static void disk_release(struct device *dev)
blk_put_queue(disk->queue);
kfree(disk);
}
+
struct class block_class = {
.name = "block",
+#ifdef CONFIG_BLK_DEV_USER_NS
+ .ns_type = &user_ns_type_operations,
+ .namespace = block_class_user_namespace,
+ .get_ownership = block_class_get_ownership,
+#endif
};
static char *block_devnode(struct device *dev, umode_t *mode,
@@ -1304,6 +1386,9 @@ struct gendisk *__alloc_disk_node(int minors, int node_id)
disk_to_dev(disk)->class = &block_class;
disk_to_dev(disk)->type = &disk_type;
device_initialize(disk_to_dev(disk));
+#ifdef CONFIG_BLK_DEV_USER_NS
+ disk->user_ns = &init_user_ns;
+#endif
return disk;
out_destroy_part_tbl:
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 6fc26f7bdf71e..ba47fc047b03d 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -167,6 +167,9 @@ struct gendisk {
int node_id;
struct badblocks *bb;
struct lockdep_map lockdep_map;
+#ifdef CONFIG_BLK_DEV_USER_NS
+ struct user_namespace *user_ns;
+#endif
};
/*