a056f39
From: Prasad J Pandit <pjp@fedoraproject.org>
a056f39
Date: Thu, 16 Nov 2017 13:21:55 +0530
a056f39
Subject: [PATCH] ps2: check PS2Queue pointers in post_load routine
a056f39
a056f39
During Qemu guest migration, a destination process invokes ps2
a056f39
post_load function. In that, if 'rptr' and 'count' values were
a056f39
invalid, it could lead to OOB access or infinite loop issue.
a056f39
Add check to avoid it.
a056f39
a056f39
Reported-by: Cyrille Chatras <cyrille.chatras@orange.com>
a056f39
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
a056f39
Message-id: 20171116075155.22378-1-ppandit@redhat.com
a056f39
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
a056f39
(cherry picked from commit 802cbcb73002b92e6ddc8464d39b668a71b78d74)
a056f39
---
a056f39
 hw/input/ps2.c | 21 +++++++++------------
a056f39
 1 file changed, 9 insertions(+), 12 deletions(-)
a056f39
a056f39
diff --git a/hw/input/ps2.c b/hw/input/ps2.c
a056f39
index 77906d5f46..99d9bb06f6 100644
a056f39
--- a/hw/input/ps2.c
a056f39
+++ b/hw/input/ps2.c
a056f39
@@ -1091,24 +1091,21 @@ static void ps2_common_reset(PS2State *s)
a056f39
 static void ps2_common_post_load(PS2State *s)
a056f39
 {
a056f39
     PS2Queue *q = &s->queue;
a056f39
-    int size;
a056f39
-    int i;
a056f39
-    int tmp_data[PS2_QUEUE_SIZE];
a056f39
+    uint8_t i, size;
a056f39
+    uint8_t tmp_data[PS2_QUEUE_SIZE];
a056f39
 
a056f39
     /* set the useful data buffer queue size, < PS2_QUEUE_SIZE */
a056f39
-    size = q->count > PS2_QUEUE_SIZE ? 0 : q->count;
a056f39
+    size = (q->count < 0 || q->count > PS2_QUEUE_SIZE) ? 0 : q->count;
a056f39
 
a056f39
     /* move the queue elements to the start of data array */
a056f39
-    if (size > 0) {
a056f39
-        for (i = 0; i < size; i++) {
a056f39
-            /* move the queue elements to the temporary buffer */
a056f39
-            tmp_data[i] = q->data[q->rptr];
a056f39
-            if (++q->rptr == 256) {
a056f39
-                q->rptr = 0;
a056f39
-            }
a056f39
+    for (i = 0; i < size; i++) {
a056f39
+        if (q->rptr < 0 || q->rptr >= sizeof(q->data)) {
a056f39
+            q->rptr = 0;
a056f39
         }
a056f39
-        memcpy(q->data, tmp_data, size);
a056f39
+        tmp_data[i] = q->data[q->rptr++];
a056f39
     }
a056f39
+    memcpy(q->data, tmp_data, size);
a056f39
+
a056f39
     /* reset rptr/wptr/count */
a056f39
     q->rptr = 0;
a056f39
     q->wptr = size;