aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@yahoo.com>2016-08-12 10:18:44 -0400
committerLibravatar GitHub <noreply@github.com>2016-08-12 10:18:44 -0400
commit1624a51126c02630366dafc612375604455ddaf8 (patch)
tree67485f151eb4f75c3f2545313b34eae2d3df5289 /src
parentreverted audit/x11 (diff)
parent--x11=xpra rewrite (diff)
downloadfirejail-1624a51126c02630366dafc612375604455ddaf8.tar.gz
firejail-1624a51126c02630366dafc612375604455ddaf8.tar.zst
firejail-1624a51126c02630366dafc612375604455ddaf8.zip
Merge pull request #701 from manevich/x11
rewrite of X11 support
Diffstat (limited to 'src')
-rw-r--r--src/firejail/x11.c265
1 files changed, 169 insertions, 96 deletions
diff --git a/src/firejail/x11.c b/src/firejail/x11.c
index 090ff6f3b..58908e9df 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
163void x11_start_xephyr(int argc, char **argv) { 163void 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,33 +320,39 @@ 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}
293 352
294void x11_start_xpra(int argc, char **argv) { 353void x11_start_xpra(int argc, char **argv) {
295 EUID_ASSERT(); 354 EUID_ASSERT();
296 int i; 355 size_t i;
297 struct stat s; 356 struct stat s;
298 pid_t client = 0; 357 pid_t client = 0;
299 pid_t server = 0; 358 pid_t server = 0;
@@ -315,40 +374,14 @@ void x11_start_xpra(int argc, char **argv) {
315 } 374 }
316 375
317 int display = random_display_number(); 376 int display = random_display_number();
377 char *display_str;
378 if (asprintf(&display_str, ":%d", display) == -1)
379 errExit("asprintf");
318 380
319 // build the start command 381 // build the start command
320 int len = 50; // xpra start... 382 char *server_argv[] = { "xpra", "start", display_str, "--no-daemon", NULL };
321 for (i = 0; i < argc; i++) {
322 len += strlen(argv[i]) + 1; // + ' '
323 }
324
325 char *cmd1 = malloc(len + 1); // + '\0'
326 if (!cmd1)
327 errExit("malloc");
328
329 sprintf(cmd1, "xpra start :%d --exit-with-children --start-child=\"", display);
330 char *ptr = cmd1 + strlen(cmd1);
331 for (i = 0; i < argc; i++) {
332 if (strcmp(argv[i], "--x11") == 0)
333 continue;
334 if (strcmp(argv[i], "--x11=xpra") == 0)
335 continue;
336 if (strcmp(argv[i], "--x11=xephyr") == 0)
337 continue;
338 ptr += sprintf(ptr, "%s ", argv[i]);
339 }
340 sprintf(ptr, "\"");
341 if (arg_debug)
342 printf("xpra server: %s\n", cmd1);
343
344 // build the attach command
345 char *cmd2;
346 if (asprintf(&cmd2, "xpra --title=\"firejail x11 sandbox\" attach :%d", display) == -1)
347 errExit("asprintf");
348 if (arg_debug)
349 printf("xpra client: %s\n", cmd2);
350 383
351 signal(SIGHUP,SIG_IGN); // fix sleep(1) below 384 // start
352 server = fork(); 385 server = fork();
353 if (server < 0) 386 if (server < 0)
354 errExit("fork"); 387 errExit("fork");
@@ -356,13 +389,7 @@ void x11_start_xpra(int argc, char **argv) {
356 if (arg_debug) 389 if (arg_debug)
357 printf("Starting xpra...\n"); 390 printf("Starting xpra...\n");
358 391
359 char *a[4]; 392 execvp(server_argv[0], server_argv);
360 a[0] = "/bin/bash";
361 a[1] = "-c";
362 a[2] = cmd1;
363 a[3] = NULL;
364
365 execvp(a[0], a);
366 perror("execvp"); 393 perror("execvp");
367 exit(1); 394 exit(1);
368 } 395 }
@@ -378,13 +405,13 @@ void x11_start_xpra(int argc, char **argv) {
378 if (stat(fname, &s) == 0) 405 if (stat(fname, &s) == 0)
379 break; 406 break;
380 }; 407 };
408// sleep(1);
381 409
382 if (n == 10) { 410 if (n == 10) {
383 fprintf(stderr, "Error: failed to start xpra\n"); 411 fprintf(stderr, "Error: failed to start xpra\n");
384 exit(1); 412 exit(1);
385 } 413 }
386 free(fname); 414 free(fname);
387 sleep(1);
388 415
389 if (arg_debug) { 416 if (arg_debug) {
390 printf("X11 sockets: "); fflush(0); 417 printf("X11 sockets: "); fflush(0);
@@ -392,28 +419,74 @@ void x11_start_xpra(int argc, char **argv) {
392 (void) rv; 419 (void) rv;
393 } 420 }
394 421
422 // build attach command
423 char *attach_argv[] = { "xpra", "--title=\"firejail x11 sandbox\"", "attach", display_str };
424
395 // run attach command 425 // run attach command
396 client = fork(); 426 client = fork();
397 if (client < 0) 427 if (client < 0)
398 errExit("fork"); 428 errExit("fork");
399 if (client == 0) { 429 if (client == 0) {
400 printf("\n*** Attaching to xpra display %d ***\n\n", display); 430 printf("\n*** Attaching to xpra display %d ***\n\n", display);
401 char *a[4]; 431 execvp(attach_argv[0], attach_argv);
402 a[0] = "/bin/bash";
403 a[1] = "-c";
404 a[2] = cmd2;
405 a[3] = NULL;
406
407 execvp(a[0], a);
408 perror("execvp"); 432 perror("execvp");
409 exit(1); 433 exit(1);
410 } 434 }
411 sleep(1);
412
413 if (!arg_quiet)
414 printf("Xpra server pid %d, client pid %d\n", server, client);
415 435
416 exit(0); 436 setenv("DISPLAY", display_str, 1);
437
438 // build jail command
439 char *firejail_argv[argc+2];
440 unsigned pos = 0;
441 for (i = 0; i < argc; i++) {
442 if (strcmp(argv[i], "--x11") == 0)
443 continue;
444 if (strcmp(argv[i], "--x11=xpra") == 0)
445 continue;
446 if (strcmp(argv[i], "--x11=xephyr") == 0)
447 continue;
448 firejail_argv[pos] = argv[i];
449 pos++;
450 }
451 firejail_argv[pos] = NULL;
452
453 assert(pos < argc+2);
454 assert(!firejail_argv[pos]);
455
456 // start jail
457 pid_t jail = fork();
458 if (jail < 0)
459 errExit("fork");
460 if (jail == 0) {
461 execvp(firejail_argv[0], firejail_argv);
462 perror("execvp");
463 exit(1);
464 }
465
466 if (!arg_quiet)
467 printf("Xpra server pid %d, xpra client pid %d, jail %d\n", server, client, jail);
468
469 // wait for jail or server to end
470 while (1) {
471 pid_t pid = wait();
472
473 if (pid == jail) {
474 sleep(3); // FIXME: find better way to wait for xpra
475 char *stop_argv[] = { "xpra", "stop", display_str, NULL };
476 pid_t stop = fork();
477 if (stop < 0)
478 errExit("fork");
479 if (stop == 0) {
480 execvp(stop_argv[0], stop_argv);
481 perror("execvp");
482 exit(1);
483 }
484 sleep(3);
485 kill(client, SIGTERM);
486 kill(server, SIGTERM);
487 exit(0);
488 }
489 }
417} 490}
418 491
419void x11_start(int argc, char **argv) { 492void x11_start(int argc, char **argv) {