* [PATCH v4] drm/qxl: fix use-after-free in qxl_irq_handler on PCI
@ 2026-09-27 10:10 Óscar Megía López
2026-09-27 10:19 ` sashiko-bot
0 siblings, 1 reply; 2+ messages in thread
From: Óscar Megía López @ 2026-09-27 10:10 UTC (permalink / raw)
To: Dave Airlie, Gerd Hoffmann
Cc: Óscar Megía López, virtualization, spice-devel,
linux-kernel, linux-kernel-mentees
Executing below script:
i=0;\
while [ 1 -eq 1 ]; do\
i=$((i+1)); echo 0000:00:01.0 > /sys/bus/pci/drivers/qxl/unbind;\
if (($i%1000==0)); then\
echo loops=$i; free;\
grep nr_free_pages /proc/vmstat;\
grep -E "VmallocUsed|Slab|Reclaimable|SUnreclaim" /proc/meminfo;\
sync; echo 3 > /proc/sys/vm/drop_caches;\
echo 1 > /proc/sys/vm/compact_memory;\
udevadm settle;\
free;\
grep nr_free_pages /proc/vmstat;\
grep -E "VmallocUsed|Slab|Reclaimable|SUnreclaim" /proc/meminfo;\
uptime;\
fi;\
echo 0000:00:01.0 > /sys/bus/pci/drivers/qxl/bind;\
done
After a few seconds, it reports:
==================================================================
BUG: KASAN: slab-use-after-free in qxl_irq_handler+0x269/0x2b0
Read of size 8 at addr ffff888001c6cd48 by task swapper/0/0
CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted
7.1.0-10963-g1a3746ccbb0a #31 PREEMPT(lazy)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009),
BIOS Arch Linux 1.17.0-2-2 04/01/2014
Call Trace:
<IRQ>
dump_stack_lvl+0x4d/0x70
print_report+0x14b/0x4b0
? __pfx__raw_spin_lock_irqsave+0x10/0x10
? profile_tick+0x56/0x90
? tick_nohz_handler+0x23c/0x5c0
kasan_report+0x117/0x140
? qxl_irq_handler+0x269/0x2b0
? qxl_irq_handler+0x269/0x2b0
? __pfx_qxl_irq_handler+0x10/0x10
qxl_irq_handler+0x269/0x2b0
? __pfx_qxl_irq_handler+0x10/0x10
? __pfx_qxl_irq_handler+0x10/0x10
__handle_irq_event_percpu+0x116/0x450
? __pfx__raw_spin_lock+0x10/0x10
handle_irq_event+0xa6/0x1c0
handle_fasteoi_irq+0x271/0xb10
? __pfx_handle_fasteoi_irq+0x10/0x10
__common_interrupt+0x60/0x130
common_interrupt+0x7a/0x90
</IRQ>
<TASK>
asm_common_interrupt+0x26/0x40
RIP: 0010:pv_native_safe_halt+0xf/0x20
Code: 42 de 00 c3 cc cc cc cc 0f 1f 00 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 f3 0f 1e fa eb 07 0f 00 2d a3 cf 20 00
fb f4 <c3> cc cc cc cc 66 2e 0f 1f 84 00 00 00 00 00 66 90
90 90 90 90 90
RSP: 0018:ffffffffb8207e48 EFLAGS: 00000206
RAX: ffff8880b296f000 RBX: ffffffffb82146c0 RCX: 0000000000000001
RDX: 0000000000000001 RSI: 0000000000000004 RDI: 0000000000067a04
RBP: fffffbfff70428d8 R08: ffffffffb7247e1d R09: 1ffff1100d846202
R10: ffffed100d846203 R11: ffffed100d846203 R12: 0000000000000000
R13: 0000000000000000 R14: 1ffffffff7040fcd R15: dffffc0000000000
? ct_kernel_exit.constprop.0+0x9d/0xc0
default_idle+0x9/0x10
default_idle_call+0x37/0x60
do_idle+0x3a8/0x5d0
? __pfx___schedule+0x10/0x10
? __pfx_do_idle+0x10/0x10
cpu_startup_entry+0x4e/0x60
rest_init+0x11a/0x120
start_kernel+0x382/0x390
x86_64_start_reservations+0x24/0x30
x86_64_start_kernel+0xd6/0xe0
common_startup_64+0x13e/0x158
</TASK>
The qxl_pci_remove() function does not call free_irq(), allowing the IRQ
handler to fire after the device has been torn down, accessing freed
memory (qdev->ram_header, qdev->io_base).
Added Disable the device from generating IRQs, Release the IRQ
at the start of qxl_pci_remove() to ensure no IRQs fire
after teardown begins.
Assisted-by: OpenCode:1.17.13-Big Pickle/DeepSeek V4 Flash
Fixes: 48bd85808443 ("drm/qxl: Convert to Linux IRQ interfaces")
Signed-off-by: Óscar Megía López <megia.oscar@gmail.com>
---
Changes in v2:
- Updated qxl_ttm_init to add ttm_device_fini on error in
qxl_ttm_init_mem_type.
Changes in v3:
- Added free_irq on qxl_probe unload.
- Set to NULL after free on qxl_device_fini and
added idr_destroy on release_idr and surf_id_idr.
- Free client_monitors_config.
Changes in v4:
- Delete all code unnecessary. Leave only code to fix the BUG.
---
drivers/gpu/drm/qxl/qxl_drv.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c
index 1e6a2392d7c6..54c1b8a3c723 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.c
+++ b/drivers/gpu/drm/qxl/qxl_drv.c
@@ -155,6 +155,9 @@ qxl_pci_remove(struct pci_dev *pdev)
{
struct drm_device *dev = pci_get_drvdata(pdev);
+ disable_irq(pdev->irq);
+ free_irq(pdev->irq, dev);
+
drm_kms_helper_poll_fini(dev);
drm_dev_unregister(dev);
drm_atomic_helper_shutdown(dev);
--
2.55.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH v4] drm/qxl: fix use-after-free in qxl_irq_handler on PCI
2026-09-27 10:10 [PATCH v4] drm/qxl: fix use-after-free in qxl_irq_handler on PCI Óscar Megía López
@ 2026-09-27 10:19 ` sashiko-bot
0 siblings, 0 replies; 2+ messages in thread
From: sashiko-bot @ 2026-09-27 10:19 UTC (permalink / raw)
To: Óscar Megía López
Cc: Michael S. Tsirkin, virtualization, Eugenio Perez
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] drm/qxl: incorrect global disablement of shared PCI interrupt
- [High] drm/qxl: hardware teardown times out due to premature free_irq()
--
commit 4dcfdbcd12c8dcfe24f833ddd26240d1479406f0
Author: Óscar Megía López <megia.oscar@gmail.com>
drm/qxl: fix use-after-free in qxl_irq_handler on PCI
This commit adds disable_irq() and free_irq() to qxl_pci_remove() to
prevent the IRQ handler from firing after device teardown begins, fixing
a reported KASAN use-after-free.
> diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c
> --- a/drivers/gpu/drm/qxl/qxl_drv.c
> +++ b/drivers/gpu/drm/qxl/qxl_drv.c
> @@ -160,6 +160,9 @@ qxl_pci_remove(struct pci_dev *pdev)
> {
> struct drm_device *dev = pci_get_drvdata(pdev);
>
> + disable_irq(pdev->irq);
[Severity: High]
Does this disable a shared interrupt line globally?
Looking at qxl_irq_init(), the interrupt is requested with IRQF_SHARED:
request_irq(pdev->irq, qxl_irq_handler, IRQF_SHARED, ...);
If this interrupt line is shared with other PCI devices, calling
disable_irq() here will mask the interrupt at the hardware controller
level (like the IO-APIC). Could this prevent other devices sharing the
same line from receiving interrupts, causing them to hang?
To safely disable shared interrupts, should the driver mask interrupts via
its own device registers instead?
> + free_irq(pdev->irq, dev);
> +
[Severity: High]
Will freeing the IRQ this early cause hardware teardown commands to time out?
After this free_irq(), drm_atomic_helper_shutdown() is called.
Furthermore, when the final reference is dropped, qxl_device_fini()
executes the following cleanup sequence:
qxl_kms.c:qxl_device_fini() {
...
qxl_io_notify_oom(qdev);
wait_event_timeout(qdev->release_event,
atomic_read(&qdev->release_count) == 0, HZ);
}
Since qxl_io_notify_oom() requires the interrupt handler to fire to process
the completion and signal release_event, will this wait now unconditionally
time out because the IRQ handler was already removed?
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260927101026.45411-1-megia.oscar@gmail.com?part=1
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-09-27 10:19 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-27 10:10 [PATCH v4] drm/qxl: fix use-after-free in qxl_irq_handler on PCI Óscar Megía López
2026-09-27 10:19 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox