Line 0
Link Here
|
|
|
1 |
From 510952d4c33ee69574167ce30829b21c815a165b Mon Sep 17 00:00:00 2001 |
2 |
From: Kevin Wolf <kwolf@redhat.com> |
3 |
Date: Wed, 3 Jun 2015 14:13:31 +0200 |
4 |
Subject: [PATCH 1/2] ide: Check array bounds before writing to io_buffer |
5 |
(CVE-2015-5154) |
6 |
|
7 |
If the end_transfer_func of a command is called because enough data has |
8 |
been read or written for the current PIO transfer, and it fails to |
9 |
correctly call the command completion functions, the DRQ bit in the |
10 |
status register and s->end_transfer_func may remain set. This allows the |
11 |
guest to access further bytes in s->io_buffer beyond s->data_end, and |
12 |
eventually overflowing the io_buffer. |
13 |
|
14 |
One case where this currently happens is emulation of the ATAPI command |
15 |
START STOP UNIT. |
16 |
|
17 |
This patch fixes the problem by adding explicit array bounds checks |
18 |
before accessing the buffer instead of relying on end_transfer_func to |
19 |
function correctly. |
20 |
|
21 |
Cc: qemu-stable@nongnu.org |
22 |
Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
23 |
--- |
24 |
hw/ide.c | 16 ++++++++++++++++ |
25 |
1 file changed, 16 insertions(+) |
26 |
|
27 |
diff --git a/hw/ide.c b/hw/ide.c |
28 |
index 791666b..211ec88 100644 |
29 |
--- a/hw/ide.c |
30 |
+++ b/hw/ide.c |
31 |
@@ -3002,6 +3002,10 @@ static void ide_data_writew(void *opaque, uint32_t addr, uint32_t val) |
32 |
buffered_pio_write(s, addr, 2); |
33 |
|
34 |
p = s->data_ptr; |
35 |
+ if (p + 2 > s->data_end) { |
36 |
+ return; |
37 |
+ } |
38 |
+ |
39 |
*(uint16_t *)p = le16_to_cpu(val); |
40 |
p += 2; |
41 |
s->data_ptr = p; |
42 |
@@ -3021,6 +3025,10 @@ static uint32_t ide_data_readw(void *opaque, uint32_t addr) |
43 |
buffered_pio_read(s, addr, 2); |
44 |
|
45 |
p = s->data_ptr; |
46 |
+ if (p + 2 > s->data_end) { |
47 |
+ return 0; |
48 |
+ } |
49 |
+ |
50 |
ret = cpu_to_le16(*(uint16_t *)p); |
51 |
p += 2; |
52 |
s->data_ptr = p; |
53 |
@@ -3040,6 +3048,10 @@ static void ide_data_writel(void *opaque, uint32_t addr, uint32_t val) |
54 |
buffered_pio_write(s, addr, 4); |
55 |
|
56 |
p = s->data_ptr; |
57 |
+ if (p + 4 > s->data_end) { |
58 |
+ return; |
59 |
+ } |
60 |
+ |
61 |
*(uint32_t *)p = le32_to_cpu(val); |
62 |
p += 4; |
63 |
s->data_ptr = p; |
64 |
@@ -3059,6 +3071,10 @@ static uint32_t ide_data_readl(void *opaque, uint32_t addr) |
65 |
buffered_pio_read(s, addr, 4); |
66 |
|
67 |
p = s->data_ptr; |
68 |
+ if (p + 4 > s->data_end) { |
69 |
+ return 0; |
70 |
+ } |
71 |
+ |
72 |
ret = cpu_to_le32(*(uint32_t *)p); |
73 |
p += 4; |
74 |
s->data_ptr = p; |
75 |
-- |
76 |
2.1.4 |
77 |
|