@samitouri / QOSamiQemu / commits / a5f8d33682

hw/display/exynos4210_fimd: Clamp windows to screen size

In exynos4210_fimd_update(), we iterate through the enabled windows, blitting them to the screen. We assume here that the guest has not programmed the window's coordinates to be outside the overall LCD screen resulation, but we never check this. This can result in the guest being able to cause us to access outside our allocated framebuffer backing memory. Since all the coordinates here are unsigned, they can't be off the left/top side of the screen, only the bottom/right. If the top left corner of the window is out of bounds, the whole window is invisible and we can skip it. If the bottom right corner is out of bounds, we clamp it to the screen size so that we only draw the visible part. Cc: qemu-stable@nongnu.org Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3795 Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-id: 20260706173324.804340-4-peter.maydell@linaro.org

Peter Maydell committed Jul 6, 2026 at 18:33 UTC a5f8d33682be079e6b9b41f07b2eb517121b3b46
1 file changed +15 -3
hw/display/exynos4210_fimd.c
+15 -3
@@ -1237,7 +1237,7 @@ static bool exynos4210_fimd_update(void *opaque)
1237 bool blend = false;
1238 uint8_t *host_fb_addr;
1239 bool is_dirty = false;
1240 - uint32_t global_width;
1240 + uint32_t global_width, global_height;
1241 uint32_t window_width;
1242
1243 if (!s || !s->console || !s->enabled ||
@@ -1246,16 +1246,28 @@ static bool exynos4210_fimd_update(void *opaque)
1246 }
1247
1248 global_width = exynos4210_fimd_global_width(s);
1249 + global_height = exynos4210_fimd_global_height(s);
1250 exynos4210_update_resolution(s);
1251 surface = qemu_console_surface(s->console);
1252
1253 for (i = 0; i < NUM_OF_WINDOWS; i++) {
1254 w = &s->window[i];
1255 if ((w->wincon & FIMD_WINCON_ENWIN) && w->host_fb_addr) {
1255 - scrn_height = w->rightbot_y - w->lefttop_y + 1;
1256 + uint32_t rightbot_x, rightbot_y;
1257 +
1258 + if (w->lefttop_x >= global_width ||
1259 + w->lefttop_y >= global_height) {
1260 + /* Guest has put the window entirely offscreen: ignore */
1261 + continue;
1262 + }
1263 +
1264 + /* Clamp right corner coords to be within the screen */
1265 + rightbot_x = MIN(w->rightbot_x, global_width - 1);
1266 + rightbot_y = MIN(w->rightbot_y, global_height - 1);
1267 + scrn_height = rightbot_y - w->lefttop_y + 1;
1268 scrn_width = w->virtpage_width;
1269 /* Number of bytes to actually draw */
1258 - window_width = w->rightbot_x - w->lefttop_x + 1;
1270 + window_width = rightbot_x - w->lefttop_x + 1;
1271 /* Total width of virtual screen page in bytes */
1272 inc_size = scrn_width + w->virtpage_offsize;
1273 host_fb_addr = w->host_fb_addr;