diff options
-rw-r--r-- | etc/inc/disable-proc.inc | 82 | ||||
-rw-r--r-- | etc/profile-a-l/jumpnbump-menu.profile | 2 | ||||
-rw-r--r-- | etc/profile-m-z/tremulous.profile | 5 | ||||
-rw-r--r-- | etc/profile-m-z/warsow.profile | 7 | ||||
-rw-r--r-- | etc/templates/profile.template | 1 | ||||
-rw-r--r-- | src/fbuilder/build_fs.c | 3 | ||||
-rw-r--r-- | src/firejail/firejail.h | 3 | ||||
-rw-r--r-- | src/firejail/fs.c | 11 | ||||
-rw-r--r-- | src/firejail/main.c | 4 | ||||
-rw-r--r-- | src/firejail/mountinfo.c | 149 | ||||
-rw-r--r-- | src/firejail/profile.c | 5 | ||||
-rw-r--r-- | src/firejail/util.c | 74 | ||||
-rw-r--r-- | src/man/firejail.txt | 14 |
13 files changed, 226 insertions, 134 deletions
diff --git a/etc/inc/disable-proc.inc b/etc/inc/disable-proc.inc new file mode 100644 index 000000000..81a8883f3 --- /dev/null +++ b/etc/inc/disable-proc.inc | |||
@@ -0,0 +1,82 @@ | |||
1 | # This file is overwritten during software install. | ||
2 | # Persistent customizations should go in a .local file. | ||
3 | include disable-proc.local | ||
4 | |||
5 | blacklist /proc/acpi | ||
6 | blacklist /proc/asound | ||
7 | blacklist /proc/bootconfig | ||
8 | blacklist /proc/buddyinfo | ||
9 | blacklist /proc/cgroups | ||
10 | blacklist /proc/cmdline | ||
11 | blacklist /proc/config.gz | ||
12 | blacklist /proc/consoles | ||
13 | #blacklist /proc/cpuinfo | ||
14 | blacklist /proc/crypto | ||
15 | blacklist /proc/devices | ||
16 | blacklist /proc/diskstats | ||
17 | blacklist /proc/dma | ||
18 | #blacklist /proc/driver | ||
19 | blacklist /proc/dynamic_debug | ||
20 | blacklist /proc/execdomains | ||
21 | blacklist /proc/fb | ||
22 | #blacklist /proc/filesystems | ||
23 | blacklist /proc/fs | ||
24 | blacklist /proc/i8k | ||
25 | blacklist /proc/interrupts | ||
26 | blacklist /proc/iomem | ||
27 | blacklist /proc/ioports | ||
28 | blacklist /proc/irq | ||
29 | blacklist /proc/kallsyms | ||
30 | blacklist /proc/kcore | ||
31 | blacklist /proc/keys | ||
32 | blacklist /proc/key-users | ||
33 | blacklist /proc/kmsg | ||
34 | blacklist /proc/kpagecgroup | ||
35 | blacklist /proc/kpagecount | ||
36 | blacklist /proc/kpageflags | ||
37 | blacklist /proc/latency_stats | ||
38 | #blacklist /proc/loadavg | ||
39 | blacklist /proc/locks | ||
40 | blacklist /proc/mdstat | ||
41 | #blacklist /proc/meminfo | ||
42 | blacklist /proc/misc | ||
43 | #blacklist /proc/modules | ||
44 | #blacklist /proc/mounts | ||
45 | blacklist /proc/mtrr | ||
46 | #blacklist /proc/net | ||
47 | blacklist /proc/partitions | ||
48 | blacklist /proc/pressure | ||
49 | blacklist /proc/sched_debug | ||
50 | blacklist /proc/schedstat | ||
51 | blacklist /proc/scsi | ||
52 | #blacklist /proc/self | ||
53 | blacklist /proc/slabinfo | ||
54 | blacklist /proc/softirqs | ||
55 | blacklist /proc/spl | ||
56 | #blacklist /proc/stat | ||
57 | blacklist /proc/swaps | ||
58 | #blacklist /proc/sys | ||
59 | blacklist /proc/sysrq-trigger | ||
60 | blacklist /proc/sysvipc | ||
61 | #blacklist /proc/thread-self | ||
62 | blacklist /proc/timer_list | ||
63 | blacklist /proc/tty | ||
64 | #blacklist /proc/uptime | ||
65 | #blacklist /proc/version | ||
66 | blacklist /proc/version_signature | ||
67 | blacklist /proc/vmallocinfo | ||
68 | #blacklist /proc/vmstat | ||
69 | #blacklist /proc/zoneinfo | ||
70 | |||
71 | blacklist /proc/sys/abi | ||
72 | blacklist /proc/sys/crypto | ||
73 | blacklist /proc/sys/debug | ||
74 | blacklist /proc/sys/dev | ||
75 | blacklist /proc/sys/fs | ||
76 | blacklist /proc/sys/net | ||
77 | blacklist /proc/sys/user | ||
78 | blacklist /proc/sys/vm | ||
79 | |||
80 | noblacklist /proc/sys/kernel/osrelease | ||
81 | noblacklist /proc/sys/kernel/yama | ||
82 | blacklist /proc/sys/*/* | ||
diff --git a/etc/profile-a-l/jumpnbump-menu.profile b/etc/profile-a-l/jumpnbump-menu.profile index 8d391b90f..59d762f55 100644 --- a/etc/profile-a-l/jumpnbump-menu.profile +++ b/etc/profile-a-l/jumpnbump-menu.profile | |||
@@ -10,7 +10,7 @@ include jumpnbump-menu.local | |||
10 | # Allow python (blacklisted by disable-interpreters.inc) | 10 | # Allow python (blacklisted by disable-interpreters.inc) |
11 | include allow-python3.inc | 11 | include allow-python3.inc |
12 | 12 | ||
13 | private-bin jumpnbump-menu,python3* | 13 | private-bin env,jumpnbump-menu,python3* |
14 | 14 | ||
15 | # Redirect | 15 | # Redirect |
16 | include jumpnbump.profile | 16 | include jumpnbump.profile |
diff --git a/etc/profile-m-z/tremulous.profile b/etc/profile-m-z/tremulous.profile index 4e16df553..96541ae25 100644 --- a/etc/profile-m-z/tremulous.profile +++ b/etc/profile-m-z/tremulous.profile | |||
@@ -8,6 +8,9 @@ include globals.local | |||
8 | 8 | ||
9 | noblacklist ${HOME}/.tremulous | 9 | noblacklist ${HOME}/.tremulous |
10 | 10 | ||
11 | # Allow /bin/sh (blacklisted by disable-shell.inc) | ||
12 | include allow-bin-sh.inc | ||
13 | |||
11 | include disable-common.inc | 14 | include disable-common.inc |
12 | include disable-devel.inc | 15 | include disable-devel.inc |
13 | include disable-exec.inc | 16 | include disable-exec.inc |
@@ -41,7 +44,7 @@ shell none | |||
41 | tracelog | 44 | tracelog |
42 | 45 | ||
43 | disable-mnt | 46 | disable-mnt |
44 | private-bin tremded,tremulous,tremulous-wrapper | 47 | private-bin env,sh,tremded,tremulous,tremulous-wrapper |
45 | private-cache | 48 | private-cache |
46 | private-dev | 49 | private-dev |
47 | private-tmp | 50 | private-tmp |
diff --git a/etc/profile-m-z/warsow.profile b/etc/profile-m-z/warsow.profile index b57f9ba1d..2f818b733 100644 --- a/etc/profile-m-z/warsow.profile +++ b/etc/profile-m-z/warsow.profile | |||
@@ -11,6 +11,9 @@ ignore noexec ${HOME} | |||
11 | noblacklist ${HOME}/.cache/warsow-2.1 | 11 | noblacklist ${HOME}/.cache/warsow-2.1 |
12 | noblacklist ${HOME}/.local/share/warsow-2.1 | 12 | noblacklist ${HOME}/.local/share/warsow-2.1 |
13 | 13 | ||
14 | # Allow /bin/sh (blacklisted by disable-shell.inc) | ||
15 | include allow-bin-sh.inc | ||
16 | |||
14 | include disable-common.inc | 17 | include disable-common.inc |
15 | include disable-devel.inc | 18 | include disable-devel.inc |
16 | include disable-exec.inc | 19 | include disable-exec.inc |
@@ -39,13 +42,13 @@ noroot | |||
39 | notv | 42 | notv |
40 | nou2f | 43 | nou2f |
41 | novideo | 44 | novideo |
42 | protocol unix,inet,inet6 | 45 | protocol unix,inet,inet6,netlink |
43 | seccomp | 46 | seccomp |
44 | shell none | 47 | shell none |
45 | tracelog | 48 | tracelog |
46 | 49 | ||
47 | disable-mnt | 50 | disable-mnt |
48 | private-bin warsow | 51 | private-bin basename,bash,dirname,sed,sh,uname,warsow |
49 | private-cache | 52 | private-cache |
50 | private-dev | 53 | private-dev |
51 | private-tmp | 54 | private-tmp |
diff --git a/etc/templates/profile.template b/etc/templates/profile.template index 7628313e0..44197b547 100644 --- a/etc/templates/profile.template +++ b/etc/templates/profile.template | |||
@@ -116,6 +116,7 @@ include globals.local | |||
116 | #include disable-devel.inc | 116 | #include disable-devel.inc |
117 | #include disable-exec.inc | 117 | #include disable-exec.inc |
118 | #include disable-interpreters.inc | 118 | #include disable-interpreters.inc |
119 | #include disable-proc.inc | ||
119 | #include disable-programs.inc | 120 | #include disable-programs.inc |
120 | #include disable-shell.inc | 121 | #include disable-shell.inc |
121 | #include disable-write-mnt.inc | 122 | #include disable-write-mnt.inc |
diff --git a/src/fbuilder/build_fs.c b/src/fbuilder/build_fs.c index 8700e0ba1..a1847284c 100644 --- a/src/fbuilder/build_fs.c +++ b/src/fbuilder/build_fs.c | |||
@@ -236,9 +236,6 @@ void build_share(const char *fname, FILE *fp) { | |||
236 | //******************************************* | 236 | //******************************************* |
237 | static FileDB *tmp_out = NULL; | 237 | static FileDB *tmp_out = NULL; |
238 | static void tmp_callback(char *ptr) { | 238 | static void tmp_callback(char *ptr) { |
239 | // skip strace file | ||
240 | if (strncmp(ptr, "/tmp/firejail-strace", 20) == 0) | ||
241 | return; | ||
242 | if (strncmp(ptr, "/tmp/runtime-", 13) == 0) | 239 | if (strncmp(ptr, "/tmp/runtime-", 13) == 0) |
243 | return; | 240 | return; |
244 | if (strcmp(ptr, "/tmp") == 0) | 241 | if (strcmp(ptr, "/tmp") == 0) |
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 5bebec185..a6924b830 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -519,6 +519,7 @@ void touch_file_as_user(const char *fname, mode_t mode); | |||
519 | int is_dir(const char *fname); | 519 | int is_dir(const char *fname); |
520 | int is_link(const char *fname); | 520 | int is_link(const char *fname); |
521 | char *realpath_as_user(const char *fname); | 521 | char *realpath_as_user(const char *fname); |
522 | ssize_t readlink_as_user(const char *fname, char *buf, size_t sz); | ||
522 | int stat_as_user(const char *fname, struct stat *s); | 523 | int stat_as_user(const char *fname, struct stat *s); |
523 | int lstat_as_user(const char *fname, struct stat *s); | 524 | int lstat_as_user(const char *fname, struct stat *s); |
524 | void trim_trailing_slash_or_dot(char *path); | 525 | void trim_trailing_slash_or_dot(char *path); |
@@ -566,7 +567,7 @@ typedef struct { | |||
566 | // mountinfo.c | 567 | // mountinfo.c |
567 | MountData *get_last_mount(void); | 568 | MountData *get_last_mount(void); |
568 | int get_mount_id(int fd); | 569 | int get_mount_id(int fd); |
569 | char **build_mount_array(const int mount_id, const char *path); | 570 | char **build_mount_array(const int mountid, const char *path); |
570 | 571 | ||
571 | // fs_var.c | 572 | // fs_var.c |
572 | void fs_var_log(void); // mounting /var/log | 573 | void fs_var_log(void); // mounting /var/log |
diff --git a/src/firejail/fs.c b/src/firejail/fs.c index 0b9a38035..9c1b889ed 100644 --- a/src/firejail/fs.c +++ b/src/firejail/fs.c | |||
@@ -654,12 +654,13 @@ static void fs_remount_rec(const char *path, OPERATION op) { | |||
654 | 654 | ||
655 | // build array with all mount points that need to get remounted | 655 | // build array with all mount points that need to get remounted |
656 | char **arr = build_mount_array(mountid, path); | 656 | char **arr = build_mount_array(mountid, path); |
657 | assert(arr); | 657 | if (!arr) |
658 | return; | ||
658 | // remount | 659 | // remount |
659 | char **tmp = arr; | 660 | int i; |
660 | while (*tmp) { | 661 | for (i = 0; arr[i]; i++) { |
661 | fs_remount_simple(*tmp, op); | 662 | fs_remount_simple(arr[i], op); |
662 | free(*tmp++); | 663 | free(arr[i]); |
663 | } | 664 | } |
664 | free(arr); | 665 | free(arr); |
665 | } | 666 | } |
diff --git a/src/firejail/main.c b/src/firejail/main.c index c5b3d5739..1ba70b0bd 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -2156,6 +2156,10 @@ int main(int argc, char **argv, char **envp) { | |||
2156 | arg_novideo = 1; | 2156 | arg_novideo = 1; |
2157 | else if (strcmp(argv[i], "--no3d") == 0) | 2157 | else if (strcmp(argv[i], "--no3d") == 0) |
2158 | arg_no3d = 1; | 2158 | arg_no3d = 1; |
2159 | else if (strcmp(argv[i], "--noprinters") == 0) { | ||
2160 | profile_add("blacklist /dev/lp*"); | ||
2161 | profile_add("blacklist /run/cups/cups.sock"); | ||
2162 | } | ||
2159 | else if (strcmp(argv[i], "--notv") == 0) | 2163 | else if (strcmp(argv[i], "--notv") == 0) |
2160 | arg_notv = 1; | 2164 | arg_notv = 1; |
2161 | else if (strcmp(argv[i], "--nodvd") == 0) | 2165 | else if (strcmp(argv[i], "--nodvd") == 0) |
diff --git a/src/firejail/mountinfo.c b/src/firejail/mountinfo.c index 304f80eee..ee437e10b 100644 --- a/src/firejail/mountinfo.c +++ b/src/firejail/mountinfo.c | |||
@@ -33,43 +33,38 @@ static MountData mdata; | |||
33 | 33 | ||
34 | 34 | ||
35 | // Convert octal escape sequence to decimal value | 35 | // Convert octal escape sequence to decimal value |
36 | static int read_oct(const char *path) { | 36 | static unsigned read_oct(char *s) { |
37 | int dec = 0; | 37 | assert(s[0] == '\\'); |
38 | int digit, i; | 38 | s++; |
39 | // there are always exactly three octal digits | 39 | |
40 | for (i = 1; i < 4; i++) { | 40 | int i; |
41 | digit = *(path + i); | 41 | for (i = 0; i < 3; i++) |
42 | if (digit < '0' || digit > '7') { | 42 | assert(s[i] >= '0' && s[i] <= '7'); |
43 | fprintf(stderr, "Error: cannot read /proc/self/mountinfo\n"); | 43 | |
44 | exit(1); | 44 | return ((s[0] - '0') << 6 | |
45 | } | 45 | (s[1] - '0') << 3 | |
46 | dec = (dec << 3) + (digit - '0'); | 46 | (s[2] - '0') << 0); |
47 | } | ||
48 | return dec; | ||
49 | } | 47 | } |
50 | 48 | ||
51 | // Restore empty spaces in pathnames extracted from /proc/self/mountinfo | 49 | // Restore empty spaces in pathnames extracted from /proc/self/mountinfo |
52 | static void unmangle_path(char *path) { | 50 | static void unmangle_path(char *path) { |
53 | char *p = strchr(path, '\\'); | 51 | char *r = strchr(path, '\\'); |
54 | if (p && read_oct(p) == ' ') { | 52 | if (!r) |
55 | *p = ' '; | 53 | return; |
56 | int i = 3; | 54 | |
57 | do { | 55 | char *w = r; |
58 | p++; | 56 | do { |
59 | if (*(p + i) == '\\' && read_oct(p + i) == ' ') { | 57 | while (*r == '\\') { |
60 | *p = ' '; | 58 | *w++ = read_oct(r); |
61 | i += 3; | 59 | r += 4; |
62 | } | 60 | } |
63 | else | 61 | *w++ = *r; |
64 | *p = *(p + i); | 62 | } while (*r++); |
65 | } while (*p); | ||
66 | } | ||
67 | } | 63 | } |
68 | 64 | ||
69 | // Parse a line from /proc/self/mountinfo, | 65 | // Parse a line from /proc/self/mountinfo, |
70 | // the function does an exit(1) if anything goes wrong. | 66 | // the function does an exit(1) if anything goes wrong. |
71 | static void parse_line(char *line, MountData *output) { | 67 | static void parse_line(char *line, MountData *output) { |
72 | assert(line && output); | ||
73 | memset(output, 0, sizeof(*output)); | 68 | memset(output, 0, sizeof(*output)); |
74 | // extract mount id, filesystem name, directory and filesystem types | 69 | // extract mount id, filesystem name, directory and filesystem types |
75 | // examples: | 70 | // examples: |
@@ -87,8 +82,6 @@ static void parse_line(char *line, MountData *output) { | |||
87 | char *ptr = strtok(line, " "); | 82 | char *ptr = strtok(line, " "); |
88 | if (!ptr) | 83 | if (!ptr) |
89 | goto errexit; | 84 | goto errexit; |
90 | if (ptr != line) | ||
91 | goto errexit; | ||
92 | output->mountid = atoi(ptr); | 85 | output->mountid = atoi(ptr); |
93 | int cnt = 1; | 86 | int cnt = 1; |
94 | 87 | ||
@@ -109,10 +102,9 @@ static void parse_line(char *line, MountData *output) { | |||
109 | ptr = strtok(NULL, " "); | 102 | ptr = strtok(NULL, " "); |
110 | if (!ptr) | 103 | if (!ptr) |
111 | goto errexit; | 104 | goto errexit; |
112 | output->fstype = ptr++; | 105 | output->fstype = ptr; |
113 | 106 | ||
114 | 107 | if (output->mountid < 0 || | |
115 | if (output->mountid == 0 || | ||
116 | output->fsname == NULL || | 108 | output->fsname == NULL || |
117 | output->dir == NULL || | 109 | output->dir == NULL || |
118 | output->fstype == NULL) | 110 | output->fstype == NULL) |
@@ -195,9 +187,9 @@ static int get_mount_id_from_fdinfo(int fd) { | |||
195 | char buf[MAX_BUF]; | 187 | char buf[MAX_BUF]; |
196 | while (fgets(buf, MAX_BUF, fp)) { | 188 | while (fgets(buf, MAX_BUF, fp)) { |
197 | if (strncmp(buf, "mnt_id:", 7) == 0) { | 189 | if (strncmp(buf, "mnt_id:", 7) == 0) { |
198 | if (sscanf(buf + 7, "%d", &rv) != 1) | 190 | if (sscanf(buf + 7, "%d", &rv) == 1) |
199 | goto errexit; | 191 | break; |
200 | break; | 192 | goto errexit; |
201 | } | 193 | } |
202 | } | 194 | } |
203 | 195 | ||
@@ -219,62 +211,50 @@ int get_mount_id(int fd) { | |||
219 | 211 | ||
220 | // Check /proc/self/mountinfo if path contains any mounts points. | 212 | // Check /proc/self/mountinfo if path contains any mounts points. |
221 | // Returns an array that can be iterated over for recursive remounting. | 213 | // Returns an array that can be iterated over for recursive remounting. |
222 | char **build_mount_array(const int mount_id, const char *path) { | 214 | char **build_mount_array(const int mountid, const char *path) { |
223 | assert(path); | 215 | assert(path); |
224 | 216 | ||
225 | // open /proc/self/mountinfo | ||
226 | FILE *fp = fopen("/proc/self/mountinfo", "re"); | 217 | FILE *fp = fopen("/proc/self/mountinfo", "re"); |
227 | if (!fp) { | 218 | if (!fp) { |
228 | fprintf(stderr, "Error: cannot read /proc/self/mountinfo\n"); | 219 | fprintf(stderr, "Error: cannot read /proc/self/mountinfo\n"); |
229 | exit(1); | 220 | exit(1); |
230 | } | 221 | } |
231 | 222 | ||
232 | // array to be returned | 223 | // try to find line with mount id |
233 | size_t cnt = 0; | 224 | int found = 0; |
225 | MountData mntp; | ||
226 | char line[MAX_BUF]; | ||
227 | while (fgets(line, MAX_BUF, fp)) { | ||
228 | parse_line(line, &mntp); | ||
229 | if (mntp.mountid == mountid) { | ||
230 | found = 1; | ||
231 | break; | ||
232 | } | ||
233 | } | ||
234 | |||
235 | if (!found) { | ||
236 | fclose(fp); | ||
237 | return NULL; | ||
238 | } | ||
239 | |||
240 | // allocate array | ||
234 | size_t size = 32; | 241 | size_t size = 32; |
235 | char **rv = malloc(size * sizeof(*rv)); | 242 | char **rv = malloc(size * sizeof(*rv)); |
236 | if (!rv) | 243 | if (!rv) |
237 | errExit("malloc"); | 244 | errExit("malloc"); |
238 | 245 | ||
239 | // read /proc/self/mountinfo | 246 | // add directory itself |
240 | size_t pathlen = strlen(path); | 247 | size_t cnt = 0; |
241 | char buf[MAX_BUF]; | 248 | rv[cnt] = strdup(path); |
242 | MountData mntp; | 249 | if (rv[cnt] == NULL) |
243 | int found = 0; | 250 | errExit("strdup"); |
244 | 251 | ||
245 | if (fgets(buf, MAX_BUF, fp) == NULL) { | 252 | // and add all following mountpoints contained in this directory |
246 | fprintf(stderr, "Error: cannot read /proc/self/mountinfo\n"); | 253 | size_t pathlen = strlen(path); |
247 | exit(1); | 254 | while (fgets(line, MAX_BUF, fp)) { |
248 | } | 255 | parse_line(line, &mntp); |
249 | do { | 256 | if (strncmp(mntp.dir, path, pathlen) == 0 && mntp.dir[pathlen] == '/') { |
250 | parse_line(buf, &mntp); | 257 | if (++cnt == size) { |
251 | // find mount point with mount id | ||
252 | if (!found) { | ||
253 | if (mntp.mountid == mount_id) { | ||
254 | // give up if mount id has been reassigned, | ||
255 | // don't remount blacklisted path | ||
256 | if (strncmp(mntp.dir, path, strlen(mntp.dir)) || | ||
257 | strstr(mntp.fsname, "firejail.ro.dir") || | ||
258 | strstr(mntp.fsname, "firejail.ro.file")) | ||
259 | break; | ||
260 | |||
261 | rv[cnt] = strdup(path); | ||
262 | if (rv[cnt] == NULL) | ||
263 | errExit("strdup"); | ||
264 | cnt++; | ||
265 | found = 1; | ||
266 | continue; | ||
267 | } | ||
268 | continue; | ||
269 | } | ||
270 | // from here on add all mount points below path, | ||
271 | // don't remount blacklisted paths | ||
272 | if (strncmp(mntp.dir, path, pathlen) == 0 && | ||
273 | mntp.dir[pathlen] == '/' && | ||
274 | strstr(mntp.fsname, "firejail.ro.dir") == NULL && | ||
275 | strstr(mntp.fsname, "firejail.ro.file") == NULL) { | ||
276 | |||
277 | if (cnt == size) { | ||
278 | size *= 2; | 258 | size *= 2; |
279 | rv = realloc(rv, size * sizeof(*rv)); | 259 | rv = realloc(rv, size * sizeof(*rv)); |
280 | if (!rv) | 260 | if (!rv) |
@@ -283,18 +263,17 @@ char **build_mount_array(const int mount_id, const char *path) { | |||
283 | rv[cnt] = strdup(mntp.dir); | 263 | rv[cnt] = strdup(mntp.dir); |
284 | if (rv[cnt] == NULL) | 264 | if (rv[cnt] == NULL) |
285 | errExit("strdup"); | 265 | errExit("strdup"); |
286 | cnt++; | ||
287 | } | 266 | } |
288 | } while (fgets(buf, MAX_BUF, fp)); | 267 | } |
268 | fclose(fp); | ||
289 | 269 | ||
290 | if (cnt == size) { | 270 | // end of array |
291 | size++; | 271 | if (++cnt == size) { |
272 | ++size; | ||
292 | rv = realloc(rv, size * sizeof(*rv)); | 273 | rv = realloc(rv, size * sizeof(*rv)); |
293 | if (!rv) | 274 | if (!rv) |
294 | errExit("realloc"); | 275 | errExit("realloc"); |
295 | } | 276 | } |
296 | rv[cnt] = NULL; // end of the array | 277 | rv[cnt] = NULL; |
297 | |||
298 | fclose(fp); | ||
299 | return rv; | 278 | return rv; |
300 | } | 279 | } |
diff --git a/src/firejail/profile.c b/src/firejail/profile.c index 9d92b6199..babc3941e 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c | |||
@@ -449,6 +449,11 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
449 | arg_no3d = 1; | 449 | arg_no3d = 1; |
450 | return 0; | 450 | return 0; |
451 | } | 451 | } |
452 | else if (strcmp(ptr, "noprinters") == 0) { | ||
453 | profile_add("blacklist /dev/lp*"); | ||
454 | profile_add("blacklist /run/cups/cups.sock"); | ||
455 | return 0; | ||
456 | } | ||
452 | else if (strcmp(ptr, "noinput") == 0) { | 457 | else if (strcmp(ptr, "noinput") == 0) { |
453 | arg_noinput = 1; | 458 | arg_noinput = 1; |
454 | return 0; | 459 | return 0; |
diff --git a/src/firejail/util.c b/src/firejail/util.c index 732e93134..55dcdc246 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c | |||
@@ -484,13 +484,6 @@ int is_link(const char *fname) { | |||
484 | if (*fname == '\0') | 484 | if (*fname == '\0') |
485 | return 0; | 485 | return 0; |
486 | 486 | ||
487 | int called_as_root = 0; | ||
488 | if (geteuid() == 0) | ||
489 | called_as_root = 1; | ||
490 | |||
491 | if (called_as_root) | ||
492 | EUID_USER(); | ||
493 | |||
494 | // remove trailing '/' if any | 487 | // remove trailing '/' if any |
495 | char *tmp = strdup(fname); | 488 | char *tmp = strdup(fname); |
496 | if (!tmp) | 489 | if (!tmp) |
@@ -498,12 +491,9 @@ int is_link(const char *fname) { | |||
498 | trim_trailing_slash_or_dot(tmp); | 491 | trim_trailing_slash_or_dot(tmp); |
499 | 492 | ||
500 | char c; | 493 | char c; |
501 | ssize_t rv = readlink(tmp, &c, 1); | 494 | ssize_t rv = readlink_as_user(tmp, &c, 1); |
502 | free(tmp); | 495 | free(tmp); |
503 | 496 | ||
504 | if (called_as_root) | ||
505 | EUID_ROOT(); | ||
506 | |||
507 | return (rv != -1); | 497 | return (rv != -1); |
508 | } | 498 | } |
509 | 499 | ||
@@ -525,6 +515,24 @@ char *realpath_as_user(const char *fname) { | |||
525 | return rv; | 515 | return rv; |
526 | } | 516 | } |
527 | 517 | ||
518 | ssize_t readlink_as_user(const char *fname, char *buf, size_t sz) { | ||
519 | assert(fname && buf && sz); | ||
520 | |||
521 | int called_as_root = 0; | ||
522 | if (geteuid() == 0) | ||
523 | called_as_root = 1; | ||
524 | |||
525 | if (called_as_root) | ||
526 | EUID_USER(); | ||
527 | |||
528 | ssize_t rv = readlink(fname, buf, sz); | ||
529 | |||
530 | if (called_as_root) | ||
531 | EUID_ROOT(); | ||
532 | |||
533 | return rv; | ||
534 | } | ||
535 | |||
528 | int stat_as_user(const char *fname, struct stat *s) { | 536 | int stat_as_user(const char *fname, struct stat *s) { |
529 | assert(fname); | 537 | assert(fname); |
530 | 538 | ||
@@ -997,31 +1005,33 @@ int create_empty_dir_as_user(const char *dir, mode_t mode) { | |||
997 | assert(dir); | 1005 | assert(dir); |
998 | mode &= 07777; | 1006 | mode &= 07777; |
999 | 1007 | ||
1000 | if (access(dir, F_OK) != 0) { | 1008 | if (access(dir, F_OK) == 0) |
1009 | return 0; | ||
1010 | |||
1011 | pid_t child = fork(); | ||
1012 | if (child < 0) | ||
1013 | errExit("fork"); | ||
1014 | if (child == 0) { | ||
1015 | // drop privileges | ||
1016 | drop_privs(0); | ||
1017 | |||
1001 | if (arg_debug) | 1018 | if (arg_debug) |
1002 | printf("Creating empty %s directory\n", dir); | 1019 | printf("Creating empty %s directory\n", dir); |
1003 | pid_t child = fork(); | 1020 | if (mkdir(dir, mode) == 0) { |
1004 | if (child < 0) | 1021 | int err = chmod(dir, mode); |
1005 | errExit("fork"); | 1022 | (void) err; |
1006 | if (child == 0) { | 1023 | } |
1007 | // drop privileges | 1024 | else if (arg_debug) |
1008 | drop_privs(0); | 1025 | printf("Directory %s not created: %s\n", dir, strerror(errno)); |
1009 | |||
1010 | if (mkdir(dir, mode) == 0) { | ||
1011 | int err = chmod(dir, mode); | ||
1012 | (void) err; | ||
1013 | } | ||
1014 | else if (arg_debug) | ||
1015 | printf("Directory %s not created: %s\n", dir, strerror(errno)); | ||
1016 | 1026 | ||
1017 | __gcov_flush(); | 1027 | __gcov_flush(); |
1018 | 1028 | ||
1019 | _exit(0); | 1029 | _exit(0); |
1020 | } | ||
1021 | waitpid(child, NULL, 0); | ||
1022 | if (access(dir, F_OK) == 0) | ||
1023 | return 1; | ||
1024 | } | 1030 | } |
1031 | waitpid(child, NULL, 0); | ||
1032 | |||
1033 | if (access(dir, F_OK) == 0) | ||
1034 | return 1; | ||
1025 | return 0; | 1035 | return 0; |
1026 | } | 1036 | } |
1027 | 1037 | ||
@@ -1411,7 +1421,7 @@ static int has_link(const char *dir) { | |||
1411 | void check_homedir(const char *dir) { | 1421 | void check_homedir(const char *dir) { |
1412 | assert(dir); | 1422 | assert(dir); |
1413 | if (dir[0] != '/') { | 1423 | if (dir[0] != '/') { |
1414 | fprintf(stderr, "Error: invalid user directory \"%s\"\n", cfg.homedir); | 1424 | fprintf(stderr, "Error: invalid user directory \"%s\"\n", dir); |
1415 | exit(1); | 1425 | exit(1); |
1416 | } | 1426 | } |
1417 | // symlinks are rejected in many places | 1427 | // symlinks are rejected in many places |
diff --git a/src/man/firejail.txt b/src/man/firejail.txt index 154def585..e724e4bb9 100644 --- a/src/man/firejail.txt +++ b/src/man/firejail.txt | |||
@@ -310,6 +310,11 @@ regular user, nonewprivs and a default capabilities filter are enabled. | |||
310 | Example: | 310 | Example: |
311 | .br | 311 | .br |
312 | $ firejail \-\-chroot=/media/ubuntu warzone2100 | 312 | $ firejail \-\-chroot=/media/ubuntu warzone2100 |
313 | .br | ||
314 | |||
315 | .br | ||
316 | For automatic mounting of X11 and PulseAudio sockets set environment variables | ||
317 | FIREJAIL_CHROOT_X11 and FIREJAIL_CHROOT_PULSE. | ||
313 | #endif | 318 | #endif |
314 | .TP | 319 | .TP |
315 | \fB\-\-cpu=cpu-number,cpu-number,cpu-number | 320 | \fB\-\-cpu=cpu-number,cpu-number,cpu-number |
@@ -2192,6 +2197,11 @@ More information about groups can be found in /usr/share/doc/firejail/syscalls.t | |||
2192 | .br | 2197 | .br |
2193 | 2198 | ||
2194 | .br | 2199 | .br |
2200 | The default list can be customized, see \-\-seccomp= for a description. | ||
2201 | It can be customized also globally in /etc/firejail/firejail.config file. | ||
2202 | .br | ||
2203 | |||
2204 | .br | ||
2195 | System architecture is strictly imposed only if flag | 2205 | System architecture is strictly imposed only if flag |
2196 | \-\-seccomp.block-secondary is used. The filter is applied at run time | 2206 | \-\-seccomp.block-secondary is used. The filter is applied at run time |
2197 | only if the correct architecture was detected. For the case of I386 | 2207 | only if the correct architecture was detected. For the case of I386 |
@@ -2206,11 +2216,7 @@ Firejail will print seccomp violations to the audit log if the kernel was compil | |||
2206 | Example: | 2216 | Example: |
2207 | .br | 2217 | .br |
2208 | $ firejail \-\-seccomp | 2218 | $ firejail \-\-seccomp |
2209 | .br | ||
2210 | 2219 | ||
2211 | .br | ||
2212 | The default list can be customized, see \-\-seccomp= for a description. It can be customized | ||
2213 | also globally in /etc/firejail/firejail.config file. | ||
2214 | 2220 | ||
2215 | .TP | 2221 | .TP |
2216 | \fB\-\-seccomp=syscall,@group,!syscall2 | 2222 | \fB\-\-seccomp=syscall,@group,!syscall2 |