diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-07-24 20:02:58 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-07-24 20:02:58 -0700 |
| commit | 0ce37745d4bfbc493f718169c3974898ffec8ee7 (patch) | |
| tree | c5c6ce1ae2a2fe201155cc041cd6b3a57ab3915b | |
| parent | 73387b89d99f7b588870c5a98eb6a89689c65a1a (diff) | |
| parent | 093fbffe03f5c1bb9c10a9e5aa65b23250844403 (diff) | |
| download | linux-0ce37745d4bfbc493f718169c3974898ffec8ee7.tar.gz linux-0ce37745d4bfbc493f718169c3974898ffec8ee7.tar.bz2 linux-0ce37745d4bfbc493f718169c3974898ffec8ee7.zip | |
Merge tag 'block-7.2-20260724' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linuxHEADmaster
Pull block fixes from Jens Axboe:
- Fix a ublk recovery hang, where END_USER_RECOVERY without a
successful START_USER_RECOVERY could be satisfied by a stale
completion latch
- Fix a stack out-of-bounds read in the CDROMVOLCTRL ioctl
- MAINTAINERS email address update for Roger Pau Monne
* tag 'block-7.2-20260724' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux:
MAINTAINERS: update my email address
cdrom: fix stack out-of-bounds read in CDROMVOLCTRL
ublk: wait on ublk_dev_ready() instead of ub->completion
| -rw-r--r-- | MAINTAINERS | 2 | ||||
| -rw-r--r-- | drivers/block/ublk_drv.c | 47 | ||||
| -rw-r--r-- | drivers/cdrom/cdrom.c | 1 |
3 files changed, 32 insertions, 18 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index ff93f3954fd1..ff08a65d942a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -29400,7 +29400,7 @@ F: net/xdp/ F: tools/testing/selftests/bpf/*xsk* XEN BLOCK SUBSYSTEM -M: Roger Pau Monné <roger.pau@citrix.com> +M: Roger Pau Monné <roger@xenproject.org> L: xen-devel@lists.xenproject.org (moderated for non-subscribers) S: Supported F: drivers/block/xen* diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c index c2c11f2a01e7..4ca6ec738c93 100644 --- a/drivers/block/ublk_drv.c +++ b/drivers/block/ublk_drv.c @@ -19,6 +19,7 @@ #include <linux/errno.h> #include <linux/major.h> #include <linux/wait.h> +#include <linux/wait_bit.h> #include <linux/blkdev.h> #include <linux/init.h> #include <linux/swap.h> @@ -26,7 +27,6 @@ #include <linux/compat.h> #include <linux/mutex.h> #include <linux/writeback.h> -#include <linux/completion.h> #include <linux/highmem.h> #include <linux/sysfs.h> #include <linux/miscdevice.h> @@ -327,7 +327,6 @@ struct ublk_device { struct ublk_params params; - struct completion completion; u32 nr_queue_ready; bool unprivileged_daemons; struct mutex cancel_mutex; @@ -3054,12 +3053,12 @@ static void ublk_mark_io_ready(struct ublk_device *ub, u16 q_id, if (ublk_dev_ready(ub)) { /* * All queues ready - clear device-level canceling flag - * and complete the recovery/initialization. + * and wake ublk_dev_ready() waiters. */ mutex_lock(&ub->cancel_mutex); ub->canceling = false; mutex_unlock(&ub->cancel_mutex); - complete_all(&ub->completion); + wake_up_var(&ub->nr_queue_ready); } } @@ -4273,7 +4272,6 @@ static int ublk_init_queues(struct ublk_device *ub) goto fail; } - init_completion(&ub->completion); return 0; fail: @@ -4417,6 +4415,26 @@ static bool ublk_validate_user_pid(struct ublk_device *ub, pid_t ublksrv_pid) return ub->ublksrv_tgid == ublksrv_pid; } +/* + * Wait until all queues have fetched their I/O commands, and return with + * ub->mutex held and readiness guaranteed: then every queue's ->canceling + * is cleared. Ready may regress between wakeup and mutex_lock() (F_BATCH + * UNPREP, daemon death), so re-check it under the mutex and wait again. + */ +static int ublk_wait_dev_ready_and_lock(struct ublk_device *ub) +{ + while (true) { + if (wait_var_event_interruptible(&ub->nr_queue_ready, + ublk_dev_ready(ub))) + return -EINTR; + + mutex_lock(&ub->mutex); + if (ublk_dev_ready(ub)) + return 0; + mutex_unlock(&ub->mutex); + } +} + static int ublk_ctrl_start_dev(struct ublk_device *ub, const struct ublksrv_ctrl_cmd *header) { @@ -4499,15 +4517,10 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub, }; } - if (wait_for_completion_interruptible(&ub->completion) != 0) + if (ublk_wait_dev_ready_and_lock(ub)) return -EINTR; - if (!ublk_validate_user_pid(ub, ublksrv_pid)) - return -EINVAL; - - mutex_lock(&ub->mutex); - /* device may become not ready in case of F_BATCH */ - if (!ublk_dev_ready(ub)) { + if (!ublk_validate_user_pid(ub, ublksrv_pid)) { ret = -EINVAL; goto out_unlock; } @@ -5071,7 +5084,6 @@ static int ublk_ctrl_start_recovery(struct ublk_device *ub) goto out_unlock; } pr_devel("%s: start recovery for dev id %d\n", __func__, ub->ub_number); - init_completion(&ub->completion); ret = 0; out_unlock: mutex_unlock(&ub->mutex); @@ -5087,16 +5099,17 @@ static int ublk_ctrl_end_recovery(struct ublk_device *ub, pr_devel("%s: Waiting for all FETCH_REQs, dev id %d...\n", __func__, header->dev_id); - if (wait_for_completion_interruptible(&ub->completion)) + if (ublk_wait_dev_ready_and_lock(ub)) return -EINTR; pr_devel("%s: All FETCH_REQs received, dev id %d\n", __func__, header->dev_id); - if (!ublk_validate_user_pid(ub, ublksrv_pid)) - return -EINVAL; + if (!ublk_validate_user_pid(ub, ublksrv_pid)) { + ret = -EINVAL; + goto out_unlock; + } - mutex_lock(&ub->mutex); if (ublk_nosrv_should_stop_dev(ub)) goto out_unlock; diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 62934cf4b10d..4f1fd389260f 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -3187,6 +3187,7 @@ static noinline int mmc_ioctl_cdrom_volume(struct cdrom_device_info *cdi, /* set volume */ cgc->buffer = buffer + offset - 8; + cgc->buflen -= offset - 8; memset(cgc->buffer, 0, 8); return cdrom_mode_select(cdi, cgc); } |