From: Shao Mingyin nvme_set_max_append() computes the zone append limit as ctrl->max_zone_append = 1 << (id->zasl + 3); where zasl is a u8 from the controller's Identify Controller ZNS data structure. A value of 29 or more shifts a 32-bit int by 32 or more, which is undefined behaviour even with the kernel's -fno-strict-overflow; GCC may turn the result into zero, one, or another arbitrary value. The limit then either disables zone append or advertises a size larger than the controller and the block layer expect. This is reachable with a malicious or buggy controller. Use an unsigned shift, and fall back to max_hw_sectors, as for a zero ZASL, when the reported value does not fit. Warn once about the invalid value so the device can be identified. Fixes: 240e6ee272c0 ("nvme: support for zoned namespaces") Cc: stable@vger.kernel.org Signed-off-by: Shao Mingyin --- Tested on 7.3.0-next-20261030 (QEMU/TCG guest) with a host-managed zoned null_blk exported through nvmet and connected over the loop transport, so the host driver and the target run in the same guest. A TEST-ONLY hook makes the target report ZASL = 29 in its Identify Controller ZNS data; only the nvme host patch differs between the two runs. The out-of-range shift silently collapses the zone append limit to one sector on the unpatched driver; the fix falls back to max_hw_sectors and warns once: unpatched patched zone_append_max_bytes 512 zone_append_max_bytes 1044480 (max_zone_append = 1 sector) (fallback to max_hw_sectors) no warning "invalid zone append size limit 29" drivers/nvme/host/zns.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/nvme/host/zns.c b/drivers/nvme/host/zns.c index e31ec6f4f94f..c34015e68f81 100644 --- a/drivers/nvme/host/zns.c +++ b/drivers/nvme/host/zns.c @@ -27,10 +27,15 @@ static int nvme_set_max_append(struct nvme_ctrl *ctrl) return status; } - if (id->zasl) - ctrl->max_zone_append = 1 << (id->zasl + 3); - else + if (id->zasl && id->zasl + 3 < 32) { + ctrl->max_zone_append = 1U << (id->zasl + 3); + } else { + if (id->zasl) + dev_warn(ctrl->device, + "invalid zone append size limit %u\n", + id->zasl); ctrl->max_zone_append = ctrl->max_hw_sectors; + } kfree(id); return 0; } -- 2.43.0