diff options
-rw-r--r-- | src/firejail/x11.c | 97 |
1 files changed, 76 insertions, 21 deletions
diff --git a/src/firejail/x11.c b/src/firejail/x11.c index 90ce1fc36..ed6fa3741 100644 --- a/src/firejail/x11.c +++ b/src/firejail/x11.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include "firejail.h" | 20 | #include "firejail.h" |
21 | #include <sys/types.h> | 21 | #include <sys/types.h> |
22 | #include <sys/stat.h> | 22 | #include <sys/stat.h> |
23 | #include <fcntl.h> | ||
23 | #include <unistd.h> | 24 | #include <unistd.h> |
24 | #include <signal.h> | 25 | #include <signal.h> |
25 | #include <stdlib.h> | 26 | #include <stdlib.h> |
@@ -164,7 +165,7 @@ void x11_start_xephyr(int argc, char **argv) { | |||
164 | EUID_ASSERT(); | 165 | EUID_ASSERT(); |
165 | size_t i; | 166 | size_t i; |
166 | struct stat s; | 167 | struct stat s; |
167 | pid_t client = 0; | 168 | pid_t jail = 0; |
168 | pid_t server = 0; | 169 | pid_t server = 0; |
169 | 170 | ||
170 | setenv("FIREJAIL_X11", "yes", 1); | 171 | setenv("FIREJAIL_X11", "yes", 1); |
@@ -255,7 +256,7 @@ void x11_start_xephyr(int argc, char **argv) { | |||
255 | } | 256 | } |
256 | 257 | ||
257 | // remove --x11 arg | 258 | // remove --x11 arg |
258 | char *client_argv[argc+2]; | 259 | char *jail_argv[argc+2]; |
259 | size_t j = 0; | 260 | size_t j = 0; |
260 | for (i = 0; i < argc; i++) { | 261 | for (i = 0; i < argc; i++) { |
261 | if (strcmp(argv[i], "--x11") == 0) | 262 | if (strcmp(argv[i], "--x11") == 0) |
@@ -264,18 +265,18 @@ void x11_start_xephyr(int argc, char **argv) { | |||
264 | continue; | 265 | continue; |
265 | if (strcmp(argv[i], "--x11=xephyr") == 0) | 266 | if (strcmp(argv[i], "--x11=xephyr") == 0) |
266 | continue; | 267 | continue; |
267 | client_argv[j] = argv[i]; | 268 | jail_argv[j] = argv[i]; |
268 | j++; | 269 | j++; |
269 | } | 270 | } |
270 | client_argv[j] = NULL; | 271 | jail_argv[j] = NULL; |
271 | 272 | ||
272 | assert(j < argc+2); // no overrun | 273 | assert(j < argc+2); // no overrun |
273 | 274 | ||
274 | if (arg_debug) { | 275 | if (arg_debug) { |
275 | size_t i = 0; | 276 | size_t i = 0; |
276 | printf("xephyr client:"); | 277 | printf("xephyr client:"); |
277 | while (client_argv[i]!=NULL) { | 278 | while (jail_argv[i]!=NULL) { |
278 | printf(" \"%s\"", client_argv[i]); | 279 | printf(" \"%s\"", jail_argv[i]); |
279 | i++; | 280 | i++; |
280 | } | 281 | } |
281 | putchar('\n'); | 282 | putchar('\n'); |
@@ -322,13 +323,14 @@ void x11_start_xephyr(int argc, char **argv) { | |||
322 | 323 | ||
323 | setenv("DISPLAY", display_str, 1); | 324 | setenv("DISPLAY", display_str, 1); |
324 | // run attach command | 325 | // run attach command |
325 | client = fork(); | 326 | jail = fork(); |
326 | if (client < 0) | 327 | if (jail < 0) |
327 | errExit("fork"); | 328 | errExit("fork"); |
328 | if (client == 0) { | 329 | if (jail == 0) { |
329 | printf("\n*** Attaching to Xephyr display %d ***\n\n", display); | 330 | if (!arg_quiet) |
331 | printf("\n*** Attaching to Xephyr display %d ***\n\n", display); | ||
330 | 332 | ||
331 | execvp(client_argv[0], client_argv); | 333 | execvp(jail_argv[0], jail_argv); |
332 | perror("execvp"); | 334 | perror("execvp"); |
333 | exit(1); | 335 | exit(1); |
334 | } | 336 | } |
@@ -337,16 +339,21 @@ void x11_start_xephyr(int argc, char **argv) { | |||
337 | free(display_str); | 339 | free(display_str); |
338 | free(temp); | 340 | free(temp); |
339 | 341 | ||
340 | // wait for either server or client termination | 342 | // wait for either server or jail termination |
341 | pid_t pid = wait(); | 343 | pid_t pid = wait(NULL); |
342 | 344 | ||
343 | // see which process terminated and kill other | 345 | // see which process terminated and kill other |
344 | if (pid == server) { | 346 | if (pid == server) { |
345 | kill(client, SIGTERM); | 347 | kill(jail, SIGTERM); |
346 | } else if (pid == client) { | 348 | } else if (pid == jail) { |
347 | kill(server, SIGTERM); | 349 | kill(server, SIGTERM); |
348 | } | 350 | } |
349 | 351 | ||
352 | // without this closing Xephyr window may mess your terminal: | ||
353 | // "monitoring" process will release terminal before | ||
354 | // jail process ends and releases terminal | ||
355 | wait(NULL); // fulneral | ||
356 | |||
350 | exit(0); | 357 | exit(0); |
351 | } | 358 | } |
352 | 359 | ||
@@ -381,6 +388,13 @@ void x11_start_xpra(int argc, char **argv) { | |||
381 | // build the start command | 388 | // build the start command |
382 | char *server_argv[] = { "xpra", "start", display_str, "--no-daemon", NULL }; | 389 | char *server_argv[] = { "xpra", "start", display_str, "--no-daemon", NULL }; |
383 | 390 | ||
391 | int fd_null = -1; | ||
392 | if (arg_quiet) { | ||
393 | fd_null = open("/dev/null", O_RDWR); | ||
394 | if (fd_null == -1) | ||
395 | errExit("open"); | ||
396 | } | ||
397 | |||
384 | // start | 398 | // start |
385 | server = fork(); | 399 | server = fork(); |
386 | if (server < 0) | 400 | if (server < 0) |
@@ -388,6 +402,12 @@ void x11_start_xpra(int argc, char **argv) { | |||
388 | if (server == 0) { | 402 | if (server == 0) { |
389 | if (arg_debug) | 403 | if (arg_debug) |
390 | printf("Starting xpra...\n"); | 404 | printf("Starting xpra...\n"); |
405 | |||
406 | if (arg_quiet && fd_null != -1) { | ||
407 | dup2(fd_null,0); | ||
408 | dup2(fd_null,1); | ||
409 | dup2(fd_null,2); | ||
410 | } | ||
391 | 411 | ||
392 | execvp(server_argv[0], server_argv); | 412 | execvp(server_argv[0], server_argv); |
393 | perror("execvp"); | 413 | perror("execvp"); |
@@ -404,8 +424,7 @@ void x11_start_xpra(int argc, char **argv) { | |||
404 | sleep(1); | 424 | sleep(1); |
405 | if (stat(fname, &s) == 0) | 425 | if (stat(fname, &s) == 0) |
406 | break; | 426 | break; |
407 | }; | 427 | } |
408 | // sleep(1); | ||
409 | 428 | ||
410 | if (n == 10) { | 429 | if (n == 10) { |
411 | fprintf(stderr, "Error: failed to start xpra\n"); | 430 | fprintf(stderr, "Error: failed to start xpra\n"); |
@@ -427,7 +446,15 @@ void x11_start_xpra(int argc, char **argv) { | |||
427 | if (client < 0) | 446 | if (client < 0) |
428 | errExit("fork"); | 447 | errExit("fork"); |
429 | if (client == 0) { | 448 | if (client == 0) { |
430 | printf("\n*** Attaching to xpra display %d ***\n\n", display); | 449 | if (arg_quiet && fd_null != -1) { |
450 | dup2(fd_null,0); | ||
451 | dup2(fd_null,1); | ||
452 | dup2(fd_null,2); | ||
453 | } | ||
454 | |||
455 | if (!arg_quiet) | ||
456 | printf("\n*** Attaching to xpra display %d ***\n\n", display); | ||
457 | |||
431 | execvp(attach_argv[0], attach_argv); | 458 | execvp(attach_argv[0], attach_argv); |
432 | perror("execvp"); | 459 | perror("execvp"); |
433 | exit(1); | 460 | exit(1); |
@@ -467,26 +494,54 @@ void x11_start_xpra(int argc, char **argv) { | |||
467 | if (!arg_quiet) | 494 | if (!arg_quiet) |
468 | printf("Xpra server pid %d, xpra client pid %d, jail %d\n", server, client, jail); | 495 | printf("Xpra server pid %d, xpra client pid %d, jail %d\n", server, client, jail); |
469 | 496 | ||
497 | sleep(1); // let jail start | ||
498 | |||
470 | // wait for jail or server to end | 499 | // wait for jail or server to end |
471 | while (1) { | 500 | while (1) { |
472 | pid_t pid = wait(); | 501 | pid_t pid = wait(NULL); |
473 | 502 | ||
474 | if (pid == jail) { | 503 | if (pid == jail) { |
475 | sleep(3); // FIXME: find better way to wait for xpra | ||
476 | char *stop_argv[] = { "xpra", "stop", display_str, NULL }; | 504 | char *stop_argv[] = { "xpra", "stop", display_str, NULL }; |
477 | pid_t stop = fork(); | 505 | pid_t stop = fork(); |
478 | if (stop < 0) | 506 | if (stop < 0) |
479 | errExit("fork"); | 507 | errExit("fork"); |
480 | if (stop == 0) { | 508 | if (stop == 0) { |
509 | if (arg_quiet && fd_null != -1) { | ||
510 | dup2(fd_null,0); | ||
511 | dup2(fd_null,1); | ||
512 | dup2(fd_null,2); | ||
513 | } | ||
481 | execvp(stop_argv[0], stop_argv); | 514 | execvp(stop_argv[0], stop_argv); |
482 | perror("execvp"); | 515 | perror("execvp"); |
483 | exit(1); | 516 | exit(1); |
484 | } | 517 | } |
485 | sleep(3); | 518 | |
519 | // wait for xpra server to stop, 10 seconds limit | ||
520 | while (++n < 10) { | ||
521 | sleep(1); | ||
522 | pid = waitpid(server, NULL, WNOHANG); | ||
523 | if (pid == server) | ||
524 | break; | ||
525 | } | ||
526 | |||
527 | if (arg_debug) | ||
528 | if (n == 10) | ||
529 | printf("failed to stop xpra server gratefully\n"); | ||
530 | else | ||
531 | printf("xpra server successfully stoped in %d secs\n", n); | ||
532 | |||
533 | // kill xpra server and xpra client | ||
486 | kill(client, SIGTERM); | 534 | kill(client, SIGTERM); |
487 | kill(server, SIGTERM); | 535 | kill(server, SIGTERM); |
488 | exit(0); | 536 | exit(0); |
489 | } | 537 | } |
538 | else if (pid == server) { | ||
539 | // kill firejail process | ||
540 | kill(jail, SIGTERM); | ||
541 | // kill xpra client (should die with server, but...) | ||
542 | kill(client, SIGTERM); | ||
543 | exit(0); | ||
544 | } | ||
490 | } | 545 | } |
491 | } | 546 | } |
492 | 547 | ||