aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@yahoo.com>2017-02-14 18:42:34 -0500
committerLibravatar netblue30 <netblue30@yahoo.com>2017-02-14 18:42:34 -0500
commit75a10497476ea1feb6275951e33eedcbe0110b8b (patch)
tree332f69c1646b06799d3a3069bf8ba7b69708730e
parentcompile cleanup (diff)
downloadfirejail-75a10497476ea1feb6275951e33eedcbe0110b8b.tar.gz
firejail-75a10497476ea1feb6275951e33eedcbe0110b8b.tar.zst
firejail-75a10497476ea1feb6275951e33eedcbe0110b8b.zip
merge #1100 from zackw: rework DISPLAY environment parsing, rework masking X11 sockets in /tmp/.X11-unix directory
-rw-r--r--README2
-rw-r--r--src/firejail/x11.c109
2 files changed, 95 insertions, 16 deletions
diff --git a/README b/README
index 617ec3ec8..52c5f7dd2 100644
--- a/README
+++ b/README
@@ -103,6 +103,8 @@ valoq (https://github.com/valoq)
103 - added iridium browser profile 103 - added iridium browser profile
104Zack Weinberg (https://github.com/zackw) 104Zack Weinberg (https://github.com/zackw)
105 - removed libconnect 105 - removed libconnect
106 - fixed memory corruption in noblacklist processing
107 - rework DISPLAY environment parsing, rework masking X11 sockets in /tmp/.X11-unix directory
106Igor Bukanov (https://github.com/ibukanov) 108Igor Bukanov (https://github.com/ibukanov)
107 - found/fiixed privilege escalation in --hosts-file option 109 - found/fiixed privilege escalation in --hosts-file option
108Cat (https://github.com/ecat3) 110Cat (https://github.com/ecat3)
diff --git a/src/firejail/x11.c b/src/firejail/x11.c
index 2fedcc355..b551a2d2a 100644
--- a/src/firejail/x11.c
+++ b/src/firejail/x11.c
@@ -27,6 +27,8 @@
27#include <dirent.h> 27#include <dirent.h>
28#include <sys/mount.h> 28#include <sys/mount.h>
29#include <sys/wait.h> 29#include <sys/wait.h>
30#include <errno.h>
31#include <limits.h>
30int mask_x11_abstract_socket = 0; 32int mask_x11_abstract_socket = 0;
31 33
32#ifdef HAVE_X11 34#ifdef HAVE_X11
@@ -103,21 +105,44 @@ static int random_display_number(void) {
103} 105}
104#endif 106#endif
105 107
106// return display number, -1 if not configured 108
109// Parse the DISPLAY environment variable and return a display number.
110// Returns -1 if DISPLAY is not set, or is set to anything other than :ddd.
107int x11_display(void) { 111int x11_display(void) {
108 // extract display 112 const char *display_str = getenv("DISPLAY");
109 char *d = getenv("DISPLAY"); 113 char *endp;
110 if (!d) 114 unsigned long display;
111 return - 1; 115
112 116 if (!display_str) {
113 int display; 117 if (arg_debug)
114 int rv = sscanf(d, ":%d", &display); 118 fputs("DISPLAY is not set\n", stderr);
115 if (rv != 1) 119 return -1;
116 return -1; 120 }
117 if (arg_debug) 121
118 printf("DISPLAY %s, %d\n", d, display); 122 if (display_str[0] != ':' || display_str[1] < '0' || display_str[1] > '9') {
119 123 if (arg_debug)
120 return display; 124 fprintf(stderr, "unsupported DISPLAY form '%s'\n", display_str);
125 return -1;
126 }
127
128 errno = 0;
129 display = strtoul(display_str+1, &endp, 10);
130 if (endp == display_str+1 || (*endp != '\0' && *endp != '.')) { // handling DISPLAY=:0 and also :0.0
131 if (arg_debug)
132 fprintf(stderr, "unsupported DISPLAY form '%s'\n", display_str);
133 return -1;
134 }
135 if (errno || display > (unsigned long)INT_MAX) {
136 if (arg_debug)
137 fprintf(stderr, "display number %s is outside the valid range\n",
138 display_str+1);
139 return -1;
140 }
141
142 if (arg_debug)
143 fprintf(stderr, "DISPLAY=%s parsed as %lu\n", display_str, display);
144
145 return (int)display;
121} 146}
122 147
123void fs_x11(void) { 148void fs_x11(void) {
@@ -129,10 +154,60 @@ void fs_x11(void) {
129 char *x11file; 154 char *x11file;
130 if (asprintf(&x11file, "/tmp/.X11-unix/X%d", display) == -1) 155 if (asprintf(&x11file, "/tmp/.X11-unix/X%d", display) == -1)
131 errExit("asprintf"); 156 errExit("asprintf");
132 struct stat s; 157 struct stat x11stat;
133 if (stat(x11file, &s) == -1) 158 if (stat(x11file, &x11stat) == -1 || !S_ISSOCK(x11stat.st_mode)) {
159 free(x11file);
134 return; 160 return;
161 }
135 162
163 if (arg_debug || arg_debug_whitelists)
164 fprintf(stderr, "Masking all X11 sockets except %s\n", x11file);
165
166 // Move the real /tmp/.X11-unix to a scratch location
167 // so we can still access x11file after we mount a
168 // tmpfs over /tmp/.X11-unix.
169 int rv = mkdir(RUN_WHITELIST_X11_DIR, 0700);
170 if (rv == -1)
171 errExit("mkdir");
172 if (set_perms(RUN_WHITELIST_X11_DIR, 0, 0, 0700))
173 errExit("set_perms");
174
175 if (mount("/tmp/.X11-unix", RUN_WHITELIST_X11_DIR, 0, MS_BIND|MS_REC, 0) < 0)
176 errExit("mount bind");
177
178 // This directory must be mode 1777, or Xlib will barf.
179 if (mount("tmpfs", "/tmp/.X11-unix", "tmpfs",
180 MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_STRICTATIME | MS_REC,
181 "mode=1777,uid=0,gid=0") < 0)
182 errExit("mounting tmpfs on /tmp/.X11-unix");
183 fs_logger("tmpfs /tmp/.X11-unix");
184
185 // create an empty file which will have the desired socket bind-mounted over it
186 int fd = open(x11file, O_RDWR|O_CREAT|O_EXCL, x11stat.st_mode & ~S_IFMT);
187 if (fd < 0)
188 errExit(x11file);
189 if (fchown(fd, x11stat.st_uid, x11stat.st_gid))
190 errExit("fchown");
191 close(fd);
192
193 // do the mount
194 char *wx11file;
195 if (asprintf(&wx11file, "%s/X%d", RUN_WHITELIST_X11_DIR, display) == -1)
196 errExit("asprintf");
197 if (mount(wx11file, x11file, NULL, MS_BIND|MS_REC, NULL) < 0)
198 errExit("mount bind");
199 fs_logger2("whitelist", x11file);
200
201 free(x11file);
202 free(wx11file);
203
204 // block access to RUN_WHITELIST_X11_DIR
205 if (mount(RUN_RO_DIR, RUN_WHITELIST_X11_DIR, 0, MS_BIND, 0) < 0)
206 errExit("mount");
207 fs_logger2("blacklist", RUN_WHITELIST_X11_DIR);
208
209
210#if 0
136 // keep a copy of real /tmp/.X11-unix directory in WHITELIST_TMP_DIR 211 // keep a copy of real /tmp/.X11-unix directory in WHITELIST_TMP_DIR
137 int rv = mkdir(RUN_WHITELIST_X11_DIR, 1777); 212 int rv = mkdir(RUN_WHITELIST_X11_DIR, 1777);
138 if (rv == -1) 213 if (rv == -1)
@@ -177,6 +252,8 @@ void fs_x11(void) {
177 errExit("mount"); 252 errExit("mount");
178 fs_logger2("blacklist", RUN_WHITELIST_X11_DIR); 253 fs_logger2("blacklist", RUN_WHITELIST_X11_DIR);
179#endif 254#endif
255
256#endif
180} 257}
181 258
182 259