cmd_features_set_feature() uses set_feat_info->data_size as the memset
length when zeroing write-attribute buffers on Finish/Abort.  data_size
accumulates bytes_to_copy across transfer parts but is only reset on
INITIATE.  Since QEMU never returns Feature Transfer Out of Order,
repeated transfers at the same offset grow data_size past sizeof(struct),
and the final memset overflows the target buffer.

b71a179148 bounded the per-transfer memcpy against sizeof, but the
cleanup memset still runs on the accumulated data_size, so the overflow
survives that fix.

Pass sizeof() of the target struct to memset instead of data_size.

Fixes: d88f66741410 ("hw/cxl/cxl-mailbox-utils: Add device patrol scrub control 
feature")
Fixes: 2d41ce38fb9a ("hw/cxl/cxl-mailbox-utils: Add device DDR5 ECS control 
feature")
Fixes: 5e5a86bab830 ("hw/cxl: Add support for Maintenance command and Post 
Package Repair (PPR)")
Fixes: da5cafdc4ddd ("hw/cxl: Add emulation for memory sparing control feature")
Cc: [email protected]
Signed-off-by: Junjie Cao <[email protected]>
---
 hw/cxl/cxl-mailbox-utils.c | 22 ++++++++++++++--------
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
index ec18338b42..f81b7b3303 100644
--- a/hw/cxl/cxl-mailbox-utils.c
+++ b/hw/cxl/cxl-mailbox-utils.c
@@ -1947,22 +1947,28 @@ static CXLRetCode cmd_features_set_feature(const struct 
cxl_cmd *cmd,
         data_transfer_flag ==  CXL_SET_FEATURE_FLAG_ABORT_DATA_TRANSFER) {
         memset(&set_feat_info->uuid, 0, sizeof(QemuUUID));
         if (qemu_uuid_is_equal(&hdr->uuid, &patrol_scrub_uuid)) {
-            memset(&ct3d->patrol_scrub_wr_attrs, 0, set_feat_info->data_size);
+            memset(&ct3d->patrol_scrub_wr_attrs, 0,
+                   sizeof(ct3d->patrol_scrub_wr_attrs));
         } else if (qemu_uuid_is_equal(&hdr->uuid, &ecs_uuid)) {
-            memset(&ct3d->ecs_wr_attrs, 0, set_feat_info->data_size);
+            memset(&ct3d->ecs_wr_attrs, 0, sizeof(ct3d->ecs_wr_attrs));
         } else if (qemu_uuid_is_equal(&hdr->uuid, &soft_ppr_uuid)) {
-            memset(&ct3d->soft_ppr_wr_attrs, 0, set_feat_info->data_size);
+            memset(&ct3d->soft_ppr_wr_attrs, 0,
+                   sizeof(ct3d->soft_ppr_wr_attrs));
         } else if (qemu_uuid_is_equal(&hdr->uuid, &hard_ppr_uuid)) {
-            memset(&ct3d->hard_ppr_wr_attrs, 0, set_feat_info->data_size);
+            memset(&ct3d->hard_ppr_wr_attrs, 0,
+                   sizeof(ct3d->hard_ppr_wr_attrs));
         } else if (qemu_uuid_is_equal(&hdr->uuid, &cacheline_sparing_uuid)) {
             memset(&ct3d->cacheline_sparing_wr_attrs, 0,
-                   set_feat_info->data_size);
+                   sizeof(ct3d->cacheline_sparing_wr_attrs));
         } else if (qemu_uuid_is_equal(&hdr->uuid, &row_sparing_uuid)) {
-            memset(&ct3d->row_sparing_wr_attrs, 0, set_feat_info->data_size);
+            memset(&ct3d->row_sparing_wr_attrs, 0,
+                   sizeof(ct3d->row_sparing_wr_attrs));
         } else if (qemu_uuid_is_equal(&hdr->uuid, &bank_sparing_uuid)) {
-            memset(&ct3d->bank_sparing_wr_attrs, 0, set_feat_info->data_size);
+            memset(&ct3d->bank_sparing_wr_attrs, 0,
+                   sizeof(ct3d->bank_sparing_wr_attrs));
         } else if (qemu_uuid_is_equal(&hdr->uuid, &rank_sparing_uuid)) {
-            memset(&ct3d->rank_sparing_wr_attrs, 0, set_feat_info->data_size);
+            memset(&ct3d->rank_sparing_wr_attrs, 0,
+                   sizeof(ct3d->rank_sparing_wr_attrs));
         }
         set_feat_info->data_transfer_flag = 0;
         set_feat_info->data_saved_across_reset = false;

base-commit: af06b5df2610fe5de6c02d17c17bced9e9f0d47d
-- 
2.43.0


Reply via email to