[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Stable-7.2.7 27/62] hw/display/ramfb: plug slight guest-triggerable lea
From: |
Michael Tokarev |
Subject: |
[Stable-7.2.7 27/62] hw/display/ramfb: plug slight guest-triggerable leak on mode setting |
Date: |
Thu, 9 Nov 2023 16:58:55 +0300 |
From: Laszlo Ersek <lersek@redhat.com>
The fw_cfg DMA write callback in ramfb prepares a new display surface in
QEMU; this new surface is put to use ("swapped in") upon the next display
update. At that time, the old surface (if any) is released.
If the guest triggers the fw_cfg DMA write callback at least twice between
two adjacent display updates, then the second callback (and further such
callbacks) will leak the previously prepared (but not yet swapped in)
display surface.
The issue can be shown by:
(1) starting QEMU with "-trace displaysurface_free", and
(2) running the following program in the guest UEFI shell:
> #include <Library/ShellCEntryLib.h> // ShellAppMain()
> #include <Library/UefiBootServicesTableLib.h> // gBS
> #include <Protocol/GraphicsOutput.h> // EFI_GRAPHICS_OUTPUT_PROTOCOL
>
> INTN
> EFIAPI
> ShellAppMain (
> IN UINTN Argc,
> IN CHAR16 **Argv
> )
> {
> EFI_STATUS Status;
> VOID *Interface;
> EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop;
> UINT32 Mode;
>
> Status = gBS->LocateProtocol (
> &gEfiGraphicsOutputProtocolGuid,
> NULL,
> &Interface
> );
> if (EFI_ERROR (Status)) {
> return 1;
> }
>
> Gop = Interface;
>
> Mode = 1;
> for ( ; ;) {
> Status = Gop->SetMode (Gop, Mode);
> if (EFI_ERROR (Status)) {
> break;
> }
>
> Mode = 1 - Mode;
> }
>
> return 1;
> }
The symptom is then that:
- only one trace message appears periodically,
- the time between adjacent messages keeps increasing -- implying that
some list structure (containing the leaked resources) keeps growing,
- the "surface" pointer is ever different.
> 18566@1695127471.449586:displaysurface_free surface=0x7f2fcc09a7c0
> 18566@1695127471.529559:displaysurface_free surface=0x7f2fcc9dac10
> 18566@1695127471.659812:displaysurface_free surface=0x7f2fcc441dd0
> 18566@1695127471.839669:displaysurface_free surface=0x7f2fcc0363d0
> 18566@1695127472.069674:displaysurface_free surface=0x7f2fcc413a80
> 18566@1695127472.349580:displaysurface_free surface=0x7f2fcc09cd00
> 18566@1695127472.679783:displaysurface_free surface=0x7f2fcc1395f0
> 18566@1695127473.059848:displaysurface_free surface=0x7f2fcc1cae50
> 18566@1695127473.489724:displaysurface_free surface=0x7f2fcc42fc50
> 18566@1695127473.969791:displaysurface_free surface=0x7f2fcc45dcc0
> 18566@1695127474.499708:displaysurface_free surface=0x7f2fcc70b9d0
> 18566@1695127475.079769:displaysurface_free surface=0x7f2fcc82acc0
> 18566@1695127475.709941:displaysurface_free surface=0x7f2fcc369c00
> 18566@1695127476.389619:displaysurface_free surface=0x7f2fcc32b910
> 18566@1695127477.119772:displaysurface_free surface=0x7f2fcc0d5a20
> 18566@1695127477.899517:displaysurface_free surface=0x7f2fcc086c40
> 18566@1695127478.729962:displaysurface_free surface=0x7f2fccc72020
> 18566@1695127479.609839:displaysurface_free surface=0x7f2fcc185160
> 18566@1695127480.539688:displaysurface_free surface=0x7f2fcc23a7e0
> 18566@1695127481.519759:displaysurface_free surface=0x7f2fcc3ec870
> 18566@1695127482.549930:displaysurface_free surface=0x7f2fcc634960
> 18566@1695127483.629661:displaysurface_free surface=0x7f2fcc26b140
> 18566@1695127484.759987:displaysurface_free surface=0x7f2fcc321700
> 18566@1695127485.940289:displaysurface_free surface=0x7f2fccaad100
We figured this wasn't a CVE-worthy problem, as only small amounts of
memory were leaked (the framebuffer itself is mapped from guest RAM, QEMU
only allocates administrative structures), plus libvirt restricts QEMU
memory footprint anyway, thus the guest can only DoS itself.
Plug the leak, by releasing the last prepared (not yet swapped in) display
surface, if any, in the fw_cfg DMA write callback.
Regarding the "reproducer", with the fix in place, the log is flooded with
trace messages (one per fw_cfg write), *and* the trace message alternates
between just two "surface" pointer values (i.e., nothing is leaked, the
allocator flip-flops between two objects in effect).
This issue appears to date back to the introducion of ramfb (995b30179bdc,
"hw/display: add ramfb, a simple boot framebuffer living in guest ram",
2018-06-18).
Cc: Gerd Hoffmann <kraxel@redhat.com> (maintainer:ramfb)
Cc: qemu-stable@nongnu.org
Fixes: 995b30179bdc
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20230919131955.27223-1-lersek@redhat.com>
(cherry picked from commit e0288a778473ebd35eac6cc1924faca7d477d241)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/hw/display/ramfb.c b/hw/display/ramfb.c
index 79b9754a58..c2b002d534 100644
--- a/hw/display/ramfb.c
+++ b/hw/display/ramfb.c
@@ -97,6 +97,7 @@ static void ramfb_fw_cfg_write(void *dev, off_t offset,
size_t len)
s->width = width;
s->height = height;
+ qemu_free_displaysurface(s->ds);
s->ds = surface;
}
--
2.39.2
- [Stable-7.2.7 14/62] ui/vnc: fix debug output for invalid audio message, (continued)
- [Stable-7.2.7 14/62] ui/vnc: fix debug output for invalid audio message, Michael Tokarev, 2023/11/09
- [Stable-7.2.7 16/62] optionrom: Remove build-id section, Michael Tokarev, 2023/11/09
- [Stable-7.2.7 21/62] tests/tcg/i386: correct mask for VPERM2F128/VPERM2I128, Michael Tokarev, 2023/11/09
- [Stable-7.2.7 19/62] scsi-disk: ensure that FORMAT UNIT commands are terminated, Michael Tokarev, 2023/11/09
- [Stable-7.2.7 18/62] esp: restrict non-DMA transfer length to that of available data, Michael Tokarev, 2023/11/09
- [Stable-7.2.7 20/62] target/i386: fix operand size of unary SSE operations, Michael Tokarev, 2023/11/09
- [Stable-7.2.7 24/62] target/i386: Fix exception classes for MOVNTPS/MOVNTPD., Michael Tokarev, 2023/11/09
- [Stable-7.2.7 23/62] target/i386: Fix exception classes for SSE/AVX instructions., Michael Tokarev, 2023/11/09
- [Stable-7.2.7 26/62] target/i386: fix memory operand size for CVTPS2PD, Michael Tokarev, 2023/11/09
- [Stable-7.2.7 17/62] esp: use correct type for esp_dma_enable() in sysbus_esp_gpio_demux(), Michael Tokarev, 2023/11/09
- [Stable-7.2.7 27/62] hw/display/ramfb: plug slight guest-triggerable leak on mode setting,
Michael Tokarev <=
- [Stable-7.2.7 25/62] target/i386: generalize operand size "ph" for use in CVTPS2PD, Michael Tokarev, 2023/11/09
- [Stable-7.2.7 28/62] chardev/char-pty: Avoid losing bytes when the other side just (re-)connected, Michael Tokarev, 2023/11/09
- [Stable-7.2.7 30/62] amd_iommu: Fix APIC address check, Michael Tokarev, 2023/11/09
- [Stable-7.2.7 29/62] linux-user/hppa: Fix struct target_sigcontext layout, Michael Tokarev, 2023/11/09
- [Stable-7.2.7 31/62] migration/qmp: Fix crash on setting tls-authz with null, Michael Tokarev, 2023/11/09
- [Stable-7.2.7 32/62] hw/audio/es1370: reset current sample counter, Michael Tokarev, 2023/11/09
- [Stable-7.2.7 33/62] disas/riscv: Fix the typo of inverted order of pmpaddr13 and pmpaddr14, Michael Tokarev, 2023/11/09
- [Stable-7.2.7 34/62] hw/pvrdma: Protect against buggy or malicious guest driver, Michael Tokarev, 2023/11/09
- [Stable-7.2.7 36/62] linux-user/mips: fix abort on integer overflow, Michael Tokarev, 2023/11/09
- [Stable-7.2.7 38/62] lasips2: LASI PS/2 devices are not user-createable, Michael Tokarev, 2023/11/09