diff options
author | 2021-06-03 18:47:30 +0200 | |
---|---|---|
committer | 2021-06-03 18:47:30 +0200 | |
commit | acbdbe29da9a04bd3b7a6c584e7633aae8dbe5c5 (patch) | |
tree | 3b7b09abebad7994c013c083c7d49bbd7b8ab27e /src | |
parent | Update profile.template (diff) | |
download | firejail-acbdbe29da9a04bd3b7a6c584e7633aae8dbe5c5.tar.gz firejail-acbdbe29da9a04bd3b7a6c584e7633aae8dbe5c5.tar.zst firejail-acbdbe29da9a04bd3b7a6c584e7633aae8dbe5c5.zip |
simplify X11 socket whitelisting
Diffstat (limited to 'src')
-rw-r--r-- | src/firejail/x11.c | 63 | ||||
-rw-r--r-- | src/include/rundefs.h | 4 |
2 files changed, 22 insertions, 45 deletions
diff --git a/src/firejail/x11.c b/src/firejail/x11.c index 257d376a1..f4f093138 100644 --- a/src/firejail/x11.c +++ b/src/firejail/x11.c | |||
@@ -1327,7 +1327,7 @@ void fs_x11(void) { | |||
1327 | struct stat s1, s2; | 1327 | struct stat s1, s2; |
1328 | if (stat("/tmp", &s1) != 0 || lstat("/tmp/.X11-unix", &s2) != 0) | 1328 | if (stat("/tmp", &s1) != 0 || lstat("/tmp/.X11-unix", &s2) != 0) |
1329 | return; | 1329 | return; |
1330 | if ((s1.st_mode & S_ISVTX) == 0) { | 1330 | if ((s1.st_mode & S_ISVTX) != S_ISVTX) { |
1331 | fwarning("cannot mask X11 sockets: sticky bit not set on /tmp directory\n"); | 1331 | fwarning("cannot mask X11 sockets: sticky bit not set on /tmp directory\n"); |
1332 | return; | 1332 | return; |
1333 | } | 1333 | } |
@@ -1335,26 +1335,26 @@ void fs_x11(void) { | |||
1335 | fwarning("cannot mask X11 sockets: /tmp/.X11-unix not owned by root user\n"); | 1335 | fwarning("cannot mask X11 sockets: /tmp/.X11-unix not owned by root user\n"); |
1336 | return; | 1336 | return; |
1337 | } | 1337 | } |
1338 | |||
1338 | char *x11file; | 1339 | char *x11file; |
1339 | if (asprintf(&x11file, "/tmp/.X11-unix/X%d", display) == -1) | 1340 | if (asprintf(&x11file, "/tmp/.X11-unix/X%d", display) == -1) |
1340 | errExit("asprintf"); | 1341 | errExit("asprintf"); |
1342 | int src = open(x11file, O_PATH|O_NOFOLLOW|O_CLOEXEC); | ||
1343 | if (src < 0) { | ||
1344 | free(x11file); | ||
1345 | return; | ||
1346 | } | ||
1341 | struct stat x11stat; | 1347 | struct stat x11stat; |
1342 | if (lstat(x11file, &x11stat) != 0 || !S_ISSOCK(x11stat.st_mode)) { | 1348 | if (fstat(src, &x11stat) < 0) |
1349 | errExit("fstat"); | ||
1350 | if (!S_ISSOCK(x11stat.st_mode)) { | ||
1351 | close(src); | ||
1343 | free(x11file); | 1352 | free(x11file); |
1344 | return; | 1353 | return; |
1345 | } | 1354 | } |
1346 | 1355 | ||
1347 | if (arg_debug || arg_debug_whitelists) | 1356 | if (arg_debug || arg_debug_whitelists) |
1348 | fprintf(stderr, "Masking all X11 sockets except %s\n", x11file); | 1357 | fprintf(stderr, "Masking all X11 sockets except %s\n", x11file); |
1349 | |||
1350 | // Move the real /tmp/.X11-unix to a scratch location | ||
1351 | // so we can still access x11file after we mount a | ||
1352 | // tmpfs over /tmp/.X11-unix. | ||
1353 | if (mkdir(RUN_WHITELIST_X11_DIR, 0700) == -1) | ||
1354 | errExit("mkdir"); | ||
1355 | if (mount("/tmp/.X11-unix", RUN_WHITELIST_X11_DIR, 0, MS_BIND|MS_REC, 0) < 0) | ||
1356 | errExit("mount bind"); | ||
1357 | |||
1358 | // This directory must be mode 1777 | 1358 | // This directory must be mode 1777 |
1359 | if (mount("tmpfs", "/tmp/.X11-unix", "tmpfs", | 1359 | if (mount("tmpfs", "/tmp/.X11-unix", "tmpfs", |
1360 | MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_STRICTATIME, | 1360 | MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_STRICTATIME, |
@@ -1363,40 +1363,21 @@ void fs_x11(void) { | |||
1363 | fs_logger("tmpfs /tmp/.X11-unix"); | 1363 | fs_logger("tmpfs /tmp/.X11-unix"); |
1364 | 1364 | ||
1365 | // create an empty root-owned file which will have the desired socket bind-mounted over it | 1365 | // create an empty root-owned file which will have the desired socket bind-mounted over it |
1366 | int fd = open(x11file, O_RDONLY|O_CREAT|O_EXCL|O_CLOEXEC, S_IRUSR | S_IWUSR); | 1366 | int dst = open(x11file, O_RDONLY|O_CREAT|O_EXCL|O_CLOEXEC, S_IRUSR | S_IWUSR); |
1367 | if (fd < 0) | 1367 | if (dst < 0) |
1368 | errExit(x11file); | 1368 | errExit("open"); |
1369 | close(fd); | ||
1370 | 1369 | ||
1371 | // the mount source is under control of the user, so be careful and | 1370 | char *proc_src, *proc_dst; |
1372 | // mount without following symbolic links, using a file descriptor | 1371 | if (asprintf(&proc_src, "/proc/self/fd/%d", src) == -1 || |
1373 | char *wx11file; | 1372 | asprintf(&proc_dst, "/proc/self/fd/%d", dst) == -1) |
1374 | if (asprintf(&wx11file, "%s/X%d", RUN_WHITELIST_X11_DIR, display) == -1) | ||
1375 | errExit("asprintf"); | ||
1376 | fd = safer_openat(-1, wx11file, O_PATH|O_NOFOLLOW|O_CLOEXEC); | ||
1377 | if (fd == -1) | ||
1378 | errExit("opening X11 socket"); | ||
1379 | // confirm once more we are mounting a socket | ||
1380 | if (fstat(fd, &x11stat) == -1) | ||
1381 | errExit("fstat"); | ||
1382 | if (!S_ISSOCK(x11stat.st_mode)) { | ||
1383 | errno = ENOTSOCK; | ||
1384 | errExit("mounting X11 socket"); | ||
1385 | } | ||
1386 | char *proc; | ||
1387 | if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1) | ||
1388 | errExit("asprintf"); | 1373 | errExit("asprintf"); |
1389 | if (mount(proc, x11file, NULL, MS_BIND|MS_REC, NULL) < 0) | 1374 | if (mount(proc_src, proc_dst, NULL, MS_BIND | MS_REC, NULL) < 0) |
1390 | errExit("mount bind"); | 1375 | errExit("mount bind"); |
1376 | free(proc_src); | ||
1377 | free(proc_dst); | ||
1378 | close(src); | ||
1379 | close(dst); | ||
1391 | fs_logger2("whitelist", x11file); | 1380 | fs_logger2("whitelist", x11file); |
1392 | close(fd); | ||
1393 | free(proc); | ||
1394 | |||
1395 | // block access to RUN_WHITELIST_X11_DIR | ||
1396 | if (mount(RUN_RO_DIR, RUN_WHITELIST_X11_DIR, 0, MS_BIND, 0) < 0) | ||
1397 | errExit("mount"); | ||
1398 | fs_logger2("blacklist", RUN_WHITELIST_X11_DIR); | ||
1399 | free(wx11file); | ||
1400 | free(x11file); | 1381 | free(x11file); |
1401 | #endif | 1382 | #endif |
1402 | } | 1383 | } |
diff --git a/src/include/rundefs.h b/src/include/rundefs.h index a172dd511..3db750da3 100644 --- a/src/include/rundefs.h +++ b/src/include/rundefs.h | |||
@@ -79,12 +79,8 @@ | |||
79 | #define PATH_SECCOMP_MDWX_32 LIBDIR "/firejail/seccomp.mdwx.32" | 79 | #define PATH_SECCOMP_MDWX_32 LIBDIR "/firejail/seccomp.mdwx.32" |
80 | #define PATH_SECCOMP_BLOCK_SECONDARY LIBDIR "/firejail/seccomp.block_secondary" // secondary arch blocking filter built during make | 80 | #define PATH_SECCOMP_BLOCK_SECONDARY LIBDIR "/firejail/seccomp.block_secondary" // secondary arch blocking filter built during make |
81 | 81 | ||
82 | |||
83 | #define RUN_DEV_DIR RUN_MNT_DIR "/dev" | 82 | #define RUN_DEV_DIR RUN_MNT_DIR "/dev" |
84 | #define RUN_DEVLOG_FILE RUN_MNT_DIR "/devlog" | 83 | #define RUN_DEVLOG_FILE RUN_MNT_DIR "/devlog" |
85 | |||
86 | #define RUN_WHITELIST_X11_DIR RUN_MNT_DIR "/orig-x11" | ||
87 | |||
88 | #define RUN_XAUTHORITY_FILE RUN_MNT_DIR "/.Xauthority" // private options | 84 | #define RUN_XAUTHORITY_FILE RUN_MNT_DIR "/.Xauthority" // private options |
89 | #define RUN_XAUTH_FILE RUN_MNT_DIR "/xauth" // x11=xorg | 85 | #define RUN_XAUTH_FILE RUN_MNT_DIR "/xauth" // x11=xorg |
90 | #define RUN_XAUTHORITY_SEC_DIR RUN_MNT_DIR "/.sec.Xauthority" // x11=xorg | 86 | #define RUN_XAUTHORITY_SEC_DIR RUN_MNT_DIR "/.sec.Xauthority" // x11=xorg |