xserver: Branch 'master'

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Jul 16 12:09:30 UTC 2024


 dix/selection.c |   71 ++++++++++++++++++++++++--------------------------------
 1 file changed, 31 insertions(+), 40 deletions(-)

New commits:
commit 6a1d7300068383197d432289647e5aaec4533543
Author: Enrico Weigelt, metux IT consult <info at metux.net>
Date:   Wed Jun 26 17:21:01 2024 +0200

    dix: create empty selection objects as-needed in dixLookupSelection()
    
    For now, new selection objects are only created in ProcSetSelectionOwner()
    when dixLookupSelection() can't find the requested one (returns BadMatch).
    
    When somebody's trying to listen on a not-yet existing selection, via
    XFixesSelectSelectionInput() -- XFIXES:SelectSelectionInput message -- he's
    also getting BadMatch. The spec isn't explicitly clear on the exact behaviour
    in those specific situations: it doesn't tell anything about selection's
    lifetimes (when are they actually *created* or *destroyed*), just about their
    ownership.
    
    But there are real-world clients not expecting an error here and crashing
    with a BadMatch error.
    
    Since the spec doesn't mandate any Selection lifetime, it's safe to assume,
    they can be created as-needed (as other related code paths already do).
    Doing so ensures such an error cannot happen anymore.
    
    XACE consumers get properly notified by the new Selection object creation
    (eg. SElinux is attaching it's private data to it). And all callers already
    prepared to get a cleared Selection object, because that's always been a
    perfectly normal situation - Selection objects never get removed again,
    just cleared.
    
    Fixes: 601fd0fd8 - xfixes/xace: fix pointer type mismatch on XFixesSelectSelectionInput()
    Signed-off-by: Enrico Weigelt, metux IT consult <info at metux.net>
    Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1574>

diff --git a/dix/selection.c b/dix/selection.c
index a107eb6cf..f0ca73624 100644
--- a/dix/selection.c
+++ b/dix/selection.c
@@ -82,8 +82,21 @@ dixLookupSelection(Selection ** result, Atom selectionName,
         if (pSel->selection == selectionName)
             break;
 
-    if (pSel)
-        rc = XaceHookSelectionAccess(client, &pSel, access_mode);
+    if (!pSel) {
+        pSel = dixAllocateObjectWithPrivates(Selection, PRIVATE_SELECTION);
+        if (!pSel)
+            return BadAlloc;
+        pSel->selection = selectionName;
+        pSel->next = CurrentSelections;
+        CurrentSelections = pSel;
+    }
+
+    /* security creation/labeling check */
+    rc = XaceHookSelectionAccess(client, &pSel, access_mode | DixCreateAccess);
+    if (rc != Success) {
+        return rc;
+    }
+
     *result = pSel;
     return rc;
 }
@@ -175,46 +188,24 @@ ProcSetSelectionOwner(ClientPtr client)
      */
     rc = dixLookupSelection(&pSel, stuff->selection, client, DixSetAttrAccess);
 
-    if (rc == Success) {
-        /* If the timestamp in client's request is in the past relative
-           to the time stamp indicating the last time the owner of the
-           selection was set, do not set the selection, just return
-           success. */
-        if (CompareTimeStamps(time, pSel->lastTimeChanged) == EARLIER)
-            return Success;
-        if (pSel->client && (!pWin || (pSel->client != client))) {
-            xEvent event = {
-                .u.selectionClear.time = time.milliseconds,
-                .u.selectionClear.window = pSel->window,
-                .u.selectionClear.atom = pSel->selection
-            };
-            event.u.u.type = SelectionClear;
-            WriteEventsToClient(pSel->client, 1, &event);
-        }
-    }
-    else if (rc == BadMatch) {
-        /*
-         * It doesn't exist, so add it...
-         */
-        pSel = dixAllocateObjectWithPrivates(Selection, PRIVATE_SELECTION);
-        if (!pSel)
-            return BadAlloc;
-
-        pSel->selection = stuff->selection;
-
-        /* security creation/labeling check */
-        rc = XaceHookSelectionAccess(client, &pSel,
-                                     DixCreateAccess | DixSetAttrAccess);
-        if (rc != Success) {
-            free(pSel);
-            return rc;
-        }
+    if (rc != Success)
+        return rc;
 
-        pSel->next = CurrentSelections;
-        CurrentSelections = pSel;
+    /* If the timestamp in client's request is in the past relative
+       to the time stamp indicating the last time the owner of the
+       selection was set, do not set the selection, just return
+       success. */
+    if (CompareTimeStamps(time, pSel->lastTimeChanged) == EARLIER)
+        return Success;
+    if (pSel->client && (!pWin || (pSel->client != client))) {
+        xEvent event = {
+            .u.selectionClear.time = time.milliseconds,
+            .u.selectionClear.window = pSel->window,
+            .u.selectionClear.atom = pSel->selection
+        };
+        event.u.u.type = SelectionClear;
+        WriteEventsToClient(pSel->client, 1, &event);
     }
-    else
-        return rc;
 
     pSel->lastTimeChanged = time;
     pSel->window = stuff->window;


More information about the xorg-commit mailing list