diff options
-rw-r--r-- | README | 5 | ||||
-rw-r--r-- | src/firejail/x11.c | 115 |
2 files changed, 70 insertions, 50 deletions
@@ -104,7 +104,10 @@ valoq (https://github.com/valoq) | |||
104 | Zack Weinberg (https://github.com/zackw) | 104 | Zack Weinberg (https://github.com/zackw) |
105 | - removed libconnect | 105 | - removed libconnect |
106 | - fixed memory corruption in noblacklist processing | 106 | - fixed memory corruption in noblacklist processing |
107 | - rework DISPLAY environment parsing, rework masking X11 sockets in /tmp/.X11-unix directory | 107 | - rework DISPLAY environment parsing |
108 | - rework masking X11 sockets in /tmp/.X11-unix directory | ||
109 | - rework xpra and xephyr detection | ||
110 | - rework abstract X11 socket detection | ||
108 | Igor Bukanov (https://github.com/ibukanov) | 111 | Igor Bukanov (https://github.com/ibukanov) |
109 | - found/fiixed privilege escalation in --hosts-file option | 112 | - found/fiixed privilege escalation in --hosts-file option |
110 | Cat (https://github.com/ecat3) | 113 | 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 @@ | |||
31 | #include <limits.h> | 31 | #include <limits.h> |
32 | int mask_x11_abstract_socket = 0; | 32 | int mask_x11_abstract_socket = 0; |
33 | 33 | ||
34 | |||
35 | // Parse the DISPLAY environment variable and return a display number. | ||
36 | // Returns -1 if DISPLAY is not set, or is set to anything other than :ddd. | ||
37 | int x11_display(void) { | ||
38 | const char *display_str = getenv("DISPLAY"); | ||
39 | char *endp; | ||
40 | unsigned long display; | ||
41 | |||
42 | if (!display_str) { | ||
43 | if (arg_debug) | ||
44 | fputs("DISPLAY is not set\n", stderr); | ||
45 | return -1; | ||
46 | } | ||
47 | |||
48 | if (display_str[0] != ':' || display_str[1] < '0' || display_str[1] > '9') { | ||
49 | if (arg_debug) | ||
50 | fprintf(stderr, "unsupported DISPLAY form '%s'\n", display_str); | ||
51 | return -1; | ||
52 | } | ||
53 | |||
54 | errno = 0; | ||
55 | display = strtoul(display_str+1, &endp, 10); | ||
56 | if (endp == display_str+1 || (*endp != '\0' && *endp != '.')) { // handling DISPLAY=:0 and also :0.0 | ||
57 | if (arg_debug) | ||
58 | fprintf(stderr, "unsupported DISPLAY form '%s'\n", display_str); | ||
59 | return -1; | ||
60 | } | ||
61 | if (errno || display > (unsigned long)INT_MAX) { | ||
62 | if (arg_debug) | ||
63 | fprintf(stderr, "display number %s is outside the valid range\n", | ||
64 | display_str+1); | ||
65 | return -1; | ||
66 | } | ||
67 | |||
68 | if (arg_debug) | ||
69 | fprintf(stderr, "DISPLAY=%s parsed as %lu\n", display_str, display); | ||
70 | |||
71 | return (int)display; | ||
72 | } | ||
73 | |||
74 | |||
34 | #ifdef HAVE_X11 | 75 | #ifdef HAVE_X11 |
35 | // check for X11 abstract sockets | 76 | // check for X11 abstract sockets |
36 | static int x11_abstract_sockets_present(void) { | 77 | static int x11_abstract_sockets_present(void) { |
37 | char *path; | ||
38 | 78 | ||
39 | EUID_ROOT(); // grsecurity fix | 79 | EUID_ROOT(); // grsecurity fix |
40 | FILE *fp = fopen("/proc/net/unix", "r"); | 80 | FILE *fp = fopen("/proc/net/unix", "r"); |
41 | EUID_USER(); | ||
42 | |||
43 | if (!fp) | 81 | if (!fp) |
44 | errExit("fopen"); | 82 | errExit("fopen"); |
83 | EUID_USER(); | ||
84 | |||
85 | char *linebuf = 0; | ||
86 | size_t bufsz = 0; | ||
87 | int found = 0; | ||
88 | errno = 0; | ||
45 | 89 | ||
46 | while (fscanf(fp, "%*s %*s %*s %*s %*s %*s %*s %ms\n", &path) != EOF) { | 90 | for (;;) { |
47 | if (path && strncmp(path, "@/tmp/.X11-unix/", 16) == 0) { | 91 | if (getline(&linebuf, &bufsz, fp) == -1) { |
48 | free(path); | 92 | if (errno) |
49 | fclose(fp); | 93 | errExit("getline"); |
50 | return 1; | 94 | break; |
95 | } | ||
96 | // The last space-separated field in 'linebuf' is the | ||
97 | // pathname of the socket. Abstract sockets' pathnames | ||
98 | // all begin with '@/', normal ones begin with '/'. | ||
99 | char *p = strrchr(linebuf, ' '); | ||
100 | if (!p) { | ||
101 | fputs("error parsing /proc/net/unix\n", stderr); | ||
102 | exit(1); | ||
103 | } | ||
104 | if (strncmp(p+1, "@/tmp/.X11-unix/", 16) == 0) { | ||
105 | found = 1; | ||
106 | break; | ||
51 | } | 107 | } |
52 | } | 108 | } |
53 | 109 | ||
54 | free(path); | 110 | free(linebuf); |
55 | fclose(fp); | 111 | fclose(fp); |
56 | 112 | return found; | |
57 | return 0; | ||
58 | } | 113 | } |
59 | 114 | ||
60 | static int random_display_number(void) { | 115 | static int random_display_number(void) { |
@@ -84,44 +139,6 @@ static int random_display_number(void) { | |||
84 | #endif | 139 | #endif |
85 | 140 | ||
86 | 141 | ||
87 | // Parse the DISPLAY environment variable and return a display number. | ||
88 | // Returns -1 if DISPLAY is not set, or is set to anything other than :ddd. | ||
89 | int x11_display(void) { | ||
90 | const char *display_str = getenv("DISPLAY"); | ||
91 | char *endp; | ||
92 | unsigned long display; | ||
93 | |||
94 | if (!display_str) { | ||
95 | if (arg_debug) | ||
96 | fputs("DISPLAY is not set\n", stderr); | ||
97 | return -1; | ||
98 | } | ||
99 | |||
100 | if (display_str[0] != ':' || display_str[1] < '0' || display_str[1] > '9') { | ||
101 | if (arg_debug) | ||
102 | fprintf(stderr, "unsupported DISPLAY form '%s'\n", display_str); | ||
103 | return -1; | ||
104 | } | ||
105 | |||
106 | errno = 0; | ||
107 | display = strtoul(display_str+1, &endp, 10); | ||
108 | if (endp == display_str+1 || (*endp != '\0' && *endp != '.')) { // handling DISPLAY=:0 and also :0.0 | ||
109 | if (arg_debug) | ||
110 | fprintf(stderr, "unsupported DISPLAY form '%s'\n", display_str); | ||
111 | return -1; | ||
112 | } | ||
113 | if (errno || display > (unsigned long)INT_MAX) { | ||
114 | if (arg_debug) | ||
115 | fprintf(stderr, "display number %s is outside the valid range\n", | ||
116 | display_str+1); | ||
117 | return -1; | ||
118 | } | ||
119 | |||
120 | if (arg_debug) | ||
121 | fprintf(stderr, "DISPLAY=%s parsed as %lu\n", display_str, display); | ||
122 | |||
123 | return (int)display; | ||
124 | } | ||
125 | 142 | ||
126 | void fs_x11(void) { | 143 | void fs_x11(void) { |
127 | #ifdef HAVE_X11 | 144 | #ifdef HAVE_X11 |