diff options
-rw-r--r-- | src/firejail/firejail.h | 1 | ||||
-rw-r--r-- | src/firejail/fs_trace.c | 76 | ||||
-rw-r--r-- | src/firejail/fs_whitelist.c | 5 | ||||
-rw-r--r-- | src/firejail/sandbox.c | 10 |
4 files changed, 51 insertions, 41 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 4a59522bf..a6377261f 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -560,6 +560,7 @@ void caps_drop_dac_override(void); | |||
560 | 560 | ||
561 | // fs_trace.c | 561 | // fs_trace.c |
562 | void fs_trace_preload(void); | 562 | void fs_trace_preload(void); |
563 | void fs_tracefile(void); | ||
563 | void fs_trace(void); | 564 | void fs_trace(void); |
564 | 565 | ||
565 | // fs_hostname.c | 566 | // fs_hostname.c |
diff --git a/src/firejail/fs_trace.c b/src/firejail/fs_trace.c index 9ade0bdc3..c1b821cce 100644 --- a/src/firejail/fs_trace.c +++ b/src/firejail/fs_trace.c | |||
@@ -41,44 +41,46 @@ void fs_trace_preload(void) { | |||
41 | fclose(fp); | 41 | fclose(fp); |
42 | fs_logger("touch /etc/ld.so.preload"); | 42 | fs_logger("touch /etc/ld.so.preload"); |
43 | } | 43 | } |
44 | if (arg_tracefile) { | 44 | } |
45 | if (arg_debug) | 45 | |
46 | printf("Creating an empty trace log file: %s\n", arg_tracefile); | 46 | void fs_tracefile(void) { |
47 | // create a bind mounted trace logfile that the sandbox can see | 47 | // create a bind mounted trace logfile that the sandbox can see |
48 | EUID_USER(); | 48 | if (arg_debug) |
49 | int fd = open(arg_tracefile, O_CREAT|O_RDWR, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH); | 49 | printf("Creating an empty trace log file: %s\n", arg_tracefile); |
50 | if (fd == -1) { | 50 | EUID_USER(); |
51 | perror("open"); | 51 | int fd = open(arg_tracefile, O_CREAT|O_WRONLY|O_CLOEXEC, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH); |
52 | fprintf(stderr, "Error: cannot open trace log file %s\n", arg_tracefile); | 52 | if (fd == -1) { |
53 | exit(1); | 53 | perror("open"); |
54 | } | 54 | fprintf(stderr, "Error: cannot open trace log file %s for writing\n", arg_tracefile); |
55 | if (fstat(fd, &s) == -1) | 55 | exit(1); |
56 | errExit("fstat"); | 56 | } |
57 | if (!S_ISREG(s.st_mode)) { | 57 | struct stat s; |
58 | fprintf(stderr, "Error: cannot write trace log: %s is no regular file\n", arg_tracefile); | 58 | if (fstat(fd, &s) == -1) |
59 | exit(1); | 59 | errExit("fstat"); |
60 | } | 60 | if (!S_ISREG(s.st_mode)) { |
61 | if (ftruncate(fd, 0) == -1) | 61 | fprintf(stderr, "Error: cannot write trace log: %s is no regular file\n", arg_tracefile); |
62 | errExit("ftruncate"); | 62 | exit(1); |
63 | EUID_ROOT(); | ||
64 | FILE *fp = fopen(RUN_TRACE_FILE, "w"); | ||
65 | if (!fp) | ||
66 | errExit("fopen " RUN_TRACE_FILE); | ||
67 | fclose(fp); | ||
68 | fs_logger2("touch ", arg_tracefile); | ||
69 | // mount using the symbolic link in /proc/self/fd | ||
70 | if (arg_debug) | ||
71 | printf("Bind mount %s to %s\n", arg_tracefile, RUN_TRACE_FILE); | ||
72 | char *proc; | ||
73 | if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1) | ||
74 | errExit("asprintf"); | ||
75 | if (mount(proc, RUN_TRACE_FILE, NULL, MS_BIND|MS_REC, NULL) < 0) | ||
76 | errExit("mount bind " RUN_TRACE_FILE); | ||
77 | free(proc); | ||
78 | close(fd); | ||
79 | // now that RUN_TRACE_FILE is user-writable, mount it noexec | ||
80 | fs_remount(RUN_TRACE_FILE, MOUNT_NOEXEC, 0); | ||
81 | } | 63 | } |
64 | if (ftruncate(fd, 0) == -1) | ||
65 | errExit("ftruncate"); | ||
66 | EUID_ROOT(); | ||
67 | FILE *fp = fopen(RUN_TRACE_FILE, "w"); | ||
68 | if (!fp) | ||
69 | errExit("fopen " RUN_TRACE_FILE); | ||
70 | fclose(fp); | ||
71 | fs_logger2("touch ", arg_tracefile); | ||
72 | // mount using the symbolic link in /proc/self/fd | ||
73 | if (arg_debug) | ||
74 | printf("Bind mount %s to %s\n", arg_tracefile, RUN_TRACE_FILE); | ||
75 | char *proc; | ||
76 | if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1) | ||
77 | errExit("asprintf"); | ||
78 | if (mount(proc, RUN_TRACE_FILE, NULL, MS_BIND|MS_REC, NULL) < 0) | ||
79 | errExit("mount bind " RUN_TRACE_FILE); | ||
80 | free(proc); | ||
81 | close(fd); | ||
82 | // now that RUN_TRACE_FILE is user-writable, mount it noexec | ||
83 | fs_remount(RUN_TRACE_FILE, MOUNT_NOEXEC, 0); | ||
82 | } | 84 | } |
83 | 85 | ||
84 | void fs_trace(void) { | 86 | void fs_trace(void) { |
diff --git a/src/firejail/fs_whitelist.c b/src/firejail/fs_whitelist.c index fa93751cc..d2ea495ed 100644 --- a/src/firejail/fs_whitelist.c +++ b/src/firejail/fs_whitelist.c | |||
@@ -290,7 +290,8 @@ static void whitelist_path(ProfileEntry *entry) { | |||
290 | 290 | ||
291 | fs_logger2("whitelist", path); | 291 | fs_logger2("whitelist", path); |
292 | 292 | ||
293 | // mount via the link in /proc/self/fd | 293 | // in order to make this mount resilient against symlink attacks, use |
294 | // a magic link in /proc/self/fd instead of mounting on path directly | ||
294 | char *proc; | 295 | char *proc; |
295 | if (asprintf(&proc, "/proc/self/fd/%d", fd3) == -1) | 296 | if (asprintf(&proc, "/proc/self/fd/%d", fd3) == -1) |
296 | errExit("asprintf"); | 297 | errExit("asprintf"); |
@@ -315,7 +316,7 @@ static void whitelist_path(ProfileEntry *entry) { | |||
315 | // - there should be more than one '/' char in dest string | 316 | // - there should be more than one '/' char in dest string |
316 | if (mptr->dir == strrchr(mptr->dir, '/')) | 317 | if (mptr->dir == strrchr(mptr->dir, '/')) |
317 | errLogExit("invalid whitelist mount"); | 318 | errLogExit("invalid whitelist mount"); |
318 | // confirm the right file was mounted | 319 | // confirm the right file was mounted by comparing device and inode numbers |
319 | int fd4 = safe_fd(path, O_PATH|O_NOFOLLOW|O_CLOEXEC); | 320 | int fd4 = safe_fd(path, O_PATH|O_NOFOLLOW|O_CLOEXEC); |
320 | if (fd4 == -1) | 321 | if (fd4 == -1) |
321 | errExit("safe_fd"); | 322 | errExit("safe_fd"); |
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 288726d22..51c531159 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c | |||
@@ -800,8 +800,11 @@ int sandbox(void* sandbox_arg) { | |||
800 | } | 800 | } |
801 | 801 | ||
802 | // trace pre-install | 802 | // trace pre-install |
803 | if (need_preload) | 803 | if (need_preload) { |
804 | fs_trace_preload(); | 804 | fs_trace_preload(); |
805 | if (arg_tracefile && !cfg.chrootdir) | ||
806 | fs_tracefile(); | ||
807 | } | ||
805 | 808 | ||
806 | // store hosts file | 809 | // store hosts file |
807 | if (cfg.hosts_file) | 810 | if (cfg.hosts_file) |
@@ -817,8 +820,11 @@ int sandbox(void* sandbox_arg) { | |||
817 | //**************************** | 820 | //**************************** |
818 | // trace pre-install, this time inside chroot | 821 | // trace pre-install, this time inside chroot |
819 | //**************************** | 822 | //**************************** |
820 | if (need_preload) | 823 | if (need_preload) { |
821 | fs_trace_preload(); | 824 | fs_trace_preload(); |
825 | if (arg_tracefile) | ||
826 | fs_tracefile(); | ||
827 | } | ||
822 | } | 828 | } |
823 | else | 829 | else |
824 | #endif | 830 | #endif |