aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@yahoo.com>2019-01-09 09:42:55 -0500
committerLibravatar netblue30 <netblue30@yahoo.com>2019-01-09 09:42:55 -0500
commit6fc51f43e88605682bd307515090df51b871b717 (patch)
tree39402990d193a19699d3770b0362042fc7264be2
parentmainline merge: fix netfilter-default functionality in /etc/firejail/firejail... (diff)
downloadfirejail-6fc51f43e88605682bd307515090df51b871b717.tar.gz
firejail-6fc51f43e88605682bd307515090df51b871b717.tar.zst
firejail-6fc51f43e88605682bd307515090df51b871b717.zip
mainline merge: fix join/seccomp #2296
-rw-r--r--src/firejail/firejail.h3
-rw-r--r--src/firejail/join.c65
-rw-r--r--src/firejail/seccomp.c77
-rwxr-xr-xtest/filters/seccomp-run-files.exp4
4 files changed, 110 insertions, 39 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index 00c6cd8f3..fcaee18a2 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -55,7 +55,7 @@
55#define RUN_LIB_FILE "/run/firejail/mnt/libfiles" 55#define RUN_LIB_FILE "/run/firejail/mnt/libfiles"
56#define RUN_DNS_ETC "/run/firejail/mnt/dns-etc" 56#define RUN_DNS_ETC "/run/firejail/mnt/dns-etc"
57 57
58 58#define RUN_SECCOMP_LIST "/run/firejail/mnt/seccomp.list" // list of seccomp files installed
59#define RUN_SECCOMP_PROTOCOL "/run/firejail/mnt/seccomp.protocol" // protocol filter 59#define RUN_SECCOMP_PROTOCOL "/run/firejail/mnt/seccomp.protocol" // protocol filter
60#define RUN_SECCOMP_CFG "/run/firejail/mnt/seccomp" // configured filter 60#define RUN_SECCOMP_CFG "/run/firejail/mnt/seccomp" // configured filter
61#define RUN_SECCOMP_32 "/run/firejail/mnt/seccomp.32" // 32bit arch filter installed on 64bit architectures 61#define RUN_SECCOMP_32 "/run/firejail/mnt/seccomp.32" // 32bit arch filter installed on 64bit architectures
@@ -545,6 +545,7 @@ void fs_private_home_list(void);
545 545
546 546
547// seccomp.c 547// seccomp.c
548void seccomp_load_file_list(void);
548char *seccomp_check_list(const char *str); 549char *seccomp_check_list(const char *str);
549int seccomp_install_filters(void); 550int seccomp_install_filters(void);
550int seccomp_load(const char *fname); 551int seccomp_load(const char *fname);
diff --git a/src/firejail/join.c b/src/firejail/join.c
index 731842275..28fd1b290 100644
--- a/src/firejail/join.c
+++ b/src/firejail/join.c
@@ -22,6 +22,8 @@
22#include <sys/wait.h> 22#include <sys/wait.h>
23#include <fcntl.h> 23#include <fcntl.h>
24#include <unistd.h> 24#include <unistd.h>
25#include <errno.h>
26
25#include <sys/prctl.h> 27#include <sys/prctl.h>
26#include <errno.h> 28#include <errno.h>
27 29
@@ -71,8 +73,10 @@ static void extract_nogroups(pid_t pid) {
71 errExit("asprintf"); 73 errExit("asprintf");
72 74
73 struct stat s; 75 struct stat s;
74 if (stat(fname, &s) == -1) 76 if (stat(fname, &s) == -1) {
77 free(fname);
75 return; 78 return;
79 }
76 80
77 arg_nogroups = 1; 81 arg_nogroups = 1;
78 free(fname); 82 free(fname);
@@ -84,8 +88,10 @@ static void extract_cpu(pid_t pid) {
84 errExit("asprintf"); 88 errExit("asprintf");
85 89
86 struct stat s; 90 struct stat s;
87 if (stat(fname, &s) == -1) 91 if (stat(fname, &s) == -1) {
92 free(fname);
88 return; 93 return;
94 }
89 95
90 // there is a CPU_CFG file, load it! 96 // there is a CPU_CFG file, load it!
91 load_cpu(fname); 97 load_cpu(fname);
@@ -93,7 +99,7 @@ static void extract_cpu(pid_t pid) {
93} 99}
94 100
95 101
96static void extract_caps_seccomp(pid_t pid) { 102static void extract_caps(pid_t pid) {
97 // open stat file 103 // open stat file
98 char *file; 104 char *file;
99 if (asprintf(&file, "/proc/%u/status", pid) == -1) { 105 if (asprintf(&file, "/proc/%u/status", pid) == -1) {
@@ -101,32 +107,35 @@ static void extract_caps_seccomp(pid_t pid) {
101 exit(1); 107 exit(1);
102 } 108 }
103 FILE *fp = fopen(file, "r"); 109 FILE *fp = fopen(file, "r");
104 if (!fp) { 110 if (!fp)
105 free(file); 111 goto errexit;
106 fprintf(stderr, "Error: cannot open stat file for process %u\n", pid);
107 exit(1);
108 }
109 112
110 char buf[BUFLEN]; 113 char buf[BUFLEN];
111 while (fgets(buf, BUFLEN - 1, fp)) { 114 while (fgets(buf, BUFLEN - 1, fp)) {
112 if (strncmp(buf, "Seccomp:", 8) == 0) { 115 if (strncmp(buf, "CapBnd:", 7) == 0) {
113 char *ptr = buf + 8;
114 int val;
115 sscanf(ptr, "%d", &val);
116 if (val == 2)
117 apply_seccomp = 1;
118 break;
119 }
120 else if (strncmp(buf, "CapBnd:", 7) == 0) {
121 char *ptr = buf + 7; 116 char *ptr = buf + 7;
122 unsigned long long val; 117 unsigned long long val;
123 sscanf(ptr, "%llx", &val); 118 if (sscanf(ptr, "%llx", &val) != 1)
119 goto errexit;
124 apply_caps = 1; 120 apply_caps = 1;
125 caps = val; 121 caps = val;
126 } 122 }
123 else if (strncmp(buf, "NoNewPrivs:", 11) == 0) {
124 char *ptr = buf + 11;
125 int val;
126 if (sscanf(ptr, "%d", &val) != 1)
127 goto errexit;
128 if (val)
129 arg_nonewprivs = 1;
130 }
127 } 131 }
128 fclose(fp); 132 fclose(fp);
129 free(file); 133 free(file);
134 return;
135
136errexit:
137 fprintf(stderr, "Error: cannot read stat file for process %u\n", pid);
138 exit(1);
130} 139}
131 140
132static void extract_user_namespace(pid_t pid) { 141static void extract_user_namespace(pid_t pid) {
@@ -187,7 +196,7 @@ pid_t switch_to_child(pid_t pid) {
187 char *comm = pid_proc_comm(pid); 196 char *comm = pid_proc_comm(pid);
188 if (!comm) { 197 if (!comm) {
189 if (errno == ENOENT) { 198 if (errno == ENOENT) {
190 fprintf(stderr, "Error: cannot find process with id %d\n", pid); 199 fprintf(stderr, "Error: cannot find process with pid %d\n", pid);
191 exit(1); 200 exit(1);
192 } 201 }
193 else { 202 else {
@@ -240,7 +249,7 @@ void join(pid_t pid, int argc, char **argv, int index) {
240 EUID_ROOT(); 249 EUID_ROOT();
241 // in user mode set caps seccomp, cpu, cgroup, etc 250 // in user mode set caps seccomp, cpu, cgroup, etc
242 if (getuid() != 0) { 251 if (getuid() != 0) {
243 extract_caps_seccomp(pid); 252 extract_caps(pid);
244 extract_cpu(pid); 253 extract_cpu(pid);
245 extract_nogroups(pid); 254 extract_nogroups(pid);
246 extract_user_namespace(pid); 255 extract_user_namespace(pid);
@@ -309,15 +318,8 @@ void join(pid_t pid, int argc, char **argv, int index) {
309 if (apply_caps == 1) // not available for uid 0 318 if (apply_caps == 1) // not available for uid 0
310 caps_set(caps); 319 caps_set(caps);
311#ifdef HAVE_SECCOMP 320#ifdef HAVE_SECCOMP
312 // read cfg.protocol from file
313 if (getuid() != 0) 321 if (getuid() != 0)
314 protocol_filter_load(RUN_PROTOCOL_CFG); 322 seccomp_load_file_list();
315 if (cfg.protocol) // not available for uid 0
316 seccomp_load(RUN_SECCOMP_PROTOCOL); // install filter
317
318 // set seccomp filter
319 if (apply_seccomp == 1) // not available for uid 0
320 seccomp_load(RUN_SECCOMP_CFG);
321#endif 323#endif
322 324
323 // mount user namespace or drop privileges 325 // mount user namespace or drop privileges
@@ -333,6 +335,13 @@ void join(pid_t pid, int argc, char **argv, int index) {
333 caps_set(caps); 335 caps_set(caps);
334 } 336 }
335 337
338 // set nonewprivs
339 if (arg_nonewprivs == 1) { // not available for uid 0
340 int rv = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
341 if (arg_debug && rv == 0)
342 printf("NO_NEW_PRIVS set\n");
343 }
344
336 EUID_USER(); 345 EUID_USER();
337 // set nice 346 // set nice
338 if (arg_nice) { 347 if (arg_nice) {
diff --git a/src/firejail/seccomp.c b/src/firejail/seccomp.c
index 7be7b3950..a5323d840 100644
--- a/src/firejail/seccomp.c
+++ b/src/firejail/seccomp.c
@@ -89,6 +89,41 @@ int seccomp_install_filters(void) {
89 return r; 89 return r;
90} 90}
91 91
92static void seccomp_save_file_list(const char *fname) {
93 assert(fname);
94
95 FILE *fp = fopen(RUN_SECCOMP_LIST, "a+");
96 if (!fp)
97 errExit("fopen");
98
99 fprintf(fp, "%s\n", fname);
100 fclose(fp);
101 int rv = chown(RUN_SECCOMP_LIST, getuid(), getgid());
102 (void) rv;
103}
104
105#define MAXBUF 4096
106static int load_file_list_flag = 0;
107void seccomp_load_file_list(void) {
108 FILE *fp = fopen(RUN_SECCOMP_LIST, "r");
109 if (!fp)
110 return; // no seccomp configuration whatsoever
111
112 load_file_list_flag = 1;
113 char buf[MAXBUF];
114 while (fgets(buf, MAXBUF, fp)) {
115 // clean '\n'
116 char *ptr = strchr(buf, '\n');
117 if (ptr)
118 *ptr = '\0';
119 seccomp_load(buf);
120 }
121
122 fclose(fp);
123 load_file_list_flag = 0;
124}
125
126
92int seccomp_load(const char *fname) { 127int seccomp_load(const char *fname) {
93 assert(fname); 128 assert(fname);
94 129
@@ -131,6 +166,10 @@ int seccomp_load(const char *fname) {
131 PATH_FSEC_PRINT, fname); 166 PATH_FSEC_PRINT, fname);
132 } 167 }
133 168
169 // save the file name in seccomp list
170 if (!load_file_list_flag)
171 seccomp_save_file_list(fname);
172
134 return 0; 173 return 0;
135errexit: 174errexit:
136 fprintf(stderr, "Error: cannot read %s\n", fname); 175 fprintf(stderr, "Error: cannot read %s\n", fname);
@@ -314,23 +353,45 @@ void seccomp_print_filter(pid_t pid) {
314 } 353 }
315 } 354 }
316 355
317 // find the seccomp filter 356 // find the seccomp list file
318 EUID_ROOT(); 357 EUID_ROOT();
319 char *fname; 358 char *fname;
320 if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_SECCOMP_CFG) == -1) 359 if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_SECCOMP_LIST) == -1)
321 errExit("asprintf"); 360 errExit("asprintf");
322 361
323 struct stat s; 362 struct stat s;
324 if (stat(fname, &s) == -1) { 363 if (stat(fname, &s) == -1)
325 printf("Cannot access seccomp filter.\n"); 364 goto errexit;
326 exit(1);
327 }
328 365
329 // read and print the filter - run this as root, the user doesn't have access 366 FILE *fp = fopen(fname, "r");
330 sbox_run(SBOX_ROOT | SBOX_SECCOMP, 2, PATH_FSEC_PRINT, fname); 367 if (!fp)
368 goto errexit;
331 free(fname); 369 free(fname);
332 370
371 char buf[MAXBUF];
372 while (fgets(buf, MAXBUF, fp)) {
373 // clean '\n'
374 char *ptr = strchr(buf, '\n');
375 if (ptr)
376 *ptr = '\0';
377
378 if (asprintf(&fname, "/proc/%d/root%s", pid, buf) == -1)
379 errExit("asprintf");
380 printf("FILE: %s\n", fname); fflush(0);
381
382 // read and print the filter - run this as root, the user doesn't have access
383 sbox_run(SBOX_ROOT | SBOX_SECCOMP, 2, PATH_FSEC_PRINT, fname);
384 fflush(0);
385
386 printf("\n"); fflush(0);
387 free(fname);
388 }
389 fclose(fp);
333 exit(0); 390 exit(0);
391
392errexit:
393 printf("Cannot access seccomp filter.\n");
394 exit(1);
334} 395}
335 396
336#endif // HAVE_SECCOMP 397#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
24send -- "ls -l /run/firejail/mnt | grep -c seccomp\r" 24send -- "ls -l /run/firejail/mnt | grep -c seccomp\r"
25expect { 25expect {
26 timeout {puts "TESTING ERROR 3\n";exit} 26 timeout {puts "TESTING ERROR 3\n";exit}
27 "4" 27 "5"
28} 28}
29send -- "exit\r" 29send -- "exit\r"
30sleep 1 30sleep 1
@@ -90,7 +90,7 @@ after 100
90send -- "ls -l /run/firejail/mnt | grep -c seccomp\r" 90send -- "ls -l /run/firejail/mnt | grep -c seccomp\r"
91expect { 91expect {
92 timeout {puts "TESTING ERROR 18\n";exit} 92 timeout {puts "TESTING ERROR 18\n";exit}
93 "5" 93 "6"
94} 94}
95send -- "exit\r" 95send -- "exit\r"
96sleep 1 96sleep 1