* [PATCH 08/12] vhost-scsi: improve CDB size validation and remove TODO comment
From: Weimin Xiong @ 2026-07-15 8:09 UTC (permalink / raw)
To: virtualization
From: xiongweimin <xiongwm2026@163.com>
Improve the CDB size validation by adding a zero-length check for
additional safety. Also remove the misleading TODO comment since
scsi_command_size() already correctly handles both fixed and
variable-length CDBs.
Signed-off-by: Weimin Xiong <xiongwm2026@163.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
---
drivers/vhost/scsi.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index 219d9d881..2fbc328c9 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -1432,12 +1432,15 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
lun = vhost_buf_to_lun(v_req.lun);
}
/*
- * Check that the received CDB size does not exceeded our
- * hardcoded max for vhost-scsi, then get a pre-allocated
- * cmd descriptor for the new virtio-scsi tag.
- *
- * TODO what if cdb was too small for varlen cdb header?
+ * Check that the received CDB size is valid and does not
+ * exceed our hardcoded max for vhost-scsi, then get a
+ * pre-allocated cmd descriptor for the new virtio-scsi tag.
+ * scsi_command_size() handles both fixed and variable-length CDBs.
*/
+ if (unlikely(scsi_command_size(cdb) == 0)) {
+ vq_err(vq, "Received SCSI CDB with zero length\n");
+ goto err;
+ }
if (unlikely(scsi_command_size(cdb) > VHOST_SCSI_MAX_CDB_SIZE)) {
vq_err(vq, "Received SCSI CDB with command_size: %d that"
" exceeds SCSI_MAX_VARLEN_CDB_SIZE: %d\n",
--
2.43.0
^ permalink raw reply related
* [PATCH 05/12] vhost-vdpa: add comment for VHOST_SET_LOG_BASE not supported
From: Weimin Xiong @ 2026-07-15 8:09 UTC (permalink / raw)
To: virtualization
From: xiongweimin <xiongwm2026@163.com>
Add a comment explaining why VHOST_SET_LOG_BASE and VHOST_SET_LOG_FD
ioctls are not supported in vhost-vdpa. The vDPA devices use their own
logging mechanism through the vdpa bus instead.
Signed-off-by: Weimin Xiong <xiongwm2026@163.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
---
drivers/vhost/vdpa.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
index a18ed439e..6ddd5f0f9 100644
--- a/drivers/vhost/vdpa.c
+++ b/drivers/vhost/vdpa.c
@@ -848,6 +848,9 @@ static long vhost_vdpa_unlocked_ioctl(struct file *filep,
if (copy_to_user(argp, &v->vdpa->nas, sizeof(v->vdpa->nas)))
r = -EFAULT;
break;
+ /* vDPA devices use their own logging mechanism through the bus
+ * and don't support the traditional vhost-user log ioctls.
+ */
case VHOST_SET_LOG_BASE:
case VHOST_SET_LOG_FD:
r = -ENOIOCTLCMD;
--
2.43.0
^ permalink raw reply related
* [PATCH 06/12] vhost: rename confusing 'min' variable in log_write_hva
From: Weimin Xiong @ 2026-07-15 8:09 UTC (permalink / raw)
To: virtualization
From: xiongweimin <xiongwm2026@163.com>
Rename variable 'min' to 'logged_len' for clarity. The original expression
'min(l, min)' where 'min' is both a macro and a variable was confusing.
Also fix the misleading comment about GPAs - this function works with HVAs
and UMEM mappings.
Signed-off-by: Weimin Xiong <xiongwm2026@163.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
---
drivers/vhost/vhost.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 4c525b3e1..3c080c454 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -2461,14 +2461,14 @@ static int log_write_hva(struct vhost_virtqueue *vq, u64 hva, u64 len)
{
struct vhost_iotlb *umem = vq->umem;
struct vhost_iotlb_map *u;
- u64 start, end, l, min;
+ u64 start, end, l, logged_len;
int r;
bool hit = false;
while (len) {
- min = len;
- /* More than one GPAs can be mapped into a single HVA. So
- * iterate all possible umems here to be safe.
+ logged_len = len;
+ /* Multiple UMEM mappings may cover this HVA range.
+ * Iterate all mappings to ensure we log all dirty pages.
*/
list_for_each_entry(u, &umem->list, link) {
if (u->addr > hva - 1 + len ||
@@ -2483,14 +2483,14 @@ static int log_write_hva(struct vhost_virtqueue *vq, u64 hva, u64 len)
if (r < 0)
return r;
hit = true;
- min = min(l, min);
+ logged_len = min(l, logged_len);
}
if (!hit)
return -EFAULT;
- len -= min;
- hva += min;
+ len -= logged_len;
+ hva += logged_len;
}
return 0;
--
2.43.0
^ permalink raw reply related
* [PATCH 10/12] vhost-vringh: use size_mul() for overflow-safe multiplication
From: Weimin Xiong @ 2026-07-15 8:09 UTC (permalink / raw)
To: virtualization
From: xiongweimin <xiongwm2026@163.com>
The multiplication sizeof(*dst) * num could potentially overflow if num
is very large. Use size_mul_overflow() for overflow-safe multiplication,
consistent with patterns used elsewhere in the kernel.
Signed-off-by: Weimin Xiong <xiongwm2026@163.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
---
drivers/vhost/vringh.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/vhost/vringh.c b/drivers/vhost/vringh.c
index 9066f9f12..b4a06454f 100644
--- a/drivers/vhost/vringh.c
+++ b/drivers/vhost/vringh.c
@@ -9,6 +9,7 @@
#include <linux/vringh.h>
#include <linux/virtio_ring.h>
#include <linux/kernel.h>
+#include <linux/overflow.h>
#include <linux/ratelimit.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
@@ -621,8 +622,11 @@ static inline int putused_user(const struct vringh *vrh,
const struct vring_used_elem *src,
unsigned int num)
{
- return copy_to_user((__force void __user *)dst, src,
- sizeof(*dst) * num) ? -EFAULT : 0;
+ size_t total_size;
+
+ if (unlikely(size_mul_overflow(sizeof(*dst), num, &total_size)))
+ return -EINVAL;
+ return copy_to_user((__force void __user *)dst, src, total_size) ? -EFAULT : 0;
}
static inline int xfer_from_user(const struct vringh *vrh, void *src,
--
2.43.0
^ permalink raw reply related
* [PATCH 11/12] vhost-vringh: use uintptr_t for address casting
From: Weimin Xiong @ 2026-07-15 8:09 UTC (permalink / raw)
To: virtualization
From: xiongweimin <xiongwm2026@163.com>
Use (void *)(uintptr_t) instead of (void *)(long) for cleaner
unsigned address handling. The uintptr_t type makes the intent clearer
that we're handling pointer-sized unsigned values.
Signed-off-by: Weimin Xiong <xiongwm2026@163.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
---
drivers/vhost/vringh.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/vhost/vringh.c b/drivers/vhost/vringh.c
index b4a06454f..654567ee5 100644
--- a/drivers/vhost/vringh.c
+++ b/drivers/vhost/vringh.c
@@ -351,7 +351,7 @@ __vringh_iov(struct vringh *vrh, u16 i,
slowrange = range;
}
- addr = (void *)(long)(a + range.offset);
+ addr = (void *)(uintptr_t)(a + range.offset);
err = move_to_indirect(vrh, &up_next, &i, addr, &desc,
&descs, &desc_max);
if (err)
--
2.43.0
^ permalink raw reply related
* [PATCH 12/12] vhost-vdpa: add explicit cast for void* to u64__user*
From: Weimin Xiong @ 2026-07-15 8:09 UTC (permalink / raw)
To: virtualization
From: xiongweimin <xiongwm2026@163.com>
Add explicit cast from void __user* to u64 __user* for maximum
compatibility with static analysis tools. While the implicit conversion
is valid C, explicit casts improve sparse checking compatibility.
Signed-off-by: Weimin Xiong <xiongwm2026@163.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
---
drivers/vhost/vdpa.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
index 6ddd5f0f9..bb96b1aa5 100644
--- a/drivers/vhost/vdpa.c
+++ b/drivers/vhost/vdpa.c
@@ -779,7 +779,7 @@ static long vhost_vdpa_unlocked_ioctl(struct file *filep,
struct vhost_vdpa *v = filep->private_data;
struct vhost_dev *d = &v->vdev;
void __user *argp = (void __user *)arg;
- u64 __user *featurep = argp;
+ u64 __user *featurep = (u64 __user *)argp;
u64 features;
long r = 0;
--
2.43.0
^ permalink raw reply related
* [PATCH 00/12] vhost: cleanups and improvements - PLEASE IGNORE
From: Weimin Xiong @ 2026-07-15 8:14 UTC (permalink / raw)
To: virtualization
Cc: kvm, netdev, linux-kernel, mst, jasowangio, michael.christie
Please ignore the previous series "[PATCH 00/12] vhost: cleanups and improvements"
sent earlier today. There were missing CC recipients. A corrected version
will be resent shortly.
Sorry for the noise.
Weimin Xiong
^ permalink raw reply
* [PATCH 00/12] vhost: cleanups and improvements - PLEASE IGNORE
From: Weimin Xiong @ 2026-07-15 8:33 UTC (permalink / raw)
To: virtualization
Please ignore the previous series "[PATCH 00/12] vhost: cleanups and improvements"
sent earlier today. There were missing CC recipients. A corrected version
will be resent shortly.
Sorry for the noise.
Weimin Xiong
^ permalink raw reply
* Re: [PATCH] virtio_net: fix spelling of aggressively in comments
From: Jakub Raczynski @ 2026-07-15 8:49 UTC (permalink / raw)
To: weimin xiong
Cc: netdev, mst, jasowangio, xuanzhuo, eperezma, virtualization,
xiongweimin
In-Reply-To: <20260714024037.186799-1-15927021679@163.com>
[-- Attachment #1: Type: text/plain, Size: 1540 bytes --]
Please read
https://www.kernel.org/doc/html/latest/process/maintainer-netdev.html
This patch should target net-next tree and is not actively CC'ing any
maintainer. Use 'get_maintainer.pl' script to get correct recipents.
BR
Jakub Raczynski
On Tue, Jul 14, 2026 at 10:40:37AM +0800, weimin xiong wrote:
> From: xiongweimin <xiongweimin@kylinos.cn>
>
> Two receive-path comments misspell "aggressively" as "agressively".
>
> Signed-off-by: xiongweimin <xiongweimin@kylinos.cn>
> ---
> drivers/net/virtio_net.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index 3e2a5876c..f3c7b28ce 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -3190,7 +3190,7 @@ static int virtnet_open(struct net_device *dev)
>
> for (i = 0; i < vi->max_queue_pairs; i++) {
> if (i < vi->curr_queue_pairs)
> - /* Pre-fill rq agressively, to make sure we are ready to
> + /* Pre-fill rq aggressively, to make sure we are ready to
> * get packets immediately.
> */
> try_fill_recv(vi, &vi->rq[i], GFP_KERNEL);
> @@ -3419,7 +3419,7 @@ static void virtnet_rx_resume(struct virtnet_info *vi,
> bool refill)
> {
> if (netif_running(vi->dev)) {
> - /* Pre-fill rq agressively, to make sure we are ready to get
> + /* Pre-fill rq aggressively, to make sure we are ready to get
> * packets immediately.
> */
> if (refill)
> --
> 2.43.0
>
>
> No virus found
> Checked by Hillstone Network AntiVirus
>
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply
* Re: [PATCH 01/12] vhost-scsi: improve BIDI operation comments
From: Bobby Eshleman @ 2026-07-15 9:24 UTC (permalink / raw)
To: Weimin Xiong; +Cc: virtualization
In-Reply-To: <20260715080906.21689-1-xiongwm2026@163.com>
On Wed, Jul 15, 2026 at 04:09:06PM +0800, Weimin Xiong wrote:
> From: xiongweimin <xiongwm2026@163.com>
>
> Replace FIXME comments with clearer Note comments documenting
> that BIDI (bidirectional) operations are not yet supported.
>
> Signed-off-by: Weimin Xiong <xiongwm2026@163.com>
> Co-authored-by: Cursor <cursoragent@cursor.com>
> ---
> drivers/vhost/scsi.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
> index 9a1253b9d..81e905c4c 100644
> --- a/drivers/vhost/scsi.c
> +++ b/drivers/vhost/scsi.c
> @@ -1047,7 +1047,7 @@ static void vhost_scsi_target_queue_cmd(struct vhost_scsi_nexus *nexus,
> struct se_cmd *se_cmd = &cmd->tvc_se_cmd;
> struct scatterlist *sg_ptr, *sg_prot_ptr = NULL;
>
> - /* FIXME: BIDI operation */
> + /* Note: BIDI (bidirectional) operations are not yet supported */
> if (cmd->tvc_sgl_count) {
> sg_ptr = cmd->table.sgl;
>
> @@ -1168,7 +1168,7 @@ vhost_scsi_get_desc(struct vhost_scsi *vs, struct vhost_virtqueue *vq,
>
> /*
> * Get the size of request and response buffers.
> - * FIXME: Not correct for BIDI operation
> + * Note: Size calculation is not correct for BIDI operations.
> */
> vc->out_size = iov_length(vq->iov, vc->out);
> vc->in_size = iov_length(&vq->iov[vc->out], vc->in);
> --
> 2.43.0
>
Hey Weimin,
This series is probably going to be ignored. Comment-only changes are
almost never merged, and the code changes here don't look like genuine
bugs.
In the case that there are some real bugs, I'd recommend to setup a
system and trigger a bug, and provide a reproducer.
Best,
Bobby
^ permalink raw reply
* Re:Re: [PATCH 01/12] vhost-scsi: improve BIDI operation comments
From: xiongwm2026 @ 2026-07-15 9:36 UTC (permalink / raw)
To: Bobby Eshleman; +Cc: virtualization
In-Reply-To: <aldR5cNr3SlVoBX/@devvm29614.prn0.facebook.com>
Hi Bobby,
Thanks for the feedback.
Understood. I will drop this comment-only change and focus on fixes with
a concrete bug scenario or reproducer.
Best,
Weimin
At 2026-07-15 17:24:53, "Bobby Eshleman" <bobbyeshleman@gmail.com> wrote:
>On Wed, Jul 15, 2026 at 04:09:06PM +0800, Weimin Xiong wrote:
>> From: xiongweimin <xiongwm2026@163.com>
>>
>> Replace FIXME comments with clearer Note comments documenting
>> that BIDI (bidirectional) operations are not yet supported.
>>
>> Signed-off-by: Weimin Xiong <xiongwm2026@163.com>
>> Co-authored-by: Cursor <cursoragent@cursor.com>
>> ---
>> drivers/vhost/scsi.c | 4 ++--
>> 1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
>> index 9a1253b9d..81e905c4c 100644
>> --- a/drivers/vhost/scsi.c
>> +++ b/drivers/vhost/scsi.c
>> @@ -1047,7 +1047,7 @@ static void vhost_scsi_target_queue_cmd(struct vhost_scsi_nexus *nexus,
>> struct se_cmd *se_cmd = &cmd->tvc_se_cmd;
>> struct scatterlist *sg_ptr, *sg_prot_ptr = NULL;
>>
>> - /* FIXME: BIDI operation */
>> + /* Note: BIDI (bidirectional) operations are not yet supported */
>> if (cmd->tvc_sgl_count) {
>> sg_ptr = cmd->table.sgl;
>>
>> @@ -1168,7 +1168,7 @@ vhost_scsi_get_desc(struct vhost_scsi *vs, struct vhost_virtqueue *vq,
>>
>> /*
>> * Get the size of request and response buffers.
>> - * FIXME: Not correct for BIDI operation
>> + * Note: Size calculation is not correct for BIDI operations.
>> */
>> vc->out_size = iov_length(vq->iov, vc->out);
>> vc->in_size = iov_length(&vq->iov[vc->out], vc->in);
>> --
>> 2.43.0
>>
>
>Hey Weimin,
>
>This series is probably going to be ignored. Comment-only changes are
>almost never merged, and the code changes here don't look like genuine
>bugs.
>
>In the case that there are some real bugs, I'd recommend to setup a
>system and trigger a bug, and provide a reproducer.
>
>Best,
>Bobby
^ permalink raw reply
* Re: [PATCH v2 2/3] drm/virtio: honor blob_alignment requirements
From: Alyssa Ross @ 2026-07-15 10:13 UTC (permalink / raw)
To: Dmitry Osipenko, Sergio Lopez, Yiwei Zhang, Sergi Blanch Torne,
Valentine Burley
Cc: Chia-I Wu, Jason Wang, Michael S. Tsirkin, Eugenio Pérez,
Xuan Zhuo, linux-kernel, Simona Vetter, Thomas Zimmermann,
David Airlie, Gurchetan Singh, Gerd Hoffmann, virtualization,
dri-devel, Maxime Ripard, Maarten Lankhorst
In-Reply-To: <17764937-21dc-4b4a-8def-e738b361bcd1@collabora.com>
[-- Attachment #1: Type: text/plain, Size: 2444 bytes --]
Dmitry Osipenko <dmitry.osipenko@collabora.com> writes:
> On 7/13/26 14:19, Alyssa Ross wrote:
>> Dmitry Osipenko <dmitry.osipenko@collabora.com> writes:
>>
>>> On 7/1/26 14:10, Alyssa Ross wrote:
>>>> On Tue, Apr 28, 2026 at 09:44:49PM +0200, Sergio Lopez wrote:
>>>>> If VIRTIO_GPU_F_BLOB_ALIGNMENT has been negotiated, blob size must be
>>>>> aligned to blob_alignment. Validate this in verify_blob() so that
>>>>> invalid requests are rejected early.
>>>>>
>>>>> Signed-off-by: Sergio Lopez <slp@redhat.com>
>>>>
>>>> FYI: this change breaks crosvm, which is squatting the 5 and 6 values
>>>> of VIRTIO_GPU_F_* with different meanings. I've reported it as a
>>>> crosvm bug, so hopefully it can be taken care of there.
>>>>
>>>> https://issuetracker.google.com/issues/529852979
>>>>
>>>>> ---
>>>>> drivers/gpu/drm/virtio/virtgpu_ioctl.c | 5 +++++
>>>>> 1 file changed, 5 insertions(+)
>>>>>
>>>>> diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
>>>>> index c33c057365f8..d0c4edf1eaf4 100644
>>>>> --- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c
>>>>> +++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
>>>>> @@ -489,6 +489,11 @@ static int verify_blob(struct virtio_gpu_device *vgdev,
>>>>> params->size = rc_blob->size;
>>>>> params->blob = true;
>>>>> params->blob_flags = rc_blob->blob_flags;
>>>>> +
>>>>> + if (vgdev->has_blob_alignment &&
>>>>> + !IS_ALIGNED(params->size, vgdev->blob_alignment))
>>>>> + return -EINVAL;
>>>>> +
>>>>> return 0;
>>>>> }
>>>>>
>>>>> --
>>>>> 2.53.0
>>>>>
>>>
>>> Thanks for the report. Indeed, crosvm will need to fix its experimental
>>> caps. CI will likely run into this problem first once it will update
>>> guest to 7.2+ kernel.
>>
>> I sent
>> https://chromium-review.googlesource.com/c/crosvm/crosvm/+/8064741 last
>> week but still waiting to hear anything. Do you have any insight into
>> whether it's still used / being pursued?
>
> The GUEST_HANDLE should be used by Android [1]. The FENCE_PASSING
> shouldn't be used in production, though don't know for sure.
>
> Crosvm should bump its experimental defines by +10 to prevent clash with
> upstream in future.
>
> [1]
> https://github.com/google/gfxstream/blob/main/host/vulkan/vk_decoder_global_state.cpp#L107
Thanks for the extra info. :) They've agreed to go ahead and remove both
of them, so the problem is solved.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 227 bytes --]
^ permalink raw reply
* Re: [PATCH v1 2/2] iommu/virtio: Handle iommu_device_register() failures
From: Will Deacon @ 2026-07-15 11:46 UTC (permalink / raw)
To: weimin xiong
Cc: Jean-Philippe Brucker, Joerg Roedel, Robin Murphy, virtualization,
iommu, linux-kernel, Xiong Weimin
In-Reply-To: <20260714024949.190014-3-15927021679@163.com>
On Tue, Jul 14, 2026 at 10:49:49AM +0800, weimin xiong wrote:
> From: Xiong Weimin <xiongweimin@kylinos.cn>
>
> iommu_device_register() returns an error when the IOMMU core fails to
> register the hardware instance or probe the buses. viommu_probe()
> currently ignores that error and continues as if the device was
> registered successfully.
>
> Propagate the failure and unwind the sysfs entry and virtqueues that
> were set up earlier. Clear the driver data on the error path as well,
> since it is set before registration so bus probing can find the
> virtio-IOMMU instance.
>
> Signed-off-by: Xiong Weimin <xiongweimin@kylinos.cn>
> ---
> drivers/iommu/virtio-iommu.c | 7 ++++++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
> index 342785c76..9118377d7 100644
> --- a/drivers/iommu/virtio-iommu.c
> +++ b/drivers/iommu/virtio-iommu.c
> @@ -1240,7 +1240,9 @@ static int viommu_probe(struct virtio_device *vdev)
>
> vdev->priv = viommu;
>
> - iommu_device_register(&viommu->iommu, &viommu_ops, parent_dev);
> + ret = iommu_device_register(&viommu->iommu, &viommu_ops, parent_dev);
> + if (ret)
> + goto err_remove_sysfs;
Given that the first patch shouldn't be needed (per Robin's comments at
[1]) and this is augmented an error path that we shouldn't be hitting in
practice, I don't think we need to treat this as a fix. You can probably
just lump it in with your virtio-iommu hardening series.
Will
^ permalink raw reply
* [PATCH 0/4] virtio: validate device-reported values across drivers
From: Hari Mishal @ 2026-07-15 14:22 UTC (permalink / raw)
To: Amit Shah, Arnd Bergmann, Greg Kroah-Hartman, Gerd Hoffmann,
Michael S . Tsirkin, Jason Wang, David Hildenbrand,
Henrik Rydberg
Cc: Xuan Zhuo, Eugenio Pérez, virtualization, linux-kernel,
linux-input, Hari Mishal
These four patches harden virtio-mem, virtio_input, and virtio_console
against untrusted values coming from the device/backend side of the virtio
interface. The fourth fixes a use-after-free in virtio_console caused by a
missing refcount.
Hari Mishal (4):
virtio-mem: validate device-reported block size
virtio_input: validate device-reported multitouch slot count
virtio_console: avoid NULL portdev dereference in in_intr()
virtio_console: take a kref in find_port_by_vq() to fix port UAF
drivers/char/virtio_console.c | 18 +++++++++++++++++-
drivers/virtio/virtio_input.c | 4 ++++
drivers/virtio/virtio_mem.c | 7 +++++++
3 files changed, 28 insertions(+), 1 deletion(-)
--
2.43.0
^ permalink raw reply
* [PATCH 1/4] virtio-mem: validate device-reported block size
From: Hari Mishal @ 2026-07-15 14:22 UTC (permalink / raw)
To: Amit Shah, Arnd Bergmann, Greg Kroah-Hartman, Gerd Hoffmann,
Michael S . Tsirkin, Jason Wang, David Hildenbrand,
Henrik Rydberg
Cc: Xuan Zhuo, Eugenio Pérez, virtualization, linux-kernel,
linux-input, Hari Mishal
In-Reply-To: <20260715142337.22811-1-harimishal1@gmail.com>
The device_block_size read from the virtio-mem config space is used
as a divisor and also in ALIGN_DOWN() further down the code path in
the driver without further validation. A zero value leads to a division
by zero, and a non-power-of-two value corrupts the ALIGN_DOWN() bitmask
arithmetic leading to a misreporting of guest usable guest ram, post
crash. Reject both at init time instead of trusting the device.
Assisted-by: gkh_clanker:t1000
Signed-off-by: Hari Mishal <harimishal1@gmail.com>
---
drivers/virtio/virtio_mem.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/virtio/virtio_mem.c b/drivers/virtio/virtio_mem.c
index 11c441501582..43d12ec7c323 100644
--- a/drivers/virtio/virtio_mem.c
+++ b/drivers/virtio/virtio_mem.c
@@ -2847,6 +2847,13 @@ static int virtio_mem_init(struct virtio_mem *vm)
&vm->plugged_size);
virtio_cread_le(vm->vdev, struct virtio_mem_config, block_size,
&vm->device_block_size);
+ if (!vm->device_block_size ||
+ !is_power_of_2(vm->device_block_size)) {
+ dev_err(&vm->vdev->dev,
+ "invalid device block size: 0x%llx\n",
+ (unsigned long long)vm->device_block_size);
+ return -EINVAL;
+ }
virtio_cread_le(vm->vdev, struct virtio_mem_config, node_id,
&node_id);
vm->nid = virtio_mem_translate_node_id(vm, node_id);
--
2.43.0
^ permalink raw reply related
* [PATCH 2/4] virtio_input: validate device-reported multitouch slot count
From: Hari Mishal @ 2026-07-15 14:22 UTC (permalink / raw)
To: Amit Shah, Arnd Bergmann, Greg Kroah-Hartman, Gerd Hoffmann,
Michael S . Tsirkin, Jason Wang, David Hildenbrand,
Henrik Rydberg
Cc: Xuan Zhuo, Eugenio Pérez, virtualization, linux-kernel,
linux-input, Hari Mishal
In-Reply-To: <20260715142337.22811-1-harimishal1@gmail.com>
nslots is derived from the ABS_MT_SLOT maximum reported by the
virtio device. A device could report a bogus maximum (e.g. -1)
making nslots = 0, which input_mt_init_slots() does not reject;
it returns success without allocating any slot storage, silently
leaving the device registered as multitouch capable with no
backing state. Reject non-positive slot counts before calling
input_mt_init_slots().
Assisted-by: gkh_clanker:t1000
Signed-off-by: Hari Mishal <harimishal1@gmail.com>
---
drivers/virtio/virtio_input.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/virtio/virtio_input.c b/drivers/virtio/virtio_input.c
index deec24e8e682..2cc19782cdd3 100644
--- a/drivers/virtio/virtio_input.c
+++ b/drivers/virtio/virtio_input.c
@@ -312,6 +312,10 @@ static int virtinput_probe(struct virtio_device *vdev)
if (test_bit(ABS_MT_SLOT, vi->idev->absbit)) {
nslots = input_abs_get_max(vi->idev, ABS_MT_SLOT) + 1;
+ if (nslots <= 0) {
+ err = -EINVAL;
+ goto err_mt_init_slots;
+ }
err = input_mt_init_slots(vi->idev, nslots, 0);
if (err)
goto err_mt_init_slots;
--
2.43.0
^ permalink raw reply related
* [PATCH 3/4] virtio_console: avoid NULL portdev dereference in in_intr()
From: Hari Mishal @ 2026-07-15 14:22 UTC (permalink / raw)
To: Amit Shah, Arnd Bergmann, Greg Kroah-Hartman, Gerd Hoffmann,
Michael S . Tsirkin, Jason Wang, David Hildenbrand,
Henrik Rydberg
Cc: Xuan Zhuo, Eugenio Pérez, virtualization, linux-kernel,
linux-input, Hari Mishal
In-Reply-To: <20260715142337.22811-1-harimishal1@gmail.com>
A port's virtqueue is not torn down immediately if the port itself is
hot-unplugged (unplug_port() only nulls port->portdev; the vq
callback stays registered until the whole device is removed).
If in_intr() fires for a port in that window it dereferences
port->portdev->vdev via is_rproc_serial(), crashing on the NULL
portdev.
Bail out early when portdev has already been cleared.
Assisted-by: gkh_clanker:t1000
Signed-off-by: Hari Mishal <harimishal1@gmail.com>
---
drivers/char/virtio_console.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 198b97314168..faef362dae85 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -1720,6 +1720,11 @@ static void in_intr(struct virtqueue *vq)
}
spin_lock_irqsave(&port->inbuf_lock, flags);
+ if (!port->portdev) {
+ /* Port is being unplugged, ignore further data. */
+ spin_unlock_irqrestore(&port->inbuf_lock, flags);
+ return;
+ }
port->inbuf = get_inbuf(port);
/*
--
2.43.0
^ permalink raw reply related
* [PATCH 4/4] virtio_console: take a kref in find_port_by_vq() to fix port UAF
From: Hari Mishal @ 2026-07-15 14:22 UTC (permalink / raw)
To: Amit Shah, Arnd Bergmann, Greg Kroah-Hartman, Gerd Hoffmann,
Michael S . Tsirkin, Jason Wang, David Hildenbrand,
Henrik Rydberg
Cc: Xuan Zhuo, Eugenio Pérez, virtualization, linux-kernel,
linux-input, Hari Mishal
In-Reply-To: <20260715142337.22811-1-harimishal1@gmail.com>
find_port_by_vq() returns a raw struct port pointer without taking a
reference on it, unlike find_port_by_devt_in_portdev() which does.
find_port_by_vq()'s only two callers, in_intr() and out_intr(), run
as virtqueue interrupt callbacks, entirely independent of and
possibly concurrently with unplug_port(), which itself runs from a
workqueue when the host sends a VIRTIO_CONSOLE_PORT_REMOVE control
message.
unplug_port() removes the port from portdev->ports under ports_lock,
then later drops its last reference with kref_put(), freeing it via
remove_port(). find_port_by_vq() also walks portdev->ports under
ports_lock, so if it finds the port still on the list, the list
removal, and therefore the eventual kref_put(), has not happened yet,
and taking a reference at that point is always safe. Without doing
so, in_intr()/out_intr() can be left holding a pointer to a port that
unplug_port() frees on another core before they are done using it.
Both triggers are host-controlled as the host decides when to send the
PORT_REMOVE control message and when to kick the port's data vq. So a
malicious backend could race the two on purpose, without any guest side
cooperation. The freed object is a generic kmalloc allocation containing
a wait_queue_head_t, which in_intr()/out_intr() pass to
wake_up_interruptible() after touching the stale pointer.
wake_up_interruptible() invokes a function pointer read out of the
wait queue's entries. If the freed slab slot is reclaimed with
attacker influenced content before that call, then this is an arbitrary
function call primitive rather than just undefined behaviour.
Take a reference in find_port_by_vq() while still holding ports_lock,
matching find_port_by_devt_in_portdev(), and release it in in_intr()
and out_intr() once they are done with the port.
Signed-off-by: Hari Mishal <harimishal1@gmail.com>
---
drivers/char/virtio_console.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index faef362dae85..1b7593684ed9 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -304,6 +304,11 @@ static struct port *find_port_by_id(struct ports_device *portdev, u32 id)
return port;
}
+/*
+ * The port object's reference is incremented now and
+ * it is the caller's responsibility to decrement it
+ */
+
static struct port *find_port_by_vq(struct ports_device *portdev,
struct virtqueue *vq)
{
@@ -312,8 +317,10 @@ static struct port *find_port_by_vq(struct ports_device *portdev,
spin_lock_irqsave(&portdev->ports_lock, flags);
list_for_each_entry(port, &portdev->ports, list)
- if (port->in_vq == vq || port->out_vq == vq)
+ if (port->in_vq == vq || port->out_vq == vq) {
+ kref_get(&port->kref);
goto out;
+ }
port = NULL;
out:
spin_unlock_irqrestore(&portdev->ports_lock, flags);
@@ -1706,6 +1713,7 @@ static void out_intr(struct virtqueue *vq)
}
wake_up_interruptible(&port->waitqueue);
+ kref_put(&port->kref, remove_port);
}
static void in_intr(struct virtqueue *vq)
@@ -1723,6 +1731,7 @@ static void in_intr(struct virtqueue *vq)
if (!port->portdev) {
/* Port is being unplugged, ignore further data. */
spin_unlock_irqrestore(&port->inbuf_lock, flags);
+ kref_put(&port->kref, remove_port);
return;
}
port->inbuf = get_inbuf(port);
@@ -1756,6 +1765,8 @@ static void in_intr(struct virtqueue *vq)
if (is_console_port(port) && hvc_poll(port->cons.hvc))
hvc_kick();
+
+ kref_put(&port->kref, remove_port);
}
static void control_intr(struct virtqueue *vq)
--
2.43.0
^ permalink raw reply related
* [PATCH v2 4/4] virtio_console: take a kref in find_port_by_vq() to fix port UAF
From: Hari Mishal @ 2026-07-15 14:42 UTC (permalink / raw)
To: Amit Shah, Arnd Bergmann, Greg Kroah-Hartman
Cc: virtualization, linux-kernel, Hari Mishal
In-Reply-To: <20260715142337.22811-5-harimishal1@gmail.com>
find_port_by_vq() returns a raw struct port pointer without taking a
reference on it, unlike find_port_by_devt_in_portdev() which does.
find_port_by_vq()'s only two callers, in_intr() and out_intr(), run as
virtqueue interrupt callbacks, entirely independent of and possibly
concurrently with unplug_port(), which itself runs from a workqueue when
the host sends a VIRTIO_CONSOLE_PORT_REMOVE control message.
unplug_port() removes the port from portdev->ports under ports_lock,
then later drops its last reference with kref_put(), freeing it via
remove_port(). find_port_by_vq() also walks portdev->ports under
ports_lock, so if it finds the port still on the list, the list removal,
and therefore the eventual kref_put(), has not happened yet, and taking
a reference at that point is always safe. Without doing so,
in_intr()/out_intr() can be left holding a pointer to a port that
unplug_port() frees on another core before they are done using it.
Both triggers are host-controlled as the host decides when to send the
PORT_REMOVE control message and when to kick the port's data vq. So a
malicious backend could race the two on purpose, without any guest side
cooperation. The freed object is a generic kmalloc allocation containing
a wait_queue_head_t, which in_intr()/out_intr() pass to
wake_up_interruptible() after touching the stale pointer.
wake_up_interruptible() invokes a function pointer read out of the wait
queue's entries. If the freed slab slot is reclaimed with attacker
influenced content before that call, then this is an arbitrary function
call primitive rather than just undefined behaviour.
Take a reference in find_port_by_vq() while still holding ports_lock,
matching find_port_by_devt_in_portdev(), and release it in in_intr() and
out_intr() once they are done with the port.
Signed-off-by: Hari Mishal <harimishal1@gmail.com>
---
v2: reworded the comment above find_port_by_vq() for clarity, no
functional change since v1.
drivers/char/virtio_console.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index faef362dae85..1b63afe24e29 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -304,6 +304,12 @@ static struct port *find_port_by_id(struct ports_device *portdev, u32 id)
return port;
}
+/*
+ * Finds a port by the virtqueue and returns a pointer to struct port
+ * with the reference count incremented.
+ *
+ * Callers MUST decrement it when finished.
+ */
static struct port *find_port_by_vq(struct ports_device *portdev,
struct virtqueue *vq)
{
@@ -312,8 +318,10 @@ static struct port *find_port_by_vq(struct ports_device *portdev,
spin_lock_irqsave(&portdev->ports_lock, flags);
list_for_each_entry(port, &portdev->ports, list)
- if (port->in_vq == vq || port->out_vq == vq)
+ if (port->in_vq == vq || port->out_vq == vq) {
+ kref_get(&port->kref);
goto out;
+ }
port = NULL;
out:
spin_unlock_irqrestore(&portdev->ports_lock, flags);
@@ -1706,6 +1714,7 @@ static void out_intr(struct virtqueue *vq)
}
wake_up_interruptible(&port->waitqueue);
+ kref_put(&port->kref, remove_port);
}
static void in_intr(struct virtqueue *vq)
@@ -1723,6 +1732,7 @@ static void in_intr(struct virtqueue *vq)
if (!port->portdev) {
/* Port is being unplugged, ignore further data. */
spin_unlock_irqrestore(&port->inbuf_lock, flags);
+ kref_put(&port->kref, remove_port);
return;
}
port->inbuf = get_inbuf(port);
@@ -1756,6 +1766,8 @@ static void in_intr(struct virtqueue *vq)
if (is_console_port(port) && hvc_poll(port->cons.hvc))
hvc_kick();
+
+ kref_put(&port->kref, remove_port);
}
static void control_intr(struct virtqueue *vq)
--
2.43.0
^ permalink raw reply related
* Re: [PATCH 2/4] virtio_input: validate device-reported multitouch slot count
From: Michael S. Tsirkin @ 2026-07-15 15:50 UTC (permalink / raw)
To: Hari Mishal
Cc: Amit Shah, Arnd Bergmann, Greg Kroah-Hartman, Gerd Hoffmann,
Jason Wang, David Hildenbrand, Henrik Rydberg, Xuan Zhuo,
Eugenio Pérez, virtualization, linux-kernel, linux-input
In-Reply-To: <20260715142337.22811-3-harimishal1@gmail.com>
On Wed, Jul 15, 2026 at 04:22:41PM +0200, Hari Mishal wrote:
> nslots is derived from the ABS_MT_SLOT maximum reported by the
> virtio device. A device could report a bogus maximum (e.g. -1)
> making nslots = 0, which input_mt_init_slots() does not reject;
> it returns success without allocating any slot storage, silently
> leaving the device registered as multitouch capable with no
> backing state.
So let's disable multitouch instead?
> Reject non-positive slot counts before calling
> input_mt_init_slots().
>
> Assisted-by: gkh_clanker:t1000
> Signed-off-by: Hari Mishal <harimishal1@gmail.com>
> ---
> drivers/virtio/virtio_input.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/drivers/virtio/virtio_input.c b/drivers/virtio/virtio_input.c
> index deec24e8e682..2cc19782cdd3 100644
> --- a/drivers/virtio/virtio_input.c
> +++ b/drivers/virtio/virtio_input.c
> @@ -312,6 +312,10 @@ static int virtinput_probe(struct virtio_device *vdev)
>
> if (test_bit(ABS_MT_SLOT, vi->idev->absbit)) {
> nslots = input_abs_get_max(vi->idev, ABS_MT_SLOT) + 1;
> + if (nslots <= 0) {
> + err = -EINVAL;
> + goto err_mt_init_slots;
> + }
> err = input_mt_init_slots(vi->idev, nslots, 0);
> if (err)
> goto err_mt_init_slots;
> --
> 2.43.0
^ permalink raw reply
* Re: [PATCH 1/4] virtio-mem: validate device-reported block size
From: Michael S. Tsirkin @ 2026-07-15 15:57 UTC (permalink / raw)
To: Hari Mishal
Cc: Amit Shah, Arnd Bergmann, Greg Kroah-Hartman, Gerd Hoffmann,
Jason Wang, David Hildenbrand, Henrik Rydberg, Xuan Zhuo,
Eugenio Pérez, virtualization, linux-kernel, linux-input
In-Reply-To: <20260715142337.22811-2-harimishal1@gmail.com>
On Wed, Jul 15, 2026 at 04:22:40PM +0200, Hari Mishal wrote:
> The device_block_size read from the virtio-mem config space is used
> as a divisor and also in ALIGN_DOWN() further down the code path in
> the driver without further validation. A zero value leads to a division
> by zero, and a non-power-of-two value corrupts the ALIGN_DOWN() bitmask
> arithmetic leading to a misreporting of guest usable guest ram, post
> crash. Reject both at init time instead of trusting the device.
>
> Assisted-by: gkh_clanker:t1000
> Signed-off-by: Hari Mishal <harimishal1@gmail.com>
> ---
> drivers/virtio/virtio_mem.c | 7 +++++++
> 1 file changed, 7 insertions(+)
>
> diff --git a/drivers/virtio/virtio_mem.c b/drivers/virtio/virtio_mem.c
> index 11c441501582..43d12ec7c323 100644
> --- a/drivers/virtio/virtio_mem.c
> +++ b/drivers/virtio/virtio_mem.c
> @@ -2847,6 +2847,13 @@ static int virtio_mem_init(struct virtio_mem *vm)
> &vm->plugged_size);
> virtio_cread_le(vm->vdev, struct virtio_mem_config, block_size,
> &vm->device_block_size);
> + if (!vm->device_block_size ||
> + !is_power_of_2(vm->device_block_size)) {
0 is not a power of 2, why do we need to check twice?
> + dev_err(&vm->vdev->dev,
> + "invalid device block size: 0x%llx\n",
> + (unsigned long long)vm->device_block_size);
> + return -EINVAL;
> + }
> virtio_cread_le(vm->vdev, struct virtio_mem_config, node_id,
> &node_id);
> vm->nid = virtio_mem_translate_node_id(vm, node_id);
> --
> 2.43.0
^ permalink raw reply
* Re: [PATCH 2/4] virtio_input: validate device-reported multitouch slot count
From: Hari Mishal @ 2026-07-15 16:07 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: Amit Shah, Arnd Bergmann, Greg Kroah-Hartman, Gerd Hoffmann,
Jason Wang, David Hildenbrand, Henrik Rydberg, Xuan Zhuo,
Eugenio Pérez, virtualization, linux-kernel, linux-input
In-Reply-To: <20260715115018-mutt-send-email-mst@kernel.org>
On Wed, Jul 15, 2026 at 5:50 PM Michael S. Tsirkin <mst@redhat.com> wrote:
>
> On Wed, Jul 15, 2026 at 04:22:41PM +0200, Hari Mishal wrote:
> > nslots is derived from the ABS_MT_SLOT maximum reported by the
> > virtio device. A device could report a bogus maximum (e.g. -1)
> > making nslots = 0, which input_mt_init_slots() does not reject;
> > it returns success without allocating any slot storage, silently
> > leaving the device registered as multitouch capable with no
> > backing state.
>
> So let's disable multitouch instead?
>
So rather than failing the whole probe, just warn and clear
ABS_MT_SLOT from absbit in that case, so the rest of the device
still registers? I took my lead from input_mt_init_slots(), which
has its own internal cap and returns -EINVAL when the device
reports more than 1024 slots.
Shall I modify that case to get the same "warn and disable
multitouch" for consistency, or is a hard failure better there since
it's a different type of bad device data?
Happy to fix it either way! Just want to confirm before sending V2.
Cheers,
Hari
^ permalink raw reply
* Re: [PATCH 2/4] virtio_input: validate device-reported multitouch slot count
From: Michael S. Tsirkin @ 2026-07-15 16:11 UTC (permalink / raw)
To: Hari Mishal
Cc: Amit Shah, Arnd Bergmann, Greg Kroah-Hartman, Gerd Hoffmann,
Jason Wang, David Hildenbrand, Henrik Rydberg, Xuan Zhuo,
Eugenio Pérez, virtualization, linux-kernel, linux-input
In-Reply-To: <CAMmC+=AnE-p7B=DbBPYeNzJdcdiBf7q=5bfcuV0VQrPRK+pmug@mail.gmail.com>
On Wed, Jul 15, 2026 at 06:07:56PM +0200, Hari Mishal wrote:
> On Wed, Jul 15, 2026 at 5:50 PM Michael S. Tsirkin <mst@redhat.com> wrote:
> >
> > On Wed, Jul 15, 2026 at 04:22:41PM +0200, Hari Mishal wrote:
> > > nslots is derived from the ABS_MT_SLOT maximum reported by the
> > > virtio device. A device could report a bogus maximum (e.g. -1)
> > > making nslots = 0, which input_mt_init_slots() does not reject;
> > > it returns success without allocating any slot storage, silently
> > > leaving the device registered as multitouch capable with no
> > > backing state.
> >
> > So let's disable multitouch instead?
> >
>
> So rather than failing the whole probe, just warn and clear
> ABS_MT_SLOT from absbit in that case, so the rest of the device
> still registers? I took my lead from input_mt_init_slots(), which
> has its own internal cap and returns -EINVAL when the device
> reports more than 1024 slots.
> Shall I modify that case to get the same "warn and disable
> multitouch" for consistency, or is a hard failure better there since
> it's a different type of bad device data?
I don't really know enough for sure but generally if the device can
kinda work it's better than not working, and adding
a capability to a device that driver can't use should
generally just ignore the capability, not fail probe.
> Happy to fix it either way! Just want to confirm before sending V2.
>
> Cheers,
> Hari
^ permalink raw reply
* [PATCH v2 1/4] virtio-mem: validate device-reported block size
From: Hari Mishal @ 2026-07-15 16:41 UTC (permalink / raw)
To: David Hildenbrand, Michael S . Tsirkin, Jason Wang
Cc: Greg Kroah-Hartman, Xuan Zhuo, Eugenio Pérez, virtualization,
linux-kernel, Hari Mishal
In-Reply-To: <20260715142337.22811-2-harimishal1@gmail.com>
The device_block_size read from the virtio-mem config space is used as a
divisor and also in ALIGN_DOWN() further down the code path in the
driver without further validation. A zero value leads to a division by
zero, and a non-power-of-two value corrupts the ALIGN_DOWN() bitmask
arithmetic leading to a misreporting of guest-usable ram, post crash.
Reject both at init time instead of trusting the device.
Signed-off-by: Hari Mishal <harimishal1@gmail.com>
---
v2: dropped the redundant explicit zero check, since
is_power_of_2(0) already returns false.
drivers/virtio/virtio_mem.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/virtio/virtio_mem.c b/drivers/virtio/virtio_mem.c
index 11c441501582..0e04fec458af 100644
--- a/drivers/virtio/virtio_mem.c
+++ b/drivers/virtio/virtio_mem.c
@@ -2847,6 +2847,12 @@ static int virtio_mem_init(struct virtio_mem *vm)
&vm->plugged_size);
virtio_cread_le(vm->vdev, struct virtio_mem_config, block_size,
&vm->device_block_size);
+ if (!is_power_of_2(vm->device_block_size)) {
+ dev_err(&vm->vdev->dev,
+ "invalid device block size: 0x%llx\n",
+ (unsigned long long)vm->device_block_size);
+ return -EINVAL;
+ }
virtio_cread_le(vm->vdev, struct virtio_mem_config, node_id,
&node_id);
vm->nid = virtio_mem_translate_node_id(vm, node_id);
--
2.43.0
^ permalink raw reply related
* [PATCH v2 2/4] virtio_input: validate device-reported multitouch slot count
From: Hari Mishal @ 2026-07-15 16:41 UTC (permalink / raw)
To: Gerd Hoffmann, Michael S . Tsirkin, Jason Wang
Cc: Greg Kroah-Hartman, Xuan Zhuo, Eugenio Pérez, Henrik Rydberg,
virtualization, linux-kernel, linux-input, Hari Mishal
In-Reply-To: <20260715142337.22811-3-harimishal1@gmail.com>
nslots is derived from the ABS_MT_SLOT maximum reported by the virtio
device. A device could report a bogus maximum (e.g. -1) making nslots <=
0, and input_mt_init_slots() can independently fail too (e.g. it rejects
slot counts over 1024). Neither case was handled here, and
input_mt_init_slots() failing took down the whole probe, losing the rest
of the input device over a problem isolated to multitouch.
Instead of failing the probe, warn and disable the ABS_MT_SLOT
capability in either case, and let the rest of the device register
normally. This recovery assumes input_mt_init_slots() is called with
flags == 0: with nonzero flags it can fail after already mutating the
input_dev (e.g. via input_set_abs_params()), which this recovery does
not account for.
Signed-off-by: Hari Mishal <harimishal1@gmail.com>
---
v2: per review, disable multitouch instead of failing the whole
probe when the reported slot count is invalid or
input_mt_init_slots() otherwise fails.
drivers/virtio/virtio_input.c | 23 +++++++++++++++++++----
1 file changed, 19 insertions(+), 4 deletions(-)
diff --git a/drivers/virtio/virtio_input.c b/drivers/virtio/virtio_input.c
index deec24e8e682..786f5150724f 100644
--- a/drivers/virtio/virtio_input.c
+++ b/drivers/virtio/virtio_input.c
@@ -312,9 +312,25 @@ static int virtinput_probe(struct virtio_device *vdev)
if (test_bit(ABS_MT_SLOT, vi->idev->absbit)) {
nslots = input_abs_get_max(vi->idev, ABS_MT_SLOT) + 1;
- err = input_mt_init_slots(vi->idev, nslots, 0);
- if (err)
- goto err_mt_init_slots;
+ if (nslots <= 0) {
+ dev_warn(&vdev->dev,
+ "invalid multitouch slot count %d, disabling multitouch\n",
+ nslots);
+ __clear_bit(ABS_MT_SLOT, vi->idev->absbit);
+ } else {
+ /*
+ * flags is 0: input_mt_init_slots() can only fail
+ * before touching *idev, so the recovery below is
+ * a full rollback.
+ */
+ err = input_mt_init_slots(vi->idev, nslots, 0);
+ if (err) {
+ dev_warn(&vdev->dev,
+ "failed to init %d multitouch slots (%d), disabling multitouch\n",
+ nslots, err);
+ __clear_bit(ABS_MT_SLOT, vi->idev->absbit);
+ }
+ }
}
}
@@ -331,7 +347,6 @@ static int virtinput_probe(struct virtio_device *vdev)
spin_lock_irqsave(&vi->lock, flags);
vi->ready = false;
spin_unlock_irqrestore(&vi->lock, flags);
-err_mt_init_slots:
input_free_device(vi->idev);
err_input_alloc:
vdev->config->del_vqs(vdev);
--
2.43.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox