[Xcb-commit] libxcb: 3 commits - configure.ac src tests

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Mar 29 15:30:08 UTC 2023


 configure.ac         |   10 ---
 src/xcb_util.c       |  132 +++++++++++++++++++++++++++------------------------
 tests/check_public.c |   35 +++++++++++++
 3 files changed, 106 insertions(+), 71 deletions(-)

New commits:
commit 8935793f1f3751a6aa9d78955c7d6236177986de
Author: Demi Marie Obenour <demiobenour at gmail.com>
Date:   Sat Mar 25 15:27:33 2023 -0400

    Add tests for unix socket parsing
    
    Signed-off-by: Demi Marie Obenour <demiobenour at gmail.com>

diff --git a/src/xcb_util.c b/src/xcb_util.c
index bf93568..5b1f495 100644
--- a/src/xcb_util.c
+++ b/src/xcb_util.c
@@ -93,20 +93,25 @@ static int _xcb_parse_display_path_to_socket(const char *name, char **host, char
     struct stat sbuf;
     char path[PATH_MAX];
     size_t len;
-    int _screen = 0;
+    int _screen = 0, res;
 
     len = strlen(name);
     if (len >= sizeof(path))
         return 0;
     memcpy(path, name, len + 1);
-    if (0 != stat(path, &sbuf)) {
+    res = stat(path, &sbuf);
+    if (0 != res) {
         unsigned long lscreen;
-        char *dot = strrchr(path, '.'), *endptr;
-        if (errno != ENOENT || !dot || dot[1] < '0' || dot[1] > '9')
+	char *dot, *endptr;
+        if (res != -1 || (errno != ENOENT && errno != ENOTDIR))
+            return 0;
+        dot = strrchr(path, '.');
+        if (!dot || dot[1] < '1' || dot[1] > '9')
             return 0;
         *dot = '\0';
+        errno = 0;
         lscreen = strtoul(dot + 1, &endptr, 10);
-        if (lscreen > INT_MAX || !endptr || *endptr)
+        if (lscreen > INT_MAX || !endptr || *endptr || errno)
             return 0;
         if (0 != stat(path, &sbuf))
             return 0;
diff --git a/tests/check_public.c b/tests/check_public.c
index aed40c8..3caac1e 100644
--- a/tests/check_public.c
+++ b/tests/check_public.c
@@ -1,6 +1,10 @@
 #include <check.h>
+#include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
+#ifdef __unix__
+#include <unistd.h>
+#endif
 #include "check_suites.h"
 #include "xcb.h"
 #include "xcbext.h"
@@ -97,6 +101,37 @@ static void parse_display_fail(const char *name)
 
 START_TEST(parse_display_unix)
 {
+#ifdef __unix__
+	char buf[sizeof "/tmp/xcb-test.XXXXXXX"];
+	char buf2[sizeof(buf) + 7];
+	int r, v;
+	memcpy(buf, "/tmp/xcb-test.XXXXXXX", sizeof buf);
+	v = mkstemp(buf);
+	ck_assert_msg(v >= 0, "cannot create temporary file");
+	parse_display_pass(buf, buf, 0, 0);
+	r = snprintf(buf2, sizeof buf2, "unix:%s", buf);
+	if (r < 5 || r >= (int)sizeof buf2) {
+		ck_assert_msg(0, "snprintf() failed (return value %d)", r);
+		unlink(buf);
+		return;
+	}
+	parse_display_pass(buf2, buf, 0, 0);
+	r = snprintf(buf2, sizeof buf2, "unix:%s.1", buf);
+	if (r < 7 || r >= (int)sizeof buf2) {
+		ck_assert_msg(0, "snprintf() failed (return value %d)", r);
+		unlink(buf);
+		return;
+	}
+	parse_display_pass(buf2, buf, 0, 1);
+	r = snprintf(buf2, sizeof buf2, "%s.1", buf);
+	if (r < 2 || r >= (int)sizeof buf2) {
+		ck_assert_msg(0, "snprintf() failed (return value %d)", r);
+		unlink(buf);
+		return;
+	}
+	parse_display_pass(buf2, buf, 0, 1);
+	unlink(buf);
+#endif
 	parse_display_pass(":0", "", 0, 0);
 	parse_display_pass(":1", "", 1, 0);
 	parse_display_pass(":0.1", "", 0, 1);
commit 095255531b90f0b442e6ca41fb3752a058562d07
Author: Demi Marie Obenour <demiobenour at gmail.com>
Date:   Fri Aug 12 22:02:02 2022 -0400

    DISPLAY starting with / or unix: is always a socket path
    
    If DISPLAY starts with / or unix:, do not check for anything but a full
    filesystem socket path.  In particular, abstract AF_UNIX sockets and TCP
    sockets will not be used in this case.   Also be stricter about parsing
    the screen part of /path.screen displays, and bail out after all stat()
    errors other than ENOENT.
    
    Signed-off-by: Demi Marie Obenour <demiobenour at gmail.com>

diff --git a/src/xcb_util.c b/src/xcb_util.c
index 7a71efe..bf93568 100644
--- a/src/xcb_util.c
+++ b/src/xcb_util.c
@@ -95,22 +95,22 @@ static int _xcb_parse_display_path_to_socket(const char *name, char **host, char
     size_t len;
     int _screen = 0;
 
-    if (name[0] != '/')
-        return 0;
     len = strlen(name);
     if (len >= sizeof(path))
         return 0;
     memcpy(path, name, len + 1);
     if (0 != stat(path, &sbuf)) {
-        char *dot = strrchr(path, '.');
-        if (!dot)
+        unsigned long lscreen;
+        char *dot = strrchr(path, '.'), *endptr;
+        if (errno != ENOENT || !dot || dot[1] < '0' || dot[1] > '9')
             return 0;
         *dot = '\0';
-
+        lscreen = strtoul(dot + 1, &endptr, 10);
+        if (lscreen > INT_MAX || !endptr || *endptr)
+            return 0;
         if (0 != stat(path, &sbuf))
             return 0;
-
-        _screen = atoi(dot + 1);
+        _screen = (int)lscreen;
     }
 
     if (host) {
@@ -149,8 +149,11 @@ static int _xcb_parse_display(const char *name, char **host, char **protocol,
         return 0;
 
     /* First check for <path to socket>[.<screen>] */
-    if (_xcb_parse_display_path_to_socket(name, host, protocol, displayp, screenp))
-        return 1;
+    if (name[0] == '/')
+        return _xcb_parse_display_path_to_socket(name, host, protocol, displayp, screenp);
+
+    if (strncmp(name, "unix:", 5) == 0)
+        return _xcb_parse_display_path_to_socket(name + 5, host, protocol, displayp, screenp);
 
     slash = strrchr(name, '/');
 
@@ -235,38 +238,45 @@ static int _xcb_open(const char *host, char *protocol, const int display)
     size_t filelen;
     char *file = NULL;
     int actual_filelen;
-    struct stat sbuf;
 
-    /* If protocol or host is "unix", fall through to Unix socket code below */
-    if ((!protocol || (strcmp("unix",protocol) != 0)) &&
-        (*host != '\0') && (strcmp("unix",host) != 0))
-    {
-        /* display specifies TCP */
-        unsigned short port = X_TCP_PORT + display;
-        return _xcb_open_tcp(host, protocol, port);
-    }
+    if (protocol && strcmp("unix", protocol) == 0 && host && host[0] == '/') {
+        /* Full path to socket provided, ignore everything else */
+        filelen = strlen(host) + 1;
+        if (filelen > INT_MAX)
+            return -1;
+        file = malloc(filelen);
+        if (file == NULL)
+            return -1;
+        memcpy(file, host, filelen);
+        actual_filelen = (int)(filelen - 1);
+    } else {
+        /* If protocol or host is "unix", fall through to Unix socket code below */
+        if ((!protocol || (strcmp("unix",protocol) != 0)) &&
+            (*host != '\0') && (strcmp("unix",host) != 0))
+        {
+            /* display specifies TCP */
+            unsigned short port = X_TCP_PORT + display;
+            return _xcb_open_tcp(host, protocol, port);
+        }
 
 #ifndef _WIN32
 #if defined(HAVE_TSOL_LABEL_H) && defined(HAVE_IS_SYSTEM_LABELED)
-    /* Check special path for Unix sockets under Solaris Trusted Extensions */
-    if (is_system_labeled())
-    {
-        const char *tsol_base = "/var/tsol/doors/.X11-unix/X";
-        char tsol_socket[PATH_MAX];
-
-        snprintf(tsol_socket, sizeof(tsol_socket), "%s%d", tsol_base, display);
-
-        if (stat(tsol_socket, &sbuf) == 0)
-            base = tsol_base;
-    }
+        /* Check special path for Unix sockets under Solaris Trusted Extensions */
+        if (is_system_labeled())
+        {
+            const char *tsol_base = "/var/tsol/doors/.X11-unix/X";
+            char tsol_socket[PATH_MAX];
+            struct stat sbuf;
+
+            snprintf(tsol_socket, sizeof(tsol_socket), "%s%d", tsol_base, display);
+
+            if (stat(tsol_socket, &sbuf) == 0)
+                base = tsol_base;
+            else if (errno != ENOENT)
+                return 0;
+        }
 #endif
 
-    if (0 == stat(host, &sbuf)) {
-        file = strdup(host);
-        if(file == NULL)
-            return -1;
-        filelen = actual_filelen = strlen(file);
-    } else {
         filelen = strlen(base) + 1 + sizeof(display) * 3 + 1;
         file = malloc(filelen);
         if(file == NULL)
@@ -274,24 +284,23 @@ static int _xcb_open(const char *host, char *protocol, const int display)
 
         /* display specifies Unix socket */
         actual_filelen = snprintf(file, filelen, "%s%d", base, display);
-    }
 
-    if(actual_filelen < 0)
-    {
-        free(file);
-        return -1;
-    }
-    /* snprintf may truncate the file */
-    filelen = MIN(actual_filelen, filelen - 1);
+        if(actual_filelen < 0)
+        {
+            free(file);
+            return -1;
+        }
+        /* snprintf may truncate the file */
+        filelen = MIN(actual_filelen, filelen - 1);
 #ifdef HAVE_ABSTRACT_SOCKETS
-    fd = _xcb_open_abstract(protocol, file, filelen);
-    if (fd >= 0 || (errno != ENOENT && errno != ECONNREFUSED))
-    {
-        free(file);
-        return fd;
-    }
-
+        fd = _xcb_open_abstract(protocol, file, filelen);
+        if (fd >= 0 || (errno != ENOENT && errno != ECONNREFUSED))
+        {
+            free(file);
+            return fd;
+        }
 #endif
+    }
     fd = _xcb_open_unix(protocol, file);
     free(file);
 
commit ccdef1a8a5b6956a3fb7115d634db213433dca75
Author: Demi Marie Obenour <demiobenour at gmail.com>
Date:   Sun Jul 3 17:57:11 2022 -0400

    Allow full paths to sockets on non-macOS
    
    When combined with xorg/lib/libxtrans!7, this allows CVE-2020-25697 to
    be mitigated by placing the AF_UNIX socket in a secure directory on the
    filesystem.
    
    This enables HAVE_LAUNCHD unconditionally and deletes the configure
    switch.
    
    Signed-off-by: Demi Marie Obenour <demiobenour at gmail.com>

diff --git a/configure.ac b/configure.ac
index 3d81a6b..e4a0376 100644
--- a/configure.ac
+++ b/configure.ac
@@ -247,16 +247,6 @@ XCB_EXTENSION(XTest, yes)
 XCB_EXTENSION(Xv, yes)
 XCB_EXTENSION(XvMC, yes)
 
-AC_ARG_WITH(launchd, AS_HELP_STRING([--with-launchd], [Build with support for Apple's launchd (default: auto)]), [LAUNCHD=$withval], [LAUNCHD=auto])
-if test "x$LAUNCHD" = xauto; then
-        unset LAUNCHD
-        AC_CHECK_PROG(LAUNCHD, [launchd], [yes], [no], [$PATH$PATH_SEPARATOR/sbin])
-fi
-
-if test "x$LAUNCHD" = xyes ; then
-        AC_DEFINE(HAVE_LAUNCHD, 1, [launchd support available])
-fi
-
 AC_ARG_WITH(serverside-support, AS_HELP_STRING([--with-serverside-support], [Build with support for server-side usage of xcb. This is still EXPERIMENTAL! ABI/API may change! (default: no)]), [XCB_SERVERSIDE_SUPPORT=$withval], [XCB_SERVERSIDE_SUPPORT=no])
 
 AM_CONDITIONAL(XCB_SERVERSIDE_SUPPORT, test "x$XCB_SERVERSIDE_SUPPORT" = "xyes")
diff --git a/src/xcb_util.c b/src/xcb_util.c
index 30bcf79..7a71efe 100644
--- a/src/xcb_util.c
+++ b/src/xcb_util.c
@@ -60,9 +60,7 @@
 # include <sys/stat.h>
 #endif
 
-#ifdef HAVE_LAUNCHD
 #include <sys/stat.h>
-#endif
 
 int xcb_popcount(uint32_t mask)
 {
@@ -82,7 +80,6 @@ int xcb_sumof(uint8_t *list, int len)
   return s;
 }
 
-#ifdef HAVE_LAUNCHD
 /* Return true and parse if name matches <path to socket>[.<screen>]
  * Upon success:
  *     host = <path to socket>
@@ -95,9 +92,15 @@ static int _xcb_parse_display_path_to_socket(const char *name, char **host, char
 {
     struct stat sbuf;
     char path[PATH_MAX];
+    size_t len;
     int _screen = 0;
 
-    strlcpy(path, name, sizeof(path));
+    if (name[0] != '/')
+        return 0;
+    len = strlen(name);
+    if (len >= sizeof(path))
+        return 0;
+    memcpy(path, name, len + 1);
     if (0 != stat(path, &sbuf)) {
         char *dot = strrchr(path, '.');
         if (!dot)
@@ -133,7 +136,6 @@ static int _xcb_parse_display_path_to_socket(const char *name, char **host, char
 
     return 1;
 }
-#endif
 
 static int _xcb_parse_display(const char *name, char **host, char **protocol,
                       int *displayp, int *screenp)
@@ -146,11 +148,9 @@ static int _xcb_parse_display(const char *name, char **host, char **protocol,
     if(!name)
         return 0;
 
-#ifdef HAVE_LAUNCHD
     /* First check for <path to socket>[.<screen>] */
     if (_xcb_parse_display_path_to_socket(name, host, protocol, displayp, screenp))
         return 1;
-#endif
 
     slash = strrchr(name, '/');
 
@@ -235,6 +235,7 @@ static int _xcb_open(const char *host, char *protocol, const int display)
     size_t filelen;
     char *file = NULL;
     int actual_filelen;
+    struct stat sbuf;
 
     /* If protocol or host is "unix", fall through to Unix socket code below */
     if ((!protocol || (strcmp("unix",protocol) != 0)) &&
@@ -250,7 +251,6 @@ static int _xcb_open(const char *host, char *protocol, const int display)
     /* Check special path for Unix sockets under Solaris Trusted Extensions */
     if (is_system_labeled())
     {
-        struct stat sbuf;
         const char *tsol_base = "/var/tsol/doors/.X11-unix/X";
         char tsol_socket[PATH_MAX];
 
@@ -261,16 +261,12 @@ static int _xcb_open(const char *host, char *protocol, const int display)
     }
 #endif
 
-#ifdef HAVE_LAUNCHD
-    struct stat sbuf;
     if (0 == stat(host, &sbuf)) {
         file = strdup(host);
         if(file == NULL)
             return -1;
         filelen = actual_filelen = strlen(file);
-    } else
-#endif
-    {
+    } else {
         filelen = strlen(base) + 1 + sizeof(display) * 3 + 1;
         file = malloc(filelen);
         if(file == NULL)


More information about the xcb-commit mailing list