blob: d2bdf6b01733f82115b03858648a90443c2ca277 [file] [log] [blame]
Brad Bishopd5ae7d92018-06-14 09:52:03 -07001From 065061dca34fa5b91be6dce9a87a8755d8826c78 Mon Sep 17 00:00:00 2001
Brad Bishop316dfdd2018-06-25 12:45:53 -04002From: Prasad J Pandit <pjp@fedoraproject.org>
3Date: Thu, 16 Nov 2017 13:21:55 +0530
4Subject: [PATCH] ps2: check PS2Queue pointers in post_load routine
5
6During Qemu guest migration, a destination process invokes ps2
7post_load function. In that, if 'rptr' and 'count' values were
8invalid, it could lead to OOB access or infinite loop issue.
9Add check to avoid it.
10
11Reported-by: Cyrille Chatras <cyrille.chatras@orange.com>
12Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
13Message-id: 20171116075155.22378-1-ppandit@redhat.com
14Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
15
16CVE: CVE-2017-16845
17Upstream-Status: Backport
18Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
19---
20 hw/input/ps2.c | 21 +++++++++------------
21 1 file changed, 9 insertions(+), 12 deletions(-)
22
23diff --git a/hw/input/ps2.c b/hw/input/ps2.c
24index f388a23..de171a2 100644
25--- a/hw/input/ps2.c
26+++ b/hw/input/ps2.c
27@@ -1225,24 +1225,21 @@ static void ps2_common_reset(PS2State *s)
28 static void ps2_common_post_load(PS2State *s)
29 {
30 PS2Queue *q = &s->queue;
31- int size;
32- int i;
33- int tmp_data[PS2_QUEUE_SIZE];
34+ uint8_t i, size;
35+ uint8_t tmp_data[PS2_QUEUE_SIZE];
36
37 /* set the useful data buffer queue size, < PS2_QUEUE_SIZE */
38- size = q->count > PS2_QUEUE_SIZE ? 0 : q->count;
39+ size = (q->count < 0 || q->count > PS2_QUEUE_SIZE) ? 0 : q->count;
40
41 /* move the queue elements to the start of data array */
42- if (size > 0) {
43- for (i = 0; i < size; i++) {
44- /* move the queue elements to the temporary buffer */
45- tmp_data[i] = q->data[q->rptr];
46- if (++q->rptr == 256) {
47- q->rptr = 0;
48- }
49+ for (i = 0; i < size; i++) {
50+ if (q->rptr < 0 || q->rptr >= sizeof(q->data)) {
51+ q->rptr = 0;
52 }
53- memcpy(q->data, tmp_data, size);
54+ tmp_data[i] = q->data[q->rptr++];
55 }
56+ memcpy(q->data, tmp_data, size);
57+
58 /* reset rptr/wptr/count */
59 q->rptr = 0;
60 q->wptr = size;