diff options
author | Michel Dänzer <mdaenzer@redhat.com> | 2019-09-20 17:24:19 +0200 |
---|---|---|
committer | Michel Dänzer <michel@daenzer.net> | 2019-09-25 09:23:25 +0200 |
commit | 2faaecc69b127248718e759c6c98c84d56dd1b6b (patch) | |
tree | 0f74c0d06f8478cf36892e31e26a2c0180abcaf8 /src/radeon_kms.c | |
parent | 2cbbd8648cdd27db8076565943b932ef81337053 (diff) |
Don't unreference FBs of pixmaps from different screens in LeaveVT
FindClientResourcesByType finds pixmaps from all screens, but trying to
process ones from other screens here makes no sense and likely results
in a crash or memory corruption.
Fixes: 06a465484101 ("Make all active CRTCs scan out an all-black
framebuffer in LeaveVT")
Diffstat (limited to 'src/radeon_kms.c')
-rw-r--r-- | src/radeon_kms.c | 27 |
1 files changed, 17 insertions, 10 deletions
diff --git a/src/radeon_kms.c b/src/radeon_kms.c index 107c1ce7..b3db7c41 100644 --- a/src/radeon_kms.c +++ b/src/radeon_kms.c @@ -2602,16 +2602,25 @@ CARD32 cleanup_black_fb(OsTimerPtr timer, CARD32 now, pointer data) } static void -pixmap_unref_fb(void *value, XID id, void *cdata) +pixmap_unref_fb(PixmapPtr pixmap) { - PixmapPtr pixmap = value; - RADEONEntPtr pRADEONEnt = cdata; + ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); struct drmmode_fb **fb_ptr = radeon_pixmap_get_fb_ptr(pixmap); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); if (fb_ptr) drmmode_fb_reference(pRADEONEnt->fd, fb_ptr, NULL); } +static void +client_pixmap_unref_fb(void *value, XID id, void *pScreen) +{ + PixmapPtr pixmap = value; + + if (pixmap->drawable.pScreen == pScreen) + pixmap_unref_fb(pixmap); +} + void RADEONLeaveVT_KMS(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); @@ -2673,11 +2682,9 @@ void RADEONLeaveVT_KMS(ScrnInfoPtr pScrn) if (pScrn->is_gpu) { if (drmmode_crtc->scanout[0].pixmap) - pixmap_unref_fb(drmmode_crtc->scanout[0].pixmap, - None, pRADEONEnt); + pixmap_unref_fb(drmmode_crtc->scanout[0].pixmap); if (drmmode_crtc->scanout[1].pixmap) - pixmap_unref_fb(drmmode_crtc->scanout[1].pixmap, - None, pRADEONEnt); + pixmap_unref_fb(drmmode_crtc->scanout[1].pixmap); } else { drmmode_crtc_scanout_free(crtc); } @@ -2697,11 +2704,11 @@ void RADEONLeaveVT_KMS(ScrnInfoPtr pScrn) (!clients[i] || clients[i]->clientState != ClientStateRunning)) continue; - FindClientResourcesByType(clients[i], RT_PIXMAP, pixmap_unref_fb, - pRADEONEnt); + FindClientResourcesByType(clients[i], RT_PIXMAP, + client_pixmap_unref_fb, pScreen); } - pixmap_unref_fb(pScreen->GetScreenPixmap(pScreen), None, pRADEONEnt); + pixmap_unref_fb(pScreen->GetScreenPixmap(pScreen)); } else { memset(info->front_buffer->bo.radeon->ptr, 0, pScrn->displayWidth * info->pixel_bytes * pScrn->virtualY); |