diff options
author | Aleksey Manevich <manevich.aleksey@gmail.com> | 2016-08-12 06:10:36 +0300 |
---|---|---|
committer | Aleksey Manevich <manevich.aleksey@gmail.com> | 2016-08-12 08:42:13 +0300 |
commit | 6243b04031e0d6acad08ad808ebc0a233d1852c3 (patch) | |
tree | 96806539cb88f07a54808ceda87c7d1a4d5c0bd3 /src | |
parent | Busybox workaround (diff) | |
download | firejail-6243b04031e0d6acad08ad808ebc0a233d1852c3.tar.gz firejail-6243b04031e0d6acad08ad808ebc0a233d1852c3.tar.zst firejail-6243b04031e0d6acad08ad808ebc0a233d1852c3.zip |
--x11=xephyr rewrite
Diffstat (limited to 'src')
-rw-r--r-- | src/firejail/x11.c | 147 |
1 files changed, 103 insertions, 44 deletions
diff --git a/src/firejail/x11.c b/src/firejail/x11.c index 090ff6f3b..9e818ab67 100644 --- a/src/firejail/x11.c +++ b/src/firejail/x11.c | |||
@@ -158,16 +158,15 @@ void fs_x11(void) { | |||
158 | 158 | ||
159 | 159 | ||
160 | #ifdef HAVE_X11 | 160 | #ifdef HAVE_X11 |
161 | //$ Xephyr -ac -br -terminate -screen 800x600 :22 & | 161 | //$ Xephyr -ac -br -noreset -screen 800x600 :22 & |
162 | //$ DISPLAY=:22 firejail --net=eth0 --blacklist=/tmp/.X11-unix/x0 firefox | 162 | //$ DISPLAY=:22 firejail --net=eth0 --blacklist=/tmp/.X11-unix/x0 firefox |
163 | void x11_start_xephyr(int argc, char **argv) { | 163 | void x11_start_xephyr(int argc, char **argv) { |
164 | EUID_ASSERT(); | 164 | EUID_ASSERT(); |
165 | int i; | 165 | size_t i; |
166 | struct stat s; | 166 | struct stat s; |
167 | pid_t client = 0; | 167 | pid_t client = 0; |
168 | pid_t server = 0; | 168 | pid_t server = 0; |
169 | 169 | ||
170 | |||
171 | setenv("FIREJAIL_X11", "yes", 1); | 170 | setenv("FIREJAIL_X11", "yes", 1); |
172 | 171 | ||
173 | // unfortunately, xephyr does a number of weird things when started by root user!!! | 172 | // unfortunately, xephyr does a number of weird things when started by root user!!! |
@@ -186,29 +185,78 @@ void x11_start_xephyr(int argc, char **argv) { | |||
186 | } | 185 | } |
187 | 186 | ||
188 | int display = random_display_number(); | 187 | int display = random_display_number(); |
188 | char *display_str; | ||
189 | if (asprintf(&display_str, ":%d", display) == -1) | ||
190 | errExit("asprintf"); | ||
189 | 191 | ||
190 | // start xephyr | 192 | assert(xephyr_screen); |
191 | char *cmd1; | 193 | char *server_argv[256] = { "Xephyr", "-ac", "-br", "-noreset", "-screen", xephyr_screen }; // rest initialyzed to NULL |
194 | unsigned pos = 0; | ||
195 | while (server_argv[pos] != NULL) pos++; | ||
192 | if (checkcfg(CFG_XEPHYR_WINDOW_TITLE)) { | 196 | if (checkcfg(CFG_XEPHYR_WINDOW_TITLE)) { |
193 | if (asprintf(&cmd1, "Xephyr -ac -br -title \"firejail x11 sandbox\" -terminate -screen %s %s :%d", xephyr_screen, xephyr_extra_params, display) == -1) | 197 | server_argv[pos++] = "-title"; |
194 | errExit("asprintf"); | 198 | server_argv[pos++] = "firejail x11 sandbox"; |
195 | } | ||
196 | else { | ||
197 | if (asprintf(&cmd1, "Xephyr -ac -br -terminate -screen %s %s :%d", xephyr_screen, xephyr_extra_params, display) == -1) | ||
198 | errExit("asprintf"); | ||
199 | } | 199 | } |
200 | 200 | ||
201 | int len = 50; // DISPLAY... | 201 | assert(xephyr_extra_params); // should be "" if empty |
202 | for (i = 0; i < argc; i++) { | 202 | |
203 | len += strlen(argv[i]) + 1; // + ' ' | 203 | // parse xephyr_extra_params |
204 | // very basic quoting support | ||
205 | char *temp = strdup(xephyr_extra_params); | ||
206 | if (xephyr_extra_params != "") { | ||
207 | if (!temp) | ||
208 | errExit("strdup"); | ||
209 | bool dquote = false; | ||
210 | bool squote = false; | ||
211 | for (i = 0; i < strlen(xephyr_extra_params); i++) { | ||
212 | if (temp[i] == '\"') { | ||
213 | dquote = !dquote; | ||
214 | if (dquote) temp[i] = '\0'; // replace closing quote by \0 | ||
215 | } | ||
216 | if (temp[i] == '\'') { | ||
217 | squote = !squote; | ||
218 | if (squote) temp[i] = '\0'; // replace closing quote by \0 | ||
219 | } | ||
220 | if (!dquote && !squote && temp[i] == ' ') temp[i] = '\0'; | ||
221 | if (dquote && squote) { | ||
222 | fprintf(stderr, "Error: mixed quoting found while parsing xephyr_extra_params\n"); | ||
223 | exit(1); | ||
224 | } | ||
225 | } | ||
226 | if (dquote) { | ||
227 | fprintf(stderr, "Error: unclosed quote found while parsing xephyr_extra_params\n"); | ||
228 | exit(1); | ||
229 | } | ||
230 | |||
231 | for (i = 0; i < strlen(xephyr_extra_params)-1; i++) { | ||
232 | if (pos >= (sizeof(server_argv)/sizeof(*server_argv))) { | ||
233 | fprintf(stderr, "Error: arg count limit exceeded while parsing xephyr_extra_params\n"); | ||
234 | exit(1); | ||
235 | } | ||
236 | if (temp[i] == '\0' && (temp[i+1] == '\"' || temp[i+1] == '\'')) server_argv[pos++] = temp + i + 2; | ||
237 | else if (temp[i] == '\0' && temp[i+1] != '\0') server_argv[pos++] = temp + i + 1; | ||
238 | } | ||
204 | } | 239 | } |
205 | 240 | ||
206 | char *cmd2 = malloc(len + 1); // + '\0' | 241 | server_argv[pos++] = display_str; |
207 | if (!cmd2) | 242 | server_argv[pos++] = NULL; |
208 | errExit("malloc"); | 243 | |
244 | assert(pos < (sizeof(server_argv)/sizeof(*server_argv))); // no overrun | ||
245 | assert(server_argv[pos-1] == NULL); // last element is null | ||
209 | 246 | ||
210 | sprintf(cmd2, "DISPLAY=:%d ", display); | 247 | if (arg_debug) { |
211 | char *ptr = cmd2 + strlen(cmd2); | 248 | size_t i = 0; |
249 | printf("xephyr server:"); | ||
250 | while (server_argv[i]!=NULL) { | ||
251 | printf(" \"%s\"", server_argv[i]); | ||
252 | i++; | ||
253 | } | ||
254 | putchar('\n'); | ||
255 | } | ||
256 | |||
257 | // remove --x11 arg | ||
258 | char *client_argv[argc+2]; | ||
259 | size_t j = 0; | ||
212 | for (i = 0; i < argc; i++) { | 260 | for (i = 0; i < argc; i++) { |
213 | if (strcmp(argv[i], "--x11") == 0) | 261 | if (strcmp(argv[i], "--x11") == 0) |
214 | continue; | 262 | continue; |
@@ -216,14 +264,23 @@ void x11_start_xephyr(int argc, char **argv) { | |||
216 | continue; | 264 | continue; |
217 | if (strcmp(argv[i], "--x11=xephyr") == 0) | 265 | if (strcmp(argv[i], "--x11=xephyr") == 0) |
218 | continue; | 266 | continue; |
219 | ptr += sprintf(ptr, "%s ", argv[i]); | 267 | client_argv[j] = argv[i]; |
268 | j++; | ||
269 | } | ||
270 | client_argv[j] = NULL; | ||
271 | |||
272 | assert(j < argc+2); // no overrun | ||
273 | |||
274 | if (arg_debug) { | ||
275 | size_t i = 0; | ||
276 | printf("xephyr client:"); | ||
277 | while (client_argv[i]!=NULL) { | ||
278 | printf(" \"%s\"", client_argv[i]); | ||
279 | i++; | ||
280 | } | ||
281 | putchar('\n'); | ||
220 | } | 282 | } |
221 | if (arg_debug) | ||
222 | printf("xephyr server: %s\n", cmd1); | ||
223 | if (arg_debug) | ||
224 | printf("xephyr client: %s\n", cmd2); | ||
225 | 283 | ||
226 | signal(SIGHUP,SIG_IGN); // fix sleep(1) below | ||
227 | server = fork(); | 284 | server = fork(); |
228 | if (server < 0) | 285 | if (server < 0) |
229 | errExit("fork"); | 286 | errExit("fork"); |
@@ -231,17 +288,14 @@ void x11_start_xephyr(int argc, char **argv) { | |||
231 | if (arg_debug) | 288 | if (arg_debug) |
232 | printf("Starting xephyr...\n"); | 289 | printf("Starting xephyr...\n"); |
233 | 290 | ||
234 | char *a[4]; | 291 | execvp(server_argv[0], server_argv); |
235 | a[0] = "/bin/bash"; | ||
236 | a[1] = "-c"; | ||
237 | a[2] = cmd1; | ||
238 | a[3] = NULL; | ||
239 | |||
240 | execvp(a[0], a); | ||
241 | perror("execvp"); | 292 | perror("execvp"); |
242 | exit(1); | 293 | exit(1); |
243 | } | 294 | } |
244 | 295 | ||
296 | if (arg_debug) | ||
297 | printf("xephyr server pid %d\n", server); | ||
298 | |||
245 | // check X11 socket | 299 | // check X11 socket |
246 | char *fname; | 300 | char *fname; |
247 | if (asprintf(&fname, "/tmp/.X11-unix/X%d", display) == -1) | 301 | if (asprintf(&fname, "/tmp/.X11-unix/X%d", display) == -1) |
@@ -259,7 +313,6 @@ void x11_start_xephyr(int argc, char **argv) { | |||
259 | exit(1); | 313 | exit(1); |
260 | } | 314 | } |
261 | free(fname); | 315 | free(fname); |
262 | sleep(1); | ||
263 | 316 | ||
264 | if (arg_debug) { | 317 | if (arg_debug) { |
265 | printf("X11 sockets: "); fflush(0); | 318 | printf("X11 sockets: "); fflush(0); |
@@ -267,26 +320,32 @@ void x11_start_xephyr(int argc, char **argv) { | |||
267 | (void) rv; | 320 | (void) rv; |
268 | } | 321 | } |
269 | 322 | ||
323 | setenv("DISPLAY", display_str, 1); | ||
270 | // run attach command | 324 | // run attach command |
271 | client = fork(); | 325 | client = fork(); |
272 | if (client < 0) | 326 | if (client < 0) |
273 | errExit("fork"); | 327 | errExit("fork"); |
274 | if (client == 0) { | 328 | if (client == 0) { |
275 | printf("\n*** Attaching to Xephyr display %d ***\n\n", display); | 329 | printf("\n*** Attaching to Xephyr display %d ***\n\n", display); |
276 | char *a[4]; | 330 | |
277 | a[0] = "/bin/bash"; | 331 | execvp(client_argv[0], client_argv); |
278 | a[1] = "-c"; | ||
279 | a[2] = cmd2; | ||
280 | a[3] = NULL; | ||
281 | |||
282 | execvp(a[0], a); | ||
283 | perror("execvp"); | 332 | perror("execvp"); |
284 | exit(1); | 333 | exit(1); |
285 | } | 334 | } |
286 | sleep(1); | 335 | |
287 | 336 | // cleanup | |
288 | if (!arg_quiet) | 337 | free(display_str); |
289 | printf("Xephyr server pid %d, client pid %d\n", server, client); | 338 | free(temp); |
339 | |||
340 | // wait for either server or client termination | ||
341 | pid_t pid = wait(); | ||
342 | |||
343 | // see which process terminated and kill other | ||
344 | if (pid == server) { | ||
345 | kill(client, SIGTERM); | ||
346 | } else if (pid == client) { | ||
347 | kill(server, SIGTERM); | ||
348 | } | ||
290 | 349 | ||
291 | exit(0); | 350 | exit(0); |
292 | } | 351 | } |