aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@yahoo.com>2016-11-06 13:14:53 -0500
committerLibravatar netblue30 <netblue30@yahoo.com>2016-11-06 13:14:53 -0500
commit322ce2cdc98cf3eec22ebd0f83296ddde8347d09 (patch)
tree035026b607ee8b34a9ea03a6f1df30d03c584f43
parentcleanup (diff)
downloadfirejail-322ce2cdc98cf3eec22ebd0f83296ddde8347d09.tar.gz
firejail-322ce2cdc98cf3eec22ebd0f83296ddde8347d09.tar.zst
firejail-322ce2cdc98cf3eec22ebd0f83296ddde8347d09.zip
seccomp rework
-rw-r--r--src/firejail/errno.c207
-rw-r--r--src/firejail/firejail.h3
-rw-r--r--src/firejail/main.c56
-rw-r--r--src/firejail/profile.c16
-rw-r--r--src/firejail/sandbox.c2
-rw-r--r--src/firejail/seccomp.c72
-rw-r--r--src/fseccomp/main.c2
-rw-r--r--src/fseccomp/protocol.c2
-rw-r--r--src/fseccomp/syscall.c87
-rwxr-xr-xtest/filters/seccomp-errno.exp44
10 files changed, 106 insertions, 385 deletions
diff --git a/src/firejail/errno.c b/src/firejail/errno.c
deleted file mode 100644
index 8215c99a1..000000000
--- a/src/firejail/errno.c
+++ /dev/null
@@ -1,207 +0,0 @@
1/*
2 * Copyright (C) 2014-2016 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#ifdef HAVE_SECCOMP
21#include "firejail.h"
22#include <errno.h>
23//#include <attr/xattr.h>
24
25typedef struct {
26 char *name;
27 int nr;
28} ErrnoEntry;
29
30static ErrnoEntry errnolist[] = {
31//
32// code generated using tools/extract-errnos
33//
34 {"EPERM", EPERM},
35 {"ENOENT", ENOENT},
36 {"ESRCH", ESRCH},
37 {"EINTR", EINTR},
38 {"EIO", EIO},
39 {"ENXIO", ENXIO},
40 {"E2BIG", E2BIG},
41 {"ENOEXEC", ENOEXEC},
42 {"EBADF", EBADF},
43 {"ECHILD", ECHILD},
44 {"EAGAIN", EAGAIN},
45 {"ENOMEM", ENOMEM},
46 {"EACCES", EACCES},
47 {"EFAULT", EFAULT},
48 {"ENOTBLK", ENOTBLK},
49 {"EBUSY", EBUSY},
50 {"EEXIST", EEXIST},
51 {"EXDEV", EXDEV},
52 {"ENODEV", ENODEV},
53 {"ENOTDIR", ENOTDIR},
54 {"EISDIR", EISDIR},
55 {"EINVAL", EINVAL},
56 {"ENFILE", ENFILE},
57 {"EMFILE", EMFILE},
58 {"ENOTTY", ENOTTY},
59 {"ETXTBSY", ETXTBSY},
60 {"EFBIG", EFBIG},
61 {"ENOSPC", ENOSPC},
62 {"ESPIPE", ESPIPE},
63 {"EROFS", EROFS},
64 {"EMLINK", EMLINK},
65 {"EPIPE", EPIPE},
66 {"EDOM", EDOM},
67 {"ERANGE", ERANGE},
68 {"EDEADLK", EDEADLK},
69 {"ENAMETOOLONG", ENAMETOOLONG},
70 {"ENOLCK", ENOLCK},
71 {"ENOSYS", ENOSYS},
72 {"ENOTEMPTY", ENOTEMPTY},
73 {"ELOOP", ELOOP},
74 {"EWOULDBLOCK", EWOULDBLOCK},
75 {"ENOMSG", ENOMSG},
76 {"EIDRM", EIDRM},
77 {"ECHRNG", ECHRNG},
78 {"EL2NSYNC", EL2NSYNC},
79 {"EL3HLT", EL3HLT},
80 {"EL3RST", EL3RST},
81 {"ELNRNG", ELNRNG},
82 {"EUNATCH", EUNATCH},
83 {"ENOCSI", ENOCSI},
84 {"EL2HLT", EL2HLT},
85 {"EBADE", EBADE},
86 {"EBADR", EBADR},
87 {"EXFULL", EXFULL},
88 {"ENOANO", ENOANO},
89 {"EBADRQC", EBADRQC},
90 {"EBADSLT", EBADSLT},
91 {"EDEADLOCK", EDEADLOCK},
92 {"EBFONT", EBFONT},
93 {"ENOSTR", ENOSTR},
94 {"ENODATA", ENODATA},
95 {"ETIME", ETIME},
96 {"ENOSR", ENOSR},
97 {"ENONET", ENONET},
98 {"ENOPKG", ENOPKG},
99 {"EREMOTE", EREMOTE},
100 {"ENOLINK", ENOLINK},
101 {"EADV", EADV},
102 {"ESRMNT", ESRMNT},
103 {"ECOMM", ECOMM},
104 {"EPROTO", EPROTO},
105 {"EMULTIHOP", EMULTIHOP},
106 {"EDOTDOT", EDOTDOT},
107 {"EBADMSG", EBADMSG},
108 {"EOVERFLOW", EOVERFLOW},
109 {"ENOTUNIQ", ENOTUNIQ},
110 {"EBADFD", EBADFD},
111 {"EREMCHG", EREMCHG},
112 {"ELIBACC", ELIBACC},
113 {"ELIBBAD", ELIBBAD},
114 {"ELIBSCN", ELIBSCN},
115 {"ELIBMAX", ELIBMAX},
116 {"ELIBEXEC", ELIBEXEC},
117 {"EILSEQ", EILSEQ},
118 {"ERESTART", ERESTART},
119 {"ESTRPIPE", ESTRPIPE},
120 {"EUSERS", EUSERS},
121 {"ENOTSOCK", ENOTSOCK},
122 {"EDESTADDRREQ", EDESTADDRREQ},
123 {"EMSGSIZE", EMSGSIZE},
124 {"EPROTOTYPE", EPROTOTYPE},
125 {"ENOPROTOOPT", ENOPROTOOPT},
126 {"EPROTONOSUPPORT", EPROTONOSUPPORT},
127 {"ESOCKTNOSUPPORT", ESOCKTNOSUPPORT},
128 {"EOPNOTSUPP", EOPNOTSUPP},
129 {"EPFNOSUPPORT", EPFNOSUPPORT},
130 {"EAFNOSUPPORT", EAFNOSUPPORT},
131 {"EADDRINUSE", EADDRINUSE},
132 {"EADDRNOTAVAIL", EADDRNOTAVAIL},
133 {"ENETDOWN", ENETDOWN},
134 {"ENETUNREACH", ENETUNREACH},
135 {"ENETRESET", ENETRESET},
136 {"ECONNABORTED", ECONNABORTED},
137 {"ECONNRESET", ECONNRESET},
138 {"ENOBUFS", ENOBUFS},
139 {"EISCONN", EISCONN},
140 {"ENOTCONN", ENOTCONN},
141 {"ESHUTDOWN", ESHUTDOWN},
142 {"ETOOMANYREFS", ETOOMANYREFS},
143 {"ETIMEDOUT", ETIMEDOUT},
144 {"ECONNREFUSED", ECONNREFUSED},
145 {"EHOSTDOWN", EHOSTDOWN},
146 {"EHOSTUNREACH", EHOSTUNREACH},
147 {"EALREADY", EALREADY},
148 {"EINPROGRESS", EINPROGRESS},
149 {"ESTALE", ESTALE},
150 {"EUCLEAN", EUCLEAN},
151 {"ENOTNAM", ENOTNAM},
152 {"ENAVAIL", ENAVAIL},
153 {"EISNAM", EISNAM},
154 {"EREMOTEIO", EREMOTEIO},
155 {"EDQUOT", EDQUOT},
156 {"ENOMEDIUM", ENOMEDIUM},
157 {"EMEDIUMTYPE", EMEDIUMTYPE},
158 {"ECANCELED", ECANCELED},
159 {"ENOKEY", ENOKEY},
160 {"EKEYEXPIRED", EKEYEXPIRED},
161 {"EKEYREVOKED", EKEYREVOKED},
162 {"EKEYREJECTED", EKEYREJECTED},
163 {"EOWNERDEAD", EOWNERDEAD},
164 {"ENOTRECOVERABLE", ENOTRECOVERABLE},
165 {"ERFKILL", ERFKILL},
166 {"EHWPOISON", EHWPOISON},
167 {"ENOTSUP", ENOTSUP},
168#ifdef ENOATTR
169 {"ENOATTR", ENOATTR},
170#endif
171};
172
173int errno_highest_nr(void) {
174 int i, max = 0;
175 int elems = sizeof(errnolist) / sizeof(errnolist[0]);
176 for (i = 0; i < elems; i++) {
177 if (errnolist[i].nr > max)
178 max = errnolist[i].nr;
179 }
180
181 return max;
182}
183
184int errno_find_name(const char *name) {
185 EUID_ASSERT();
186
187 int i;
188 int elems = sizeof(errnolist) / sizeof(errnolist[0]);
189 for (i = 0; i < elems; i++) {
190 if (strcasecmp(name, errnolist[i].name) == 0)
191 return errnolist[i].nr;
192 }
193
194 return -1;
195}
196
197char *errno_find_nr(int nr) {
198 int i;
199 int elems = sizeof(errnolist) / sizeof(errnolist[0]);
200 for (i = 0; i < elems; i++) {
201 if (nr == errnolist[i].nr)
202 return errnolist[i].name;
203 }
204
205 return "unknown";
206}
207#endif // HAVE_SECCOMP
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index cf540ff91..56dbd6868 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -222,7 +222,6 @@ typedef struct config_t {
222 char *seccomp_list;// optional seccomp list on top of default filter 222 char *seccomp_list;// optional seccomp list on top of default filter
223 char *seccomp_list_drop; // seccomp drop list 223 char *seccomp_list_drop; // seccomp drop list
224 char *seccomp_list_keep; // seccomp keep list 224 char *seccomp_list_keep; // seccomp keep list
225 char **seccomp_list_errno; // seccomp errno[nr] lists
226 char *protocol; // protocol list 225 char *protocol; // protocol list
227 226
228 // rlimits 227 // rlimits
@@ -496,12 +495,12 @@ void fs_private_home_list(void);
496 495
497 496
498// seccomp.c 497// seccomp.c
498char *seccomp_check_list(const char *str);
499int seccomp_load(const char *fname); 499int seccomp_load(const char *fname);
500void seccomp_filter_32(void); 500void seccomp_filter_32(void);
501void seccomp_filter_64(void); 501void seccomp_filter_64(void);
502int seccomp_filter_drop(int enforce_seccomp); 502int seccomp_filter_drop(int enforce_seccomp);
503int seccomp_filter_keep(void); 503int seccomp_filter_keep(void);
504int seccomp_filter_errno(void);
505void seccomp_print_filter_name(const char *name); 504void seccomp_print_filter_name(const char *name);
506void seccomp_print_filter(pid_t pid); 505void seccomp_print_filter(pid_t pid);
507 506
diff --git a/src/firejail/main.c b/src/firejail/main.c
index fc86f9651..b6f3a7f59 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -851,9 +851,6 @@ int main(int argc, char **argv) {
851 int custom_profile = 0; // custom profile loaded 851 int custom_profile = 0; // custom profile loaded
852 char *custom_profile_dir = NULL; // custom profile directory 852 char *custom_profile_dir = NULL; // custom profile directory
853 int arg_noprofile = 0; // use default.profile if none other found/specified 853 int arg_noprofile = 0; // use default.profile if none other found/specified
854#ifdef HAVE_SECCOMP
855 int highest_errno = errno_highest_nr();
856#endif
857 854
858 // build /run/firejail directory structure 855 // build /run/firejail directory structure
859 preproc_build_firejail_dir(); 856 preproc_build_firejail_dir();
@@ -1155,9 +1152,7 @@ int main(int argc, char **argv) {
1155 exit(1); 1152 exit(1);
1156 } 1153 }
1157 arg_seccomp = 1; 1154 arg_seccomp = 1;
1158 cfg.seccomp_list = strdup(argv[i] + 10); 1155 cfg.seccomp_list = seccomp_check_list(argv[i] + 10);
1159 if (!cfg.seccomp_list)
1160 errExit("strdup");
1161 } 1156 }
1162 else { 1157 else {
1163 fprintf(stderr, "Error: seccomp feature is disabled in Firejail configuration file\n"); 1158 fprintf(stderr, "Error: seccomp feature is disabled in Firejail configuration file\n");
@@ -1171,9 +1166,7 @@ int main(int argc, char **argv) {
1171 exit(1); 1166 exit(1);
1172 } 1167 }
1173 arg_seccomp = 1; 1168 arg_seccomp = 1;
1174 cfg.seccomp_list_drop = strdup(argv[i] + 15); 1169 cfg.seccomp_list_drop = seccomp_check_list(argv[i] + 15);
1175 if (!cfg.seccomp_list_drop)
1176 errExit("strdup");
1177 } 1170 }
1178 else { 1171 else {
1179 fprintf(stderr, "Error: seccomp feature is disabled in Firejail configuration file\n"); 1172 fprintf(stderr, "Error: seccomp feature is disabled in Firejail configuration file\n");
@@ -1187,43 +1180,7 @@ int main(int argc, char **argv) {
1187 exit(1); 1180 exit(1);
1188 } 1181 }
1189 arg_seccomp = 1; 1182 arg_seccomp = 1;
1190 cfg.seccomp_list_keep = strdup(argv[i] + 15); 1183 cfg.seccomp_list_keep = seccomp_check_list(argv[i] + 15);
1191 if (!cfg.seccomp_list_keep)
1192 errExit("strdup");
1193 }
1194 else {
1195 fprintf(stderr, "Error: seccomp feature is disabled in Firejail configuration file\n");
1196 exit(1);
1197 }
1198 }
1199 else if (strncmp(argv[i], "--seccomp.e", 11) == 0 && strchr(argv[i], '=')) {
1200 if (checkcfg(CFG_SECCOMP)) {
1201 if (arg_seccomp && !cfg.seccomp_list_errno) {
1202 fprintf(stderr, "Error: seccomp already enabled\n");
1203 exit(1);
1204 }
1205 char *eq = strchr(argv[i], '=');
1206 char *errnoname = strndup(argv[i] + 10, eq - (argv[i] + 10));
1207 int nr = errno_find_name(errnoname);
1208 if (nr == -1) {
1209 fprintf(stderr, "Error: unknown errno %s\n", errnoname);
1210 free(errnoname);
1211 exit(1);
1212 }
1213
1214 if (!cfg.seccomp_list_errno)
1215 cfg.seccomp_list_errno = calloc(highest_errno+1, sizeof(cfg.seccomp_list_errno[0]));
1216
1217 if (cfg.seccomp_list_errno[nr]) {
1218 fprintf(stderr, "Error: errno %s already configured\n", errnoname);
1219 free(errnoname);
1220 exit(1);
1221 }
1222 arg_seccomp = 1;
1223 cfg.seccomp_list_errno[nr] = strdup(eq+1);
1224 if (!cfg.seccomp_list_errno[nr])
1225 errExit("strdup");
1226 free(errnoname);
1227 } 1184 }
1228 else { 1185 else {
1229 fprintf(stderr, "Error: seccomp feature is disabled in Firejail configuration file\n"); 1186 fprintf(stderr, "Error: seccomp feature is disabled in Firejail configuration file\n");
@@ -2606,13 +2563,6 @@ int main(int argc, char **argv) {
2606 waitpid(child, &status, 0); 2563 waitpid(child, &status, 0);
2607 2564
2608 // free globals 2565 // free globals
2609#ifdef HAVE_SECCOMP
2610 if (cfg.seccomp_list_errno) {
2611 for (i = 0; i < highest_errno; i++)
2612 free(cfg.seccomp_list_errno[i]);
2613 free(cfg.seccomp_list_errno);
2614 }
2615#endif
2616 if (cfg.profile) { 2566 if (cfg.profile) {
2617 ProfileEntry *prf = cfg.profile; 2567 ProfileEntry *prf = cfg.profile;
2618 while (prf != NULL) { 2568 while (prf != NULL) {
diff --git a/src/firejail/profile.c b/src/firejail/profile.c
index f7d5e87e6..f3a7eb727 100644
--- a/src/firejail/profile.c
+++ b/src/firejail/profile.c
@@ -529,9 +529,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
529#ifdef HAVE_SECCOMP 529#ifdef HAVE_SECCOMP
530 if (checkcfg(CFG_SECCOMP)) { 530 if (checkcfg(CFG_SECCOMP)) {
531 arg_seccomp = 1; 531 arg_seccomp = 1;
532 cfg.seccomp_list = strdup(ptr + 8); 532 cfg.seccomp_list = seccomp_check_list(ptr + 8);
533 if (!cfg.seccomp_list)
534 errExit("strdup");
535 } 533 }
536 else 534 else
537 fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n"); 535 fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n");
@@ -545,9 +543,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
545#ifdef HAVE_SECCOMP 543#ifdef HAVE_SECCOMP
546 if (checkcfg(CFG_SECCOMP)) { 544 if (checkcfg(CFG_SECCOMP)) {
547 arg_seccomp = 1; 545 arg_seccomp = 1;
548 cfg.seccomp_list_drop = strdup(ptr + 13); 546 cfg.seccomp_list_drop = seccomp_check_list(ptr + 13);
549 if (!cfg.seccomp_list_drop)
550 errExit("strdup");
551 } 547 }
552 else 548 else
553 fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n"); 549 fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n");
@@ -560,9 +556,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
560#ifdef HAVE_SECCOMP 556#ifdef HAVE_SECCOMP
561 if (checkcfg(CFG_SECCOMP)) { 557 if (checkcfg(CFG_SECCOMP)) {
562 arg_seccomp = 1; 558 arg_seccomp = 1;
563 cfg.seccomp_list_keep= strdup(ptr + 13); 559 cfg.seccomp_list_keep= seccomp_check_list(ptr + 13);
564 if (!cfg.seccomp_list_keep)
565 errExit("strdup");
566 } 560 }
567 else 561 else
568 fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n"); 562 fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n");
@@ -576,7 +570,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
576 arg_caps_list = strdup(ptr + 10); 570 arg_caps_list = strdup(ptr + 10);
577 if (!arg_caps_list) 571 if (!arg_caps_list)
578 errExit("strdup"); 572 errExit("strdup");
579 // verify seccomp list and exit if problems 573 // verify caps list and exit if problems
580 if (caps_check_list(arg_caps_list, NULL)) 574 if (caps_check_list(arg_caps_list, NULL))
581 exit(1); 575 exit(1);
582 return 0; 576 return 0;
@@ -588,7 +582,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
588 arg_caps_list = strdup(ptr + 10); 582 arg_caps_list = strdup(ptr + 10);
589 if (!arg_caps_list) 583 if (!arg_caps_list)
590 errExit("strdup"); 584 errExit("strdup");
591 // verify seccomp list and exit if problems 585 // verify caps list and exit if problems
592 if (caps_check_list(arg_caps_list, NULL)) 586 if (caps_check_list(arg_caps_list, NULL))
593 exit(1); 587 exit(1);
594 return 0; 588 return 0;
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c
index e3c95283d..556cb1fca 100644
--- a/src/firejail/sandbox.c
+++ b/src/firejail/sandbox.c
@@ -847,8 +847,6 @@ assert(0);
847 if (arg_seccomp == 1) { 847 if (arg_seccomp == 1) {
848 if (cfg.seccomp_list_keep) 848 if (cfg.seccomp_list_keep)
849 seccomp_filter_keep(); 849 seccomp_filter_keep();
850 else if (cfg.seccomp_list_errno)
851 seccomp_filter_errno();
852 else 850 else
853 seccomp_filter_drop(enforce_seccomp); 851 seccomp_filter_drop(enforce_seccomp);
854 } 852 }
diff --git a/src/firejail/seccomp.c b/src/firejail/seccomp.c
index 74d29fc9d..20807f5b1 100644
--- a/src/firejail/seccomp.c
+++ b/src/firejail/seccomp.c
@@ -22,6 +22,34 @@
22#include "firejail.h" 22#include "firejail.h"
23#include "../include/seccomp.h" 23#include "../include/seccomp.h"
24 24
25char *seccomp_check_list(const char *str) {
26 assert(str);
27 if (strlen(str) == 0) {
28 fprintf(stderr, "Error: empty syscall lists are not allowed\n");
29 exit(1);
30 }
31
32 int len = strlen(str) + 1;
33 char *rv = malloc(len);
34 if (!rv)
35 errExit("malloc");
36 memset(rv, 0, len);
37
38 const char *ptr1 = str;
39 char *ptr2 = rv;
40 while (*ptr1 != '\0') {
41 if (isalnum(*ptr1) || *ptr1 == '_' || *ptr1 == ',' || *ptr1 == ':')
42 *ptr2++ = *ptr1++;
43 else {
44 fprintf(stderr, "Error: invalid syscall list\n");
45 exit(1);
46 }
47 }
48
49 return rv;
50}
51
52
25int seccomp_load(const char *fname) { 53int seccomp_load(const char *fname) {
26 assert(fname); 54 assert(fname);
27 55
@@ -136,10 +164,6 @@ int seccomp_filter_drop(int enforce_seccomp) {
136#endif 164#endif
137 if (arg_debug) 165 if (arg_debug)
138 printf("Build default+drop seccomp filter\n"); 166 printf("Build default+drop seccomp filter\n");
139 if (strlen(cfg.seccomp_list) == 0) {
140 fprintf(stderr, "Error: empty syscall lists are not allowed\n");
141 exit(1);
142 }
143 167
144 // build the seccomp filter as a regular user 168 // build the seccomp filter as a regular user
145 int rv; 169 int rv;
@@ -157,10 +181,6 @@ int seccomp_filter_drop(int enforce_seccomp) {
157 else if (cfg.seccomp_list == NULL && cfg.seccomp_list_drop) { 181 else if (cfg.seccomp_list == NULL && cfg.seccomp_list_drop) {
158 if (arg_debug) 182 if (arg_debug)
159 printf("Build drop seccomp filter\n"); 183 printf("Build drop seccomp filter\n");
160 if (strlen(cfg.seccomp_list_drop) == 0) {
161 fprintf(stderr, "Error: empty syscall lists are not allowed\n");
162 exit(1);
163 }
164 184
165 // build the seccomp filter as a regular user 185 // build the seccomp filter as a regular user
166 int rv; 186 int rv;
@@ -199,10 +219,6 @@ int seccomp_filter_drop(int enforce_seccomp) {
199int seccomp_filter_keep(void) { 219int seccomp_filter_keep(void) {
200 if (arg_debug) 220 if (arg_debug)
201 printf("Build drop seccomp filter\n"); 221 printf("Build drop seccomp filter\n");
202 if (strlen(cfg.seccomp_list_keep) == 0) {
203 fprintf(stderr, "Error: empty syscall lists are not allowed\n");
204 exit(1);
205 }
206 222
207 // build the seccomp filter as a regular user 223 // build the seccomp filter as a regular user
208 int rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 4, 224 int rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 4,
@@ -216,38 +232,6 @@ int seccomp_filter_keep(void) {
216 return seccomp_load(RUN_SECCOMP_CFG); 232 return seccomp_load(RUN_SECCOMP_CFG);
217} 233}
218 234
219// errno filter for seccomp option
220int seccomp_filter_errno(void) {
221#if 0 //todo: disabled temporarely, bring it back
222 int i;
223 int higest_errno = errno_highest_nr();
224 filter_init();
225
226 // apply errno list
227
228 for (i = 0; i < higest_errno; i++) {
229 if (cfg.seccomp_list_errno[i]) {
230 if (syscall_check_list(cfg.seccomp_list_errno[i], filter_add_errno, i)) {
231 fprintf(stderr, "Error: cannot load seccomp filter\n");
232 exit(1);
233 }
234 }
235 }
236
237 filter_end_blacklist();
238 if (arg_debug)
239 filter_debug();
240
241 // save seccomp filter in /run/firejail/mnt/seccomp
242 // in order to use it in --join operations
243 write_seccomp_file();
244 return seccomp_load(RUN_SECCOMP_CFG);
245#else
246printf("*** --seccomp.<errno> is temporarily disabled, it will be brought back soon ***\n");
247 return 0;
248#endif
249}
250
251void seccomp_print_filter_name(const char *name) { 235void seccomp_print_filter_name(const char *name) {
252 EUID_ASSERT(); 236 EUID_ASSERT();
253 if (!name || strlen(name) == 0) { 237 if (!name || strlen(name) == 0) {
diff --git a/src/fseccomp/main.c b/src/fseccomp/main.c
index 22b13bcd9..39e72fdf9 100644
--- a/src/fseccomp/main.c
+++ b/src/fseccomp/main.c
@@ -40,7 +40,7 @@ static void usage(void) {
40int main(int argc, char **argv) { 40int main(int argc, char **argv) {
41#if 0 41#if 0
42{ 42{
43system("cat /proc/self/status"); 43//system("cat /proc/self/status");
44int i; 44int i;
45for (i = 0; i < argc; i++) 45for (i = 0; i < argc; i++)
46 printf("*%s* ", argv[i]); 46 printf("*%s* ", argv[i]);
diff --git a/src/fseccomp/protocol.c b/src/fseccomp/protocol.c
index 38c5f9d88..7bf560fe1 100644
--- a/src/fseccomp/protocol.c
+++ b/src/fseccomp/protocol.c
@@ -107,7 +107,7 @@ void protocol_build_filter(const char *prlist, const char *fname) {
107 assert(fname); 107 assert(fname);
108 108
109#ifndef SYS_socket 109#ifndef SYS_socket
110 fprintf(stderr, "Warning: --protocol not supported on this platform\n"); 110 fprintf(stderr, "Warning fseccomp: --protocol not supported on this platform\n");
111 return; 111 return;
112#else 112#else
113 // build the filter 113 // build the filter
diff --git a/src/fseccomp/syscall.c b/src/fseccomp/syscall.c
index e2052efde..6696f2b11 100644
--- a/src/fseccomp/syscall.c
+++ b/src/fseccomp/syscall.c
@@ -67,12 +67,52 @@ void syscall_print(void) {
67 printf("\n"); 67 printf("\n");
68} 68}
69 69
70// allowed input:
71// - syscall
72// - syscall(error)
73static void syscall_process_name(const char *name, int *syscall_nr, int *error_nr) {
74 assert(name);
75 if (strlen(name) == 0)
76 goto error;
77 *error_nr = -1;
78
79 // syntax check
80 char *str = strdup(name);
81 if (!str)
82 errExit("strdup");
83
84 char *syscall_name = str;
85 char *error_name = strchr(str, ':');
86 if (error_name) {
87 *error_name = '\0';
88 error_name++;
89 }
90 if (strlen(syscall_name) == 0) {
91 free(str);
92 goto error;
93 }
94
95 *syscall_nr = syscall_find_name(syscall_name);
96 if (error_name) {
97 *error_nr = errno_find_name(error_name);
98 if (*error_nr == -1)
99 *syscall_nr = -1;
100 }
101
102 free(str);
103 return;
104
105error:
106 fprintf(stderr, "Error fseccomp: invalid syscall list entry %s\n", name);
107 exit(1);
108}
109
70// return 1 if error, 0 if OK 110// return 1 if error, 0 if OK
71int syscall_check_list(const char *slist, void (*callback)(int fd, int syscall, int arg), int fd, int arg) { 111int syscall_check_list(const char *slist, void (*callback)(int fd, int syscall, int arg), int fd, int arg) {
72 // don't allow empty lists 112 // don't allow empty lists
73 if (slist == NULL || *slist == '\0') { 113 if (slist == NULL || *slist == '\0') {
74 fprintf(stderr, "Error: empty syscall lists are not allowed\n"); 114 fprintf(stderr, "Error fseccomp: empty syscall lists are not allowed\n");
75 return -1; 115 exit(1);
76 } 116 }
77 117
78 // work on a copy of the string 118 // work on a copy of the string
@@ -80,29 +120,28 @@ int syscall_check_list(const char *slist, void (*callback)(int fd, int syscall,
80 if (!str) 120 if (!str)
81 errExit("strdup"); 121 errExit("strdup");
82 122
83 char *ptr = str; 123 char *ptr =strtok(str, ",");
84 char *start = str; 124 if (ptr == NULL) {
85 while (*ptr != '\0') { 125 fprintf(stderr, "Error fseccomp: empty syscall lists are not allowed\n");
86 if (islower(*ptr) || isdigit(*ptr) || *ptr == '_') 126 exit(1);
87 ;
88 else if (*ptr == ',') {
89 *ptr = '\0';
90 int nr = syscall_find_name(start);
91 if (nr == -1)
92 fprintf(stderr, "Warning: syscall %s not found\n", start);
93 else if (callback != NULL)
94 callback(fd, nr, arg);
95
96 start = ptr + 1;
97 }
98 ptr++;
99 } 127 }
100 if (*start != '\0') { 128
101 int nr = syscall_find_name(start); 129 while (ptr) {
102 if (nr == -1) 130printf("ptr %s\n", ptr);
103 fprintf(stderr, "Warning: syscall %s not found\n", start); 131
104 else if (callback != NULL) 132 int syscall_nr;
105 callback(fd, nr, arg); 133 int error_nr;
134 syscall_process_name(ptr, &syscall_nr, &error_nr);
135printf("%d, %d\n", syscall_nr, error_nr);
136 if (syscall_nr == -1)
137 fprintf(stderr, "Warning fseccomp: syscall %s not found\n", ptr);
138 else if (callback != NULL) {
139 if (error_nr != -1)
140 filter_add_errno(fd, syscall_nr, error_nr);
141 else
142 callback(fd, syscall_nr, arg);
143 }
144 ptr = strtok(NULL, ",");
106 } 145 }
107 146
108 free(str); 147 free(str);
diff --git a/test/filters/seccomp-errno.exp b/test/filters/seccomp-errno.exp
index 4df1948be..c3af2fbe9 100755
--- a/test/filters/seccomp-errno.exp
+++ b/test/filters/seccomp-errno.exp
@@ -8,23 +8,23 @@ spawn $env(SHELL)
8match_max 100000 8match_max 100000
9 9
10send -- "touch seccomp-test-file\r" 10send -- "touch seccomp-test-file\r"
11sleep 1 11after 100
12 12
13send -- "firejail --seccomp.enoent=unlinkat rm seccomp-test-file\r" 13send -- "firejail --seccomp=unlinkat:ENOENT rm seccomp-test-file\r"
14expect { 14expect {
15 timeout {puts "TESTING ERROR 0\n";exit} 15 timeout {puts "TESTING ERROR 0\n";exit}
16 "No such file or directory" 16 "No such file or directory"
17} 17}
18sleep 1 18sleep 1
19 19
20send -- "firejail --seccomp.enoent=unlinkat --debug rm seccomp-test-file\r" 20send -- "firejail --seccomp=unlinkat:ENOENT --debug rm seccomp-test-file\r"
21expect { 21expect {
22 timeout {puts "TESTING ERROR 1\n";exit} 22 timeout {puts "TESTING ERROR 1\n";exit}
23 "unlinkat 2 ENOENT" 23 "unlinkat 2 ENOENT"
24} 24}
25sleep 1 25sleep 1
26 26
27send -- "firejail --seccomp.enoent=unlinkat,mkdir\r" 27send -- "firejail --seccomp=unlinkat:ENOENT,mkdir:ENOENT\r"
28expect { 28expect {
29 timeout {puts "TESTING ERROR 2\n";exit} 29 timeout {puts "TESTING ERROR 2\n";exit}
30 "Child process initialized" 30 "Child process initialized"
@@ -49,42 +49,6 @@ puts "\n"
49send -- "exit\r" 49send -- "exit\r"
50sleep 1 50sleep 1
51 51
52
53send -- "firejail --seccomp.enoent=unlinkat --seccomp.enoent=mkdir\r"
54expect {
55 timeout {puts "TESTING ERROR 5\n";exit}
56 "errno enoent already configured"
57}
58sleep 1
59
60send -- "firejail --seccomp.enoent=unlinkat --seccomp.eperm=mkdir\r"
61expect {
62 timeout {puts "TESTING ERROR 6\n";exit}
63 "Child process initialized"
64}
65sleep 1
66send -- "rm seccomp-test-file\r"
67expect {
68 timeout {puts "TESTING ERROR 7\n";exit}
69 "No such file or directory"
70}
71after 100
72puts "\n"
73
74send -- "mkdir seccomp-test-dir\r"
75expect {
76 timeout {puts "TESTING ERROR 8\n";exit}
77 "Operation not permitted"
78}
79after 100
80puts "\n"
81
82send -- "exit\r"
83sleep 1
84
85
86
87
88send -- "rm seccomp-test-file\r" 52send -- "rm seccomp-test-file\r"
89after 100 53after 100
90puts "all done\n" 54puts "all done\n"