@samitouri / QOSamiQemu / commits / 6a51b66dd5

hw/arm/smmuv3-accel: Fix veventq read returning true on EAGAIN/EINTR

smmuv3_accel_event_read_validate() returns true for EAGAIN/EINTR, but no data has been read into the buffer. Callers treat true as success and proceed to use the uninitialized buffer. Change the return type to int with three distinct states: 0 — success, buf is populated and valid 1 — EAGAIN/EINTR, no data available -1 — error, @errp set Resolves: Coverity CID 1660057 Fixes: d4aea0f75b ("hw/arm/smmuv3-accel: Introduce common helper for veventq read") Reported-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Shameer Kolothum <skolothumtho@nvidia.com> Reviewed-by: Eric Auger <eric.auger@redhat.com> Message-id: 20260625122843.107584-1-skolothumtho@nvidia.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Shameer Kolothum committed Jun 25, 2026 at 13:28 UTC 6a51b66dd51d59a1dc95f2eb89cc8f2d112a3892
4 files changed +33 -18
hw/arm/smmuv3-accel-stubs.c
+3 -3
@@ -47,10 +47,10 @@ bool smmuv3_accel_alloc_veventq(SMMUv3State *s, Error **errp)
47 return true;
48 }
49
50 -bool smmuv3_accel_event_read_validate(IOMMUFDVeventq *veventq, uint32_t type,
51 - void *buf, size_t size, Error **errp)
50 +int smmuv3_accel_event_read_validate(IOMMUFDVeventq *veventq, uint32_t type,
51 + void *buf, size_t size, Error **errp)
52 {
53 - return true;
53 + return 0;
54 }
55
56
hw/arm/smmuv3-accel.c
+20 -10
@@ -441,8 +441,13 @@ bool smmuv3_accel_issue_inv_cmd(SMMUv3State *bs, void *cmd, SMMUDevice *sdev,
441 sizeof(Cmd), &entry_num, cmd, errp);
442 }
443
444 -bool smmuv3_accel_event_read_validate(IOMMUFDVeventq *veventq, uint32_t type,
445 - void *buf, size_t size, Error **errp)
444 +/*
445 + * Returns 0 on success (buf is populated and valid).
446 + * Returns 1 if the read should be retried (EAGAIN/EINTR).
447 + * Returns -1 on error with @errp set.
448 + */
449 +int smmuv3_accel_event_read_validate(IOMMUFDVeventq *veventq, uint32_t type,
450 + void *buf, size_t size, Error **errp)
451 {
452 uint32_t last_seq = veventq->last_event_seq;
453 uint32_t id = veventq->veventq_id;
@@ -452,22 +457,22 @@ bool smmuv3_accel_event_read_validate(IOMMUFDVeventq *veventq, uint32_t type,
457 bytes = read(veventq->veventq_fd, buf, size);
458 if (bytes <= 0) {
459 if (errno == EAGAIN || errno == EINTR) {
455 - return true;
460 + return 1;
461 }
462 error_setg(errp, "vEVENTQ(type %u id %u): read failed (%m)", type, id);
458 - return false;
463 + return -1;
464 }
465 hdr = (struct iommufd_vevent_header *)buf;
466 if (bytes == sizeof(*hdr) &&
467 (hdr->flags & IOMMU_VEVENTQ_FLAG_LOST_EVENTS)) {
468 error_setg(errp, "vEVENTQ(type %u id %u): overflowed", type, id);
469 veventq->event_start = false;
465 - return false;
470 + return -1;
471 }
472 if (bytes < size) {
473 error_setg(errp, "vEVENTQ(type %u id %u): short read(%zd/%zd bytes)",
474 type, id, bytes, size);
470 - return false;
475 + return -1;
476 }
477 /* Check sequence in hdr for lost events if any */
478 if (veventq->event_start && (hdr->sequence - last_seq != 1)) {
@@ -476,7 +481,7 @@ bool smmuv3_accel_event_read_validate(IOMMUFDVeventq *veventq, uint32_t type,
481 }
482 veventq->last_event_seq = hdr->sequence;
483 veventq->event_start = true;
479 - return true;
484 + return 0;
485 }
486
487 static void smmuv3_accel_event_read(void *opaque)
@@ -488,13 +493,18 @@ static void smmuv3_accel_event_read(void *opaque)
493 struct iommu_vevent_arm_smmuv3 vevent;
494 } buf;
495 Error *local_err = NULL;
496 + int ret;
497
492 - if (!smmuv3_accel_event_read_validate(veventq,
493 - IOMMU_VEVENTQ_TYPE_ARM_SMMUV3, &buf,
494 - sizeof(buf), &local_err)) {
498 + ret = smmuv3_accel_event_read_validate(veventq,
499 + IOMMU_VEVENTQ_TYPE_ARM_SMMUV3, &buf,
500 + sizeof(buf), &local_err);
501 + if (ret < 0) {
502 warn_report_err_once(local_err);
503 return;
504 }
505 + if (ret > 0) {
506 + return; /* EAGAIN/EINTR */
507 + }
508 smmuv3_propagate_event(s, (Evt *)&buf.vevent);
509 }
510
hw/arm/smmuv3-accel.h
+2 -2
@@ -97,8 +97,8 @@ bool smmuv3_accel_issue_inv_cmd(SMMUv3State *s, void *cmd, SMMUDevice *sdev,
97 Error **errp);
98 void smmuv3_accel_idr_override(SMMUv3State *s);
99 bool smmuv3_accel_alloc_veventq(SMMUv3State *s, Error **errp);
100 -bool smmuv3_accel_event_read_validate(IOMMUFDVeventq *veventq, uint32_t type,
101 - void *buf, size_t size, Error **errp);
100 +int smmuv3_accel_event_read_validate(IOMMUFDVeventq *veventq, uint32_t type,
101 + void *buf, size_t size, Error **errp);
102 void smmuv3_accel_reset(SMMUv3State *s);
103 SMMUv3AccelCmdqvType smmuv3_accel_cmdqv_type(Object *obj);
104
hw/arm/tegra241-cmdqv.c
+8 -3
@@ -841,13 +841,18 @@ static void tegra241_cmdqv_event_read(void *opaque)
841 struct iommu_vevent_tegra241_cmdqv vevent;
842 } buf;
843 Error *local_err = NULL;
844 + int ret;
845
845 - if (!smmuv3_accel_event_read_validate(veventq,
846 - IOMMU_VEVENTQ_TYPE_TEGRA241_CMDQV,
847 - &buf, sizeof(buf), &local_err)) {
846 + ret = smmuv3_accel_event_read_validate(veventq,
847 + IOMMU_VEVENTQ_TYPE_TEGRA241_CMDQV,
848 + &buf, sizeof(buf), &local_err);
849 + if (ret < 0) {
850 warn_report_err_once(local_err);
851 return;
852 }
853 + if (ret > 0) {
854 + return; /* EAGAIN/EINTR */
855 + }
856
857 if (buf.vevent.lvcmdq_err_map[0] || buf.vevent.lvcmdq_err_map[1]) {
858 cmdqv->vintf_cmdq_err_map[0] =