The read count must be large enough to hold a vEVENT header. For a normal
vEVENT, it must also hold the trailing data following the header.

iommufd_veventq_fops_read() does not validate the count, but returns 0 as
if the read had succeeded while leaving the pending event in the queue.

Return -EINVAL in both undersize cases.

Fixes: e36ba5ab808e ("iommufd: Add IOMMUFD_OBJ_VEVENTQ and 
IOMMUFD_CMD_VEVENTQ_ALLOC")
Cc: [email protected]
Signed-off-by: Nicolin Chen <[email protected]>
---
 drivers/iommu/iommufd/eventq.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/iommu/iommufd/eventq.c b/drivers/iommu/iommufd/eventq.c
index 896f45be0d2ee..ac485d010a439 100644
--- a/drivers/iommu/iommufd/eventq.c
+++ b/drivers/iommu/iommufd/eventq.c
@@ -310,6 +310,9 @@ static ssize_t iommufd_veventq_fops_read(struct file 
*filep, char __user *buf,
 
        if (*ppos)
                return -ESPIPE;
+       /* Minimum read count is a vEVENT header */
+       if (count < sizeof(*hdr))
+               return -EINVAL;
 
        while ((cur = iommufd_veventq_deliver_fetch(veventq))) {
                /* Validate the remaining bytes against the header size */
@@ -323,6 +326,9 @@ static ssize_t iommufd_veventq_fops_read(struct file 
*filep, char __user *buf,
                if (!vevent_for_lost_events_header(cur) &&
                    sizeof(*hdr) + cur->data_len > count - done) {
                        iommufd_veventq_deliver_restore(veventq, cur);
+                       /* Read count doesn't fit a single normal vEVENT */
+                       if (done == 0)
+                               rc = -EINVAL;
                        break;
                }
 
-- 
2.43.0


Reply via email to