* [PATCH V3 0/6] ublk_drv: add mechanism for supporting unprivileged ublk device
@ 2022-12-07 12:32 Ming Lei
2022-12-07 12:33 ` [PATCH V3 1/6] ublk_drv: remove nr_aborted_queues from ublk_device Ming Lei
` (6 more replies)
0 siblings, 7 replies; 12+ messages in thread
From: Ming Lei @ 2022-12-07 12:32 UTC (permalink / raw)
To: Jens Axboe; +Cc: linux-block, ZiyangZhang, Ming Lei
Hello,
Stefan Hajnoczi suggested un-privileged ublk device[1] for container
use case.
So far only administrator can create/control ublk device which is too
strict and increase system administrator burden, and this patchset
implements un-privileged ublk device:
- any user can create ublk device, which can only be controlled &
accessed by the owner of the device or administrator
For using such mechanism, system administrator needs to deploy two
simple udev rules[2] after running 'make install' in ublksrv.
Userspace(ublksrv):
https://github.com/ming1/ubdsrv/tree/unprivileged-ublk
'ublk add -t $TYPE --un_privileged' is for creating one un-privileged
ublk device if the user is un-privileged.
[1] https://lore.kernel.org/linux-block/YoOr6jBfgVm8GvWg@stefanha-x1.localdomain/
[2] https://github.com/ming1/ubdsrv/blob/unprivileged-ublk/README.rst#un-privileged-mode
V3:
- don't warn on invalid user input for setting devt parameter, as
suggested by Ziyang, patch 4/6
- fix one memory corruption issue, patch 6/6
V2:
- fix "ublk_ctrl_uring_cmd_permission() error: uninitialized symbol 'mask'", reported
by Dan Carpenter' test robot
- address Ziyang's comment on dealing with nr_privileged_daemon
Ming Lei (6):
ublk_drv: remove nr_aborted_queues from ublk_device
ublk_drv: don't probe partitions if the ubq daemon isn't trusted
ublk_drv: move ublk_get_device_from_id into ublk_ctrl_uring_cmd
ublk_drv: add device parameter UBLK_PARAM_TYPE_DEVT
ublk_drv: add module parameter of ublks_max for limiting max allowed
ublk dev
ublk_drv: add mechanism for supporting unprivileged ublk device
Documentation/block/ublk.rst | 18 +-
drivers/block/ublk_drv.c | 336 ++++++++++++++++++++++++----------
include/uapi/linux/ublk_cmd.h | 49 ++++-
3 files changed, 296 insertions(+), 107 deletions(-)
--
2.31.1
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH V3 1/6] ublk_drv: remove nr_aborted_queues from ublk_device
2022-12-07 12:32 [PATCH V3 0/6] ublk_drv: add mechanism for supporting unprivileged ublk device Ming Lei
@ 2022-12-07 12:33 ` Ming Lei
2022-12-07 12:33 ` [PATCH V3 2/6] ublk_drv: don't probe partitions if the ubq daemon isn't trusted Ming Lei
` (5 subsequent siblings)
6 siblings, 0 replies; 12+ messages in thread
From: Ming Lei @ 2022-12-07 12:33 UTC (permalink / raw)
To: Jens Axboe; +Cc: linux-block, ZiyangZhang, Ming Lei
No one uses 'nr_aborted_queues' any more, so remove it.
Reviewed-by: ZiyangZhang <ZiyangZhang@linux.alibaba.com>
Signed-off-by: Ming Lei <ming.lei@redhat.com>
---
drivers/block/ublk_drv.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index e9de9d846b73..30db5e5edac4 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -159,7 +159,6 @@ struct ublk_device {
struct completion completion;
unsigned int nr_queues_ready;
- atomic_t nr_aborted_queues;
/*
* Our ubq->daemon may be killed without any notification, so
--
2.31.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH V3 2/6] ublk_drv: don't probe partitions if the ubq daemon isn't trusted
2022-12-07 12:32 [PATCH V3 0/6] ublk_drv: add mechanism for supporting unprivileged ublk device Ming Lei
2022-12-07 12:33 ` [PATCH V3 1/6] ublk_drv: remove nr_aborted_queues from ublk_device Ming Lei
@ 2022-12-07 12:33 ` Ming Lei
2022-12-07 12:33 ` [PATCH V3 3/6] ublk_drv: move ublk_get_device_from_id into ublk_ctrl_uring_cmd Ming Lei
` (4 subsequent siblings)
6 siblings, 0 replies; 12+ messages in thread
From: Ming Lei @ 2022-12-07 12:33 UTC (permalink / raw)
To: Jens Axboe; +Cc: linux-block, ZiyangZhang, Ming Lei
If any ubq daemon is unprivileged, the ublk char device is allowed
for unprivileged user actually, and we can't trust the current user,
so not probe partitions.
Fixes: 71f28f3136af ("ublk_drv: add io_uring based userspace block driver")
Reviewed-by: ZiyangZhang <ZiyangZhang@linux.alibaba.com>
Signed-off-by: Ming Lei <ming.lei@redhat.com>
---
drivers/block/ublk_drv.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index 30db5e5edac4..a3d776a1c2f5 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -159,6 +159,7 @@ struct ublk_device {
struct completion completion;
unsigned int nr_queues_ready;
+ unsigned int nr_privileged_daemon;
/*
* Our ubq->daemon may be killed without any notification, so
@@ -1178,6 +1179,9 @@ static void ublk_mark_io_ready(struct ublk_device *ub, struct ublk_queue *ubq)
ubq->ubq_daemon = current;
get_task_struct(ubq->ubq_daemon);
ub->nr_queues_ready++;
+
+ if (capable(CAP_SYS_ADMIN))
+ ub->nr_privileged_daemon++;
}
if (ub->nr_queues_ready == ub->dev_info.nr_hw_queues)
complete_all(&ub->completion);
@@ -1534,6 +1538,10 @@ static int ublk_ctrl_start_dev(struct io_uring_cmd *cmd)
if (ret)
goto out_put_disk;
+ /* don't probe partitions if any one ubq daemon is un-trusted */
+ if (ub->nr_privileged_daemon != ub->nr_queues_ready)
+ set_bit(GD_SUPPRESS_PART_SCAN, &disk->state);
+
get_device(&ub->cdev_dev);
ret = add_disk(disk);
if (ret) {
@@ -1935,6 +1943,7 @@ static int ublk_ctrl_start_recovery(struct io_uring_cmd *cmd)
/* set to NULL, otherwise new ubq_daemon cannot mmap the io_cmd_buf */
ub->mm = NULL;
ub->nr_queues_ready = 0;
+ ub->nr_privileged_daemon = 0;
init_completion(&ub->completion);
ret = 0;
out_unlock:
--
2.31.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH V3 3/6] ublk_drv: move ublk_get_device_from_id into ublk_ctrl_uring_cmd
2022-12-07 12:32 [PATCH V3 0/6] ublk_drv: add mechanism for supporting unprivileged ublk device Ming Lei
2022-12-07 12:33 ` [PATCH V3 1/6] ublk_drv: remove nr_aborted_queues from ublk_device Ming Lei
2022-12-07 12:33 ` [PATCH V3 2/6] ublk_drv: don't probe partitions if the ubq daemon isn't trusted Ming Lei
@ 2022-12-07 12:33 ` Ming Lei
2022-12-07 12:33 ` [PATCH V3 4/6] ublk_drv: add device parameter UBLK_PARAM_TYPE_DEVT Ming Lei
` (3 subsequent siblings)
6 siblings, 0 replies; 12+ messages in thread
From: Ming Lei @ 2022-12-07 12:33 UTC (permalink / raw)
To: Jens Axboe; +Cc: linux-block, ZiyangZhang, Ming Lei
It is annoying for each control command handler to get/put ublk
device and deal with failure.
Control command handler is simplified a lot by moving
ublk_get_device_from_id into ublk_ctrl_uring_cmd().
Reviewed-by: ZiyangZhang <ZiyangZhang@linux.alibaba.com>
Signed-off-by: Ming Lei <ming.lei@redhat.com>
---
drivers/block/ublk_drv.c | 138 ++++++++++++++-------------------------
1 file changed, 49 insertions(+), 89 deletions(-)
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index a3d776a1c2f5..9d1578384cba 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -1496,21 +1496,16 @@ static struct ublk_device *ublk_get_device_from_id(int idx)
return ub;
}
-static int ublk_ctrl_start_dev(struct io_uring_cmd *cmd)
+static int ublk_ctrl_start_dev(struct ublk_device *ub, struct io_uring_cmd *cmd)
{
struct ublksrv_ctrl_cmd *header = (struct ublksrv_ctrl_cmd *)cmd->cmd;
int ublksrv_pid = (int)header->data[0];
- struct ublk_device *ub;
struct gendisk *disk;
int ret = -EINVAL;
if (ublksrv_pid <= 0)
return -EINVAL;
- ub = ublk_get_device_from_id(header->dev_id);
- if (!ub)
- return -EINVAL;
-
wait_for_completion_interruptible(&ub->completion);
schedule_delayed_work(&ub->monitor_work, UBLK_DAEMON_MONITOR_PERIOD);
@@ -1559,21 +1554,20 @@ static int ublk_ctrl_start_dev(struct io_uring_cmd *cmd)
put_disk(disk);
out_unlock:
mutex_unlock(&ub->mutex);
- ublk_put_device(ub);
return ret;
}
-static int ublk_ctrl_get_queue_affinity(struct io_uring_cmd *cmd)
+static int ublk_ctrl_get_queue_affinity(struct ublk_device *ub,
+ struct io_uring_cmd *cmd)
{
struct ublksrv_ctrl_cmd *header = (struct ublksrv_ctrl_cmd *)cmd->cmd;
void __user *argp = (void __user *)(unsigned long)header->addr;
- struct ublk_device *ub;
cpumask_var_t cpumask;
unsigned long queue;
unsigned int retlen;
unsigned int i;
- int ret = -EINVAL;
-
+ int ret;
+
if (header->len * BITS_PER_BYTE < nr_cpu_ids)
return -EINVAL;
if (header->len & (sizeof(unsigned long)-1))
@@ -1581,17 +1575,12 @@ static int ublk_ctrl_get_queue_affinity(struct io_uring_cmd *cmd)
if (!header->addr)
return -EINVAL;
- ub = ublk_get_device_from_id(header->dev_id);
- if (!ub)
- return -EINVAL;
-
queue = header->data[0];
if (queue >= ub->dev_info.nr_hw_queues)
- goto out_put_device;
+ return -EINVAL;
- ret = -ENOMEM;
if (!zalloc_cpumask_var(&cpumask, GFP_KERNEL))
- goto out_put_device;
+ return -ENOMEM;
for_each_possible_cpu(i) {
if (ub->tag_set.map[HCTX_TYPE_DEFAULT].mq_map[i] == queue)
@@ -1609,8 +1598,6 @@ static int ublk_ctrl_get_queue_affinity(struct io_uring_cmd *cmd)
ret = 0;
out_free_cpumask:
free_cpumask_var(cpumask);
-out_put_device:
- ublk_put_device(ub);
return ret;
}
@@ -1731,30 +1718,27 @@ static inline bool ublk_idr_freed(int id)
return ptr == NULL;
}
-static int ublk_ctrl_del_dev(int idx)
+static int ublk_ctrl_del_dev(struct ublk_device **p_ub)
{
- struct ublk_device *ub;
+ struct ublk_device *ub = *p_ub;
+ int idx = ub->ub_number;
int ret;
ret = mutex_lock_killable(&ublk_ctl_mutex);
if (ret)
return ret;
- ub = ublk_get_device_from_id(idx);
- if (ub) {
- ublk_remove(ub);
- ublk_put_device(ub);
- ret = 0;
- } else {
- ret = -ENODEV;
- }
+ ublk_remove(ub);
+
+ /* Mark the reference as consumed */
+ *p_ub = NULL;
+ ublk_put_device(ub);
/*
* Wait until the idr is removed, then it can be reused after
* DEL_DEV command is returned.
*/
- if (!ret)
- wait_event(ublk_idr_wq, ublk_idr_freed(idx));
+ wait_event(ublk_idr_wq, ublk_idr_freed(idx));
mutex_unlock(&ublk_ctl_mutex);
return ret;
@@ -1769,50 +1753,36 @@ static inline void ublk_ctrl_cmd_dump(struct io_uring_cmd *cmd)
header->data[0], header->addr, header->len);
}
-static int ublk_ctrl_stop_dev(struct io_uring_cmd *cmd)
+static int ublk_ctrl_stop_dev(struct ublk_device *ub)
{
- struct ublksrv_ctrl_cmd *header = (struct ublksrv_ctrl_cmd *)cmd->cmd;
- struct ublk_device *ub;
-
- ub = ublk_get_device_from_id(header->dev_id);
- if (!ub)
- return -EINVAL;
-
ublk_stop_dev(ub);
cancel_work_sync(&ub->stop_work);
cancel_work_sync(&ub->quiesce_work);
- ublk_put_device(ub);
return 0;
}
-static int ublk_ctrl_get_dev_info(struct io_uring_cmd *cmd)
+static int ublk_ctrl_get_dev_info(struct ublk_device *ub,
+ struct io_uring_cmd *cmd)
{
struct ublksrv_ctrl_cmd *header = (struct ublksrv_ctrl_cmd *)cmd->cmd;
void __user *argp = (void __user *)(unsigned long)header->addr;
- struct ublk_device *ub;
- int ret = 0;
if (header->len < sizeof(struct ublksrv_ctrl_dev_info) || !header->addr)
return -EINVAL;
- ub = ublk_get_device_from_id(header->dev_id);
- if (!ub)
- return -EINVAL;
-
if (copy_to_user(argp, &ub->dev_info, sizeof(ub->dev_info)))
- ret = -EFAULT;
- ublk_put_device(ub);
+ return -EFAULT;
- return ret;
+ return 0;
}
-static int ublk_ctrl_get_params(struct io_uring_cmd *cmd)
+static int ublk_ctrl_get_params(struct ublk_device *ub,
+ struct io_uring_cmd *cmd)
{
struct ublksrv_ctrl_cmd *header = (struct ublksrv_ctrl_cmd *)cmd->cmd;
void __user *argp = (void __user *)(unsigned long)header->addr;
struct ublk_params_header ph;
- struct ublk_device *ub;
int ret;
if (header->len <= sizeof(ph) || !header->addr)
@@ -1827,10 +1797,6 @@ static int ublk_ctrl_get_params(struct io_uring_cmd *cmd)
if (ph.len > sizeof(struct ublk_params))
ph.len = sizeof(struct ublk_params);
- ub = ublk_get_device_from_id(header->dev_id);
- if (!ub)
- return -EINVAL;
-
mutex_lock(&ub->mutex);
if (copy_to_user(argp, &ub->params, ph.len))
ret = -EFAULT;
@@ -1838,16 +1804,15 @@ static int ublk_ctrl_get_params(struct io_uring_cmd *cmd)
ret = 0;
mutex_unlock(&ub->mutex);
- ublk_put_device(ub);
return ret;
}
-static int ublk_ctrl_set_params(struct io_uring_cmd *cmd)
+static int ublk_ctrl_set_params(struct ublk_device *ub,
+ struct io_uring_cmd *cmd)
{
struct ublksrv_ctrl_cmd *header = (struct ublksrv_ctrl_cmd *)cmd->cmd;
void __user *argp = (void __user *)(unsigned long)header->addr;
struct ublk_params_header ph;
- struct ublk_device *ub;
int ret = -EFAULT;
if (header->len <= sizeof(ph) || !header->addr)
@@ -1862,10 +1827,6 @@ static int ublk_ctrl_set_params(struct io_uring_cmd *cmd)
if (ph.len > sizeof(struct ublk_params))
ph.len = sizeof(struct ublk_params);
- ub = ublk_get_device_from_id(header->dev_id);
- if (!ub)
- return -EINVAL;
-
/* parameters can only be changed when device isn't live */
mutex_lock(&ub->mutex);
if (ub->dev_info.state == UBLK_S_DEV_LIVE) {
@@ -1878,7 +1839,6 @@ static int ublk_ctrl_set_params(struct io_uring_cmd *cmd)
ret = ublk_validate_params(ub);
}
mutex_unlock(&ub->mutex);
- ublk_put_device(ub);
return ret;
}
@@ -1905,17 +1865,13 @@ static void ublk_queue_reinit(struct ublk_device *ub, struct ublk_queue *ubq)
}
}
-static int ublk_ctrl_start_recovery(struct io_uring_cmd *cmd)
+static int ublk_ctrl_start_recovery(struct ublk_device *ub,
+ struct io_uring_cmd *cmd)
{
struct ublksrv_ctrl_cmd *header = (struct ublksrv_ctrl_cmd *)cmd->cmd;
- struct ublk_device *ub;
int ret = -EINVAL;
int i;
- ub = ublk_get_device_from_id(header->dev_id);
- if (!ub)
- return ret;
-
mutex_lock(&ub->mutex);
if (!ublk_can_use_recovery(ub))
goto out_unlock;
@@ -1948,21 +1904,16 @@ static int ublk_ctrl_start_recovery(struct io_uring_cmd *cmd)
ret = 0;
out_unlock:
mutex_unlock(&ub->mutex);
- ublk_put_device(ub);
return ret;
}
-static int ublk_ctrl_end_recovery(struct io_uring_cmd *cmd)
+static int ublk_ctrl_end_recovery(struct ublk_device *ub,
+ struct io_uring_cmd *cmd)
{
struct ublksrv_ctrl_cmd *header = (struct ublksrv_ctrl_cmd *)cmd->cmd;
int ublksrv_pid = (int)header->data[0];
- struct ublk_device *ub;
int ret = -EINVAL;
- ub = ublk_get_device_from_id(header->dev_id);
- if (!ub)
- return ret;
-
pr_devel("%s: Waiting for new ubq_daemons(nr: %d) are ready, dev id %d...\n",
__func__, ub->dev_info.nr_hw_queues, header->dev_id);
/* wait until new ubq_daemon sending all FETCH_REQ */
@@ -1990,7 +1941,6 @@ static int ublk_ctrl_end_recovery(struct io_uring_cmd *cmd)
ret = 0;
out_unlock:
mutex_unlock(&ub->mutex);
- ublk_put_device(ub);
return ret;
}
@@ -1998,6 +1948,7 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd,
unsigned int issue_flags)
{
struct ublksrv_ctrl_cmd *header = (struct ublksrv_ctrl_cmd *)cmd->cmd;
+ struct ublk_device *ub = NULL;
int ret = -EINVAL;
ublk_ctrl_cmd_dump(cmd);
@@ -2009,41 +1960,50 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd,
if (!capable(CAP_SYS_ADMIN))
goto out;
- ret = -ENODEV;
+ if (cmd->cmd_op != UBLK_CMD_ADD_DEV) {
+ ret = -ENODEV;
+ ub = ublk_get_device_from_id(header->dev_id);
+ if (!ub)
+ goto out;
+ }
+
switch (cmd->cmd_op) {
case UBLK_CMD_START_DEV:
- ret = ublk_ctrl_start_dev(cmd);
+ ret = ublk_ctrl_start_dev(ub, cmd);
break;
case UBLK_CMD_STOP_DEV:
- ret = ublk_ctrl_stop_dev(cmd);
+ ret = ublk_ctrl_stop_dev(ub);
break;
case UBLK_CMD_GET_DEV_INFO:
- ret = ublk_ctrl_get_dev_info(cmd);
+ ret = ublk_ctrl_get_dev_info(ub, cmd);
break;
case UBLK_CMD_ADD_DEV:
ret = ublk_ctrl_add_dev(cmd);
break;
case UBLK_CMD_DEL_DEV:
- ret = ublk_ctrl_del_dev(header->dev_id);
+ ret = ublk_ctrl_del_dev(&ub);
break;
case UBLK_CMD_GET_QUEUE_AFFINITY:
- ret = ublk_ctrl_get_queue_affinity(cmd);
+ ret = ublk_ctrl_get_queue_affinity(ub, cmd);
break;
case UBLK_CMD_GET_PARAMS:
- ret = ublk_ctrl_get_params(cmd);
+ ret = ublk_ctrl_get_params(ub, cmd);
break;
case UBLK_CMD_SET_PARAMS:
- ret = ublk_ctrl_set_params(cmd);
+ ret = ublk_ctrl_set_params(ub, cmd);
break;
case UBLK_CMD_START_USER_RECOVERY:
- ret = ublk_ctrl_start_recovery(cmd);
+ ret = ublk_ctrl_start_recovery(ub, cmd);
break;
case UBLK_CMD_END_USER_RECOVERY:
- ret = ublk_ctrl_end_recovery(cmd);
+ ret = ublk_ctrl_end_recovery(ub, cmd);
break;
default:
+ ret = -ENOTSUPP;
break;
}
+ if (ub)
+ ublk_put_device(ub);
out:
io_uring_cmd_done(cmd, ret, 0);
pr_devel("%s: cmd done ret %d cmd_op %x, dev id %d qid %d\n",
--
2.31.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH V3 4/6] ublk_drv: add device parameter UBLK_PARAM_TYPE_DEVT
2022-12-07 12:32 [PATCH V3 0/6] ublk_drv: add mechanism for supporting unprivileged ublk device Ming Lei
` (2 preceding siblings ...)
2022-12-07 12:33 ` [PATCH V3 3/6] ublk_drv: move ublk_get_device_from_id into ublk_ctrl_uring_cmd Ming Lei
@ 2022-12-07 12:33 ` Ming Lei
2022-12-07 12:33 ` [PATCH V3 5/6] ublk_drv: add module parameter of ublks_max for limiting max allowed ublk dev Ming Lei
` (2 subsequent siblings)
6 siblings, 0 replies; 12+ messages in thread
From: Ming Lei @ 2022-12-07 12:33 UTC (permalink / raw)
To: Jens Axboe; +Cc: linux-block, ZiyangZhang, Ming Lei
Userspace side only knows device ID, but the associated path of ublkc* and
ublkb* could be changed by udev, and that depends on userspace's policy, so
add parameter of UBLK_PARAM_TYPE_DEVT for retrieving major/minor of the
ublkc* and ublkb*, then user may figure out major/minor of the ublk disks
he/she owns. With major/minor, it is easy to find the device node path.
Signed-off-by: Ming Lei <ming.lei@redhat.com>
---
drivers/block/ublk_drv.c | 24 +++++++++++++++++++++++-
include/uapi/linux/ublk_cmd.h | 13 +++++++++++++
2 files changed, 36 insertions(+), 1 deletion(-)
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index 9d1578384cba..baea8933a3d9 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -54,7 +54,8 @@
| UBLK_F_USER_RECOVERY_REISSUE)
/* All UBLK_PARAM_TYPE_* should be included here */
-#define UBLK_PARAM_TYPE_ALL (UBLK_PARAM_TYPE_BASIC | UBLK_PARAM_TYPE_DISCARD)
+#define UBLK_PARAM_TYPE_ALL (UBLK_PARAM_TYPE_BASIC | \
+ UBLK_PARAM_TYPE_DISCARD | UBLK_PARAM_TYPE_DEVT)
struct ublk_rq_data {
struct llist_node node;
@@ -255,6 +256,10 @@ static int ublk_validate_params(const struct ublk_device *ub)
return -EINVAL;
}
+ /* dev_t is read-only */
+ if (ub->params.types & UBLK_PARAM_TYPE_DEVT)
+ return -EINVAL;
+
return 0;
}
@@ -1777,6 +1782,22 @@ static int ublk_ctrl_get_dev_info(struct ublk_device *ub,
return 0;
}
+/* TYPE_DEVT is readonly, so fill it up before returning to userspace */
+static void ublk_ctrl_fill_params_devt(struct ublk_device *ub)
+{
+ ub->params.devt.char_major = MAJOR(ub->cdev_dev.devt);
+ ub->params.devt.char_minor = MINOR(ub->cdev_dev.devt);
+
+ if (ub->ub_disk) {
+ ub->params.devt.disk_major = MAJOR(disk_devt(ub->ub_disk));
+ ub->params.devt.disk_minor = MINOR(disk_devt(ub->ub_disk));
+ } else {
+ ub->params.devt.disk_major = 0;
+ ub->params.devt.disk_minor = 0;
+ }
+ ub->params.types |= UBLK_PARAM_TYPE_DEVT;
+}
+
static int ublk_ctrl_get_params(struct ublk_device *ub,
struct io_uring_cmd *cmd)
{
@@ -1798,6 +1819,7 @@ static int ublk_ctrl_get_params(struct ublk_device *ub,
ph.len = sizeof(struct ublk_params);
mutex_lock(&ub->mutex);
+ ublk_ctrl_fill_params_devt(ub);
if (copy_to_user(argp, &ub->params, ph.len))
ret = -EFAULT;
else
diff --git a/include/uapi/linux/ublk_cmd.h b/include/uapi/linux/ublk_cmd.h
index 8f88e3a29998..4e38b9aa0293 100644
--- a/include/uapi/linux/ublk_cmd.h
+++ b/include/uapi/linux/ublk_cmd.h
@@ -214,6 +214,17 @@ struct ublk_param_discard {
__u16 reserved0;
};
+/*
+ * read-only, can't set via UBLK_CMD_SET_PARAMS, disk_devt is available
+ * after device is started
+ */
+struct ublk_param_devt {
+ __u32 char_major;
+ __u32 char_minor;
+ __u32 disk_major;
+ __u32 disk_minor;
+};
+
struct ublk_params {
/*
* Total length of parameters, userspace has to set 'len' for both
@@ -224,10 +235,12 @@ struct ublk_params {
__u32 len;
#define UBLK_PARAM_TYPE_BASIC (1 << 0)
#define UBLK_PARAM_TYPE_DISCARD (1 << 1)
+#define UBLK_PARAM_TYPE_DEVT (1 << 2)
__u32 types; /* types of parameter included */
struct ublk_param_basic basic;
struct ublk_param_discard discard;
+ struct ublk_param_devt devt;
};
#endif
--
2.31.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH V3 5/6] ublk_drv: add module parameter of ublks_max for limiting max allowed ublk dev
2022-12-07 12:32 [PATCH V3 0/6] ublk_drv: add mechanism for supporting unprivileged ublk device Ming Lei
` (3 preceding siblings ...)
2022-12-07 12:33 ` [PATCH V3 4/6] ublk_drv: add device parameter UBLK_PARAM_TYPE_DEVT Ming Lei
@ 2022-12-07 12:33 ` Ming Lei
2022-12-07 12:33 ` [PATCH V3 6/6] ublk_drv: add mechanism for supporting unprivileged ublk device Ming Lei
2022-12-12 3:59 ` [PATCH V3 0/6] " Ming Lei
6 siblings, 0 replies; 12+ messages in thread
From: Ming Lei @ 2022-12-07 12:33 UTC (permalink / raw)
To: Jens Axboe; +Cc: linux-block, ZiyangZhang, Ming Lei
Prepare for supporting unprivileged ublk device by limiting max number
ublk devices added. Otherwise too many ublk devices could be added by
un-trusted user, which can be thought as one DoS.
Reviewed-by: ZiyangZhang <ZiyangZhang@linux.alibaba.com>
Signed-off-by: Ming Lei <ming.lei@redhat.com>
---
drivers/block/ublk_drv.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index baea8933a3d9..f91b3e124cc2 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -186,6 +186,15 @@ static wait_queue_head_t ublk_idr_wq; /* wait until one idr is freed */
static DEFINE_MUTEX(ublk_ctl_mutex);
+/*
+ * Max ublk devices allowed to add
+ *
+ * It can be extended to one per-user limit in future or even controlled
+ * by cgroup.
+ */
+static unsigned int ublks_max = 64;
+static unsigned int ublks_added; /* protected by ublk_ctl_mutex */
+
static struct miscdevice ublk_misc;
static void ublk_dev_param_basic_apply(struct ublk_device *ub)
@@ -1441,6 +1450,8 @@ static int ublk_add_chdev(struct ublk_device *ub)
ret = cdev_device_add(&ub->cdev, dev);
if (ret)
goto fail;
+
+ ublks_added++;
return 0;
fail:
put_device(dev);
@@ -1483,6 +1494,7 @@ static void ublk_remove(struct ublk_device *ub)
cancel_work_sync(&ub->quiesce_work);
cdev_device_del(&ub->cdev, &ub->cdev_dev);
put_device(&ub->cdev_dev);
+ ublks_added--;
}
static struct ublk_device *ublk_get_device_from_id(int idx)
@@ -1642,6 +1654,10 @@ static int ublk_ctrl_add_dev(struct io_uring_cmd *cmd)
if (ret)
return ret;
+ ret = -EACCES;
+ if (ublks_added >= ublks_max)
+ goto out_unlock;
+
ret = -ENOMEM;
ub = kzalloc(sizeof(*ub), GFP_KERNEL);
if (!ub)
@@ -2093,5 +2109,8 @@ static void __exit ublk_exit(void)
module_init(ublk_init);
module_exit(ublk_exit);
+module_param(ublks_max, int, 0444);
+MODULE_PARM_DESC(ublks_max, "max number of ublk devices allowed to add(default: 64)");
+
MODULE_AUTHOR("Ming Lei <ming.lei@redhat.com>");
MODULE_LICENSE("GPL");
--
2.31.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH V3 6/6] ublk_drv: add mechanism for supporting unprivileged ublk device
2022-12-07 12:32 [PATCH V3 0/6] ublk_drv: add mechanism for supporting unprivileged ublk device Ming Lei
` (4 preceding siblings ...)
2022-12-07 12:33 ` [PATCH V3 5/6] ublk_drv: add module parameter of ublks_max for limiting max allowed ublk dev Ming Lei
@ 2022-12-07 12:33 ` Ming Lei
2023-01-03 20:35 ` Jonathan Corbet
2022-12-12 3:59 ` [PATCH V3 0/6] " Ming Lei
6 siblings, 1 reply; 12+ messages in thread
From: Ming Lei @ 2022-12-07 12:33 UTC (permalink / raw)
To: Jens Axboe; +Cc: linux-block, ZiyangZhang, Ming Lei, Stefan Hajnoczi
unprivileged ublk device is helpful for container use case, such
as: ublk device created in one unprivileged container can be controlled
and accessed by this container only.
Implement this feature by adding flag of UBLK_F_UNPRIVILEGED_DEV, and if
this flag isn't set, any control command has been run from privileged
user. Otherwise, any control command can be sent from any unprivileged
user, but the user has to be permitted to access the ublk char device
to be controlled.
In case of UBLK_F_UNPRIVILEGED_DEV:
1) for command UBLK_CMD_ADD_DEV, it is always allowed, and user needs
to provide owner's uid/gid in this command, so that udev can set correct
ownership for the created ublk device, since the device owner uid/gid
can be queried via command of UBLK_CMD_GET_DEV_INFO.
2) for other control commands, they can only be run successfully if the
current user is allowed to access the specified ublk char device, for
running the permission check, path of the ublk char device has to be
provided by these commands.
Also add one control of command UBLK_CMD_GET_DEV_INFO2 which always
include the char dev path in payload since userspace may not have
knowledge if this device is created in unprivileged mode.
For applying this mechanism, system administrator needs to take
the following policies:
1) chmod 0666 /dev/ublk-control
2) change ownership of ublkcN & ublkbN
- chown owner_uid:owner_gid /dev/ublkcN
- chown owner_uid:owner_gid /dev/ublkbN
Both can be done via one simple udev rule.
Userspace:
https://github.com/ming1/ubdsrv/tree/unprivileged-ublk
'ublk add -t $TYPE --un_privileged=1' is for creating one un-privileged
ublk device if the user is un-privileged.
Link: https://lore.kernel.org/linux-block/YoOr6jBfgVm8GvWg@stefanha-x1.localdomain/
Suggested-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Ming Lei <ming.lei@redhat.com>
---
Documentation/block/ublk.rst | 18 ++---
drivers/block/ublk_drv.c | 147 ++++++++++++++++++++++++++++++++--
include/uapi/linux/ublk_cmd.h | 36 ++++++++-
3 files changed, 184 insertions(+), 17 deletions(-)
diff --git a/Documentation/block/ublk.rst b/Documentation/block/ublk.rst
index ba45c46cc0da..403ffd0f4511 100644
--- a/Documentation/block/ublk.rst
+++ b/Documentation/block/ublk.rst
@@ -180,6 +180,15 @@ managing and controlling ublk devices with help of several control commands:
double-write since the driver may issue the same I/O request twice. It
might be useful to a read-only FS or a VM backend.
+Unprivileged ublk device is supported by passing UBLK_F_UNPRIVILEGED_DEV.
+Once the flag is set, all control commands can be sent by unprivileged
+user. Except for command of ``UBLK_CMD_ADD_DEV``, permission check on
+the specified char device(``/dev/ublkc*``) is done for all other control
+commands by ublk driver, for doing that, path of the char device has to
+be provided in these commands' payload from ublk server. With this way,
+ublk device becomes container-ware, and device created in one container
+can be controlled/accessed just inside this container.
+
Data plane
----------
@@ -254,15 +263,6 @@ with specified IO tag in the command data:
Future development
==================
-Container-aware ublk deivice
-----------------------------
-
-ublk driver doesn't handle any IO logic. Its function is well defined
-for now and very limited userspace interfaces are needed, which is also
-well defined too. It is possible to make ublk devices container-aware block
-devices in future as Stefan Hajnoczi suggested [#stefan]_, by removing
-ADMIN privilege.
-
Zero copy
---------
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index f91b3e124cc2..e7a7affd9af7 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -42,6 +42,7 @@
#include <linux/mm.h>
#include <asm/page.h>
#include <linux/task_work.h>
+#include <linux/namei.h>
#include <uapi/linux/ublk_cmd.h>
#define UBLK_MINORS (1U << MINORBITS)
@@ -51,7 +52,8 @@
| UBLK_F_URING_CMD_COMP_IN_TASK \
| UBLK_F_NEED_GET_DATA \
| UBLK_F_USER_RECOVERY \
- | UBLK_F_USER_RECOVERY_REISSUE)
+ | UBLK_F_USER_RECOVERY_REISSUE \
+ | UBLK_F_UNPRIVILEGED_DEV)
/* All UBLK_PARAM_TYPE_* should be included here */
#define UBLK_PARAM_TYPE_ALL (UBLK_PARAM_TYPE_BASIC | \
@@ -1641,15 +1643,33 @@ static int ublk_ctrl_add_dev(struct io_uring_cmd *cmd)
__func__, header->queue_id);
return -EINVAL;
}
+
if (copy_from_user(&info, argp, sizeof(info)))
return -EFAULT;
- ublk_dump_dev_info(&info);
+
+ if (info.flags & UBLK_F_UNPRIVILEGED_DEV) {
+ /*
+ * user needs to provide proper owner_uid/owner_gid,
+ * which will be provided to udev rule for setting
+ * ownership on the ublk device to be created.
+ */
+ ;
+ } else {
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if (info.owner_uid != 0 || info.owner_gid != 0)
+ return -EINVAL;
+ }
+
if (header->dev_id != info.dev_id) {
pr_warn("%s: dev id not match %u %u\n",
__func__, header->dev_id, info.dev_id);
return -EINVAL;
}
+ ublk_dump_dev_info(&info);
+
ret = mutex_lock_killable(&ublk_ctl_mutex);
if (ret)
return ret;
@@ -1982,6 +2002,114 @@ static int ublk_ctrl_end_recovery(struct ublk_device *ub,
return ret;
}
+/*
+ * All control commands are sent via /dev/ublk-control, so we have to check
+ * the destination device's permission
+ */
+static int ublk_char_dev_permission(struct ublk_device *ub,
+ const char *dev_path, int mask)
+{
+ int err;
+ struct path path;
+ struct kstat stat;
+
+ err = kern_path(dev_path, LOOKUP_FOLLOW, &path);
+ if (err)
+ return err;
+
+ err = vfs_getattr(&path, &stat, STATX_TYPE, AT_STATX_SYNC_AS_STAT);
+ if (err)
+ goto exit;
+
+ if (stat.rdev != ub->cdev_dev.devt || !S_ISCHR(stat.mode))
+ goto exit;
+
+ err = inode_permission(&init_user_ns,
+ d_backing_inode(path.dentry), mask);
+exit:
+ path_put(&path);
+ return err;
+}
+
+static int ublk_ctrl_uring_cmd_permission(struct ublk_device *ub,
+ struct io_uring_cmd *cmd)
+{
+ struct ublksrv_ctrl_cmd *header = (struct ublksrv_ctrl_cmd *)cmd->cmd;
+ bool unprivileged = ub->dev_info.flags & UBLK_F_UNPRIVILEGED_DEV;
+ void __user *argp = (void __user *)(unsigned long)header->addr;
+ char *dev_path = NULL;
+ int ret = 0;
+ int mask;
+
+ if (!unprivileged) {
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ /*
+ * The new added command of UBLK_CMD_GET_DEV_INFO2 includes
+ * char_dev_path in payload too, since userspace may not
+ * know if the specified device is created as unprivileged
+ * mode.
+ */
+ if (cmd->cmd_op != UBLK_CMD_GET_DEV_INFO2)
+ return 0;
+ }
+
+ /*
+ * User has to provide the char device path for unprivileged ublk
+ *
+ * header->addr always points to the dev path buffer, and
+ * header->dev_path_len records length of dev path buffer.
+ */
+ if (!header->dev_path_len || header->dev_path_len > PATH_MAX)
+ return -EINVAL;
+
+ if (header->len < header->dev_path_len)
+ return -EINVAL;
+
+ dev_path = kmalloc(header->dev_path_len + 1, GFP_KERNEL);
+ if (!dev_path)
+ return -ENOMEM;
+
+ ret = -EFAULT;
+ if (copy_from_user(dev_path, argp, header->dev_path_len))
+ goto exit;
+ dev_path[header->dev_path_len] = 0;
+
+ ret = -EINVAL;
+ switch (cmd->cmd_op) {
+ case UBLK_CMD_GET_DEV_INFO:
+ case UBLK_CMD_GET_DEV_INFO2:
+ case UBLK_CMD_GET_QUEUE_AFFINITY:
+ case UBLK_CMD_GET_PARAMS:
+ mask = MAY_READ;
+ break;
+ case UBLK_CMD_START_DEV:
+ case UBLK_CMD_STOP_DEV:
+ case UBLK_CMD_ADD_DEV:
+ case UBLK_CMD_DEL_DEV:
+ case UBLK_CMD_SET_PARAMS:
+ case UBLK_CMD_START_USER_RECOVERY:
+ case UBLK_CMD_END_USER_RECOVERY:
+ mask = MAY_READ | MAY_WRITE;
+ break;
+ default:
+ goto exit;
+ }
+
+ ret = ublk_char_dev_permission(ub, dev_path, mask);
+ if (!ret) {
+ header->len -= header->dev_path_len;
+ header->addr += header->dev_path_len;
+ }
+ pr_devel("%s: dev id %d cmd_op %x uid %d gid %d path %s ret %d\n",
+ __func__, ub->ub_number, cmd->cmd_op,
+ ub->dev_info.owner_uid, ub->dev_info.owner_gid,
+ dev_path, ret);
+exit:
+ kfree(dev_path);
+ return ret;
+}
+
static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd,
unsigned int issue_flags)
{
@@ -1994,17 +2122,21 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd,
if (!(issue_flags & IO_URING_F_SQE128))
goto out;
- ret = -EPERM;
- if (!capable(CAP_SYS_ADMIN))
- goto out;
-
if (cmd->cmd_op != UBLK_CMD_ADD_DEV) {
ret = -ENODEV;
ub = ublk_get_device_from_id(header->dev_id);
if (!ub)
goto out;
+
+ ret = ublk_ctrl_uring_cmd_permission(ub, cmd);
+ } else {
+ /* ADD_DEV permission check is done in command handler */
+ ret = 0;
}
+ if (ret)
+ goto put_dev;
+
switch (cmd->cmd_op) {
case UBLK_CMD_START_DEV:
ret = ublk_ctrl_start_dev(ub, cmd);
@@ -2013,6 +2145,7 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd,
ret = ublk_ctrl_stop_dev(ub);
break;
case UBLK_CMD_GET_DEV_INFO:
+ case UBLK_CMD_GET_DEV_INFO2:
ret = ublk_ctrl_get_dev_info(ub, cmd);
break;
case UBLK_CMD_ADD_DEV:
@@ -2040,6 +2173,8 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd,
ret = -ENOTSUPP;
break;
}
+
+ put_dev:
if (ub)
ublk_put_device(ub);
out:
diff --git a/include/uapi/linux/ublk_cmd.h b/include/uapi/linux/ublk_cmd.h
index 4e38b9aa0293..ae80bfef3b9f 100644
--- a/include/uapi/linux/ublk_cmd.h
+++ b/include/uapi/linux/ublk_cmd.h
@@ -19,6 +19,8 @@
#define UBLK_CMD_GET_PARAMS 0x09
#define UBLK_CMD_START_USER_RECOVERY 0x10
#define UBLK_CMD_END_USER_RECOVERY 0x11
+#define UBLK_CMD_GET_DEV_INFO2 0x12
+
/*
* IO commands, issued by ublk server, and handled by ublk driver.
*
@@ -79,6 +81,27 @@
#define UBLK_F_USER_RECOVERY_REISSUE (1UL << 4)
+/*
+ * Unprivileged user can create /dev/ublkcN and /dev/ublkbN.
+ *
+ * /dev/ublk-control needs to be available for unprivileged user, and it
+ * can be done via udev rule to make all control commands available to
+ * unprivileged user. Except for the command of UBLK_CMD_ADD_DEV, all
+ * other commands are only allowed for the owner of the specified device.
+ *
+ * When userspace sends UBLK_CMD_ADD_DEV, the device pair's owner_uid and
+ * owner_gid need to be provided via ublksrv_ctrl_dev_info, and the two
+ * ids need to match with ublk server's uid/gid, otherwise the created
+ * ublk device can't be started successfully.
+ *
+ * We still need udev rule to set correct OWNER/GROUP with the stored
+ * owner_uid and owner_gid.
+ *
+ * Then ublk server can be run as unprivileged user, and /dev/ublkbN can
+ * be accessed by user of owner_uid/owner_gid.
+ */
+#define UBLK_F_UNPRIVILEGED_DEV (1UL << 5)
+
/* device state */
#define UBLK_S_DEV_DEAD 0
#define UBLK_S_DEV_LIVE 1
@@ -98,7 +121,15 @@ struct ublksrv_ctrl_cmd {
__u64 addr;
/* inline data */
- __u64 data[2];
+ __u64 data[1];
+
+ /*
+ * Used for UBLK_F_UNPRIVILEGED_DEV and UBLK_CMD_GET_DEV_INFO2
+ * only, include null char
+ */
+ __u16 dev_path_len;
+ __u16 pad;
+ __u32 reserved;
};
struct ublksrv_ctrl_dev_info {
@@ -118,7 +149,8 @@ struct ublksrv_ctrl_dev_info {
/* For ublksrv internal use, invisible to ublk driver */
__u64 ublksrv_flags;
- __u64 reserved0;
+ __u32 owner_uid;
+ __u32 owner_gid;
__u64 reserved1;
__u64 reserved2;
};
--
2.31.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH V3 0/6] ublk_drv: add mechanism for supporting unprivileged ublk device
2022-12-07 12:32 [PATCH V3 0/6] ublk_drv: add mechanism for supporting unprivileged ublk device Ming Lei
` (5 preceding siblings ...)
2022-12-07 12:33 ` [PATCH V3 6/6] ublk_drv: add mechanism for supporting unprivileged ublk device Ming Lei
@ 2022-12-12 3:59 ` Ming Lei
2022-12-14 17:54 ` Jens Axboe
6 siblings, 1 reply; 12+ messages in thread
From: Ming Lei @ 2022-12-12 3:59 UTC (permalink / raw)
To: Jens Axboe; +Cc: linux-block, ZiyangZhang, ming.lei
On Wed, Dec 07, 2022 at 08:32:59PM +0800, Ming Lei wrote:
> Hello,
>
> Stefan Hajnoczi suggested un-privileged ublk device[1] for container
> use case.
>
> So far only administrator can create/control ublk device which is too
> strict and increase system administrator burden, and this patchset
> implements un-privileged ublk device:
>
> - any user can create ublk device, which can only be controlled &
> accessed by the owner of the device or administrator
>
> For using such mechanism, system administrator needs to deploy two
> simple udev rules[2] after running 'make install' in ublksrv.
>
> Userspace(ublksrv):
>
> https://github.com/ming1/ubdsrv/tree/unprivileged-ublk
>
> 'ublk add -t $TYPE --un_privileged' is for creating one un-privileged
> ublk device if the user is un-privileged.
>
>
> [1] https://lore.kernel.org/linux-block/YoOr6jBfgVm8GvWg@stefanha-x1.localdomain/
> [2] https://github.com/ming1/ubdsrv/blob/unprivileged-ublk/README.rst#un-privileged-mode
>
> V3:
> - don't warn on invalid user input for setting devt parameter, as
> suggested by Ziyang, patch 4/6
> - fix one memory corruption issue, patch 6/6
Hello Guys,
Ping...
thanks,
Ming
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH V3 0/6] ublk_drv: add mechanism for supporting unprivileged ublk device
2022-12-12 3:59 ` [PATCH V3 0/6] " Ming Lei
@ 2022-12-14 17:54 ` Jens Axboe
2022-12-15 0:35 ` Ming Lei
0 siblings, 1 reply; 12+ messages in thread
From: Jens Axboe @ 2022-12-14 17:54 UTC (permalink / raw)
To: Ming Lei; +Cc: linux-block, ZiyangZhang
On 12/11/22 8:59 PM, Ming Lei wrote:
> On Wed, Dec 07, 2022 at 08:32:59PM +0800, Ming Lei wrote:
>> Hello,
>>
>> Stefan Hajnoczi suggested un-privileged ublk device[1] for container
>> use case.
>>
>> So far only administrator can create/control ublk device which is too
>> strict and increase system administrator burden, and this patchset
>> implements un-privileged ublk device:
>>
>> - any user can create ublk device, which can only be controlled &
>> accessed by the owner of the device or administrator
>>
>> For using such mechanism, system administrator needs to deploy two
>> simple udev rules[2] after running 'make install' in ublksrv.
>>
>> Userspace(ublksrv):
>>
>> https://github.com/ming1/ubdsrv/tree/unprivileged-ublk
>>
>> 'ublk add -t $TYPE --un_privileged' is for creating one un-privileged
>> ublk device if the user is un-privileged.
>>
>>
>> [1] https://lore.kernel.org/linux-block/YoOr6jBfgVm8GvWg@stefanha-x1.localdomain/
>> [2] https://github.com/ming1/ubdsrv/blob/unprivileged-ublk/README.rst#un-privileged-mode
>>
>> V3:
>> - don't warn on invalid user input for setting devt parameter, as
>> suggested by Ziyang, patch 4/6
>> - fix one memory corruption issue, patch 6/6
>
> Hello Guys,
>
> Ping...
I think timing was just a tad late on this. OK if we defer for 6.3, or are
there strong arguments for 6.2?
--
Jens Axboe
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH V3 0/6] ublk_drv: add mechanism for supporting unprivileged ublk device
2022-12-14 17:54 ` Jens Axboe
@ 2022-12-15 0:35 ` Ming Lei
0 siblings, 0 replies; 12+ messages in thread
From: Ming Lei @ 2022-12-15 0:35 UTC (permalink / raw)
To: Jens Axboe; +Cc: linux-block, ZiyangZhang
On Wed, Dec 14, 2022 at 10:54:33AM -0700, Jens Axboe wrote:
> On 12/11/22 8:59 PM, Ming Lei wrote:
> > On Wed, Dec 07, 2022 at 08:32:59PM +0800, Ming Lei wrote:
> >> Hello,
> >>
> >> Stefan Hajnoczi suggested un-privileged ublk device[1] for container
> >> use case.
> >>
> >> So far only administrator can create/control ublk device which is too
> >> strict and increase system administrator burden, and this patchset
> >> implements un-privileged ublk device:
> >>
> >> - any user can create ublk device, which can only be controlled &
> >> accessed by the owner of the device or administrator
> >>
> >> For using such mechanism, system administrator needs to deploy two
> >> simple udev rules[2] after running 'make install' in ublksrv.
> >>
> >> Userspace(ublksrv):
> >>
> >> https://github.com/ming1/ubdsrv/tree/unprivileged-ublk
> >>
> >> 'ublk add -t $TYPE --un_privileged' is for creating one un-privileged
> >> ublk device if the user is un-privileged.
> >>
> >>
> >> [1] https://lore.kernel.org/linux-block/YoOr6jBfgVm8GvWg@stefanha-x1.localdomain/
> >> [2] https://github.com/ming1/ubdsrv/blob/unprivileged-ublk/README.rst#un-privileged-mode
> >>
> >> V3:
> >> - don't warn on invalid user input for setting devt parameter, as
> >> suggested by Ziyang, patch 4/6
> >> - fix one memory corruption issue, patch 6/6
> >
> > Hello Guys,
> >
> > Ping...
>
> I think timing was just a tad late on this. OK if we defer for 6.3, or are
> there strong arguments for 6.2?
I am OK with deferring for 6.3.
Thanks,
Ming
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH V3 6/6] ublk_drv: add mechanism for supporting unprivileged ublk device
2022-12-07 12:33 ` [PATCH V3 6/6] ublk_drv: add mechanism for supporting unprivileged ublk device Ming Lei
@ 2023-01-03 20:35 ` Jonathan Corbet
2023-01-04 8:19 ` Ming Lei
0 siblings, 1 reply; 12+ messages in thread
From: Jonathan Corbet @ 2023-01-03 20:35 UTC (permalink / raw)
To: Ming Lei, Jens Axboe; +Cc: linux-block, ZiyangZhang, Ming Lei, Stefan Hajnoczi
I have one quick question...
Ming Lei <ming.lei@redhat.com> writes:
> In case of UBLK_F_UNPRIVILEGED_DEV:
>
> 1) for command UBLK_CMD_ADD_DEV, it is always allowed, and user needs
> to provide owner's uid/gid in this command, so that udev can set correct
> ownership for the created ublk device, since the device owner uid/gid
> can be queried via command of UBLK_CMD_GET_DEV_INFO.
Why do you have the user provide the uid/gid rather than just using the
user's credentials directly? It seems a bit strange to me to let
unprivileged users create devices with arbitrary ownership. What am I
missing here?
Thanks,
jon
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH V3 6/6] ublk_drv: add mechanism for supporting unprivileged ublk device
2023-01-03 20:35 ` Jonathan Corbet
@ 2023-01-04 8:19 ` Ming Lei
0 siblings, 0 replies; 12+ messages in thread
From: Ming Lei @ 2023-01-04 8:19 UTC (permalink / raw)
To: Jonathan Corbet
Cc: Jens Axboe, linux-block, ZiyangZhang, Stefan Hajnoczi, ming.lei
Hi Jonathan,
On Tue, Jan 03, 2023 at 01:35:14PM -0700, Jonathan Corbet wrote:
> I have one quick question...
>
> Ming Lei <ming.lei@redhat.com> writes:
>
> > In case of UBLK_F_UNPRIVILEGED_DEV:
> >
> > 1) for command UBLK_CMD_ADD_DEV, it is always allowed, and user needs
> > to provide owner's uid/gid in this command, so that udev can set correct
> > ownership for the created ublk device, since the device owner uid/gid
> > can be queried via command of UBLK_CMD_GET_DEV_INFO.
>
> Why do you have the user provide the uid/gid rather than just using the
> user's credentials directly? It seems a bit strange to me to let
> unprivileged users create devices with arbitrary ownership. What am I
> missing here?
It is one good question.
The original idea is to allow user A to create device for another user
B, and it still depends on user A's capability, such as, if the created
daemon can open the created device which is owned by user B actually.
The above behavior may be extended in future if there is such
requirement. I will switch to just allow to create device for the
current user in V4, then we can start with this easy/simple model.
BTW, that is exactly the current userspace implementation, only the
current uid/gid is passed.
https://github.com/ming1/ubdsrv/tree/unprivileged-ublk
Thanks,
Ming
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2023-01-04 8:20 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-12-07 12:32 [PATCH V3 0/6] ublk_drv: add mechanism for supporting unprivileged ublk device Ming Lei
2022-12-07 12:33 ` [PATCH V3 1/6] ublk_drv: remove nr_aborted_queues from ublk_device Ming Lei
2022-12-07 12:33 ` [PATCH V3 2/6] ublk_drv: don't probe partitions if the ubq daemon isn't trusted Ming Lei
2022-12-07 12:33 ` [PATCH V3 3/6] ublk_drv: move ublk_get_device_from_id into ublk_ctrl_uring_cmd Ming Lei
2022-12-07 12:33 ` [PATCH V3 4/6] ublk_drv: add device parameter UBLK_PARAM_TYPE_DEVT Ming Lei
2022-12-07 12:33 ` [PATCH V3 5/6] ublk_drv: add module parameter of ublks_max for limiting max allowed ublk dev Ming Lei
2022-12-07 12:33 ` [PATCH V3 6/6] ublk_drv: add mechanism for supporting unprivileged ublk device Ming Lei
2023-01-03 20:35 ` Jonathan Corbet
2023-01-04 8:19 ` Ming Lei
2022-12-12 3:59 ` [PATCH V3 0/6] " Ming Lei
2022-12-14 17:54 ` Jens Axboe
2022-12-15 0:35 ` Ming Lei
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).