xserver: Branch 'server-21.1-branch' - 10 commits

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Oct 14 14:30:43 UTC 2021


 dix/privates.c                                   |   16 ++++-----
 glamor/glamor_program.c                          |    2 +
 hw/xfree86/common/xf86platformBus.c              |    7 +++-
 hw/xfree86/drivers/modesetting/drmmode_display.c |   37 +++++++++++------------
 hw/xfree86/drivers/modesetting/modesetting.man   |   11 +++++-
 hw/xfree86/drivers/modesetting/vblank.c          |   11 +++++-
 hw/xfree86/modes/xf86RandR12.c                   |   24 ++++++++++++--
 xkb/xkb.c                                        |   26 +++++++---------
 8 files changed, 83 insertions(+), 51 deletions(-)

New commits:
commit 3fb94f3c5ca73f15a78dbc6904380b9b9e402bf4
Author: Alex Richardson <Alexander.Richardson at cl.cam.ac.uk>
Date:   Fri Jul 23 09:23:45 2021 +0100

    dix/privates.c: Avoid undefined behaviour after realloc()
    
    Adding the offset between the realloc result and the old allocation to
    update pointers into the new allocation is undefined behaviour: the
    old pointers are no longer valid after realloc() according to the C
    standard. While this works on almost all architectures and compilers,
    it causes  problems on architectures that track pointer bounds (e.g.
    CHERI or Arm's Morello): the DevPrivateKey pointers will still have the
    bounds of the previous allocation and therefore any dereference will
    result in a run-time trap.
    
    I found this due to a crash (dereferencing an invalid capability) while
    trying to run `XVnc` on a CHERI-RISC-V system. With this commit I can
    successfully connect to the XVnc instance running inside a QEMU with a
    VNC viewer on my host.
    
    This also changes the check whether the allocation was moved to use
    uintptr_t instead of a pointer since according to the C standard:
    "The value of a pointer becomes indeterminate when the object it
    points to (or just past) reaches the end of its lifetime." Casting to an
    integer type avoids this undefined behaviour.
    
    Signed-off-by: Alex Richardson <Alexander.Richardson at cl.cam.ac.uk>
    (cherry picked from commit f9f705bf3cf0d169d54a70f235cc99e106dbda43)

diff --git a/dix/privates.c b/dix/privates.c
index 384936fbd..71a72fb22 100644
--- a/dix/privates.c
+++ b/dix/privates.c
@@ -155,14 +155,13 @@ dixMovePrivates(PrivatePtr *privates, int new_offset, unsigned bytes)
 static Bool
 fixupOneScreen(ScreenPtr pScreen, FixupFunc fixup, unsigned bytes)
 {
-    intptr_t        dist;
-    char            *old;
+    uintptr_t       old;
     char            *new;
     DevPrivateKey   *keyp, key;
     DevPrivateType  type;
     int             size;
 
-    old = (char *) pScreen->devPrivates;
+    old = (uintptr_t) pScreen->devPrivates;
     size = global_keys[PRIVATE_SCREEN].offset;
     if (!fixup (&pScreen->devPrivates, size, bytes))
         return FALSE;
@@ -182,9 +181,7 @@ fixupOneScreen(ScreenPtr pScreen, FixupFunc fixup, unsigned bytes)
     if (fixup == dixMovePrivates)
         new += bytes;
 
-    dist = new - old;
-
-    if (dist) {
+    if ((uintptr_t) new != old) {
         for (type = PRIVATE_XSELINUX; type < PRIVATE_LAST; type++)
 
             /* Walk the privates list, being careful as the
@@ -199,10 +196,11 @@ fixupOneScreen(ScreenPtr pScreen, FixupFunc fixup, unsigned bytes)
                  * is contained within the allocation. Privates
                  * stored elsewhere will be left alone
                  */
-                if (old <= (char *) key && (char *) key < old + size)
+                if (old <= (uintptr_t) key && (uintptr_t) key < old + size)
                 {
-                    /* Compute new location of key */
-                    key = (DevPrivateKey) ((char *) key + dist);
+                    /* Compute new location of key (deriving from the new
+                     * allocation to avoid UB) */
+                    key = (DevPrivateKey) (new + ((uintptr_t) key - old));
 
                     /* Patch the list */
                     *keyp = key;
commit b89fdd523e2c9e9b0cdf37b263833c4b0a8868b8
Author: nerdopolis <rbos at rbos>
Date:   Thu Sep 30 08:51:18 2021 -0400

    xf86: Accept devices with the 'simpledrm' driver.
    
    SimpleDRM 'devices' are a fallback device, and do not have a busid
    so they are getting skipped. This will allow simpledrm to work
    with the modesetting driver
    
    (cherry picked from commit b9218fadf3c09d83566549279d68886d8258f79c)

diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c
index 0e0a995ac..45028f7a6 100644
--- a/hw/xfree86/common/xf86platformBus.c
+++ b/hw/xfree86/common/xf86platformBus.c
@@ -557,8 +557,13 @@ xf86platformProbeDev(DriverPtr drvp)
             }
             else {
                 /* for non-seat0 servers assume first device is the master */
-                if (ServerIsNotSeat0())
+                if (ServerIsNotSeat0()) {
                     break;
+                } else {
+                    /* Accept the device if the driver is simpledrm */
+                    if (strcmp(xf86_platform_devices[j].attribs->driver, "simpledrm") == 0)
+                        break;
+                }
 
                 if (xf86IsPrimaryPlatform(&xf86_platform_devices[j]))
                     break;
commit fbc690ccaf12d6536951d0ba403dfbb92c7c4115
Author: Mario Kleiner <mario.kleiner.de at gmail.com>
Date:   Fri Oct 1 09:47:41 2021 +0200

    modesetting: Consider RandR primary output for selectioh of sync crtc.
    
    The "sync crtc" is the crtc used to drive the display timing of a
    drawable under DRI2 and DRI3/Present. If a drawable intersects
    multiple video outputs, then normally the crtc is chosen which has
    the largest intersection area with the drawable.
    
    If multiple outputs / crtc's have exacty the same intersection
    area then the crtc chosen was simply the first one with maximum
    intersection. Iow. the choice was random, depending on plugging
    order of displays.
    
    This adds the ability to choose a preferred output in such a tie
    situation. The RandR output marked as "primary output" is chosen
    on such a tie.
    
    This new behaviour and its implementation is consistent with other
    video ddx drivers. See amdgpu-ddx, ati-ddx and nouveau-ddx for
    reference. This commit is a straightforward port from amdgpu-ddx.
    
    Signed-off-by: Mario Kleiner <mario.kleiner.de at gmail.com>
    (cherry picked from commit 4b75e65766a9ef3a26d4c1c9d7af9fc6d1d7be5b)

diff --git a/hw/xfree86/drivers/modesetting/vblank.c b/hw/xfree86/drivers/modesetting/vblank.c
index c8da476b5..ea9e7a88c 100644
--- a/hw/xfree86/drivers/modesetting/vblank.c
+++ b/hw/xfree86/drivers/modesetting/vblank.c
@@ -120,7 +120,8 @@ static RRCrtcPtr
 rr_crtc_covering_box(ScreenPtr pScreen, BoxPtr box, Bool screen_is_xf86_hint)
 {
     rrScrPrivPtr pScrPriv;
-    RRCrtcPtr crtc, best_crtc;
+    RROutputPtr primary_output;
+    RRCrtcPtr crtc, best_crtc, primary_crtc;
     int coverage, best_coverage;
     int c;
     BoxRec crtc_box, cover_box;
@@ -136,6 +137,11 @@ rr_crtc_covering_box(ScreenPtr pScreen, BoxPtr box, Bool screen_is_xf86_hint)
     if (!pScrPriv)
         return NULL;
 
+    primary_crtc = NULL;
+    primary_output = RRFirstOutput(pScreen);
+    if (primary_output)
+        primary_crtc = primary_output->crtc;
+
     for (c = 0; c < pScrPriv->numCrtcs; c++) {
         crtc = pScrPriv->crtcs[c];
 
@@ -146,7 +152,8 @@ rr_crtc_covering_box(ScreenPtr pScreen, BoxPtr box, Bool screen_is_xf86_hint)
         rr_crtc_box(crtc, &crtc_box);
         box_intersect(&cover_box, &crtc_box, box);
         coverage = box_area(&cover_box);
-        if (coverage > best_coverage) {
+        if ((coverage > best_coverage) ||
+            (coverage == best_coverage && crtc == primary_crtc)) {
             best_crtc = crtc;
             best_coverage = coverage;
         }
commit 22f4ff1026eeffc566f87453d7f1f70dc23ad4e0
Author: Mario Kleiner <mario.kleiner.de at gmail.com>
Date:   Fri Oct 1 08:49:10 2021 +0200

    modesetting: Handle mixed VRR and non-VRR display setups better.
    
    In a setup with both VRR capable and non-VRR capable displays,
    it was so far inconsistent if the driver would allow use of
    VRR support or not, as "is_connector_vrr_capable" was set to
    whatever the capabilities of the last added drm output were.
    Iow. the plugging order of monitors determined the outcome.
    
    Fix this: Now if at least one display is VRR capable, the driver
    will treat an X-Screen as capable for VRR, plugging order no
    longer matters.
    
    Tested with a dual-display setup with one VRR monitor and one
    non-VRR monitor. This is also beneficial with the new Option
    "AsyncFlipSecondaries".
    
    When we are at it, also add some so far missing description of
    the "VariableRefresh" driver option, copied from amdgpu-ddx.
    
    Signed-off-by: Mario Kleiner <mario.kleiner.de at gmail.com>
    (cherry picked from commit 017ce263376aa64a495c4d71a140a24b1dff7054)

diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index d6df28f5a..48dccad73 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -3309,7 +3309,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
         }
     }
 
-    ms->is_connector_vrr_capable =
+    ms->is_connector_vrr_capable |=
 	         drmmode_connector_check_vrr_capable(drmmode->fd,
                                                   drmmode_output->output_id);
     return 1;
diff --git a/hw/xfree86/drivers/modesetting/modesetting.man b/hw/xfree86/drivers/modesetting/modesetting.man
index bb948380b..71790011e 100644
--- a/hw/xfree86/drivers/modesetting/modesetting.man
+++ b/hw/xfree86/drivers/modesetting/modesetting.man
@@ -71,6 +71,13 @@ One of \*qglamor\*q or \*qnone\*q.  Default: glamor.
 Enable DRI3 page flipping.  The default is
 .B on.
 .TP
+.BI "Option \*qVariableRefresh\*q \*q" boolean \*q
+Enables support for enabling variable refresh on the Screen's CRTCs
+when an suitable application is flipping via the Present extension.
+.br
+The default is
+.B off.
+.TP
 .BI "Option \*qAsyncFlipSecondaries\*q \*q" boolean \*q
 Use async flips for secondary video outputs on multi-display setups. If a screen
 has multiple displays attached and DRI3 page flipping is used, then only one of
commit 0d0986bf3b924ccb26e4bc6a8c06aed41f238683
Author: Mario Kleiner <mario.kleiner.de at gmail.com>
Date:   Fri Oct 1 07:42:01 2021 +0200

    modesetting: Enable GAMMA_LUT for lut's with up to 4096 slots.
    
    A lut size of 4096 slots has been verified to work correctly,
    as tested with amdgpu-kms. Intel Tigerlake Gen12 hw has a very
    large GAMMA_LUT size of 262145 slots, but also issues with its
    current GAMMA_LUT implementation, as of Linux 5.14.
    
    Therefore we keep GAMMA_LUT off for large lut's. This currently
    excludes Intel Icelake, Tigerlake and later.
    
    This can be overriden via the "UseGammaLUT" boolean xorg.conf option
    to force use of GAMMA_LUT on or off.
    
    See following link for the Tigerlake situation:
    https://gitlab.freedesktop.org/drm/intel/-/issues/3916#note_1085315
    
    Signed-off-by: Mario Kleiner <mario.kleiner.de at gmail.com>
    (cherry picked from commit 66e5a5bb12c58413a4d71781c5a7f63f675bfe55)

diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index c10504c32..d6df28f5a 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -2404,10 +2404,23 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, MS_LOGLEVEL_DEBUG,
                    "Allocated crtc nr. %d to this screen.\n", num);
 
-    drmmode_crtc->use_gamma_lut =
-        drmmode_crtc->props[DRMMODE_CRTC_GAMMA_LUT_SIZE].prop_id &&
-        drmmode_crtc->props[DRMMODE_CRTC_GAMMA_LUT_SIZE].value &&
-        xf86ReturnOptValBool(drmmode->Options, OPTION_USE_GAMMA_LUT, TRUE);
+    if (drmmode_crtc->props[DRMMODE_CRTC_GAMMA_LUT_SIZE].prop_id &&
+        drmmode_crtc->props[DRMMODE_CRTC_GAMMA_LUT_SIZE].value) {
+        /*
+         * GAMMA_LUT property supported, and so far tested to be safe to use by
+         * default for lut sizes up to 4096 slots. Intel Tigerlake+ has some
+         * issues, and a large GAMMA_LUT with 262145 slots, so keep GAMMA_LUT
+         * off for large lut sizes by default for now.
+         */
+        drmmode_crtc->use_gamma_lut = drmmode_crtc->props[DRMMODE_CRTC_GAMMA_LUT_SIZE].value <= 4096;
+
+        /* Allow config override. */
+        drmmode_crtc->use_gamma_lut = xf86ReturnOptValBool(drmmode->Options,
+                                                           OPTION_USE_GAMMA_LUT,
+                                                           drmmode_crtc->use_gamma_lut);
+    } else {
+        drmmode_crtc->use_gamma_lut = FALSE;
+    }
 
     if (drmmode_crtc->use_gamma_lut &&
         drmmode_crtc->props[DRMMODE_CRTC_CTM].prop_id) {
diff --git a/hw/xfree86/drivers/modesetting/modesetting.man b/hw/xfree86/drivers/modesetting/modesetting.man
index 0145344d2..bb948380b 100644
--- a/hw/xfree86/drivers/modesetting/modesetting.man
+++ b/hw/xfree86/drivers/modesetting/modesetting.man
@@ -99,8 +99,8 @@ will assign xrandr outputs LVDS and VGA-0 to this instance of the driver.
 .BI "Option \*qUseGammaLUT\*q \*q" boolean \*q
 Enable or disable use of the GAMMA_LUT property, when available.
 When enabled, this option allows the driver to use gamma ramps with more
-entries, if supported by the kernel.
-Default: on.
+entries, if supported by the kernel. By default, GAMMA_LUT will be used for
+kms drivers which are known to be safe for use of GAMMA_LUT.
 .TP
 .SH "SEE ALSO"
 @xservername@(@appmansuffix@), @xconfigfile@(@filemansuffix@), Xserver(@appmansuffix@),
commit bc1327e6de82da560c97f66c9c196d9bbd2d24be
Author: Ray Strode <rstrode at redhat.com>
Date:   Mon Oct 4 14:27:54 2021 -0400

    xkb: Drop check for XkbSetMapResizeTypes
    
    Commit 446ff2d3177087b8173fa779fa5b77a2a128988b added checks to
    prevalidate the size of incoming SetMap requests.
    
    That commit checks for the XkbSetMapResizeTypes flag to be set before
    allowing key types data to be processed.
    
    key types data can be changed or even just sent wholesale unchanged
    without the number of key types changing, however. The check for
    XkbSetMapResizeTypes rejects those legitimate requests. In particular,
    XkbChangeMap never sets XkbSetMapResizeTypes and so always fails now
    any time XkbKeyTypesMask is in the changed mask.
    
    This commit drops the check for XkbSetMapResizeTypes in flags when
    prevalidating the request length.
    
    (cherry picked from commit 8b7f4d3259e8b7d1eb3d8a83e8852989e869596a)

diff --git a/xkb/xkb.c b/xkb/xkb.c
index 183d6ffa1..62dee9cb6 100644
--- a/xkb/xkb.c
+++ b/xkb/xkb.c
@@ -2405,21 +2405,19 @@ _XkbSetMapCheckLength(xkbSetMapReq *req)
         keytype = (xkbKeyTypeWireDesc *)(req + 1);
         for (i = 0; i < req->nTypes; i++) {
             _add_check_len(XkbPaddedSize(sz_xkbKeyTypeWireDesc));
-            if (req->flags & XkbSetMapResizeTypes) {
-                _add_check_len(keytype->nMapEntries
-                               * sz_xkbKTSetMapEntryWireDesc);
-                preserve = keytype->preserve;
-                map_count = keytype->nMapEntries;
-                if (preserve) {
-                    _add_check_len(map_count * sz_xkbModsWireDesc);
-                }
-                keytype += 1;
-                keytype = (xkbKeyTypeWireDesc *)
-                          ((xkbKTSetMapEntryWireDesc *)keytype + map_count);
-                if (preserve)
-                    keytype = (xkbKeyTypeWireDesc *)
-                              ((xkbModsWireDesc *)keytype + map_count);
+            _add_check_len(keytype->nMapEntries
+                           * sz_xkbKTSetMapEntryWireDesc);
+            preserve = keytype->preserve;
+            map_count = keytype->nMapEntries;
+            if (preserve) {
+                _add_check_len(map_count * sz_xkbModsWireDesc);
             }
+            keytype += 1;
+            keytype = (xkbKeyTypeWireDesc *)
+                      ((xkbKTSetMapEntryWireDesc *)keytype + map_count);
+            if (preserve)
+                keytype = (xkbKeyTypeWireDesc *)
+                          ((xkbModsWireDesc *)keytype + map_count);
         }
     }
     /* syms */
commit b87536682c185b6a825525d01e95e264018c0997
Author: Mario Kleiner <mario.kleiner.de at gmail.com>
Date:   Tue Sep 14 07:52:33 2021 +0200

    Revert "modesetting: Only use GAMMA_LUT if its size is 1024"
    
    This reverts commit 617f591fc44e24413e1f91017d16734999bbbac1.
    
    The problem described in that commit exists, but the two
    preceeding commits with improvements to the servers RandR
    code should avoid the mentioned problems while allowing the
    use of GAMMA_LUT's instead of legacy gamma lut.
    
    Use of legacy gamma lut's is not a good fix, because it will reduce
    color output precision of gpu's with more than 1024 GAMMA_LUT
    slots, e.g., AMD, ARM MALI and KOMEDA with 4096 slot luts,
    and some Mediathek parts with 512 slot luts. On KOMEDA, legacy
    lut's are completely unsupported by the kms driver, so gamma
    correction gets disabled.
    
    The situation is especially bad on Intel Icelake and later:
    Use of legacy gamma tables will cause the kms driver to switch
    to hardware legacy lut's with 256 slots, 8 bit wide, without
    interpolation. This way color output precision is restricted to
    8 bpc and any deep color / HDR output (10 bpc, fp16, fixed point 16)
    becomes impossible. The latest Intel gen gpu's would have worse
    color precision than parts which are more than 10 years old.
    
    Signed-off-by: Mario Kleiner <mario.kleiner.de at gmail.com>
    (cherry picked from commit 545fa90cbf37a4c18f013dabc9f3bfb8310a5a98)

diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index ab352a451..c10504c32 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -2406,21 +2406,7 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res
 
     drmmode_crtc->use_gamma_lut =
         drmmode_crtc->props[DRMMODE_CRTC_GAMMA_LUT_SIZE].prop_id &&
-        /* Only use GAMMA_LUT if the size is 1024.
-         *
-         * Currently, the modesetting driver always passes a sigRGBbits value of
-         * 10 to xf86HandleColormaps.  This causes it to create a RRCrtc gamma
-         * ramp of 1024 elements. If DRMMODE_CRTC_GAMMA_LUT_SIZE is larger than
-         * 1024 (for example on Intel GEN11, where it has a value of 262145)
-         * then xf86RandR12CrtcSetGamma will read past the end of the RRCrtc's
-         * gamma ramp when trying to copy it into the larger xf86Crtc gamma
-         * ramp.
-         *
-         * Since the larger GEN11 gamma ramp size hasn't been tested, just
-         * disable it for now. This will cause the modesetting driver to disable
-         * the CTM property and use the legacy DRM gamma ramp rather than the
-         * GAMMA_LUT property. */
-        drmmode_crtc->props[DRMMODE_CRTC_GAMMA_LUT_SIZE].value == 1024 &&
+        drmmode_crtc->props[DRMMODE_CRTC_GAMMA_LUT_SIZE].value &&
         xf86ReturnOptValBool(drmmode->Options, OPTION_USE_GAMMA_LUT, TRUE);
 
     if (drmmode_crtc->use_gamma_lut &&
commit 473a48660fc8a326312df2d5925017ce8152c7db
Author: Mario Kleiner <mario.kleiner.de at gmail.com>
Date:   Tue Sep 14 07:51:46 2021 +0200

    xfree86: Let xf86RandR12CrtcComputeGamma() deal with non-power-of-2 sizes.
    
    The assumption in the upsampling code was that the crtc->gamma_size
    size of the crtc's gamma table is a power of two. This is true for
    almost all current driver + gpu combos at least on Linux, with typical
    sizes of 256, 512, 1024 or 4096 slots.
    
    However, Intel Gen-11 Icelake and later are outliers, as their gamma
    table has 2^18 + 1 slots, very big and not a power of two!
    
    Try to make upsampling behave at least reasonable: Replicate the
    last gamma value to fill up remaining crtc->gamma_red/green/blue
    slots, which would normally stay uninitialized. This is important,
    because while the intel display driver does not actually use all
    2^18+1 values passed as part of a GAMMA_LUT, it does need the
    very last slot, which would not get initialized by the old code.
    
    This should hopefully create reasonable behaviour with Icelake+
    but is untested on the actual Intel hw due to lack of suitable
    hw.
    
    Signed-off-by: Mario Kleiner <mario.kleiner.de at gmail.com>
    (cherry picked from commit 7326e131df3d1373dd796d9e2d931e81a3536bad)

diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index df46fb32b..5b90f4bf1 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -1255,8 +1255,8 @@ xf86RandR12CrtcComputeGamma(xf86CrtcPtr crtc, LOCO *palette,
 {
     int gamma_slots;
     unsigned shift;
-    CARD32 value;
     int i, j;
+    CARD32 value = 0;
 
     for (shift = 0; (gamma_size << shift) < (1 << 16); shift++);
 
@@ -1273,6 +1273,10 @@ xf86RandR12CrtcComputeGamma(xf86CrtcPtr crtc, LOCO *palette,
             for (j = 0; j < gamma_slots; j++)
                 crtc->gamma_red[i * gamma_slots + j] = value;
         }
+
+        /* Replicate last value until end of crtc for gamma_size not a power of 2 */
+        for (j = i * gamma_slots; j < crtc->gamma_size; j++)
+                crtc->gamma_red[j] = value;
     } else {
         /* Downsampling of larger palette to smaller hw lut size */
         for (i = 0; i < crtc->gamma_size; i++) {
@@ -1299,6 +1303,10 @@ xf86RandR12CrtcComputeGamma(xf86CrtcPtr crtc, LOCO *palette,
             for (j = 0; j < gamma_slots; j++)
                 crtc->gamma_green[i * gamma_slots + j] = value;
         }
+
+        /* Replicate last value until end of crtc for gamma_size not a power of 2 */
+        for (j = i * gamma_slots; j < crtc->gamma_size; j++)
+            crtc->gamma_green[j] = value;
     } else {
         /* Downsampling of larger palette to smaller hw lut size */
         for (i = 0; i < crtc->gamma_size; i++) {
@@ -1325,6 +1333,10 @@ xf86RandR12CrtcComputeGamma(xf86CrtcPtr crtc, LOCO *palette,
             for (j = 0; j < gamma_slots; j++)
                 crtc->gamma_blue[i * gamma_slots + j] = value;
         }
+
+        /* Replicate last value until end of crtc for gamma_size not a power of 2 */
+        for (j = i * gamma_slots; j < crtc->gamma_size; j++)
+            crtc->gamma_blue[j] = value;
     } else {
         /* Downsampling of larger palette to smaller hw lut size */
         for (i = 0; i < crtc->gamma_size; i++) {
commit b33f487a7ca276e11214eb45b87aab970ca43d79
Author: Mario Kleiner <mario.kleiner.de at gmail.com>
Date:   Tue Sep 14 07:40:49 2021 +0200

    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 <mario.kleiner.de at gmail.com>
    (cherry picked from commit 966f567432e91762382db09129f8fb4e2e434437)

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);
commit d1ca47e1242b51c79cec7287f52c36c8e494706b
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Tue Sep 14 16:32:45 2021 +0200

    glamor: Fix leak in glamor_build_program()
    
    Fix the possible leak of `vs_prog_string` and `fs_prog_string` in case
    of failure, as reported by covscan.
    
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Michel Dänzer <mdaenzer at redhat.com>
    (cherry picked from commit 2906ee5e4a722138cccb3265a615da7705a52589)

diff --git a/glamor/glamor_program.c b/glamor/glamor_program.c
index bd5ee5e5b..c51577fc3 100644
--- a/glamor/glamor_program.c
+++ b/glamor/glamor_program.c
@@ -383,6 +383,8 @@ fail:
         glDeleteProgram(prog->prog);
         prog->prog = 0;
     }
+    free(vs_prog_string);
+    free(fs_prog_string);
     free(version_string);
     free(fs_vars);
     free(vs_vars);


More information about the xorg-commit mailing list