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] =