diff options
-rw-r--r-- | src/firejail/firejail.h | 3 | ||||
-rw-r--r-- | src/firejail/join.c | 24 | ||||
-rw-r--r-- | src/firejail/seccomp.c | 77 | ||||
-rwxr-xr-x | test/filters/seccomp-run-files.exp | 4 |
4 files changed, 77 insertions, 31 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 245ea5bde..a3d3dfcd4 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -57,7 +57,7 @@ | |||
57 | #define RUN_LIB_FILE "/run/firejail/mnt/libfiles" | 57 | #define RUN_LIB_FILE "/run/firejail/mnt/libfiles" |
58 | #define RUN_DNS_ETC "/run/firejail/mnt/dns-etc" | 58 | #define RUN_DNS_ETC "/run/firejail/mnt/dns-etc" |
59 | 59 | ||
60 | 60 | #define RUN_SECCOMP_LIST "/run/firejail/mnt/seccomp.list" // list of seccomp files installed | |
61 | #define RUN_SECCOMP_PROTOCOL "/run/firejail/mnt/seccomp.protocol" // protocol filter | 61 | #define RUN_SECCOMP_PROTOCOL "/run/firejail/mnt/seccomp.protocol" // protocol filter |
62 | #define RUN_SECCOMP_CFG "/run/firejail/mnt/seccomp" // configured filter | 62 | #define RUN_SECCOMP_CFG "/run/firejail/mnt/seccomp" // configured filter |
63 | #define RUN_SECCOMP_32 "/run/firejail/mnt/seccomp.32" // 32bit arch filter installed on 64bit architectures | 63 | #define RUN_SECCOMP_32 "/run/firejail/mnt/seccomp.32" // 32bit arch filter installed on 64bit architectures |
@@ -607,6 +607,7 @@ int seccomp_filter_keep(void); | |||
607 | void seccomp_print_filter(pid_t pid); | 607 | void seccomp_print_filter(pid_t pid); |
608 | 608 | ||
609 | // caps.c | 609 | // caps.c |
610 | void seccomp_load_file_list(void); | ||
610 | int caps_default_filter(void); | 611 | int caps_default_filter(void); |
611 | void caps_print(void); | 612 | void caps_print(void); |
612 | void caps_drop_all(void); | 613 | void caps_drop_all(void); |
diff --git a/src/firejail/join.c b/src/firejail/join.c index 3ee069305..9cc4cd75d 100644 --- a/src/firejail/join.c +++ b/src/firejail/join.c | |||
@@ -160,7 +160,7 @@ static void extract_cgroup(pid_t pid) { | |||
160 | free(fname); | 160 | free(fname); |
161 | } | 161 | } |
162 | 162 | ||
163 | static void extract_caps_seccomp(pid_t pid) { | 163 | static void extract_caps(pid_t pid) { |
164 | // open stat file | 164 | // open stat file |
165 | char *file; | 165 | char *file; |
166 | if (asprintf(&file, "/proc/%u/status", pid) == -1) { | 166 | if (asprintf(&file, "/proc/%u/status", pid) == -1) { |
@@ -173,16 +173,7 @@ static void extract_caps_seccomp(pid_t pid) { | |||
173 | 173 | ||
174 | char buf[BUFLEN]; | 174 | char buf[BUFLEN]; |
175 | while (fgets(buf, BUFLEN - 1, fp)) { | 175 | while (fgets(buf, BUFLEN - 1, fp)) { |
176 | if (strncmp(buf, "Seccomp:", 8) == 0) { | 176 | if (strncmp(buf, "CapBnd:", 7) == 0) { |
177 | char *ptr = buf + 8; | ||
178 | int val; | ||
179 | if (sscanf(ptr, "%d", &val) != 1) | ||
180 | goto errexit; | ||
181 | if (val == 2) | ||
182 | apply_seccomp = 1; | ||
183 | break; | ||
184 | } | ||
185 | else if (strncmp(buf, "CapBnd:", 7) == 0) { | ||
186 | char *ptr = buf + 7; | 177 | char *ptr = buf + 7; |
187 | unsigned long long val; | 178 | unsigned long long val; |
188 | if (sscanf(ptr, "%llx", &val) != 1) | 179 | if (sscanf(ptr, "%llx", &val) != 1) |
@@ -323,7 +314,7 @@ void join(pid_t pid, int argc, char **argv, int index) { | |||
323 | // in user mode set caps seccomp, cpu, cgroup, etc | 314 | // in user mode set caps seccomp, cpu, cgroup, etc |
324 | if (getuid() != 0) { | 315 | if (getuid() != 0) { |
325 | extract_nonewprivs(pid); // redundant on Linux >= 4.10; duplicated in function extract_caps_seccomp | 316 | extract_nonewprivs(pid); // redundant on Linux >= 4.10; duplicated in function extract_caps_seccomp |
326 | extract_caps_seccomp(pid); | 317 | extract_caps(pid); |
327 | extract_cpu(pid); | 318 | extract_cpu(pid); |
328 | extract_cgroup(pid); | 319 | extract_cgroup(pid); |
329 | extract_nogroups(pid); | 320 | extract_nogroups(pid); |
@@ -397,15 +388,8 @@ void join(pid_t pid, int argc, char **argv, int index) { | |||
397 | if (apply_caps == 1) // not available for uid 0 | 388 | if (apply_caps == 1) // not available for uid 0 |
398 | caps_set(caps); | 389 | caps_set(caps); |
399 | #ifdef HAVE_SECCOMP | 390 | #ifdef HAVE_SECCOMP |
400 | // read cfg.protocol from file | ||
401 | if (getuid() != 0) | 391 | if (getuid() != 0) |
402 | protocol_filter_load(RUN_PROTOCOL_CFG); | 392 | seccomp_load_file_list(); |
403 | if (cfg.protocol) // not available for uid 0 | ||
404 | seccomp_load(RUN_SECCOMP_PROTOCOL); // install filter | ||
405 | |||
406 | // set seccomp filter | ||
407 | if (apply_seccomp == 1) // not available for uid 0 | ||
408 | seccomp_load(RUN_SECCOMP_CFG); | ||
409 | #endif | 393 | #endif |
410 | 394 | ||
411 | // mount user namespace or drop privileges | 395 | // mount user namespace or drop privileges |
diff --git a/src/firejail/seccomp.c b/src/firejail/seccomp.c index 974e36ba7..1cdd96025 100644 --- a/src/firejail/seccomp.c +++ b/src/firejail/seccomp.c | |||
@@ -83,6 +83,41 @@ int seccomp_install_filters(void) { | |||
83 | return r; | 83 | return r; |
84 | } | 84 | } |
85 | 85 | ||
86 | static void seccomp_save_file_list(const char *fname) { | ||
87 | assert(fname); | ||
88 | |||
89 | FILE *fp = fopen(RUN_SECCOMP_LIST, "a+"); | ||
90 | if (!fp) | ||
91 | errExit("fopen"); | ||
92 | |||
93 | fprintf(fp, "%s\n", fname); | ||
94 | fclose(fp); | ||
95 | int rv = chown(RUN_SECCOMP_LIST, getuid(), getgid()); | ||
96 | (void) rv; | ||
97 | } | ||
98 | |||
99 | #define MAXBUF 4096 | ||
100 | static int load_file_list_flag = 0; | ||
101 | void seccomp_load_file_list(void) { | ||
102 | FILE *fp = fopen(RUN_SECCOMP_LIST, "r"); | ||
103 | if (!fp) | ||
104 | return; // no seccomp configuration whatsoever | ||
105 | |||
106 | load_file_list_flag = 1; | ||
107 | char buf[MAXBUF]; | ||
108 | while (fgets(buf, MAXBUF, fp)) { | ||
109 | // clean '\n' | ||
110 | char *ptr = strchr(buf, '\n'); | ||
111 | if (ptr) | ||
112 | *ptr = '\0'; | ||
113 | seccomp_load(buf); | ||
114 | } | ||
115 | |||
116 | fclose(fp); | ||
117 | load_file_list_flag = 0; | ||
118 | } | ||
119 | |||
120 | |||
86 | int seccomp_load(const char *fname) { | 121 | int seccomp_load(const char *fname) { |
87 | assert(fname); | 122 | assert(fname); |
88 | 123 | ||
@@ -125,6 +160,10 @@ int seccomp_load(const char *fname) { | |||
125 | PATH_FSEC_PRINT, fname); | 160 | PATH_FSEC_PRINT, fname); |
126 | } | 161 | } |
127 | 162 | ||
163 | // save the file name in seccomp list | ||
164 | if (!load_file_list_flag) | ||
165 | seccomp_save_file_list(fname); | ||
166 | |||
128 | return 0; | 167 | return 0; |
129 | errexit: | 168 | errexit: |
130 | fprintf(stderr, "Error: cannot read %s\n", fname); | 169 | fprintf(stderr, "Error: cannot read %s\n", fname); |
@@ -308,23 +347,45 @@ void seccomp_print_filter(pid_t pid) { | |||
308 | } | 347 | } |
309 | } | 348 | } |
310 | 349 | ||
311 | // find the seccomp filter | 350 | // find the seccomp list file |
312 | EUID_ROOT(); | 351 | EUID_ROOT(); |
313 | char *fname; | 352 | char *fname; |
314 | if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_SECCOMP_CFG) == -1) | 353 | if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_SECCOMP_LIST) == -1) |
315 | errExit("asprintf"); | 354 | errExit("asprintf"); |
316 | 355 | ||
317 | struct stat s; | 356 | struct stat s; |
318 | if (stat(fname, &s) == -1) { | 357 | if (stat(fname, &s) == -1) |
319 | printf("Cannot access seccomp filter.\n"); | 358 | goto errexit; |
320 | exit(1); | ||
321 | } | ||
322 | 359 | ||
323 | // read and print the filter - run this as root, the user doesn't have access | 360 | FILE *fp = fopen(fname, "r"); |
324 | sbox_run(SBOX_ROOT | SBOX_SECCOMP, 2, PATH_FSEC_PRINT, fname); | 361 | if (!fp) |
362 | goto errexit; | ||
325 | free(fname); | 363 | free(fname); |
326 | 364 | ||
365 | char buf[MAXBUF]; | ||
366 | while (fgets(buf, MAXBUF, fp)) { | ||
367 | // clean '\n' | ||
368 | char *ptr = strchr(buf, '\n'); | ||
369 | if (ptr) | ||
370 | *ptr = '\0'; | ||
371 | |||
372 | if (asprintf(&fname, "/proc/%d/root%s", pid, buf) == -1) | ||
373 | errExit("asprintf"); | ||
374 | printf("FILE: %s\n", fname); fflush(0); | ||
375 | |||
376 | // read and print the filter - run this as root, the user doesn't have access | ||
377 | sbox_run(SBOX_ROOT | SBOX_SECCOMP, 2, PATH_FSEC_PRINT, fname); | ||
378 | fflush(0); | ||
379 | |||
380 | printf("\n"); fflush(0); | ||
381 | free(fname); | ||
382 | } | ||
383 | fclose(fp); | ||
327 | exit(0); | 384 | exit(0); |
385 | |||
386 | errexit: | ||
387 | printf("Cannot access seccomp filter.\n"); | ||
388 | exit(1); | ||
328 | } | 389 | } |
329 | 390 | ||
330 | #endif // HAVE_SECCOMP | 391 | #endif // HAVE_SECCOMP |
diff --git a/test/filters/seccomp-run-files.exp b/test/filters/seccomp-run-files.exp index 7c436b664..7a1345902 100755 --- a/test/filters/seccomp-run-files.exp +++ b/test/filters/seccomp-run-files.exp | |||
@@ -24,7 +24,7 @@ after 100 | |||
24 | send -- "ls -l /run/firejail/mnt | grep -c seccomp\r" | 24 | send -- "ls -l /run/firejail/mnt | grep -c seccomp\r" |
25 | expect { | 25 | expect { |
26 | timeout {puts "TESTING ERROR 3\n";exit} | 26 | timeout {puts "TESTING ERROR 3\n";exit} |
27 | "4" | 27 | "5" |
28 | } | 28 | } |
29 | send -- "exit\r" | 29 | send -- "exit\r" |
30 | sleep 1 | 30 | sleep 1 |
@@ -90,7 +90,7 @@ after 100 | |||
90 | send -- "ls -l /run/firejail/mnt | grep -c seccomp\r" | 90 | send -- "ls -l /run/firejail/mnt | grep -c seccomp\r" |
91 | expect { | 91 | expect { |
92 | timeout {puts "TESTING ERROR 18\n";exit} | 92 | timeout {puts "TESTING ERROR 18\n";exit} |
93 | "5" | 93 | "6" |
94 | } | 94 | } |
95 | send -- "exit\r" | 95 | send -- "exit\r" |
96 | sleep 1 | 96 | sleep 1 |