[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Stable-8.1.2 50/57] hw/display/ramfb: plug slight guest-triggerable lea
From: |
Michael Tokarev |
Subject: |
[Stable-8.1.2 50/57] hw/display/ramfb: plug slight guest-triggerable leak on mode setting |
Date: |
Fri, 6 Oct 2023 21:14:39 +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-8.1.2 00/57] Patch Round-up for stable 8.1.2, freeze on 2023-10-14, Michael Tokarev, 2023/10/06
- [Stable-8.1.2 46/57] subprojects/berkeley-testfloat-3: Update to fix a problem with compiler warnings, Michael Tokarev, 2023/10/06
- [Stable-8.1.2 47/57] target/i386: generalize operand size "ph" for use in CVTPS2PD, Michael Tokarev, 2023/10/06
- [Stable-8.1.2 48/57] target/i386: fix memory operand size for CVTPS2PD, Michael Tokarev, 2023/10/06
- [Stable-8.1.2 49/57] win32: avoid discarding the exception handler, Michael Tokarev, 2023/10/06
- [Stable-8.1.2 50/57] hw/display/ramfb: plug slight guest-triggerable leak on mode setting,
Michael Tokarev <=
- [Stable-8.1.2 51/57] chardev/char-pty: Avoid losing bytes when the other side just (re-)connected, Michael Tokarev, 2023/10/06
- [Stable-8.1.2 52/57] linux-user/hppa: Fix struct target_sigcontext layout, Michael Tokarev, 2023/10/06
- [Stable-8.1.2 53/57] vdpa net: zero vhost_vdpa iova_tree pointer at cleanup, Michael Tokarev, 2023/10/06
- [Stable-8.1.2 54/57] vdpa net: fix error message setting virtio status, Michael Tokarev, 2023/10/06
- [Stable-8.1.2 55/57] vdpa net: stop probing if cannot set features, Michael Tokarev, 2023/10/06
- [Stable-8.1.2 56/57] vdpa net: follow VirtIO initialization properly at cvq isolation probing, Michael Tokarev, 2023/10/06
- [Stable-8.1.2 57/57] amd_iommu: Fix APIC address check, Michael Tokarev, 2023/10/06