From 85195f55733b5a369ddbc335393b3a16e10647a5 Mon Sep 17 00:00:00 2001 From: Aleksey Manevich Date: Sat, 10 Sep 2016 21:16:09 +0300 Subject: add x11=block option --- src/firejail/firejail.h | 2 ++ src/firejail/main.c | 8 +++++++ src/firejail/profile.c | 39 +++++++++++++++++++++++++++++++++++ src/firejail/x11.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 104 insertions(+) (limited to 'src') diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 776bfbc74..ed9d901c0 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -315,6 +315,7 @@ extern int arg_audit; // audit extern char *arg_audit_prog; // audit extern int arg_apparmor; // apparmor extern int arg_allow_debuggers; // allow debuggers +extern int arg_x11_block; // block X11 extern int login_shell; extern int parent_to_child_fds[2]; @@ -623,6 +624,7 @@ int x11_display(void); void x11_start(int argc, char **argv); void x11_start_xpra(int argc, char **argv); void x11_start_xephyr(int argc, char **argv); +void x11_block(void); // ls.c #define SANDBOX_FS_LS 0 diff --git a/src/firejail/main.c b/src/firejail/main.c index 569fc7add..e171919d1 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c @@ -105,6 +105,7 @@ int arg_audit = 0; // audit char *arg_audit_prog = NULL; // audit int arg_apparmor = 0; // apparmor int arg_allow_debuggers = 0; // allow debuggers +int arg_x11_block = 0; // block X11 int login_shell = 0; int parent_to_child_fds[2]; @@ -2118,6 +2119,9 @@ int main(int argc, char **argv) { return 1; } } + else if (strcmp(argv[i], "--x11=block") == 0) { + arg_x11_block = 1; + } else if (strcmp(argv[i], "--") == 0) { // double dash - positional params to follow arg_doubledash = 1; @@ -2284,6 +2288,10 @@ int main(int argc, char **argv) { } } + // block X11 sockets + if (arg_x11_block) + x11_block(); + // check network configuration options - it will exit if anything went wrong net_check_cfg(); diff --git a/src/firejail/profile.c b/src/firejail/profile.c index a516f3216..00301037f 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c @@ -625,6 +625,45 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { arg_private = 1; return 0; } + + if (strcmp(ptr, "x11 block") == 0) { +#ifdef HAVE_X11 + arg_x11_block = 1; +#endif + return 0; + } + + if (strcmp(ptr, "x11 xephyr") == 0) { +#ifdef HAVE_X11 + if (checkcfg(CFG_X11)) { + char *x11env = getenv("FIREJAIL_X11"); + if (x11env && strcmp(x11env, "yes") == 0) + return 0; + else { + // start x11 + x11_start_xephyr(cfg.original_argc, cfg.original_argv); + exit(0); + } + } +#endif + return 0; + } + + if (strcmp(ptr, "x11 xpra") == 0) { +#ifdef HAVE_X11 + if (checkcfg(CFG_X11)) { + char *x11env = getenv("FIREJAIL_X11"); + if (x11env && strcmp(x11env, "yes") == 0) + return 0; + else { + // start x11 + x11_start_xpra(cfg.original_argc, cfg.original_argv); + exit(0); + } + } +#endif + return 0; + } if (strcmp(ptr, "x11") == 0) { #ifdef HAVE_X11 diff --git a/src/firejail/x11.c b/src/firejail/x11.c index 5c6f045e7..29111d5ff 100644 --- a/src/firejail/x11.c +++ b/src/firejail/x11.c @@ -51,6 +51,27 @@ static int x11_check_xephyr(void) { return 1; } +// check for X11 abstract sockets +static int x11_abstract_sockets_present(void) { + char *path; + FILE *fp = fopen("/proc/net/unix", "r"); + if (!fp) + errExit("fopen"); + + while (fscanf(fp, "%*s %*s %*s %*s %*s %*s %*s %ms\n", &path) != EOF) { + if (path && strncmp(path, "@/tmp/.X11-unix/", 16) == 0) { + free(path); + fclose(fp); + return 1; + } + } + + free(path); + fclose(fp); + + return 0; +} + static int random_display_number(void) { int i; int found = 1; @@ -566,3 +587,37 @@ void x11_start(int argc, char **argv) { } #endif + +void x11_block(void) { +#ifdef HAVE_X11 + // check abstract socket presence and network namespace options + if ((!arg_nonetwork && !cfg.bridge0.configured && !cfg.interface0.configured) + && x11_abstract_sockets_present()) { + fprintf(stderr, "ERROR: --x11=block specified, but abstract X11 socket still accessible.\n" + "Additional setup required. To block abstract X11 socket you need either:\n" + " * use network namespace (--net=none, --net=...)\n" + " * add \"-nolisten local\" to xserver options (eg. /etc/X11/xinit/xserverrc)\n"); + exit(1); + } + + // blacklist sockets + profile_check_line("blacklist /tmp/.X11-unix", 0, NULL); + profile_add(strdup("blacklist /tmp/.X11-unix")); + + // blacklist .Xauthority + profile_check_line("blacklist ${HOME}/.Xauthority", 0, NULL); + profile_add(strdup("blacklist ${HOME}/.Xauthority")); + char *xauthority = getenv("XAUTHORITY"); + if (xauthority) { + char *line; + if (asprintf(&line, "blacklist %s", xauthority) == -1) + errExit("asprintf"); + profile_check_line(line, 0, NULL); + profile_add(line); + } + + // clear enviroment + env_store("DISPLAY", RMENV); + env_store("XAUTHORITY", RMENV); +#endif +} -- cgit v1.2.3-70-g09d2