From 966f567432e91762382db09129f8fb4e2e434437 Mon Sep 17 00:00:00 2001 From: Mario Kleiner Date: Tue, 14 Sep 2021 07:40:49 +0200 Subject: [PATCH] xfree86: Avoid crash in xf86RandR12CrtcSetGamma() memcpy path. If randrp->palette_size is zero, the memcpy() path can read past the end of the randr_crtc's gammaRed/Green/Blue tables if the hw crtc's gamma_size is greater than the randr_crtc's gammaSize. Avoid this by clamping the to-be-copied size to the smaller of both sizes. Note that during regular server startup, the memcpy() path is only taken initially twice, but then a suitable palette is created for use during a session. Therefore during an actual running X-Session, the xf86RandR12CrtcComputeGamma() will be used, which makes sure that data is properly up- or down-sampled for mismatching source and target crtc gamma sizes. This should avoid reading past randr_crtc gamma memory for gpu's with big crtc->gamma_size, e.g., AMD/MALI/KOMEDA 4096 slots, or Intel Icelake and later with 262145 slots. Tested against modesetting-ddx and amdgpu-ddx under screen color depth 24 (8 bpc) and 30 (10 bpc) to make sure that clamping happens properly. This is an alternative fix for the one attempted in commit 617f591fc44e24413e1f91017d16734999bbbac1. Signed-off-by: Mario Kleiner --- hw/xfree86/modes/xf86RandR12.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c index d4651f4e8..df46fb32b 100644 --- a/hw/xfree86/modes/xf86RandR12.c +++ b/hw/xfree86/modes/xf86RandR12.c @@ -1358,6 +1358,7 @@ xf86RandR12CrtcSetGamma(ScreenPtr pScreen, RRCrtcPtr randr_crtc) { XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); xf86CrtcPtr crtc = randr_crtc->devPrivate; + int max_size = crtc->gamma_size; if (crtc->funcs->gamma_set == NULL) return FALSE; @@ -1372,12 +1373,15 @@ xf86RandR12CrtcSetGamma(ScreenPtr pScreen, RRCrtcPtr randr_crtc) randr_crtc->gammaBlue, randr_crtc->gammaSize); } else { + if (max_size > randr_crtc->gammaSize) + max_size = randr_crtc->gammaSize; + memcpy(crtc->gamma_red, randr_crtc->gammaRed, - crtc->gamma_size * sizeof(crtc->gamma_red[0])); + max_size * sizeof(crtc->gamma_red[0])); memcpy(crtc->gamma_green, randr_crtc->gammaGreen, - crtc->gamma_size * sizeof(crtc->gamma_green[0])); + max_size * sizeof(crtc->gamma_green[0])); memcpy(crtc->gamma_blue, randr_crtc->gammaBlue, - crtc->gamma_size * sizeof(crtc->gamma_blue[0])); + max_size * sizeof(crtc->gamma_blue[0])); } xf86RandR12CrtcReloadGamma(crtc);