From 32520201bb8eefa584c0d20f80d207cb93aa85f4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 13 Oct 2025 10:27:57 +0200 Subject: [PATCH] 5.4-stable patches added patches: uio_hv_generic-let-userspace-take-care-of-interrupt-mask.patch --- queue-5.4/series | 1 + ...serspace-take-care-of-interrupt-mask.patch | 97 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 queue-5.4/uio_hv_generic-let-userspace-take-care-of-interrupt-mask.patch diff --git a/queue-5.4/series b/queue-5.4/series index 06bc8ce472..16eb552257 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -71,3 +71,4 @@ nfp-fix-rss-hash-key-size-when-rss-is-not-supported.patch net-ena-return-0-in-ena_get_rxfh_key_size-when-rss-h.patch revert-net-mlx5e-update-and-set-xon-xoff-upon-mtu-se.patch squashfs-fix-uninit-value-in-squashfs_get_parent.patch +uio_hv_generic-let-userspace-take-care-of-interrupt-mask.patch diff --git a/queue-5.4/uio_hv_generic-let-userspace-take-care-of-interrupt-mask.patch b/queue-5.4/uio_hv_generic-let-userspace-take-care-of-interrupt-mask.patch new file mode 100644 index 0000000000..2ffd512ddb --- /dev/null +++ b/queue-5.4/uio_hv_generic-let-userspace-take-care-of-interrupt-mask.patch @@ -0,0 +1,97 @@ +From b15b7d2a1b09ef5428a8db260251897405a19496 Mon Sep 17 00:00:00 2001 +From: Naman Jain +Date: Thu, 28 Aug 2025 10:12:00 +0530 +Subject: uio_hv_generic: Let userspace take care of interrupt mask +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Naman Jain + +commit b15b7d2a1b09ef5428a8db260251897405a19496 upstream. + +Remove the logic to set interrupt mask by default in uio_hv_generic +driver as the interrupt mask value is supposed to be controlled +completely by the user space. If the mask bit gets changed +by the driver, concurrently with user mode operating on the ring, +the mask bit may be set when it is supposed to be clear, and the +user-mode driver will miss an interrupt which will cause a hang. + +For eg- when the driver sets inbound ring buffer interrupt mask to 1, +the host does not interrupt the guest on the UIO VMBus channel. +However, setting the mask does not prevent the host from putting a +message in the inbound ring buffer. So let’s assume that happens, +the host puts a message into the ring buffer but does not interrupt. + +Subsequently, the user space code in the guest sets the inbound ring +buffer interrupt mask to 0, saying “Hey, I’m ready for interrupts”. +User space code then calls pread() to wait for an interrupt. +Then one of two things happens: + +* The host never sends another message. So the pread() waits forever. +* The host does send another message. But because there’s already a + message in the ring buffer, it doesn’t generate an interrupt. + This is the correct behavior, because the host should only send an + interrupt when the inbound ring buffer transitions from empty to + not-empty. Adding an additional message to a ring buffer that is not + empty is not supposed to generate an interrupt on the guest. + Since the guest is waiting in pread() and not removing messages from + the ring buffer, the pread() waits forever. + +This could be easily reproduced in hv_fcopy_uio_daemon if we delay +setting interrupt mask to 0. + +Similarly if hv_uio_channel_cb() sets the interrupt_mask to 1, +there’s a race condition. Once user space empties the inbound ring +buffer, but before user space sets interrupt_mask to 0, the host could +put another message in the ring buffer but it wouldn’t interrupt. +Then the next pread() would hang. + +Fix these by removing all instances where interrupt_mask is changed, +while keeping the one in set_event() unchanged to enable userspace +control the interrupt mask by writing 0/1 to /dev/uioX. + +Fixes: 95096f2fbd10 ("uio-hv-generic: new userspace i/o driver for VMBus") +Suggested-by: John Starks +Signed-off-by: Naman Jain +Cc: stable@vger.kernel.org +Reviewed-by: Michael Kelley +Reviewed-by: Long Li +Reviewed-by: Tianyu Lan +Tested-by: Tianyu Lan +Link: https://lore.kernel.org/r/20250828044200.492030-1-namjain@linux.microsoft.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/uio/uio_hv_generic.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +--- a/drivers/uio/uio_hv_generic.c ++++ b/drivers/uio/uio_hv_generic.c +@@ -96,7 +96,6 @@ static void hv_uio_channel_cb(void *cont + struct hv_device *hv_dev = chan->device_obj; + struct hv_uio_private_data *pdata = hv_get_drvdata(hv_dev); + +- chan->inbound.ring_buffer->interrupt_mask = 1; + virt_mb(); + + uio_event_notify(&pdata->info); +@@ -173,8 +172,6 @@ hv_uio_new_channel(struct vmbus_channel + return; + } + +- /* Disable interrupts on sub channel */ +- new_sc->inbound.ring_buffer->interrupt_mask = 1; + set_channel_read_mode(new_sc, HV_CALL_ISR); + + ret = sysfs_create_bin_file(&new_sc->kobj, &ring_buffer_bin_attr); +@@ -218,9 +215,7 @@ hv_uio_open(struct uio_info *info, struc + + ret = vmbus_connect_ring(dev->channel, + hv_uio_channel_cb, dev->channel); +- if (ret == 0) +- dev->channel->inbound.ring_buffer->interrupt_mask = 1; +- else ++ if (ret) + atomic_dec(&pdata->refcnt); + + return ret; -- 2.47.3