xserver: Branch 'xwayland-23.2' - 10 commits

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Jan 12 13:09:30 UTC 2024


 Xext/xtest.c                            |    5 --
 Xi/xichangehierarchy.c                  |    4 +-
 dix/devices.c                           |    3 +
 glamor/glamor_copy.c                    |    4 +-
 glamor/glamor_gradient.c                |    4 +-
 glamor/glamor_pixmap.c                  |   18 +++++++++-
 glamor/glamor_priv.h                    |    2 -
 glamor/glamor_render.c                  |   30 +++++++++++++++-
 glamor/glamor_transform.c               |    4 +-
 glamor/glamor_xv.c                      |    2 -
 hw/xwayland/xwayland-glamor-eglstream.c |    2 -
 hw/xwayland/xwayland-xtest.c            |   14 +++----
 include/exevents.h                      |    7 +++
 include/meson.build                     |    2 +
 os/access.c                             |   20 ++++++++++-
 os/client.c                             |   57 +++++++++++++++++++++++++++++++-
 16 files changed, 151 insertions(+), 27 deletions(-)

New commits:
commit 4acc5cfb751449364a3af229ea906729dff17469
Author: Michel Dänzer <mdaenzer at redhat.com>
Date:   Thu Jan 4 16:14:17 2024 +0100

    glamor: Fall back for mixed depth 24/32 in glamor_set_alu
    
    For ALUs which may leave the alpha channel at values other than 1.0.
    
    Closes: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1615
    
    v2:
    * List safe ALUs instead of unsafe ones
    
    (cherry picked from commit e5a3f3e84dbbc1484d56d9a64f14508a4bf8af19)

diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c
index ed273ccbb..c573e7982 100644
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -136,6 +136,21 @@ glamor_set_alu(DrawablePtr drawable, unsigned char alu)
         glDisable(GL_COLOR_LOGIC_OP);
         return TRUE;
     }
+
+    switch (alu) {
+    case GXnoop:
+    case GXor:
+    case GXset:
+        /* These leave the alpha channel at 1.0 */
+        break;
+    default:
+        if (glamor_drawable_effective_depth(drawable) == 24 &&
+            glamor_get_drawable_pixmap(drawable)->drawable.depth == 32) {
+            glamor_fallback("ALU %x not supported with mixed depth\n", alu);
+            return FALSE;
+        }
+    }
+
     glEnable(GL_COLOR_LOGIC_OP);
     switch (alu) {
     case GXclear:
commit ea76920a531c0ddcd55240975c1116c38950481d
Author: Michel Dänzer <mdaenzer at redhat.com>
Date:   Thu Jan 4 16:03:01 2024 +0100

    glamor: Make glamor_set_alu take a DrawablePtr
    
    Preparation for the following commit, no functional change intended.
    
    (cherry picked from commit 8f66c15694d59601d2578f52d76082afcacb879e)

diff --git a/glamor/glamor_copy.c b/glamor/glamor_copy.c
index 08b55b67b..6915f54ab 100644
--- a/glamor/glamor_copy.c
+++ b/glamor/glamor_copy.c
@@ -378,7 +378,7 @@ glamor_copy_fbo_fbo_draw(DrawablePtr src,
     if (gc && !glamor_set_planemask(gc->depth, gc->planemask))
         goto bail_ctx;
 
-    if (!glamor_set_alu(screen, gc ? gc->alu : GXcopy))
+    if (!glamor_set_alu(dst, gc ? gc->alu : GXcopy))
         goto bail_ctx;
 
     if (bitplane && !glamor_priv->can_copyplane)
@@ -529,7 +529,7 @@ glamor_copy_fbo_fbo_temp(DrawablePtr src,
     if (gc && !glamor_set_planemask(gc->depth, gc->planemask))
         goto bail_ctx;
 
-    if (!glamor_set_alu(screen, gc ? gc->alu : GXcopy))
+    if (!glamor_set_alu(dst, gc ? gc->alu : GXcopy))
         goto bail_ctx;
 
     /* Find the size of the area to copy
diff --git a/glamor/glamor_gradient.c b/glamor/glamor_gradient.c
index 4c7ae4d77..1036ff5e1 100644
--- a/glamor/glamor_gradient.c
+++ b/glamor/glamor_gradient.c
@@ -971,7 +971,7 @@ glamor_generate_radial_gradient_picture(ScreenPtr screen,
          0))
         goto GRADIENT_FAIL;
 
-    glamor_set_alu(screen, GXcopy);
+    glamor_set_alu(&pixmap->drawable, GXcopy);
 
     /* Set all the stops and colors to shader. */
     if (stops_count > RADIAL_SMALL_STOPS) {
@@ -1288,7 +1288,7 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen,
          1))
         goto GRADIENT_FAIL;
 
-    glamor_set_alu(screen, GXcopy);
+    glamor_set_alu(&pixmap->drawable, GXcopy);
 
     /* Normalize the PTs. */
     glamor_set_normalize_pt(xscale, yscale,
diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c
index 2c8cc3ba0..ed273ccbb 100644
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -120,8 +120,9 @@ glamor_set_planemask(int depth, unsigned long planemask)
 }
 
 Bool
-glamor_set_alu(ScreenPtr screen, unsigned char alu)
+glamor_set_alu(DrawablePtr drawable, unsigned char alu)
 {
+    ScreenPtr screen = drawable->pScreen;
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
 
     if (glamor_priv->is_gles) {
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 71aaeb8c2..968a11be4 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -642,7 +642,7 @@ void glamor_set_destination_pixmap_fbo(glamor_screen_private *glamor_priv, glamo
  * */
 void glamor_set_destination_pixmap_priv_nc(glamor_screen_private *glamor_priv, PixmapPtr pixmap, glamor_pixmap_private *pixmap_priv);
 
-Bool glamor_set_alu(ScreenPtr screen, unsigned char alu);
+Bool glamor_set_alu(DrawablePtr drawable, unsigned char alu);
 Bool glamor_set_planemask(int depth, unsigned long planemask);
 RegionPtr glamor_bitmap_to_region(PixmapPtr pixmap);
 
diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index 60e1c64ac..7f6dedbf6 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -1231,7 +1231,7 @@ glamor_composite_with_shader(CARD8 op,
 
     glamor_set_destination_pixmap_priv_nc(glamor_priv, dest_pixmap, dest_pixmap_priv);
     glamor_composite_set_shader_blend(glamor_priv, dest_pixmap_priv, &key, shader, &op_info);
-    glamor_set_alu(screen, GXcopy);
+    glamor_set_alu(dest->pDrawable, GXcopy);
 
     glamor_priv->has_source_coords = key.source != SHADER_SOURCE_SOLID;
     glamor_priv->has_mask_coords = (key.mask != SHADER_MASK_NONE &&
diff --git a/glamor/glamor_transform.c b/glamor/glamor_transform.c
index b969bc114..891f7ee51 100644
--- a/glamor/glamor_transform.c
+++ b/glamor/glamor_transform.c
@@ -143,7 +143,7 @@ glamor_set_solid(DrawablePtr    drawable,
 
     pixel = gc->fgPixel;
 
-    if (!glamor_set_alu(drawable->pScreen, alu)) {
+    if (!glamor_set_alu(drawable, alu)) {
         switch (gc->alu) {
         case GXclear:
             pixel = 0;
@@ -209,7 +209,7 @@ glamor_set_tiled(DrawablePtr    drawable,
                  GLint          offset_uniform,
                  GLint          size_inv_uniform)
 {
-    if (!glamor_set_alu(drawable->pScreen, gc->alu))
+    if (!glamor_set_alu(drawable, gc->alu))
         return FALSE;
 
     if (!glamor_set_planemask(gc->depth, gc->planemask))
diff --git a/glamor/glamor_xv.c b/glamor/glamor_xv.c
index e0e8e0ba9..59fca909b 100644
--- a/glamor/glamor_xv.c
+++ b/glamor/glamor_xv.c
@@ -356,7 +356,7 @@ glamor_xv_render(glamor_port_private *port_priv, int id)
     off[2] = Loff * yco + Coff * (uco[2] + vco[2]) + bright;
     gamma = 1.0;
 
-    glamor_set_alu(screen, GXcopy);
+    glamor_set_alu(&pixmap->drawable, GXcopy);
 
     for (i = 0; i < 3; i++) {
         if (port_priv->src_pix[i]) {
diff --git a/hw/xwayland/xwayland-glamor-eglstream.c b/hw/xwayland/xwayland-glamor-eglstream.c
index c911ed987..c12c9bb6a 100644
--- a/hw/xwayland/xwayland-glamor-eglstream.c
+++ b/hw/xwayland/xwayland-glamor-eglstream.c
@@ -559,7 +559,7 @@ xwl_glamor_eglstream_post_damage(struct xwl_window *xwl_window,
      * won't actually draw to it
      */
     xwl_glamor_egl_make_current(xwl_screen);
-    glamor_set_alu(xwl_screen->screen, GXcopy);
+    glamor_set_alu(&pixmap->drawable, GXcopy);
 
     glBindFramebuffer(GL_FRAMEBUFFER, 0);
 
commit 02236e3fda2cbae61e87d679ce59fed8d5b0d08d
Author: Michel Dänzer <mdaenzer at redhat.com>
Date:   Fri Jan 5 18:31:11 2024 +0100

    glamor: Don't override source alpha to 1.0 if it's used for blending
    
    It caused an incorrect result of the blend operation.
    
    Use glColorMask to prevent non-1.0 alpha channel values in a depth 32
    pixmap backing an effective depth 24 window. For blending operations,
    the expectation is that the destination drawable contains valid pixel
    values, so the alpha channel should already be 1.0.
    
    Fixes: d1f142891ef3 ("glamor: Ignore destination alpha as necessary for composite operation")
    Issue: https://gitlab.gnome.org/GNOME/mutter/-/issues/3104
    (cherry picked from commit d1bbf82d72566e16e90800c77cf70fe5fc4ef2e8)

diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index 0d233f27b..60e1c64ac 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -834,6 +834,20 @@ glamor_render_format_is_supported(PicturePtr picture)
     }
 }
 
+static Bool
+render_op_uses_src_alpha(CARD8 op)
+{
+    struct blendinfo *info = &composite_op_info[op];
+
+    switch (info->dest_blend) {
+    case GL_ONE_MINUS_SRC_ALPHA:
+    case GL_SRC_ALPHA:
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
 static Bool
 glamor_composite_choose_shader(CARD8 op,
                                PicturePtr source,
@@ -947,7 +961,8 @@ glamor_composite_choose_shader(CARD8 op,
         key.dest_swizzle = SHADER_DEST_SWIZZLE_ALPHA_TO_RED;
     } else {
         if (dest_pixmap->drawable.depth == 32 &&
-            glamor_drawable_effective_depth(dest->pDrawable) == 24)
+            glamor_drawable_effective_depth(dest->pDrawable) == 24 &&
+            !render_op_uses_src_alpha(op))
             key.dest_swizzle = SHADER_DEST_SWIZZLE_IGNORE_ALPHA;
         else
             key.dest_swizzle = SHADER_DEST_SWIZZLE_DEFAULT;
@@ -1181,6 +1196,7 @@ glamor_composite_with_shader(CARD8 op,
     Bool ret = FALSE;
     glamor_composite_shader *shader = NULL, *shader_ca = NULL;
     struct blendinfo op_info, op_info_ca;
+    Bool restore_colormask = FALSE;
 
     if (!glamor_composite_choose_shader(op, source, mask, dest,
                                         source_pixmap, mask_pixmap, dest_pixmap,
@@ -1205,6 +1221,14 @@ glamor_composite_with_shader(CARD8 op,
 
     glamor_make_current(glamor_priv);
 
+    if (ca_state != CA_TWO_PASS &&
+        key.dest_swizzle == SHADER_DEST_SWIZZLE_DEFAULT &&
+        dest_pixmap->drawable.depth == 32 &&
+        glamor_drawable_effective_depth(dest->pDrawable) == 24) {
+        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
+        restore_colormask = TRUE;
+    }
+
     glamor_set_destination_pixmap_priv_nc(glamor_priv, dest_pixmap, dest_pixmap_priv);
     glamor_composite_set_shader_blend(glamor_priv, dest_pixmap_priv, &key, shader, &op_info);
     glamor_set_alu(screen, GXcopy);
@@ -1347,6 +1371,8 @@ glamor_composite_with_shader(CARD8 op,
 
     glDisable(GL_SCISSOR_TEST);
 disable_va:
+    if (restore_colormask)
+        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
     glDisableVertexAttribArray(GLAMOR_VERTEX_MASK);
commit 7b3010b26d4b704ae35bd89b570694cbffbea48c
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Thu Dec 21 11:28:04 2023 +1000

    dix: initialize the XTest sendEventsProc for all devices
    
    XTest requests lets the client specify a device ID, only if none
    is specified do we fall back to the XTEST special device.
    As of commit
      aa4074251 input: Add new hook DeviceSendEventsProc for XTEST
    regular devices are no longer able to send XTest events because they
    have no sendEventsProc set.
    
    This caused issue #1574 and the crash was fixed with commit
      e820030de xtest: Check whether there is a sendEventsProc to call
    but we still cannot send XTest events through a specific device.
    
    Fix this by defaulting every device to the XTest send function and
    punting it to the DDX (i.e. Xwayland) to override the devices as
    necessary.
    
    Fixes e820030de2da3d0064f36504ccad53302e0f718d
    Fixes aa4074251fa6135f65687b39cf11e1432208846c
    
    (cherry picked from commit de0031eefd5648c2b7464efc2e89fede7c364097)

diff --git a/Xext/xtest.c b/Xext/xtest.c
index 4d2910a60..f03d8c951 100644
--- a/Xext/xtest.c
+++ b/Xext/xtest.c
@@ -148,7 +148,7 @@ ProcXTestCompareCursor(ClientPtr client)
     return Success;
 }
 
-static void
+void
 XTestDeviceSendEvents(DeviceIntPtr dev,
                       int type,
                       int detail,
@@ -645,9 +645,6 @@ AllocXTestDevice(ClientPtr client, const char *name,
                                      XIGetKnownProperty(XI_PROP_XTEST_DEVICE),
                                      FALSE);
         XIRegisterPropertyHandler(*keybd, DeviceSetXTestProperty, NULL, NULL);
-
-        (*ptr)->sendEventsProc = XTestDeviceSendEvents;
-        (*keybd)->sendEventsProc = XTestDeviceSendEvents;
     }
 
     free(xtestname);
diff --git a/dix/devices.c b/dix/devices.c
index 257dad184..8fe4a341c 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -283,6 +283,8 @@ AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart)
     dev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
     dev->deviceGrab.sync.event = calloc(1, sizeof(InternalEvent));
 
+    dev->sendEventsProc = XTestDeviceSendEvents;
+
     XkbSetExtension(dev, ProcessKeyboardEvent);
 
     dev->coreEvents = TRUE;
diff --git a/include/exevents.h b/include/exevents.h
index c900c7b2c..7e3029fc9 100644
--- a/include/exevents.h
+++ b/include/exevents.h
@@ -305,4 +305,11 @@ XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
 extern int
  XICheckInvalidMaskBits(ClientPtr client, unsigned char *mask, int len);
 
+void
+XTestDeviceSendEvents(DeviceIntPtr dev,
+                      int type,
+                      int detail,
+                      int flags,
+                      const ValuatorMask *mask);
+
 #endif                          /* EXEVENTS_H */
commit 335d2c9fc896b0ca3d2d8e0388724dc039838338
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Thu Dec 21 11:34:26 2023 +1000

    xwayland: override the XTest sendEventsProc for all devices
    
    Otherwise only XTest events on the XTest device get handled, XTest
    requests on real devices are still processed as normal events.
    
    (cherry picked from commit 7f7adfdef803d548b867e032586783ab00288381)

diff --git a/hw/xwayland/xwayland-xtest.c b/hw/xwayland/xwayland-xtest.c
index def8926d8..e4a297ab5 100644
--- a/hw/xwayland/xwayland-xtest.c
+++ b/hw/xwayland/xwayland-xtest.c
@@ -647,6 +647,9 @@ xwayland_xtest_send_events(DeviceIntPtr dev,
     struct xwl_ei_client *xwl_ei_client;
     bool accept = false;
 
+    if (!IsXTestDevice(dev, NULL))
+        return;
+
     client = GetCurrentClient();
     xwl_ei_client = get_xwl_ei_client(client);
     if (!xwl_ei_client) {
@@ -915,9 +918,7 @@ xwayland_override_xtest(void)
     DeviceIntPtr d;
 
     nt_list_for_each_entry(d, inputInfo.devices, next) {
-        if (IsXTestDevice(d, NULL)) {
-            xwayland_override_events_proc(d);
-        }
+        xwayland_override_events_proc(d);
     }
 }
 
@@ -927,8 +928,6 @@ xwayland_restore_xtest(void)
     DeviceIntPtr d;
 
     nt_list_for_each_entry(d, inputInfo.devices, next) {
-        if (IsXTestDevice(d, NULL)) {
-            xwayland_restore_events_proc(d);
-        }
+        xwayland_restore_events_proc(d);
     }
 }
commit d5c278fab44ca1ac76cd447f5f037c791b1f2620
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Thu Jan 4 10:31:51 2024 +1000

    dix: don't allow for devices with 0 axes
    
    This just makes the existing behavior explicit, previously we relied on
    a malloc(numAxes * ...) to return NULL to error out.
    
    (cherry picked from commit 7aba2514b28de455ee3daef5f84424f4376a5d37)

diff --git a/dix/devices.c b/dix/devices.c
index 20fef1692..257dad184 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -1326,6 +1326,7 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, Atom *labels,
     ValuatorClassPtr valc;
 
     BUG_RETURN_VAL(dev == NULL, FALSE);
+    BUG_RETURN_VAL(numAxes == 0, FALSE);
 
     if (numAxes > MAX_VALUATORS) {
         LogMessage(X_WARNING,
commit 8134574102ae5e3184e4b228706e82aa5f785a11
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Thu Dec 21 14:10:11 2023 +1000

    Xi: require a pointer and keyboard device for XIAttachToMaster
    
    If we remove a master device and specify which other master devices
    attached slaves should be returned to, enforce that those two are
    indeeed a pointer and a keyboard.
    
    Otherwise we can try to attach the keyboards to pointers and vice versa,
    leading to possible crashes later.
    
    (cherry picked from commit 37539cb0bfe4ed96d4499bf371e6b1a474a740fe)

diff --git a/Xi/xichangehierarchy.c b/Xi/xichangehierarchy.c
index 504defe56..d2d985848 100644
--- a/Xi/xichangehierarchy.c
+++ b/Xi/xichangehierarchy.c
@@ -270,7 +270,7 @@ remove_master(ClientPtr client, xXIRemoveMasterInfo * r, int flags[MAXDEVICES])
         if (rc != Success)
             goto unwind;
 
-        if (!IsMaster(newptr)) {
+        if (!IsMaster(newptr) || !IsPointerDevice(newptr)) {
             client->errorValue = r->return_pointer;
             rc = BadDevice;
             goto unwind;
@@ -281,7 +281,7 @@ remove_master(ClientPtr client, xXIRemoveMasterInfo * r, int flags[MAXDEVICES])
         if (rc != Success)
             goto unwind;
 
-        if (!IsMaster(newkeybd)) {
+        if (!IsMaster(newkeybd) || !IsKeyboardDevice(newkeybd)) {
             client->errorValue = r->return_keyboard;
             rc = BadDevice;
             goto unwind;
commit 630da5cb174bc192ccb813c8171c470ca3ba3ca0
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Tue Dec 12 11:48:30 2023 +0100

    xwayland: Pass the correct oeffis device types
    
    Xwayland uses OEFFIS_DEVICE_ALL_DEVICES to get all possible device types
    enabled.
    
    Be more selective and specify explicitly keyboard and pointer instead of
    relying on what "all devices" translates to in the stack.
    
    See-also: https://gitlab.gnome.org/GNOME/mutter/-/issues/3194
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    (cherry picked from commit 1bf4d60acd18463af56371bc89b79720c954f485)

diff --git a/hw/xwayland/xwayland-xtest.c b/hw/xwayland/xwayland-xtest.c
index b5eef57e6..def8926d8 100644
--- a/hw/xwayland/xwayland-xtest.c
+++ b/hw/xwayland/xwayland-xtest.c
@@ -300,7 +300,8 @@ setup_oeffis(struct xwl_ei_client *xwl_ei_client)
     SetNotifyFd(xwl_ei_client->oeffis_fd, xwl_handle_oeffis_event,
         X_NOTIFY_READ, xwl_ei_client);
 
-    oeffis_create_session(xwl_ei_client->oeffis, OEFFIS_DEVICE_ALL_DEVICES);
+    oeffis_create_session(xwl_ei_client->oeffis,
+                          OEFFIS_DEVICE_KEYBOARD | OEFFIS_DEVICE_POINTER);
 
     return true;
 #else
commit d1176c1457fff77924b5ebe45afe3b41ad70e435
Author: Jan Beich <jbeich at FreeBSD.org>
Date:   Fri Jan 27 09:55:33 2023 +0000

    os: Use KERN_PROC_ARGS to determine client command on DragonFly and FreeBSD
    
    (cherry picked from commit 5c8f70a17c2eea3e04f0b41a8ac59e4c60ccd8c3)

diff --git a/os/client.c b/os/client.c
index 953431bd9..3295949a4 100644
--- a/os/client.c
+++ b/os/client.c
@@ -73,6 +73,11 @@
 #include <limits.h>
 #endif
 
+#if defined(__DragonFly__) || defined(__FreeBSD__)
+#include <sys/sysctl.h>
+#include <errno.h>
+#endif
+
 #ifdef __APPLE__
 #include <dispatch/dispatch.h>
 #include <errno.h>
@@ -136,7 +141,7 @@ DetermineClientPid(struct _Client * client)
 void
 DetermineClientCmd(pid_t pid, const char **cmdname, const char **cmdargs)
 {
-#if !defined(__APPLE__)
+#if !defined(__APPLE__) && !defined(__DragonFly__) && !defined(__FreeBSD__)
     char path[PATH_MAX + 1];
     int totsize = 0;
     int fd = 0;
@@ -248,6 +253,56 @@ DetermineClientCmd(pid_t pid, const char **cmdname, const char **cmdargs)
             *cmdargs = strdup(args);
         }
 
+        free(procargs);
+    }
+#elif defined(__DragonFly__) || defined(__FreeBSD__)
+    /* on DragonFly and FreeBSD use KERN_PROC_ARGS */
+    {
+        int mib[] = {
+            CTL_KERN,
+            KERN_PROC,
+            KERN_PROC_ARGS,
+            pid,
+        };
+
+        /* Determine exact size instead of relying on kern.argmax */
+        size_t len;
+        if (sysctl(mib, ARRAY_SIZE(mib), NULL, &len, NULL, 0) != 0) {
+            ErrorF("Failed to query KERN_PROC_ARGS length for PID %d: %s\n", pid, strerror(errno));
+            return;
+        }
+
+        /* Read KERN_PROC_ARGS contents. Similar to /proc/pid/cmdline
+         * the process name and each argument are separated by NUL byte. */
+        char *const procargs = malloc(len);
+        if (sysctl(mib, ARRAY_SIZE(mib), procargs, &len, NULL, 0) != 0) {
+            ErrorF("Failed to get KERN_PROC_ARGS for PID %d: %s\n", pid, strerror(errno));
+            free(procargs);
+            return;
+        }
+
+        /* Construct the process name without arguments. */
+        if (cmdname) {
+            *cmdname = strdup(procargs);
+        }
+
+        /* Construct the arguments for client process. */
+        if (cmdargs) {
+            size_t cmdsize = strlen(procargs) + 1;
+            size_t argsize = len - cmdsize;
+            char *args = NULL;
+
+            if (argsize > 0)
+                args = procargs + cmdsize;
+            if (args) {
+                /* Replace NUL with space except terminating NUL */
+                for (size_t i = 0; i < (argsize - 1); i++) {
+                    if (args[i] == '\0')
+                        args[i] = ' ';
+                }
+                *cmdargs = strdup(args);
+            }
+        }
         free(procargs);
     }
 #elif defined(__OpenBSD__)
commit cfa63ee2d86860ea9f84efc487c43ac7257f0b44
Author: Jan Beich <jbeich at FreeBSD.org>
Date:   Fri Jan 27 09:55:33 2023 +0000

    os: Use LOCAL_PEERCRED to determine local client PID on FreeBSD
    
    LOCAL_PEERCRED is similar to SO_PEERCRED but takes SOL_LOCAL. On DragonFly
    cr_pid isn't supported yet, so fall back to getpeereid().
    
    Based on https://gitlab.freedesktop.org/wayland/wayland/-/commit/54b237a61257
    
    (cherry picked from commit 58e8c967b6270be64ec7072dcf19970a0a4fa810)

diff --git a/include/meson.build b/include/meson.build
index e6e3d553f..a4bfaa49d 100644
--- a/include/meson.build
+++ b/include/meson.build
@@ -124,6 +124,7 @@ conf_data.set('HAVE_FNMATCH_H', cc.has_header('fnmatch.h') ? '1' : false)
 conf_data.set('HAVE_STDLIB_H', cc.has_header('stdlib.h') ? '1' : false)
 conf_data.set('HAVE_STRING_H', cc.has_header('string.h') ? '1' : false)
 conf_data.set('HAVE_STRINGS_H', cc.has_header('strings.h') ? '1' : false)
+conf_data.set('HAVE_SYS_UCRED_H', cc.has_header('sys/ucred.h') ? '1' : false)
 conf_data.set('HAVE_SYS_UTSNAME_H', cc.has_header('sys/utsname.h') ? '1' : false)
 conf_data.set('HAVE_SYS_SYSMACROS_H', cc.has_header('sys/sysmacros.h') ? '1' : false)
 
@@ -164,6 +165,7 @@ conf_data.set('HAVE_TIMINGSAFE_MEMCMP', cc.has_function('timingsafe_memcmp') ? '
 conf_data.set('HAVE_VASPRINTF', cc.has_function('vasprintf') ? '1' : false)
 conf_data.set('HAVE_VSNPRINTF', cc.has_function('vsnprintf') ? '1' : false)
 conf_data.set('HAVE_WALKCONTEXT', cc.has_function('walkcontext') ? '1' : false)
+conf_data.set('HAVE_XUCRED_CR_PID', cc.has_member('struct xucred', 'cr_pid', prefix : '#include <sys/ucred.h>') ? '1' : false)
 
 conf_data.set('BUSFAULT', conf_data.get('HAVE_SIGACTION'))
 
diff --git a/os/access.c b/os/access.c
index 900796cad..9fec1b731 100644
--- a/os/access.c
+++ b/os/access.c
@@ -116,6 +116,10 @@ SOFTWARE.
 #endif
 #endif
 
+#ifdef HAVE_SYS_UCRED_H
+#include <sys/ucred.h>
+#endif
+
 #ifdef HAVE_SYS_UN_H
 #include <sys/un.h>
 #endif
@@ -1166,7 +1170,7 @@ ComputeLocalClient(ClientPtr client)
 int
 GetLocalClientCreds(ClientPtr client, LocalClientCredRec ** lccp)
 {
-#if defined(HAVE_GETPEEREID) || defined(HAVE_GETPEERUCRED) || defined(SO_PEERCRED)
+#if defined(HAVE_GETPEEREID) || defined(HAVE_GETPEERUCRED) || defined(SO_PEERCRED) || defined(LOCAL_PEERCRED)
     int fd;
     XtransConnInfo ci;
     LocalClientCredRec *lcc;
@@ -1177,6 +1181,9 @@ GetLocalClientCreds(ClientPtr client, LocalClientCredRec ** lccp)
 #elif defined(SO_PEERCRED)
     struct ucred peercred;
     socklen_t so_len = sizeof(peercred);
+#elif defined(LOCAL_PEERCRED) && defined(HAVE_XUCRED_CR_PID)
+    struct xucred peercred;
+    socklen_t so_len = sizeof(peercred);
 #elif defined(HAVE_GETPEEREID)
     uid_t uid;
     gid_t gid;
@@ -1253,6 +1260,17 @@ GetLocalClientCreds(ClientPtr client, LocalClientCredRec ** lccp)
     lcc->pid = peercred.pid;
     lcc->fieldsSet = LCC_UID_SET | LCC_GID_SET | LCC_PID_SET;
     return 0;
+#elif defined(LOCAL_PEERCRED) && defined(HAVE_XUCRED_CR_PID)
+    if (getsockopt(fd, SOL_LOCAL, LOCAL_PEERCRED, &peercred, &so_len) != 0 ||
+        peercred.cr_version != XUCRED_VERSION) {
+        FreeLocalClientCreds(lcc);
+        return -1;
+    }
+    lcc->euid = peercred.cr_uid;
+    lcc->egid = peercred.cr_gid;
+    lcc->pid = peercred.cr_pid;
+    lcc->fieldsSet = LCC_UID_SET | LCC_GID_SET | LCC_PID_SET;
+    return 0;
 #elif defined(HAVE_GETPEEREID)
     if (getpeereid(fd, &uid, &gid) == -1) {
         FreeLocalClientCreds(lcc);


More information about the xorg-commit mailing list