From 8a11713a3c5d1fe7d916a66123d526bebe52e585 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Wed, 17 Jun 2026 02:51:20 +0300 Subject: [PATCH 1/2] modesetting: Check `crtc->randr_crtc` for NULL before dereferencing. It is not guaranteed that randr is enabled, or that `crtc->randr_crtc` is not NULL. This fixes a segfault with xinerama. Signed-off-by: stefan11111 --- .../video/modesetting/drmmode_display.c | 11 +++- hw/xfree86/drivers/video/modesetting/vblank.c | 50 +++++++++++++++---- 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/hw/xfree86/drivers/video/modesetting/drmmode_display.c b/hw/xfree86/drivers/video/modesetting/drmmode_display.c index dd90365981..f54d1b9586 100644 --- a/hw/xfree86/drivers/video/modesetting/drmmode_display.c +++ b/hw/xfree86/drivers/video/modesetting/drmmode_display.c @@ -1034,7 +1034,13 @@ static Bool drmmode_SharedPixmapPresent(PixmapPtr ppix, xf86CrtcPtr crtc, drmmode_ptr drmmode) { - ScreenPtr primary = crtc->randr_crtc->pScreen->current_primary; + ScreenPtr primary; + + if (!crtc->randr_crtc) { + return FALSE; + } + + primary = crtc->randr_crtc->pScreen->current_primary; if (primary->PresentSharedPixmap(ppix)) { /* Success, queue flip to back target */ @@ -2165,6 +2171,9 @@ drmmode_set_target_scanout_pixmap_cpu(xf86CrtcPtr crtc, PixmapPtr ppix, ppriv = msGetPixmapPriv(drmmode, ppix); if (!ppriv->secondary_damage) { + if (!crtc->randr_crtc) { + return FALSE; + } ppriv->secondary_damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE, diff --git a/hw/xfree86/drivers/video/modesetting/vblank.c b/hw/xfree86/drivers/video/modesetting/vblank.c index e0de33f59f..24a8744f26 100644 --- a/hw/xfree86/drivers/video/modesetting/vblank.c +++ b/hw/xfree86/drivers/video/modesetting/vblank.c @@ -224,13 +224,21 @@ static Bool ms_get_kernel_ust_msc(xf86CrtcPtr crtc, uint64_t *msc, uint64_t *ust) { - ScreenPtr screen = crtc->randr_crtc->pScreen; - ScrnInfoPtr scrn = xf86ScreenToScrn(screen); - modesettingPtr ms = modesettingPTR(scrn); + ScreenPtr screen; + ScrnInfoPtr scrn; + modesettingPtr ms; drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; drmVBlank vbl; int ret; + if (!crtc->randr_crtc) { + return FALSE; + } + + screen = crtc->randr_crtc->pScreen; + scrn = xf86ScreenToScrn(screen); + ms = modesettingPTR(scrn); + if (ms->has_queue_sequence || !ms->tried_queue_sequence) { uint64_t ns; ms->tried_queue_sequence = TRUE; @@ -310,13 +318,21 @@ ms_queue_vblank_internal(xf86CrtcPtr crtc, ms_queue_flag flags, uint64_t msc, uint64_t *msc_queued, uint32_t seq, Bool abort_on_fail) { - ScreenPtr screen = crtc->randr_crtc->pScreen; - ScrnInfoPtr scrn = xf86ScreenToScrn(screen); - modesettingPtr ms = modesettingPTR(scrn); + ScreenPtr screen; + ScrnInfoPtr scrn; + modesettingPtr ms; drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; drmVBlank vbl; int ret; + if (!crtc->randr_crtc) { + return FALSE; + } + + screen = crtc->randr_crtc->pScreen; + scrn = xf86ScreenToScrn(screen); + ms = modesettingPTR(scrn); + /* Try coalescing this event into another to avoid event queue exhaustion */ if (flags == MS_QUEUE_ABSOLUTE && ms_queue_coalesce(crtc, seq, msc)) return TRUE; @@ -431,11 +447,19 @@ ms_kernel_msc_to_crtc_msc(xf86CrtcPtr crtc, uint64_t sequence, Bool is64bit) int ms_get_crtc_ust_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc) { - ScreenPtr screen = crtc->randr_crtc->pScreen; - ScrnInfoPtr scrn = xf86ScreenToScrn(screen); - modesettingPtr ms = modesettingPTR(scrn); + ScreenPtr screen; + ScrnInfoPtr scrn; + modesettingPtr ms; uint64_t kernel_msc; + if (!crtc->randr_crtc) { + return BadImplementation; + } + + screen = crtc->randr_crtc->pScreen; + scrn = xf86ScreenToScrn(screen); + ms = modesettingPTR(scrn); + if (!ms_get_kernel_ust_msc(crtc, &kernel_msc, ust)) return BadMatch; *msc = ms_kernel_msc_to_crtc_msc(crtc, kernel_msc, ms->has_queue_sequence); @@ -469,10 +493,14 @@ ms_drm_queue_alloc(xf86CrtcPtr crtc, ms_drm_handler_proc handler, ms_drm_abort_proc abort) { - ScreenPtr screen = crtc->randr_crtc->pScreen; - ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + ScrnInfoPtr scrn = NULL; struct ms_drm_queue *q; + if (crtc->randr_crtc) { + ScreenPtr screen = crtc->randr_crtc->pScreen; + scrn = xf86ScreenToScrn(screen); + } + q = calloc(1, sizeof(struct ms_drm_queue)); if (!q) From 71caac0803bbd4a591cb65ce7c44faf9fbfa9a8b Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Wed, 17 Jun 2026 02:52:45 +0300 Subject: [PATCH 2/2] modesetting: Don't call into RandR if xinerama is enabled. RandR doesn't initialize alongside Xinerama. This fixes a segfault with tearing down the modesetting driver while xinerama is in use. Signed-off-by: stefan11111 --- hw/xfree86/drivers/video/modesetting/drmmode_display.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/hw/xfree86/drivers/video/modesetting/drmmode_display.c b/hw/xfree86/drivers/video/modesetting/drmmode_display.c index f54d1b9586..bac3a97d18 100644 --- a/hw/xfree86/drivers/video/modesetting/drmmode_display.c +++ b/hw/xfree86/drivers/video/modesetting/drmmode_display.c @@ -41,6 +41,7 @@ #include "os/mathx_priv.h" #include "Xext/present/present_priv.h" +#include "extinit.h" #include "inputstr.h" #include "xf86str.h" #include "X11/Xatom.h" @@ -4605,7 +4606,12 @@ out_free_res: drmModeFreeResources(mode_res); out: - RRGetInfo(xf86ScrnToScreen(scrn), TRUE); +#ifdef XINERAMA + if (noPanoramiXExtension) +#endif + { + RRGetInfo(xf86ScrnToScreen(scrn), TRUE); + } } #undef DRM_MODE_LINK_STATUS_BAD