Commit 80bdfbb3 authored by Uday Shankar's avatar Uday Shankar Committed by Jens Axboe
Browse files

ublk: enforce ublks_max only for unprivileged devices



Commit 403ebc87 ("ublk_drv: add module parameter of ublks_max for
limiting max allowed ublk dev"), claimed ublks_max was added to prevent
a DoS situation with an untrusted user creating too many ublk devices.
If that's the case, ublks_max should only restrict the number of
unprivileged ublk devices in the system. Enforce the limit only for
unprivileged ublk devices, and rename variables accordingly. Leave the
external-facing parameter name unchanged, since changing it may break
systems which use it (but still update its documentation to reflect its
new meaning).

As a result of this change, in a system where there are only normal
(non-unprivileged) devices, the maximum number of such devices is
increased to 1 << MINORBITS, or 1048576. That ought to be enough for
anyone, right?

Signed-off-by: default avatarUday Shankar <ushankar@purestorage.com>
Reviewed-by: default avatarMing Lei <ming.lei@redhat.com>
Link: https://lore.kernel.org/r/20250228-ublks_max-v1-1-04b7379190c0@purestorage.com


Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 3aab938c
Loading
Loading
Loading
Loading
+27 −15
Original line number Diff line number Diff line
@@ -490,15 +490,17 @@ static wait_queue_head_t ublk_idr_wq; /* wait until one idr is freed */

static DEFINE_MUTEX(ublk_ctl_mutex);


#define UBLK_MAX_UBLKS UBLK_MINORS

/*
 * Max ublk devices allowed to add
 * Max unprivileged ublk devices allowed to add
 *
 * It can be extended to one per-user limit in future or even controlled
 * by cgroup.
 */
#define UBLK_MAX_UBLKS UBLK_MINORS
static unsigned int ublks_max = 64;
static unsigned int ublks_added;	/* protected by ublk_ctl_mutex */
static unsigned int unprivileged_ublks_max = 64;
static unsigned int unprivileged_ublks_added; /* protected by ublk_ctl_mutex */

static struct miscdevice ublk_misc;

@@ -2203,7 +2205,8 @@ static int ublk_add_chdev(struct ublk_device *ub)
	if (ret)
		goto fail;

	ublks_added++;
	if (ub->dev_info.flags & UBLK_F_UNPRIVILEGED_DEV)
		unprivileged_ublks_added++;
	return 0;
 fail:
	put_device(dev);
@@ -2232,11 +2235,16 @@ static int ublk_add_tag_set(struct ublk_device *ub)

static void ublk_remove(struct ublk_device *ub)
{
	bool unprivileged;

	ublk_stop_dev(ub);
	cancel_work_sync(&ub->nosrv_work);
	cdev_device_del(&ub->cdev, &ub->cdev_dev);
	unprivileged = ub->dev_info.flags & UBLK_F_UNPRIVILEGED_DEV;
	ublk_put_device(ub);
	ublks_added--;

	if (unprivileged)
		unprivileged_ublks_added--;
}

static struct ublk_device *ublk_get_device_from_id(int idx)
@@ -2501,7 +2509,8 @@ static int ublk_ctrl_add_dev(struct io_uring_cmd *cmd)
		return ret;

	ret = -EACCES;
	if (ublks_added >= ublks_max)
	if ((info.flags & UBLK_F_UNPRIVILEGED_DEV) &&
	    unprivileged_ublks_added >= unprivileged_ublks_max)
		goto out_unlock;

	ret = -ENOMEM;
@@ -3138,23 +3147,26 @@ static void __exit ublk_exit(void)
module_init(ublk_init);
module_exit(ublk_exit);

static int ublk_set_max_ublks(const char *buf, const struct kernel_param *kp)
static int ublk_set_max_unprivileged_ublks(const char *buf,
					   const struct kernel_param *kp)
{
	return param_set_uint_minmax(buf, kp, 0, UBLK_MAX_UBLKS);
}

static int ublk_get_max_ublks(char *buf, const struct kernel_param *kp)
static int ublk_get_max_unprivileged_ublks(char *buf,
					   const struct kernel_param *kp)
{
	return sysfs_emit(buf, "%u\n", ublks_max);
	return sysfs_emit(buf, "%u\n", unprivileged_ublks_max);
}

static const struct kernel_param_ops ublk_max_ublks_ops = {
	.set = ublk_set_max_ublks,
	.get = ublk_get_max_ublks,
static const struct kernel_param_ops ublk_max_unprivileged_ublks_ops = {
	.set = ublk_set_max_unprivileged_ublks,
	.get = ublk_get_max_unprivileged_ublks,
};

module_param_cb(ublks_max, &ublk_max_ublks_ops, &ublks_max, 0644);
MODULE_PARM_DESC(ublks_max, "max number of ublk devices allowed to add(default: 64)");
module_param_cb(ublks_max, &ublk_max_unprivileged_ublks_ops,
		&unprivileged_ublks_max, 0644);
MODULE_PARM_DESC(ublks_max, "max number of unprivileged ublk devices allowed to add(default: 64)");

MODULE_AUTHOR("Ming Lei <ming.lei@redhat.com>");
MODULE_DESCRIPTION("Userspace block device");