devaddr is used in 1 << d->devaddr bit shifts in do_adb_request()
and adb_poll(). A crafted migration stream could set it to a value
outside [0, MAX_ADB_DEVICES), causing undefined behavior.

Add a post_load validator to reject out-of-range values.

Reported-by: Pavee Hui <[email protected]>
Fixes: 0606b2883038 ("adb: introduce realize/unrealize and VMStateDescription 
for ADB bus")
Signed-off-by: Marc-André Lureau <[email protected]>
---
 hw/input/adb.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/hw/input/adb.c b/hw/input/adb.c
index 7c67d2baa663..b6319fa31535 100644
--- a/hw/input/adb.c
+++ b/hw/input/adb.c
@@ -280,10 +280,21 @@ static const TypeInfo adb_bus_type_info = {
     .class_init = adb_bus_class_init,
 };
 
+static int adb_device_post_load(void *opaque, int version_id)
+{
+    ADBDevice *d = opaque;
+
+    if (d->devaddr < 0 || d->devaddr >= MAX_ADB_DEVICES) {
+        return -EINVAL;
+    }
+    return 0;
+}
+
 const VMStateDescription vmstate_adb_device = {
     .name = "adb_device",
     .version_id = 0,
     .minimum_version_id = 0,
+    .post_load = adb_device_post_load,
     .fields = (const VMStateField[]) {
         VMSTATE_INT32(devaddr, ADBDevice),
         VMSTATE_INT32(handler, ADBDevice),

-- 
2.56.0.rc0.29.g47ce80527c56


Reply via email to