Re: [PATCH] hw/display/vga: fix panning_buf OOB after text/graphics switch
Marc-André Lureau <[email protected]> Mon, 3 Aug 2026 14:47:05 +0400
| Newsgroups | org.nongnu.qemu-devel |
|---|---|
| Message-ID | <CAJ+F1C+w5n9V_cc0v=dK-4OG+ZS4GB3km6vOiY5kir4iPCNSgw@mail.gmail.com> |
On Tue, Jul 28, 2026 at 7:16=E2=80=AFPM <[email protected]> wrote= : > > From: Marc-Andr=C3=A9 Lureau <[email protected]> > > The fields last_width and last_height serve two purposes: the text > renderer counts in characters, the graphics renderer in pixels. > panning_buf reallocation is guarded by geometry-change check, so the > unit mismatch can trick it into thinking nothing changed when the > resolution actually grew. > > A guest can trigger this by switching graphics -> text -> graphics: > > 1. Enter graphics mode with a small width (CR01=3D0x00, 8 pixels). > The predicate fires and panning_buf is allocated for that width. > > 2. Switch to text mode with a large width (CR01=3D0xFF, 256 chars). > The text renderer stores 256 into last_width. The text path > never touches panning_buf. > > 3. Switch back to graphics with a width that happens to equal 256 > in pixels (CR01=3D0x1F, 32*8 =3D 256). The predicate sees > 256 =3D=3D 256 and skips the realloc. With horizontal pel panning > enabled, vga_draw_line4() then writes a full 256-pixel scanline > into the buffer still sized for 8 pixels -- a 960-byte heap > overflow on every scanline, every refresh. > > Fix it by reallocating unconditionally panning_buf on > vga_draw_graphic(). > > Fixes: CVE-2026-17516 > Fixes: 973a724eb006 ("vga: implement horizontal pel panning in graphics m= odes") > Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4085 > Cc: Paolo Bonzini <[email protected]> > Signed-off-by: Warisjeet Singh <[email protected]> > [ Marc- Andr=C3=A9 - drop realloc() resize condition & commit message ] > Signed-off-by: Marc-Andr=C3=A9 Lureau <[email protected]> ping > --- > hw/display/vga.c | 7 ++++--- > 1 file changed, 4 insertions(+), 3 deletions(-) > > diff --git a/hw/display/vga.c b/hw/display/vga.c > index abe3f8e07758..da0c331486eb 100644 > --- a/hw/display/vga.c > +++ b/hw/display/vga.c > @@ -1647,11 +1647,12 @@ static void vga_draw_graphic(VGACommonState *s, i= nt full_update) > s->last_line_offset =3D s->params.line_offset; > s->last_depth =3D depth; > s->last_byteswap =3D byteswap; > - /* 16 extra pixels are needed for double-width planar modes. */ > - s->panning_buf =3D g_realloc(s->panning_buf, > - (disp_width + 16) * sizeof(uint32_t))= ; > full_update =3D 1; > } > + > + /* 16 extra pixels are needed for double-width planar modes. */ > + s->panning_buf =3D g_realloc(s->panning_buf, > + (disp_width + 16) * sizeof(uint32_t)); > if (surface_data(surface) !=3D s->vram_ptr + (s->params.start_addr *= 4) > && !surface_is_allocated(surface)) { > /* base address changed (page flip) -> shared display surfaces > -- > 2.55.0 > >