qemu/hw
Laszlo Ersek e0288a7784 hw/display/ramfb: plug slight guest-triggerable leak on mode setting
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 (995b30179b,
"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: 995b30179b
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>
2023-10-03 15:40:09 +04:00
..
9pfs fsdev: Use ThrottleDirection instread of bool is_write 2023-08-29 10:49:24 +02:00
acpi hw/acpi: changes towards enabling -Wshadow=local 2023-09-29 10:07:18 +02:00
adc meson: Replace softmmu_ss -> system_ss 2023-06-20 10:01:30 +02:00
alpha hw/alpha: Use MachineClass->default_nic in the alpha machine 2023-05-26 09:10:49 +02:00
arm aspeed: Clean up local variable shadowing 2023-09-29 10:07:19 +02:00
audio hw/audio/lm4549: Add errp error reporting to init function 2023-09-22 16:30:07 +02:00
avr
block block: Clean up local variable shadowing 2023-09-29 08:13:57 +02:00
char hw/other: spelling fixes 2023-09-21 11:31:16 +03:00
core hw/core: remove needless includes 2023-10-03 15:10:12 +04:00
cpu hw/other: spelling fixes 2023-09-21 11:31:16 +03:00
cris
cxl hw/cxl: Fix CFMW config memory leak 2023-09-21 11:31:18 +03:00
display hw/display/ramfb: plug slight guest-triggerable leak on mode setting 2023-10-03 15:40:09 +04:00
dma hw/other: spelling fixes 2023-09-21 11:31:16 +03:00
gpio hw/gpio/nrf51: implement DETECT signal 2023-08-22 17:30:59 +01:00
hppa target/hppa: Report and clear BTLBs via fw_cfg at startup 2023-09-15 17:34:38 +02:00
hyperv win32: replace closesocket() with close() wrapper 2023-03-13 15:39:31 +04:00
i2c aspeed/i2c: Clean up local variable shadowing 2023-09-29 10:07:19 +02:00
i386 hw/pc: remove needless includes 2023-10-03 15:40:09 +04:00
ide hw/ide/ahci: fix broken SError handling 2023-09-06 22:48:04 -04:00
input * add host ticks function for RISC-V 2023-09-25 10:09:38 -04:00
intc hw/intc/arm_gicv3_its: Avoid shadowing variable in do_process_its_cmd() 2023-09-29 10:07:18 +02:00
ipack meson: Replace softmmu_ss -> system_ss 2023-06-20 10:01:30 +02:00
ipmi hw/other: spelling fixes 2023-09-21 11:31:16 +03:00
isa hw/isa/vt82c686: Remove via_isa_set_irq() 2023-07-11 00:11:25 +02:00
loongarch hw/loongarch: Fix ACPI processor id off-by-one error 2023-08-24 16:58:16 +08:00
m68k hw/m68k: Clean up local variable shadowing 2023-09-29 10:07:15 +02:00
mem hw/mem/cxl_type3: Add missing copyright and license notice 2023-09-21 11:31:18 +03:00
microblaze hw/microblaze: Clean up local variable shadowing 2023-09-29 10:07:16 +02:00
mips hw/mips/jazz: Simplify the NIC setup code 2023-09-25 07:58:14 +02:00
misc aspeed/i3c: Rename variable shadowing a local 2023-09-29 10:07:19 +02:00
net hw/net: spelling fixes 2023-09-20 07:54:34 +03:00
nios2 hw/nios2: Clean up local variable shadowing 2023-09-29 10:07:16 +02:00
nubus trace-events: Fix the name of the tracing.rst file 2023-09-08 13:08:51 +03:00
nvme hw/nvme: Clean up local variable shadowing in nvme_ns_init() 2023-09-29 10:07:20 +02:00
nvram hw/other: spelling fixes 2023-09-21 11:31:16 +03:00
openrisc *: Add missing includes of qemu/error-report.h 2023-03-22 15:06:57 +00:00
pci hw/pci: spelling fixes 2023-09-20 07:54:34 +03:00
pci-bridge hw/pci-bridge/cxl_upstream: Fix bandwidth entry base unit for SSLBIS 2023-09-21 11:31:18 +03:00
pci-host hw/pci: spelling fixes 2023-09-20 07:54:34 +03:00
pcmcia meson: Replace softmmu_ss -> system_ss 2023-06-20 10:01:30 +02:00
ppc spapr/drc: Clean up local variable shadowing in prop_get_fdt() 2023-09-29 10:07:18 +02:00
rdma meson: Replace softmmu_ss -> system_ss 2023-06-20 10:01:30 +02:00
remote exec/memory: Add symbol for memory listener priority for device backend 2023-06-28 14:27:59 +02:00
riscv hw/riscv: opentitan: Fixup local variables shadowing 2023-09-29 10:07:20 +02:00
rtc hw/other: spelling fixes 2023-09-21 11:31:16 +03:00
rx hw/other: spelling fixes 2023-09-21 11:31:16 +03:00
s390x s390x: do a subsystem reset before the unprotect on reboot 2023-09-12 11:13:33 +02:00
scsi mptsas: avoid shadowed local variables 2023-09-25 18:25:03 +02:00
sd aspeed queue: 2023-09-06 11:14:55 -04:00
sensor hw/i2c: spelling fixes 2023-08-31 19:47:43 +02:00
sh4 hw/other: spelling fixes 2023-09-21 11:31:16 +03:00
smbios hw/acpi: changes towards enabling -Wshadow=local 2023-09-29 10:07:18 +02:00
sparc other architectures: spelling fixes 2023-07-25 17:14:07 +03:00
sparc64 hw/pci/pci: Remove multifunction parameter from pci_new_multifunction() 2023-07-10 18:59:32 -04:00
ssi hw/other: spelling fixes 2023-09-21 11:31:16 +03:00
timer aspeed/timer: Clean up local variable shadowing 2023-09-29 10:07:19 +02:00
tpm hw/tpm: spelling fixes 2023-09-20 07:54:34 +03:00
tricore hw/tricore: Log failing test in testdevice 2023-09-29 08:28:02 +02:00
ufs hw/ufs: Support for UFS logical unit 2023-09-07 14:01:29 -04:00
usb hw/usb/hcd-xhci: Avoid variable-length array in xhci_get_port_bandwidth() 2023-08-31 19:47:43 +02:00
vfio spapr: Remove support for NVIDIA V100 GPU with NVLink2 2023-09-18 07:25:28 -03:00
virtio hw/other: spelling fixes 2023-09-21 11:31:16 +03:00
watchdog meson: Replace softmmu_ss -> system_ss 2023-06-20 10:01:30 +02:00
xen xen: spelling fix 2023-09-08 13:08:52 +03:00
xenpv hw/xenpv: Initialize Xen backend operations 2023-03-24 14:52:14 +00:00
xtensa trivial: Simplify the spots that use TARGET_BIG_ENDIAN as a numeric value 2023-09-08 13:08:52 +03:00
Kconfig hw/ufs: Initial commit for emulated Universal-Flash-Storage 2023-09-07 14:01:29 -04:00
meson.build hw/ufs: Initial commit for emulated Universal-Flash-Storage 2023-09-07 14:01:29 -04:00