From 6a8d393f25a9c6e525a450ba474e402decccee95 Mon Sep 17 00:00:00 2001 From: netblue30 Date: Wed, 15 Feb 2017 09:02:53 -0500 Subject: merge #1100 from zackw: rework abstract X11 socket detection --- README | 5 ++- src/firejail/x11.c | 115 ++++++++++++++++++++++++++++++----------------------- 2 files changed, 70 insertions(+), 50 deletions(-) diff --git a/README b/README index 52c5f7dd2..e729b4580 100644 --- a/README +++ b/README @@ -104,7 +104,10 @@ valoq (https://github.com/valoq) Zack Weinberg (https://github.com/zackw) - removed libconnect - fixed memory corruption in noblacklist processing - - rework DISPLAY environment parsing, rework masking X11 sockets in /tmp/.X11-unix directory + - rework DISPLAY environment parsing + - rework masking X11 sockets in /tmp/.X11-unix directory + - rework xpra and xephyr detection + - rework abstract X11 socket detection Igor Bukanov (https://github.com/ibukanov) - found/fiixed privilege escalation in --hosts-file option Cat (https://github.com/ecat3) diff --git a/src/firejail/x11.c b/src/firejail/x11.c index f81a52b70..328ecce18 100644 --- a/src/firejail/x11.c +++ b/src/firejail/x11.c @@ -31,30 +31,85 @@ #include int mask_x11_abstract_socket = 0; + +// Parse the DISPLAY environment variable and return a display number. +// Returns -1 if DISPLAY is not set, or is set to anything other than :ddd. +int x11_display(void) { + const char *display_str = getenv("DISPLAY"); + char *endp; + unsigned long display; + + if (!display_str) { + if (arg_debug) + fputs("DISPLAY is not set\n", stderr); + return -1; + } + + if (display_str[0] != ':' || display_str[1] < '0' || display_str[1] > '9') { + if (arg_debug) + fprintf(stderr, "unsupported DISPLAY form '%s'\n", display_str); + return -1; + } + + errno = 0; + display = strtoul(display_str+1, &endp, 10); + if (endp == display_str+1 || (*endp != '\0' && *endp != '.')) { // handling DISPLAY=:0 and also :0.0 + if (arg_debug) + fprintf(stderr, "unsupported DISPLAY form '%s'\n", display_str); + return -1; + } + if (errno || display > (unsigned long)INT_MAX) { + if (arg_debug) + fprintf(stderr, "display number %s is outside the valid range\n", + display_str+1); + return -1; + } + + if (arg_debug) + fprintf(stderr, "DISPLAY=%s parsed as %lu\n", display_str, display); + + return (int)display; +} + + #ifdef HAVE_X11 // check for X11 abstract sockets static int x11_abstract_sockets_present(void) { - char *path; EUID_ROOT(); // grsecurity fix FILE *fp = fopen("/proc/net/unix", "r"); - EUID_USER(); - if (!fp) errExit("fopen"); + EUID_USER(); + + char *linebuf = 0; + size_t bufsz = 0; + int found = 0; + errno = 0; - while (fscanf(fp, "%*s %*s %*s %*s %*s %*s %*s %ms\n", &path) != EOF) { - if (path && strncmp(path, "@/tmp/.X11-unix/", 16) == 0) { - free(path); - fclose(fp); - return 1; + for (;;) { + if (getline(&linebuf, &bufsz, fp) == -1) { + if (errno) + errExit("getline"); + break; + } + // The last space-separated field in 'linebuf' is the + // pathname of the socket. Abstract sockets' pathnames + // all begin with '@/', normal ones begin with '/'. + char *p = strrchr(linebuf, ' '); + if (!p) { + fputs("error parsing /proc/net/unix\n", stderr); + exit(1); + } + if (strncmp(p+1, "@/tmp/.X11-unix/", 16) == 0) { + found = 1; + break; } } - free(path); + free(linebuf); fclose(fp); - - return 0; + return found; } static int random_display_number(void) { @@ -84,44 +139,6 @@ static int random_display_number(void) { #endif -// Parse the DISPLAY environment variable and return a display number. -// Returns -1 if DISPLAY is not set, or is set to anything other than :ddd. -int x11_display(void) { - const char *display_str = getenv("DISPLAY"); - char *endp; - unsigned long display; - - if (!display_str) { - if (arg_debug) - fputs("DISPLAY is not set\n", stderr); - return -1; - } - - if (display_str[0] != ':' || display_str[1] < '0' || display_str[1] > '9') { - if (arg_debug) - fprintf(stderr, "unsupported DISPLAY form '%s'\n", display_str); - return -1; - } - - errno = 0; - display = strtoul(display_str+1, &endp, 10); - if (endp == display_str+1 || (*endp != '\0' && *endp != '.')) { // handling DISPLAY=:0 and also :0.0 - if (arg_debug) - fprintf(stderr, "unsupported DISPLAY form '%s'\n", display_str); - return -1; - } - if (errno || display > (unsigned long)INT_MAX) { - if (arg_debug) - fprintf(stderr, "display number %s is outside the valid range\n", - display_str+1); - return -1; - } - - if (arg_debug) - fprintf(stderr, "DISPLAY=%s parsed as %lu\n", display_str, display); - - return (int)display; -} void fs_x11(void) { #ifdef HAVE_X11 -- cgit v1.2.3-70-g09d2