diff options
-rw-r--r-- | meta/recipes-devtools/qemu/qemu.inc | 1 | ||||
-rw-r--r-- | meta/recipes-devtools/qemu/qemu/hw-display-qxl-Pass-requested-buffer-size-to-qxl_phy.patch | 236 |
2 files changed, 237 insertions, 0 deletions
diff --git a/meta/recipes-devtools/qemu/qemu.inc b/meta/recipes-devtools/qemu/qemu.inc index 600a2af022..5466303c94 100644 --- a/meta/recipes-devtools/qemu/qemu.inc +++ b/meta/recipes-devtools/qemu/qemu.inc | |||
@@ -134,6 +134,7 @@ SRC_URI = "https://download.qemu.org/${BPN}-${PV}.tar.xz \ | |||
134 | file://CVE-2021-3409-3.patch \ | 134 | file://CVE-2021-3409-3.patch \ |
135 | file://CVE-2021-3409-4.patch \ | 135 | file://CVE-2021-3409-4.patch \ |
136 | file://CVE-2021-3409-5.patch \ | 136 | file://CVE-2021-3409-5.patch \ |
137 | file://hw-display-qxl-Pass-requested-buffer-size-to-qxl_phy.patch \ | ||
137 | " | 138 | " |
138 | UPSTREAM_CHECK_REGEX = "qemu-(?P<pver>\d+(\.\d+)+)\.tar" | 139 | UPSTREAM_CHECK_REGEX = "qemu-(?P<pver>\d+(\.\d+)+)\.tar" |
139 | 140 | ||
diff --git a/meta/recipes-devtools/qemu/qemu/hw-display-qxl-Pass-requested-buffer-size-to-qxl_phy.patch b/meta/recipes-devtools/qemu/qemu/hw-display-qxl-Pass-requested-buffer-size-to-qxl_phy.patch new file mode 100644 index 0000000000..f380be486c --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/hw-display-qxl-Pass-requested-buffer-size-to-qxl_phy.patch | |||
@@ -0,0 +1,236 @@ | |||
1 | From 5a44a01c9eca6507be45d107c27377a3e8d0ee8c Mon Sep 17 00:00:00 2001 | ||
2 | From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= <philmd@linaro.org> | ||
3 | Date: Mon, 28 Nov 2022 21:27:39 +0100 | ||
4 | Subject: [PATCH] hw/display/qxl: Pass requested buffer size to qxl_phys2virt() | ||
5 | MIME-Version: 1.0 | ||
6 | Content-Type: text/plain; charset=UTF-8 | ||
7 | Content-Transfer-Encoding: 8bit | ||
8 | |||
9 | Currently qxl_phys2virt() doesn't check for buffer overrun. | ||
10 | In order to do so in the next commit, pass the buffer size | ||
11 | as argument. | ||
12 | |||
13 | For QXLCursor in qxl_render_cursor() -> qxl_cursor() we | ||
14 | verify the size of the chunked data ahead, checking we can | ||
15 | access 'sizeof(QXLCursor) + chunk->data_size' bytes. | ||
16 | Since in the SPICE_CURSOR_TYPE_MONO case the cursor is | ||
17 | assumed to fit in one chunk, no change are required. | ||
18 | In SPICE_CURSOR_TYPE_ALPHA the ahead read is handled in | ||
19 | qxl_unpack_chunks(). | ||
20 | |||
21 | Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> | ||
22 | Acked-by: Gerd Hoffmann <kraxel@redhat.com> | ||
23 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
24 | Message-Id: <20221128202741.4945-4-philmd@linaro.org> | ||
25 | |||
26 | Backport and rebase patch to fix compile error which imported by CVE-2022-4144.patch: | ||
27 | |||
28 | /qxl.c: In function 'qxl_phys2virt': | ||
29 | | /home/hitendra/work/yocto-work/cgx-data/dunfell-3.1/x86-generic-64-5.4-3.1-cgx/project/tmp/work/i586-montavistamllib32-linux/lib32-qemu/4.2.0-r0.8/qemu-4.2.0/hw/display/qxl.c:1508:67: error: 'size' undeclared (first use in this function); did you mean 'gsize'? | ||
30 | | 1508 | if (!qxl_get_check_slot_offset(qxl, pqxl, &slot, &offset, size)) { | ||
31 | | | ^~~~ | ||
32 | | | gsize | ||
33 | |||
34 | Upstream-Status: Backport [https://github.com/qemu/qemu/commit/61c34fc && https://gitlab.com/qemu-project/qemu/-/commit/8efec0ef8bbc1e75a7ebf6e325a35806ece9b39f] | ||
35 | |||
36 | Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com> | ||
37 | --- | ||
38 | hw/display/qxl-logger.c | 22 +++++++++++++++++++--- | ||
39 | hw/display/qxl-render.c | 20 ++++++++++++++++---- | ||
40 | hw/display/qxl.c | 17 +++++++++++------ | ||
41 | hw/display/qxl.h | 3 ++- | ||
42 | 4 files changed, 48 insertions(+), 14 deletions(-) | ||
43 | |||
44 | diff --git a/hw/display/qxl-logger.c b/hw/display/qxl-logger.c | ||
45 | index 2ec6d8fa..031ddfec 100644 | ||
46 | --- a/hw/display/qxl-logger.c | ||
47 | +++ b/hw/display/qxl-logger.c | ||
48 | @@ -106,7 +106,7 @@ static int qxl_log_image(PCIQXLDevice *qxl, QXLPHYSICAL addr, int group_id) | ||
49 | QXLImage *image; | ||
50 | QXLImageDescriptor *desc; | ||
51 | |||
52 | - image = qxl_phys2virt(qxl, addr, group_id); | ||
53 | + image = qxl_phys2virt(qxl, addr, group_id, sizeof(QXLImage)); | ||
54 | if (!image) { | ||
55 | return 1; | ||
56 | } | ||
57 | @@ -216,7 +216,8 @@ int qxl_log_cmd_cursor(PCIQXLDevice *qxl, QXLCursorCmd *cmd, int group_id) | ||
58 | cmd->u.set.position.y, | ||
59 | cmd->u.set.visible ? "yes" : "no", | ||
60 | cmd->u.set.shape); | ||
61 | - cursor = qxl_phys2virt(qxl, cmd->u.set.shape, group_id); | ||
62 | + cursor = qxl_phys2virt(qxl, cmd->u.set.shape, group_id, | ||
63 | + sizeof(QXLCursor)); | ||
64 | if (!cursor) { | ||
65 | return 1; | ||
66 | } | ||
67 | @@ -238,6 +239,7 @@ int qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext) | ||
68 | { | ||
69 | bool compat = ext->flags & QXL_COMMAND_FLAG_COMPAT; | ||
70 | void *data; | ||
71 | + size_t datasz; | ||
72 | int ret; | ||
73 | |||
74 | if (!qxl->cmdlog) { | ||
75 | @@ -249,7 +251,20 @@ int qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext) | ||
76 | qxl_name(qxl_type, ext->cmd.type), | ||
77 | compat ? "(compat)" : ""); | ||
78 | |||
79 | - data = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id); | ||
80 | + switch (ext->cmd.type) { | ||
81 | + case QXL_CMD_DRAW: | ||
82 | + datasz = compat ? sizeof(QXLCompatDrawable) : sizeof(QXLDrawable); | ||
83 | + break; | ||
84 | + case QXL_CMD_SURFACE: | ||
85 | + datasz = sizeof(QXLSurfaceCmd); | ||
86 | + break; | ||
87 | + case QXL_CMD_CURSOR: | ||
88 | + datasz = sizeof(QXLCursorCmd); | ||
89 | + break; | ||
90 | + default: | ||
91 | + goto out; | ||
92 | + } | ||
93 | + data = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id, datasz); | ||
94 | if (!data) { | ||
95 | return 1; | ||
96 | } | ||
97 | @@ -271,6 +286,7 @@ int qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext) | ||
98 | qxl_log_cmd_cursor(qxl, data, ext->group_id); | ||
99 | break; | ||
100 | } | ||
101 | +out: | ||
102 | fprintf(stderr, "\n"); | ||
103 | return 0; | ||
104 | } | ||
105 | diff --git a/hw/display/qxl-render.c b/hw/display/qxl-render.c | ||
106 | index d532e157..a65a6d64 100644 | ||
107 | --- a/hw/display/qxl-render.c | ||
108 | +++ b/hw/display/qxl-render.c | ||
109 | @@ -107,7 +107,9 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl) | ||
110 | qxl->guest_primary.resized = 0; | ||
111 | qxl->guest_primary.data = qxl_phys2virt(qxl, | ||
112 | qxl->guest_primary.surface.mem, | ||
113 | - MEMSLOT_GROUP_GUEST); | ||
114 | + MEMSLOT_GROUP_GUEST, | ||
115 | + qxl->guest_primary.abs_stride | ||
116 | + * height); | ||
117 | if (!qxl->guest_primary.data) { | ||
118 | return; | ||
119 | } | ||
120 | @@ -222,7 +224,8 @@ static void qxl_unpack_chunks(void *dest, size_t size, PCIQXLDevice *qxl, | ||
121 | if (offset == size) { | ||
122 | return; | ||
123 | } | ||
124 | - chunk = qxl_phys2virt(qxl, chunk->next_chunk, group_id); | ||
125 | + chunk = qxl_phys2virt(qxl, chunk->next_chunk, group_id, | ||
126 | + sizeof(QXLDataChunk) + chunk->data_size); | ||
127 | if (!chunk) { | ||
128 | return; | ||
129 | } | ||
130 | @@ -289,7 +292,8 @@ fail: | ||
131 | /* called from spice server thread context only */ | ||
132 | int qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext) | ||
133 | { | ||
134 | - QXLCursorCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id); | ||
135 | + QXLCursorCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id, | ||
136 | + sizeof(QXLCursorCmd)); | ||
137 | QXLCursor *cursor; | ||
138 | QEMUCursor *c; | ||
139 | |||
140 | @@ -308,7 +312,15 @@ int qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext) | ||
141 | } | ||
142 | switch (cmd->type) { | ||
143 | case QXL_CURSOR_SET: | ||
144 | - cursor = qxl_phys2virt(qxl, cmd->u.set.shape, ext->group_id); | ||
145 | + /* First read the QXLCursor to get QXLDataChunk::data_size ... */ | ||
146 | + cursor = qxl_phys2virt(qxl, cmd->u.set.shape, ext->group_id, | ||
147 | + sizeof(QXLCursor)); | ||
148 | + if (!cursor) { | ||
149 | + return 1; | ||
150 | + } | ||
151 | + /* Then read including the chunked data following QXLCursor. */ | ||
152 | + cursor = qxl_phys2virt(qxl, cmd->u.set.shape, ext->group_id, | ||
153 | + sizeof(QXLCursor) + cursor->chunk.data_size); | ||
154 | if (!cursor) { | ||
155 | return 1; | ||
156 | } | ||
157 | diff --git a/hw/display/qxl.c b/hw/display/qxl.c | ||
158 | index 6bc8385b..858d3e93 100644 | ||
159 | --- a/hw/display/qxl.c | ||
160 | +++ b/hw/display/qxl.c | ||
161 | @@ -275,7 +275,8 @@ static void qxl_spice_monitors_config_async(PCIQXLDevice *qxl, int replay) | ||
162 | QXL_IO_MONITORS_CONFIG_ASYNC)); | ||
163 | } | ||
164 | |||
165 | - cfg = qxl_phys2virt(qxl, qxl->guest_monitors_config, MEMSLOT_GROUP_GUEST); | ||
166 | + cfg = qxl_phys2virt(qxl, qxl->guest_monitors_config, MEMSLOT_GROUP_GUEST, | ||
167 | + sizeof(QXLMonitorsConfig)); | ||
168 | if (cfg != NULL && cfg->count == 1) { | ||
169 | qxl->guest_primary.resized = 1; | ||
170 | qxl->guest_head0_width = cfg->heads[0].width; | ||
171 | @@ -460,7 +461,8 @@ static int qxl_track_command(PCIQXLDevice *qxl, struct QXLCommandExt *ext) | ||
172 | switch (le32_to_cpu(ext->cmd.type)) { | ||
173 | case QXL_CMD_SURFACE: | ||
174 | { | ||
175 | - QXLSurfaceCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id); | ||
176 | + QXLSurfaceCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id, | ||
177 | + sizeof(QXLSurfaceCmd)); | ||
178 | |||
179 | if (!cmd) { | ||
180 | return 1; | ||
181 | @@ -494,7 +496,8 @@ static int qxl_track_command(PCIQXLDevice *qxl, struct QXLCommandExt *ext) | ||
182 | } | ||
183 | case QXL_CMD_CURSOR: | ||
184 | { | ||
185 | - QXLCursorCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id); | ||
186 | + QXLCursorCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id, | ||
187 | + sizeof(QXLCursorCmd)); | ||
188 | |||
189 | if (!cmd) { | ||
190 | return 1; | ||
191 | @@ -674,7 +677,8 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext) | ||
192 | * | ||
193 | * https://cgit.freedesktop.org/spice/win32/qxl-wddm-dod/commit/?id=f6e099db39e7d0787f294d5fd0dce328b5210faa | ||
194 | */ | ||
195 | - void *msg = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id); | ||
196 | + void *msg = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id, | ||
197 | + sizeof(QXLCommandRing)); | ||
198 | if (msg != NULL && ( | ||
199 | msg < (void *)qxl->vga.vram_ptr || | ||
200 | msg > ((void *)qxl->vga.vram_ptr + qxl->vga.vram_size))) { | ||
201 | @@ -1494,7 +1498,8 @@ static bool qxl_get_check_slot_offset(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, | ||
202 | } | ||
203 | |||
204 | /* can be also called from spice server thread context */ | ||
205 | -void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id) | ||
206 | +void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id, | ||
207 | + size_t size) | ||
208 | { | ||
209 | uint64_t offset; | ||
210 | uint32_t slot; | ||
211 | @@ -1994,7 +1999,7 @@ static void qxl_dirty_surfaces(PCIQXLDevice *qxl) | ||
212 | } | ||
213 | |||
214 | cmd = qxl_phys2virt(qxl, qxl->guest_surfaces.cmds[i], | ||
215 | - MEMSLOT_GROUP_GUEST); | ||
216 | + MEMSLOT_GROUP_GUEST, sizeof(QXLSurfaceCmd)); | ||
217 | assert(cmd); | ||
218 | assert(cmd->type == QXL_SURFACE_CMD_CREATE); | ||
219 | qxl_dirty_one_surface(qxl, cmd->u.surface_create.data, | ||
220 | diff --git a/hw/display/qxl.h b/hw/display/qxl.h | ||
221 | index 80eb0d26..fcfd133a 100644 | ||
222 | --- a/hw/display/qxl.h | ||
223 | +++ b/hw/display/qxl.h | ||
224 | @@ -147,7 +147,8 @@ typedef struct PCIQXLDevice { | ||
225 | #define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V12 | ||
226 | |||
227 | /* qxl.c */ | ||
228 | -void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id); | ||
229 | +void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id, | ||
230 | + size_t size); | ||
231 | void qxl_set_guest_bug(PCIQXLDevice *qxl, const char *msg, ...) | ||
232 | GCC_FMT_ATTR(2, 3); | ||
233 | |||
234 | -- | ||
235 | 2.25.1 | ||
236 | |||