aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/firejail/Makefile.in2
-rw-r--r--src/firejail/appimage_size.c5
-rw-r--r--src/firejail/errno.c11
-rw-r--r--src/firejail/firejail.h7
-rw-r--r--src/firejail/join.c2
-rw-r--r--src/firejail/main.c22
-rw-r--r--src/firejail/profile.c14
-rw-r--r--src/firejail/protocol.c247
-rw-r--r--src/firejail/sandbox.c20
-rw-r--r--src/firejail/sbox.c14
-rw-r--r--src/firejail/syscall.c13
-rw-r--r--src/fnet/main.c6
-rw-r--r--src/fseccomp/Makefile.in43
-rw-r--r--src/fseccomp/errno.c161
-rw-r--r--src/fseccomp/fseccomp.h18
-rw-r--r--src/fseccomp/main.c42
-rw-r--r--src/fseccomp/protocol.c219
-rw-r--r--src/fseccomp/syscall.c26
-rw-r--r--src/include/syscall.h (renamed from src/firejail/syscall.h)1
19 files changed, 599 insertions, 274 deletions
diff --git a/src/firejail/Makefile.in b/src/firejail/Makefile.in
index c4c168236..c99b6c30c 100644
--- a/src/firejail/Makefile.in
+++ b/src/firejail/Makefile.in
@@ -30,7 +30,7 @@ BINOBJS = $(foreach file, $(OBJS), $file)
30CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' $(HAVE_X11) $(HAVE_PRIVATE_HOME) $(HAVE_APPARMOR) $(HAVE_OVERLAYFS) $(HAVE_SECCOMP) $(HAVE_GLOBALCFG) $(HAVE_SECCOMP_H) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_BIND) $(HAVE_FILE_TRANSFER) $(HAVE_WHITELIST) -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security 30CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' $(HAVE_X11) $(HAVE_PRIVATE_HOME) $(HAVE_APPARMOR) $(HAVE_OVERLAYFS) $(HAVE_SECCOMP) $(HAVE_GLOBALCFG) $(HAVE_SECCOMP_H) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_BIND) $(HAVE_FILE_TRANSFER) $(HAVE_WHITELIST) -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security
31LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread 31LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread
32 32
33%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/euid_common.h ../include/pid.h ../include/seccomp.h 33%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/euid_common.h ../include/pid.h ../include/seccomp.h ../include/syscall.h
34 $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ 34 $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
35 35
36firejail: $(OBJS) ../lib/libnetlink.o ../lib/common.o 36firejail: $(OBJS) ../lib/libnetlink.o ../lib/common.o
diff --git a/src/firejail/appimage_size.c b/src/firejail/appimage_size.c
index 64fff6901..3f5c3150c 100644
--- a/src/firejail/appimage_size.c
+++ b/src/firejail/appimage_size.c
@@ -41,7 +41,6 @@ e_shoff + ( e_shentsize * e_shnum ) = 126584
41typedef Elf32_Nhdr Elf_Nhdr; 41typedef Elf32_Nhdr Elf_Nhdr;
42 42
43static Elf64_Ehdr ehdr; 43static Elf64_Ehdr ehdr;
44static Elf64_Phdr *phdr;
45 44
46#if __BYTE_ORDER == __LITTLE_ENDIAN 45#if __BYTE_ORDER == __LITTLE_ENDIAN
47#define ELFDATANATIVE ELFDATA2LSB 46#define ELFDATANATIVE ELFDATA2LSB
@@ -75,7 +74,7 @@ static uint64_t file64_to_cpu(uint64_t val) {
75// return 0 if error 74// return 0 if error
76static long unsigned int read_elf32(int fd) { 75static long unsigned int read_elf32(int fd) {
77 Elf32_Ehdr ehdr32; 76 Elf32_Ehdr ehdr32;
78 ssize_t ret, i; 77 ssize_t ret;
79 78
80 ret = pread(fd, &ehdr32, sizeof(ehdr32), 0); 79 ret = pread(fd, &ehdr32, sizeof(ehdr32), 0);
81 if (ret < 0 || (size_t)ret != sizeof(ehdr)) 80 if (ret < 0 || (size_t)ret != sizeof(ehdr))
@@ -92,7 +91,7 @@ static long unsigned int read_elf32(int fd) {
92// return 0 if error 91// return 0 if error
93static long unsigned int read_elf64(int fd) { 92static long unsigned int read_elf64(int fd) {
94 Elf64_Ehdr ehdr64; 93 Elf64_Ehdr ehdr64;
95 ssize_t ret, i; 94 ssize_t ret;
96 95
97 ret = pread(fd, &ehdr64, sizeof(ehdr64), 0); 96 ret = pread(fd, &ehdr64, sizeof(ehdr64), 0);
98 if (ret < 0 || (size_t)ret != sizeof(ehdr)) 97 if (ret < 0 || (size_t)ret != sizeof(ehdr))
diff --git a/src/firejail/errno.c b/src/firejail/errno.c
index c493dfa09..03f10bb14 100644
--- a/src/firejail/errno.c
+++ b/src/firejail/errno.c
@@ -206,15 +206,4 @@ char *errno_find_nr(int nr) {
206 return "unknown"; 206 return "unknown";
207} 207}
208 208
209void errno_print(void) {
210 EUID_ASSERT();
211
212 int i;
213 int elems = sizeof(errnolist) / sizeof(errnolist[0]);
214 for (i = 0; i < elems; i++) {
215 printf("%d\t- %s\n", errnolist[i].nr, errnolist[i].name);
216 }
217 printf("\n");
218}
219
220#endif // HAVE_SECCOMP 209#endif // HAVE_SECCOMP
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index 367f599ec..749656f8b 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -39,6 +39,7 @@
39#define RUN_RO_FILE "/run/firejail/firejail.ro.file" 39#define RUN_RO_FILE "/run/firejail/firejail.ro.file"
40#define RUN_MNT_DIR "/run/firejail/mnt" // a tmpfs is mounted on this directory before any of the files below are created 40#define RUN_MNT_DIR "/run/firejail/mnt" // a tmpfs is mounted on this directory before any of the files below are created
41#define RUN_SECCOMP_CFG "/run/firejail/mnt/seccomp" 41#define RUN_SECCOMP_CFG "/run/firejail/mnt/seccomp"
42#define RUN_SECCOMP_PROTOCOL "/run/firejail/mnt/seccomp.protocol"
42#define RUN_CGROUP_CFG "/run/firejail/mnt/cgroup" 43#define RUN_CGROUP_CFG "/run/firejail/mnt/cgroup"
43#define RUN_CPU_CFG "/run/firejail/mnt/cpu" 44#define RUN_CPU_CFG "/run/firejail/mnt/cpu"
44#define RUN_GROUPS_CFG "/run/firejail/mnt/groups" 45#define RUN_GROUPS_CFG "/run/firejail/mnt/groups"
@@ -514,8 +515,6 @@ void caps_print_filter_name(const char *name);
514const char *syscall_find_nr(int nr); 515const char *syscall_find_nr(int nr);
515// return -1 if error, 0 if no error 516// return -1 if error, 0 if no error
516int syscall_check_list(const char *slist, void (*callback)(int syscall, int arg), int arg); 517int syscall_check_list(const char *slist, void (*callback)(int syscall, int arg), int arg);
517// print all available syscallsseccomp
518void syscall_print(void);
519 518
520// fs_trace.c 519// fs_trace.c
521void fs_trace_preload(void); 520void fs_trace_preload(void);
@@ -598,7 +597,7 @@ void protocol_list();
598void protocol_print_filter_name(const char *name); 597void protocol_print_filter_name(const char *name);
599void protocol_print_filter(pid_t pid); 598void protocol_print_filter(pid_t pid);
600void protocol_store(const char *prlist); 599void protocol_store(const char *prlist);
601void protocol_filter(void); 600void protocol_filter(const char *fname);
602void protocol_filter_save(void); 601void protocol_filter_save(void);
603void protocol_filter_load(const char *fname); 602void protocol_filter_load(const char *fname);
604 603
@@ -686,11 +685,13 @@ void build_cmdline(char **command_line, char **window_title, int argc, char **ar
686// programs 685// programs
687#define PATH_FNET (LIBDIR "/firejail/fnet") 686#define PATH_FNET (LIBDIR "/firejail/fnet")
688#define PATH_FIREMON (PREFIX "/bin/firemon") 687#define PATH_FIREMON (PREFIX "/bin/firemon")
688#define PATH_FSECCOMP (LIBDIR "/firejail/fseccomp")
689// bitmapped filters for sbox_run 689// bitmapped filters for sbox_run
690#define SBOX_ROOT 1 690#define SBOX_ROOT 1
691#define SBOX_USER 2 691#define SBOX_USER 2
692#define SBOX_CAPS 4 692#define SBOX_CAPS 4
693#define SBOX_SECCOMP 8 693#define SBOX_SECCOMP 8
694// run sbox
694int sbox_run(unsigned filter, int num, ...); 695int sbox_run(unsigned filter, int num, ...);
695 696
696 697
diff --git a/src/firejail/join.c b/src/firejail/join.c
index ea44019ca..9b5fba24d 100644
--- a/src/firejail/join.c
+++ b/src/firejail/join.c
@@ -296,7 +296,7 @@ void join(pid_t pid, int argc, char **argv, int index) {
296 if (getuid() != 0) 296 if (getuid() != 0)
297 protocol_filter_load(RUN_PROTOCOL_CFG); 297 protocol_filter_load(RUN_PROTOCOL_CFG);
298 if (cfg.protocol) { // not available for uid 0 298 if (cfg.protocol) { // not available for uid 0
299 protocol_filter(); 299 protocol_filter(RUN_SECCOMP_PROTOCOL);
300 } 300 }
301 301
302 // set seccomp filter 302 // set seccomp filter
diff --git a/src/firejail/main.c b/src/firejail/main.c
index 15d42a4e0..e210ceb31 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -404,8 +404,8 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
404#ifdef HAVE_SECCOMP 404#ifdef HAVE_SECCOMP
405 else if (strcmp(argv[i], "--debug-syscalls") == 0) { 405 else if (strcmp(argv[i], "--debug-syscalls") == 0) {
406 if (checkcfg(CFG_SECCOMP)) { 406 if (checkcfg(CFG_SECCOMP)) {
407 syscall_print(); 407 int rv = sbox_run(SBOX_USER | SBOX_CAPS | SBOX_SECCOMP, 2, PATH_FSECCOMP, "debug-syscalls");
408 exit(0); 408 exit(rv);
409 } 409 }
410 else { 410 else {
411 fprintf(stderr, "Error: seccomp feature is disabled in Firejail configuration file\n"); 411 fprintf(stderr, "Error: seccomp feature is disabled in Firejail configuration file\n");
@@ -414,7 +414,8 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
414 } 414 }
415 else if (strcmp(argv[i], "--debug-errnos") == 0) { 415 else if (strcmp(argv[i], "--debug-errnos") == 0) {
416 if (checkcfg(CFG_SECCOMP)) { 416 if (checkcfg(CFG_SECCOMP)) {
417 errno_print(); 417 int rv = sbox_run(SBOX_USER | SBOX_CAPS | SBOX_SECCOMP, 2, PATH_FSECCOMP, "debug-errnos");
418 exit(rv);
418 } 419 }
419 else { 420 else {
420 fprintf(stderr, "Error: seccomp feature is disabled in Firejail configuration file\n"); 421 fprintf(stderr, "Error: seccomp feature is disabled in Firejail configuration file\n");
@@ -438,8 +439,8 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
438 exit(0); 439 exit(0);
439 } 440 }
440 else if (strcmp(argv[i], "--debug-protocols") == 0) { 441 else if (strcmp(argv[i], "--debug-protocols") == 0) {
441 protocol_list(); 442 int rv = sbox_run(SBOX_USER | SBOX_CAPS | SBOX_SECCOMP, 2, PATH_FSECCOMP, "debug-protocols");
442 exit(0); 443 exit(rv);
443 } 444 }
444 else if (strncmp(argv[i], "--protocol.print=", 17) == 0) { 445 else if (strncmp(argv[i], "--protocol.print=", 17) == 0) {
445 if (checkcfg(CFG_SECCOMP)) { 446 if (checkcfg(CFG_SECCOMP)) {
@@ -1117,7 +1118,16 @@ int main(int argc, char **argv) {
1117#ifdef HAVE_SECCOMP 1118#ifdef HAVE_SECCOMP
1118 else if (strncmp(argv[i], "--protocol=", 11) == 0) { 1119 else if (strncmp(argv[i], "--protocol=", 11) == 0) {
1119 if (checkcfg(CFG_SECCOMP)) { 1120 if (checkcfg(CFG_SECCOMP)) {
1120 protocol_store(argv[i] + 11); 1121 if (cfg.protocol) {
1122 if (!arg_quiet)
1123 fprintf(stderr, "Warning: a protocol list is present, the new list \"%s\" will not be installed\n", argv[i] + 11);
1124 }
1125 else {
1126 // store list
1127 cfg.protocol = strdup(argv[i] + 11);
1128 if (!cfg.protocol)
1129 errExit("strdup");
1130 }
1121 } 1131 }
1122 else { 1132 else {
1123 fprintf(stderr, "Error: seccomp feature is disabled in Firejail configuration file\n"); 1133 fprintf(stderr, "Error: seccomp feature is disabled in Firejail configuration file\n");
diff --git a/src/firejail/profile.c b/src/firejail/profile.c
index e5c35a89d..f7d5e87e6 100644
--- a/src/firejail/profile.c
+++ b/src/firejail/profile.c
@@ -497,8 +497,18 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
497 497
498 if (strncmp(ptr, "protocol ", 9) == 0) { 498 if (strncmp(ptr, "protocol ", 9) == 0) {
499#ifdef HAVE_SECCOMP 499#ifdef HAVE_SECCOMP
500 if (checkcfg(CFG_SECCOMP)) 500 if (checkcfg(CFG_SECCOMP)) {
501 protocol_store(ptr + 9); 501 if (cfg.protocol) {
502 if (!arg_quiet)
503 fprintf(stderr, "Warning: a protocol list is present, the new list \"%s\" will not be installed\n", ptr + 9);
504 return 0;
505 }
506
507 // store list
508 cfg.protocol = strdup(ptr + 9);
509 if (!cfg.protocol)
510 errExit("strdup");
511 }
502 else 512 else
503 fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n"); 513 fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n");
504#endif 514#endif
diff --git a/src/firejail/protocol.c b/src/firejail/protocol.c
index 6321c703a..43f30e30a 100644
--- a/src/firejail/protocol.c
+++ b/src/firejail/protocol.c
@@ -18,241 +18,44 @@
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/ 19*/
20 20
21/*
22 struct sock_filter filter[] = {
23 VALIDATE_ARCHITECTURE,
24 EXAMINE_SYSCALL,
25 ONLY(SYS_socket),
26 EXAMINE_ARGUMENT(0), // allow only AF_INET and AF_INET6, drop everything else
27 WHITELIST(AF_INET),
28 WHITELIST(AF_INET6),
29 WHITELIST(AF_PACKET),
30 RETURN_ERRNO(ENOTSUP)
31 };
32 struct sock_fprog prog = {
33 .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),
34 .filter = filter,
35 };
36
37
38 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
39 perror("prctl(NO_NEW_PRIVS)");
40 return 1;
41 }
42 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
43 perror("prctl");
44 return 1;
45 }
46*/
47
48#ifdef HAVE_SECCOMP 21#ifdef HAVE_SECCOMP
49#include "firejail.h" 22#include "firejail.h"
50#include "../include/seccomp.h" 23#include "../include/seccomp.h"
51#include <sys/types.h>
52#include <sys/socket.h>
53
54static char *protocol[] = {
55 "unix",
56 "inet",
57 "inet6",
58 "netlink",
59 "packet",
60 NULL
61};
62
63static struct sock_filter protocol_filter_command[] = {
64 WHITELIST(AF_UNIX),
65 WHITELIST(AF_INET),
66 WHITELIST(AF_INET6),
67 WHITELIST(AF_NETLINK),
68 WHITELIST(AF_PACKET)
69};
70// Note: protocol[] and protocol_filter_command are synchronized
71
72// command length
73struct sock_filter whitelist[] = {
74 WHITELIST(AF_UNIX)
75};
76unsigned whitelist_len = sizeof(whitelist) / sizeof(struct sock_filter);
77
78 24
79 25// install protocol filter
80static int is_protocol(const char *p) { 26void protocol_filter(const char *fname) {
81 int i = 0;
82 while (protocol[i] != NULL) {
83 if (strcmp(protocol[i], p) == 0)
84 return 1;
85 i++;
86 }
87
88 return 0;
89}
90
91static struct sock_filter *find_protocol_domain(const char *p) {
92 int i = 0;
93 while (protocol[i] != NULL) {
94 if (strcmp(protocol[i], p) == 0)
95 return &protocol_filter_command[i * whitelist_len];
96 i++;
97 }
98
99 return NULL;
100}
101
102// --debug-protocols
103void protocol_list(void) {
104 EUID_ASSERT();
105
106#ifndef SYS_socket 27#ifndef SYS_socket
107 fprintf(stderr, "Warning: --protocol not supported on this platform\n"); 28 if (arg_debug)
29 printf("No support for --protocol on this platform\n");
108 return; 30 return;
109#endif 31#else
110 32 assert(fname);
111 int i = 0;
112 while (protocol[i] != NULL) {
113 printf("%s, ", protocol[i]);
114 i++;
115 }
116 printf("\n");
117}
118
119 33
120// check protocol list and store it in cfg structure 34 // check file
121void protocol_store(const char *prlist) { 35 struct stat s;
122 EUID_ASSERT(); 36 if (stat(fname, &s) == -1) {
123 assert(prlist); 37 fprintf(stderr, "Error: cannot read protocol filter file\n");
124 38 exit(1);
125 if (cfg.protocol && !arg_quiet) {
126 fprintf(stderr, "Warning: a protocol list is present, the new list \"%s\" will not be installed\n", prlist);
127 return;
128 } 39 }
129 40 int size = s.st_size;
130 // temporary list
131 char *tmplist = strdup(prlist);
132 if (!tmplist)
133 errExit("strdup");
134
135 // check list
136 char *token = strtok(tmplist, ",");
137 if (!token)
138 goto errout;
139
140 while (token) {
141 if (!is_protocol(token))
142 goto errout;
143 token = strtok(NULL, ",");
144 }
145 free(tmplist);
146
147 // store list
148 cfg.protocol = strdup(prlist);
149 if (!cfg.protocol)
150 errExit("strdup");
151 return;
152
153errout:
154 fprintf(stderr, "Error: invalid protocol list\n");
155 exit(1);
156}
157 41
158// install protocol filter 42 // read filter
159void protocol_filter(void) {
160 assert(cfg.protocol);
161 if (arg_debug)
162 printf("Set protocol filter: %s\n", cfg.protocol);
163
164#ifndef SYS_socket
165 (void) find_protocol_domain;
166 fprintf(stderr, "Warning: --protocol not supported on this platform\n");
167 return;
168#else
169 // build the filter
170 struct sock_filter filter[32]; // big enough 43 struct sock_filter filter[32]; // big enough
171 memset(&filter[0], 0, sizeof(filter)); 44 memset(&filter[0], 0, sizeof(filter));
172 uint8_t *ptr = (uint8_t *) &filter[0]; 45 int src = open(fname, O_RDONLY);
173 46 int rd = 0;
174 // header 47 while (rd < size) {
175 struct sock_filter filter_start[] = { 48 int rv = read(src, (unsigned char *) filter + rd, size - rd);
176 VALIDATE_ARCHITECTURE, 49 if (rv == -1) {
177 EXAMINE_SYSCALL, 50 fprintf(stderr, "Error: cannot read %s file\n", fname);
178 ONLY(SYS_socket), 51 exit(1);
179 EXAMINE_ARGUMENT(0) 52 }
180 }; 53 rd += rv;
181 memcpy(ptr, &filter_start[0], sizeof(filter_start));
182 ptr += sizeof(filter_start);
183
184#if 0
185printf("entries %u\n", (unsigned) (sizeof(filter_start) / sizeof(struct sock_filter)));
186{
187 unsigned j;
188 unsigned char *ptr2 = (unsigned char *) &filter[0];
189 for (j = 0; j < sizeof(filter); j++, ptr2++) {
190 if ((j % (sizeof(struct sock_filter))) == 0)
191 printf("\n%u: ", 1 + (unsigned) (j / (sizeof(struct sock_filter))));
192 printf("%02x, ", (*ptr2) & 0xff);
193 }
194 printf("\n");
195}
196printf("whitelist_len %u, struct sock_filter len %u\n", whitelist_len, (unsigned) sizeof(struct sock_filter));
197#endif
198
199
200 // parse list and add commands
201 char *tmplist = strdup(cfg.protocol);
202 if (!tmplist)
203 errExit("strdup");
204 char *token = strtok(tmplist, ",");
205 if (!token)
206 errExit("strtok");
207
208 while (token) {
209 struct sock_filter *domain = find_protocol_domain(token);
210 assert(domain);
211 memcpy(ptr, domain, whitelist_len * sizeof(struct sock_filter));
212 ptr += whitelist_len * sizeof(struct sock_filter);
213 token = strtok(NULL, ",");
214
215#if 0
216printf("entries %u\n", (unsigned) ((uint64_t) ptr - (uint64_t) (filter)) / (unsigned) sizeof(struct sock_filter));
217{
218 unsigned j;
219 unsigned char *ptr2 = (unsigned char *) &filter[0];
220 for (j = 0; j < sizeof(filter); j++, ptr2++) {
221 if ((j % (sizeof(struct sock_filter))) == 0)
222 printf("\n%u: ", 1 + (unsigned) (j / (sizeof(struct sock_filter))));
223 printf("%02x, ", (*ptr2) & 0xff);
224 }
225 printf("\n");
226}
227#endif
228
229
230 }
231 free(tmplist);
232
233 // add end of filter
234 struct sock_filter filter_end[] = {
235 RETURN_ERRNO(ENOTSUP)
236 };
237 memcpy(ptr, &filter_end[0], sizeof(filter_end));
238 ptr += sizeof(filter_end);
239
240#if 0
241printf("entries %u\n", (unsigned) ((uint64_t) ptr - (uint64_t) (filter)) / (unsigned) sizeof(struct sock_filter));
242{
243 unsigned j;
244 unsigned char *ptr2 = (unsigned char *) &filter[0];
245 for (j = 0; j < sizeof(filter); j++, ptr2++) {
246 if ((j % (sizeof(struct sock_filter))) == 0)
247 printf("\n%u: ", 1 + (unsigned) (j / (sizeof(struct sock_filter))));
248 printf("%02x, ", (*ptr2) & 0xff);
249 } 54 }
250 printf("\n"); 55 close(src);
251}
252#endif
253 56
254 // install filter 57 // install filter
255 unsigned short entries = (unsigned short) ((uintptr_t) ptr - (uintptr_t) (filter)) / (unsigned) sizeof(struct sock_filter); 58 unsigned short entries = (unsigned short) size / (unsigned short) sizeof(struct sock_filter);
256 struct sock_fprog prog = { 59 struct sock_fprog prog = {
257 .len = entries, 60 .len = entries,
258 .filter = filter, 61 .filter = filter,
@@ -262,7 +65,7 @@ printf("entries %u\n", (unsigned) ((uint64_t) ptr - (uint64_t) (filter)) / (uns
262 fprintf(stderr, "Warning: seccomp disabled, it requires a Linux kernel version 3.5 or newer.\n"); 65 fprintf(stderr, "Warning: seccomp disabled, it requires a Linux kernel version 3.5 or newer.\n");
263 return; 66 return;
264 } 67 }
265#endif // SYS_socket 68#endif
266} 69}
267 70
268void protocol_filter_save(void) { 71void protocol_filter_save(void) {
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c
index f5cca7494..7a63461ef 100644
--- a/src/firejail/sandbox.c
+++ b/src/firejail/sandbox.c
@@ -819,8 +819,24 @@ int sandbox(void* sandbox_arg) {
819#ifdef HAVE_SECCOMP 819#ifdef HAVE_SECCOMP
820 // install protocol filter 820 // install protocol filter
821 if (cfg.protocol) { 821 if (cfg.protocol) {
822 protocol_filter(); // install filter 822 if (arg_debug)
823 protocol_filter_save(); // save filter in PROTOCOL_CFG 823 printf("Set protocol filter: %s\n", cfg.protocol);
824 // as root, create RUN_SECCOMP_PROTOCOL file
825 // this is where fseccomp program will store the protocol filter
826 int dst = open(RUN_SECCOMP_PROTOCOL, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
827 if (dst == -1)
828 errExit("open");
829 close(dst);
830 if (chown(RUN_SECCOMP_PROTOCOL, getuid(), getgid()) == -1)
831 errExit("chown");
832
833 // build the seccomp filter as a regular user
834 int rv = sbox_run(SBOX_USER | SBOX_CAPS | SBOX_SECCOMP, 5,
835 PATH_FSECCOMP, "protocol", "build", cfg.protocol, RUN_SECCOMP_PROTOCOL);
836 if (rv)
837 exit(rv);
838 protocol_filter(RUN_SECCOMP_PROTOCOL); // install filter
839 protocol_filter_save(); // save filter in RUN_PROTOCOL_CFG
824 } 840 }
825 841
826 // if a keep list is available, disregard the drop list 842 // if a keep list is available, disregard the drop list
diff --git a/src/firejail/sbox.c b/src/firejail/sbox.c
index 8c6ace27e..d1225c3bc 100644
--- a/src/firejail/sbox.c
+++ b/src/firejail/sbox.c
@@ -23,6 +23,7 @@
23#include <unistd.h> 23#include <unistd.h>
24#include <net/if.h> 24#include <net/if.h>
25#include <stdarg.h> 25#include <stdarg.h>
26 #include <sys/wait.h>
26#include "../include/seccomp.h" 27#include "../include/seccomp.h"
27 28
28static struct sock_filter filter[] = { 29static struct sock_filter filter[] = {
@@ -112,7 +113,7 @@ typedef struct sbox_config {
112 113
113int sbox_run(unsigned filter, int num, ...) { 114int sbox_run(unsigned filter, int num, ...) {
114 EUID_ROOT(); 115 EUID_ROOT();
115 char *path = NULL; 116
116 int i; 117 int i;
117 va_list valist; 118 va_list valist;
118 va_start(valist, num); 119 va_start(valist, num);
@@ -124,14 +125,14 @@ int sbox_run(unsigned filter, int num, ...) {
124 arg[i] = NULL; 125 arg[i] = NULL;
125 va_end(valist); 126 va_end(valist);
126 127
127#if 0 128//#if 0
128{ 129{
129int i; 130int i;
130for (i = 0; i <= num; i++) 131for (i = 0; i <= num; i++)
131 printf("#%s# ", arg[i]); 132 printf("#%s# ", arg[i]);
132printf("\n"); 133printf("\n");
133} 134}
134#endif 135//#endif
135 pid_t child = fork(); 136 pid_t child = fork();
136 if (child < 0) 137 if (child < 0)
137 errExit("fork"); 138 errExit("fork");
@@ -159,7 +160,10 @@ printf("\n");
159 else if (filter & SBOX_USER) 160 else if (filter & SBOX_USER)
160 drop_privs(1); 161 drop_privs(1);
161 162
162 execvp(arg[0], arg); 163 if (arg[0]) // get rid of scan-build warning
164 execvp(arg[0], arg);
165 else
166 assert(0);
163 perror("execl"); 167 perror("execl");
164 _exit(1); 168 _exit(1);
165 } 169 }
@@ -169,7 +173,7 @@ printf("\n");
169 errExit("waitpid"); 173 errExit("waitpid");
170 } 174 }
171 if (WIFEXITED(status) && status != 0) { 175 if (WIFEXITED(status) && status != 0) {
172 fprintf(stderr, "Error: cannot run fnet\n"); 176 fprintf(stderr, "Error: failed to run %s\n", arg[0]);
173 exit(1); 177 exit(1);
174 } 178 }
175 179
diff --git a/src/firejail/syscall.c b/src/firejail/syscall.c
index 985cc8bb8..f405f23c8 100644
--- a/src/firejail/syscall.c
+++ b/src/firejail/syscall.c
@@ -31,7 +31,7 @@ static SyscallEntry syslist[] = {
31// 31//
32// code generated using tools/extract-syscall 32// code generated using tools/extract-syscall
33// 33//
34#include "syscall.h" 34#include "../include/syscall.h"
35// 35//
36// end of generated code 36// end of generated code
37// 37//
@@ -102,15 +102,4 @@ int syscall_check_list(const char *slist, void (*callback)(int syscall, int arg)
102 return 0; 102 return 0;
103} 103}
104 104
105void syscall_print(void) {
106 EUID_ASSERT();
107
108 int i;
109 int elems = sizeof(syslist) / sizeof(syslist[0]);
110 for (i = 0; i < elems; i++) {
111 printf("%d\t- %s\n", syslist[i].nr, syslist[i].name);
112 }
113 printf("\n");
114}
115
116#endif // HAVE_SECCOMP 105#endif // HAVE_SECCOMP
diff --git a/src/fnet/main.c b/src/fnet/main.c
index 88f71c4b3..f17287cb9 100644
--- a/src/fnet/main.c
+++ b/src/fnet/main.c
@@ -17,11 +17,7 @@
17 * with this program; if not, write to the Free Software Foundation, Inc., 17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/ 19*/
20#include <stdio.h> 20#include "fnet.h"
21#include <stdlib.h>
22#include <errno.h>
23#include <sys/prctl.h>
24#include <linux/capability.h>
25 21
26static void usage(void) { 22static void usage(void) {
27 printf("Usage:\n"); 23 printf("Usage:\n");
diff --git a/src/fseccomp/Makefile.in b/src/fseccomp/Makefile.in
new file mode 100644
index 000000000..e7edd1b8f
--- /dev/null
+++ b/src/fseccomp/Makefile.in
@@ -0,0 +1,43 @@
1all: fseccomp
2
3prefix=@prefix@
4exec_prefix=@exec_prefix@
5libdir=@libdir@
6sysconfdir=@sysconfdir@
7
8VERSION=@PACKAGE_VERSION@
9NAME=@PACKAGE_NAME@
10HAVE_SECCOMP_H=@HAVE_SECCOMP_H@
11HAVE_SECCOMP=@HAVE_SECCOMP@
12HAVE_CHROOT=@HAVE_CHROOT@
13HAVE_BIND=@HAVE_BIND@
14HAVE_FATAL_WARNINGS=@HAVE_FATAL_WARNINGS@
15HAVE_NETWORK=@HAVE_NETWORK@
16HAVE_USERNS=@HAVE_USERNS@
17HAVE_X11=@HAVE_X11@
18HAVE_FILE_TRANSFER=@HAVE_FILE_TRANSFER@
19HAVE_WHITELIST=@HAVE_WHITELIST@
20HAVE_GLOBALCFG=@HAVE_GLOBALCFG@
21HAVE_APPARMOR=@HAVE_APPARMOR@
22HAVE_OVERLAYFS=@HAVE_OVERLAYFS@
23HAVE_PRIVATE_HOME=@HAVE_PRIVATE_HOME@
24EXTRA_LDFLAGS +=@EXTRA_LDFLAGS@
25
26H_FILE_LIST = $(sort $(wildcard *.[h]))
27C_FILE_LIST = $(sort $(wildcard *.c))
28OBJS = $(C_FILE_LIST:.c=.o)
29BINOBJS = $(foreach file, $(OBJS), $file)
30CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' $(HAVE_X11) $(HAVE_PRIVATE_HOME) $(HAVE_APPARMOR) $(HAVE_OVERLAYFS) $(HAVE_SECCOMP) $(HAVE_GLOBALCFG) $(HAVE_SECCOMP_H) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_BIND) $(HAVE_FILE_TRANSFER) $(HAVE_WHITELIST) -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security
31LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread
32
33%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/euid_common.h ../include/libnetlink.h ../include/pid.h ../include/syscall.h
34 $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
35
36fseccomp: $(OBJS) ../lib/libnetlink.o ../lib/common.o
37 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/libnetlink.o ../lib/common.o $(LIBS) $(EXTRA_LDFLAGS)
38
39clean:; rm -f *.o fseccomp
40
41distclean: clean
42 rm -fr Makefile
43
diff --git a/src/fseccomp/errno.c b/src/fseccomp/errno.c
new file mode 100644
index 000000000..625f484bd
--- /dev/null
+++ b/src/fseccomp/errno.c
@@ -0,0 +1,161 @@
1#include "fseccomp.h"
2
3#include <errno.h>
4//#include <attr/xattr.h>
5
6typedef struct {
7 char *name;
8 int nr;
9} ErrnoEntry;
10
11static ErrnoEntry errnolist[] = {
12//
13// code generated using tools/extract-errnos
14//
15 {"EPERM", EPERM},
16 {"ENOENT", ENOENT},
17 {"ESRCH", ESRCH},
18 {"EINTR", EINTR},
19 {"EIO", EIO},
20 {"ENXIO", ENXIO},
21 {"E2BIG", E2BIG},
22 {"ENOEXEC", ENOEXEC},
23 {"EBADF", EBADF},
24 {"ECHILD", ECHILD},
25 {"EAGAIN", EAGAIN},
26 {"ENOMEM", ENOMEM},
27 {"EACCES", EACCES},
28 {"EFAULT", EFAULT},
29 {"ENOTBLK", ENOTBLK},
30 {"EBUSY", EBUSY},
31 {"EEXIST", EEXIST},
32 {"EXDEV", EXDEV},
33 {"ENODEV", ENODEV},
34 {"ENOTDIR", ENOTDIR},
35 {"EISDIR", EISDIR},
36 {"EINVAL", EINVAL},
37 {"ENFILE", ENFILE},
38 {"EMFILE", EMFILE},
39 {"ENOTTY", ENOTTY},
40 {"ETXTBSY", ETXTBSY},
41 {"EFBIG", EFBIG},
42 {"ENOSPC", ENOSPC},
43 {"ESPIPE", ESPIPE},
44 {"EROFS", EROFS},
45 {"EMLINK", EMLINK},
46 {"EPIPE", EPIPE},
47 {"EDOM", EDOM},
48 {"ERANGE", ERANGE},
49 {"EDEADLK", EDEADLK},
50 {"ENAMETOOLONG", ENAMETOOLONG},
51 {"ENOLCK", ENOLCK},
52 {"ENOSYS", ENOSYS},
53 {"ENOTEMPTY", ENOTEMPTY},
54 {"ELOOP", ELOOP},
55 {"EWOULDBLOCK", EWOULDBLOCK},
56 {"ENOMSG", ENOMSG},
57 {"EIDRM", EIDRM},
58 {"ECHRNG", ECHRNG},
59 {"EL2NSYNC", EL2NSYNC},
60 {"EL3HLT", EL3HLT},
61 {"EL3RST", EL3RST},
62 {"ELNRNG", ELNRNG},
63 {"EUNATCH", EUNATCH},
64 {"ENOCSI", ENOCSI},
65 {"EL2HLT", EL2HLT},
66 {"EBADE", EBADE},
67 {"EBADR", EBADR},
68 {"EXFULL", EXFULL},
69 {"ENOANO", ENOANO},
70 {"EBADRQC", EBADRQC},
71 {"EBADSLT", EBADSLT},
72 {"EDEADLOCK", EDEADLOCK},
73 {"EBFONT", EBFONT},
74 {"ENOSTR", ENOSTR},
75 {"ENODATA", ENODATA},
76 {"ETIME", ETIME},
77 {"ENOSR", ENOSR},
78 {"ENONET", ENONET},
79 {"ENOPKG", ENOPKG},
80 {"EREMOTE", EREMOTE},
81 {"ENOLINK", ENOLINK},
82 {"EADV", EADV},
83 {"ESRMNT", ESRMNT},
84 {"ECOMM", ECOMM},
85 {"EPROTO", EPROTO},
86 {"EMULTIHOP", EMULTIHOP},
87 {"EDOTDOT", EDOTDOT},
88 {"EBADMSG", EBADMSG},
89 {"EOVERFLOW", EOVERFLOW},
90 {"ENOTUNIQ", ENOTUNIQ},
91 {"EBADFD", EBADFD},
92 {"EREMCHG", EREMCHG},
93 {"ELIBACC", ELIBACC},
94 {"ELIBBAD", ELIBBAD},
95 {"ELIBSCN", ELIBSCN},
96 {"ELIBMAX", ELIBMAX},
97 {"ELIBEXEC", ELIBEXEC},
98 {"EILSEQ", EILSEQ},
99 {"ERESTART", ERESTART},
100 {"ESTRPIPE", ESTRPIPE},
101 {"EUSERS", EUSERS},
102 {"ENOTSOCK", ENOTSOCK},
103 {"EDESTADDRREQ", EDESTADDRREQ},
104 {"EMSGSIZE", EMSGSIZE},
105 {"EPROTOTYPE", EPROTOTYPE},
106 {"ENOPROTOOPT", ENOPROTOOPT},
107 {"EPROTONOSUPPORT", EPROTONOSUPPORT},
108 {"ESOCKTNOSUPPORT", ESOCKTNOSUPPORT},
109 {"EOPNOTSUPP", EOPNOTSUPP},
110 {"EPFNOSUPPORT", EPFNOSUPPORT},
111 {"EAFNOSUPPORT", EAFNOSUPPORT},
112 {"EADDRINUSE", EADDRINUSE},
113 {"EADDRNOTAVAIL", EADDRNOTAVAIL},
114 {"ENETDOWN", ENETDOWN},
115 {"ENETUNREACH", ENETUNREACH},
116 {"ENETRESET", ENETRESET},
117 {"ECONNABORTED", ECONNABORTED},
118 {"ECONNRESET", ECONNRESET},
119 {"ENOBUFS", ENOBUFS},
120 {"EISCONN", EISCONN},
121 {"ENOTCONN", ENOTCONN},
122 {"ESHUTDOWN", ESHUTDOWN},
123 {"ETOOMANYREFS", ETOOMANYREFS},
124 {"ETIMEDOUT", ETIMEDOUT},
125 {"ECONNREFUSED", ECONNREFUSED},
126 {"EHOSTDOWN", EHOSTDOWN},
127 {"EHOSTUNREACH", EHOSTUNREACH},
128 {"EALREADY", EALREADY},
129 {"EINPROGRESS", EINPROGRESS},
130 {"ESTALE", ESTALE},
131 {"EUCLEAN", EUCLEAN},
132 {"ENOTNAM", ENOTNAM},
133 {"ENAVAIL", ENAVAIL},
134 {"EISNAM", EISNAM},
135 {"EREMOTEIO", EREMOTEIO},
136 {"EDQUOT", EDQUOT},
137 {"ENOMEDIUM", ENOMEDIUM},
138 {"EMEDIUMTYPE", EMEDIUMTYPE},
139 {"ECANCELED", ECANCELED},
140 {"ENOKEY", ENOKEY},
141 {"EKEYEXPIRED", EKEYEXPIRED},
142 {"EKEYREVOKED", EKEYREVOKED},
143 {"EKEYREJECTED", EKEYREJECTED},
144 {"EOWNERDEAD", EOWNERDEAD},
145 {"ENOTRECOVERABLE", ENOTRECOVERABLE},
146 {"ERFKILL", ERFKILL},
147 {"EHWPOISON", EHWPOISON},
148 {"ENOTSUP", ENOTSUP},
149#ifdef ENOATTR
150 {"ENOATTR", ENOATTR},
151#endif
152};
153
154void errno_print(void) {
155 int i;
156 int elems = sizeof(errnolist) / sizeof(errnolist[0]);
157 for (i = 0; i < elems; i++) {
158 printf("%d\t- %s\n", errnolist[i].nr, errnolist[i].name);
159 }
160 printf("\n");
161}
diff --git a/src/fseccomp/fseccomp.h b/src/fseccomp/fseccomp.h
new file mode 100644
index 000000000..57757ea6c
--- /dev/null
+++ b/src/fseccomp/fseccomp.h
@@ -0,0 +1,18 @@
1#ifndef FSECCOMP_H
2#define FSECCOMP_H
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6#include <assert.h>
7#include "../include/common.h"
8
9// syscall.c
10void syscall_print(void);
11
12// errno.c
13void errno_print(void);
14
15// protocol.c
16void protocol_print(void);
17void protocol_build_filter(const char *prlist, const char *fname);
18#endif
diff --git a/src/fseccomp/main.c b/src/fseccomp/main.c
new file mode 100644
index 000000000..59d426a78
--- /dev/null
+++ b/src/fseccomp/main.c
@@ -0,0 +1,42 @@
1#include "fseccomp.h"
2
3static void usage(void) {
4 printf("Usage:\n");
5 printf("\tfseccomp debug-syscalls\n");
6 printf("\tfseccomp debug-errnos\n");
7 printf("\tfseccomp debug-protocols\n");
8 printf("\tfseccomp protocol build list file\n");
9}
10
11int main(int argc, char **argv) {
12//#if 0
13{
14//system("cat /proc/self/status");
15int i;
16for (i = 0; i < argc; i++)
17 printf("*%s* ", argv[i]);
18printf("\n");
19}
20//#endif
21 if (argc < 2)
22 return 1;
23
24 if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") ==0) {
25 usage();
26 return 0;
27 }
28 else if (argc == 2 && strcmp(argv[1], "debug-syscalls") == 0)
29 syscall_print();
30 else if (argc == 2 && strcmp(argv[1], "debug-errnos") == 0)
31 errno_print();
32 else if (argc == 2 && strcmp(argv[1], "debug-protocols") == 0)
33 protocol_print();
34 else if (argc == 5 && strcmp(argv[1], "protocol") == 0 && strcmp(argv[2], "build") == 0)
35 protocol_build_filter(argv[3], argv[4]);
36 else {
37 fprintf(stderr, "Error fseccomp: invalid arguments\n");
38 return 1;
39 }
40
41 return 0;
42} \ No newline at end of file
diff --git a/src/fseccomp/protocol.c b/src/fseccomp/protocol.c
new file mode 100644
index 000000000..38c5f9d88
--- /dev/null
+++ b/src/fseccomp/protocol.c
@@ -0,0 +1,219 @@
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
21/*
22 struct sock_filter filter[] = {
23 VALIDATE_ARCHITECTURE,
24 EXAMINE_SYSCALL,
25 ONLY(SYS_socket),
26 EXAMINE_ARGUMENT(0), // allow only AF_INET and AF_INET6, drop everything else
27 WHITELIST(AF_INET),
28 WHITELIST(AF_INET6),
29 WHITELIST(AF_PACKET),
30 RETURN_ERRNO(ENOTSUP)
31 };
32 struct sock_fprog prog = {
33 .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),
34 .filter = filter,
35 };
36
37
38 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
39 perror("prctl(NO_NEW_PRIVS)");
40 return 1;
41 }
42 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
43 perror("prctl");
44 return 1;
45 }
46*/
47
48#include "fseccomp.h"
49#include "../include/seccomp.h"
50#include <sys/syscall.h>
51#include <sys/types.h>
52#include <sys/socket.h>
53
54static char *protocol[] = {
55 "unix",
56 "inet",
57 "inet6",
58 "netlink",
59 "packet",
60 NULL
61};
62
63static struct sock_filter protocol_filter_command[] = {
64 WHITELIST(AF_UNIX),
65 WHITELIST(AF_INET),
66 WHITELIST(AF_INET6),
67 WHITELIST(AF_NETLINK),
68 WHITELIST(AF_PACKET)
69};
70// Note: protocol[] and protocol_filter_command are synchronized
71
72// command length
73struct sock_filter whitelist[] = {
74 WHITELIST(AF_UNIX)
75};
76unsigned whitelist_len = sizeof(whitelist) / sizeof(struct sock_filter);
77
78static struct sock_filter *find_protocol_domain(const char *p) {
79 int i = 0;
80 while (protocol[i] != NULL) {
81 if (strcmp(protocol[i], p) == 0)
82 return &protocol_filter_command[i * whitelist_len];
83 i++;
84 }
85
86 return NULL;
87}
88
89
90void protocol_print(void) {
91#ifndef SYS_socket
92 fprintf(stderr, "Warning fseccomp: firejail --protocol not supported on this platform\n");
93 return;
94#endif
95
96 int i = 0;
97 while (protocol[i] != NULL) {
98 printf("%s, ", protocol[i]);
99 i++;
100 }
101 printf("\n");
102}
103
104// install protocol filter
105void protocol_build_filter(const char *prlist, const char *fname) {
106 assert(prlist);
107 assert(fname);
108
109#ifndef SYS_socket
110 fprintf(stderr, "Warning: --protocol not supported on this platform\n");
111 return;
112#else
113 // build the filter
114 struct sock_filter filter[32]; // big enough
115 memset(&filter[0], 0, sizeof(filter));
116 uint8_t *ptr = (uint8_t *) &filter[0];
117
118 // header
119 struct sock_filter filter_start[] = {
120 VALIDATE_ARCHITECTURE,
121 EXAMINE_SYSCALL,
122 ONLY(SYS_socket),
123 EXAMINE_ARGUMENT(0)
124 };
125 memcpy(ptr, &filter_start[0], sizeof(filter_start));
126 ptr += sizeof(filter_start);
127
128#if 0
129printf("entries %u\n", (unsigned) (sizeof(filter_start) / sizeof(struct sock_filter)));
130{
131 unsigned j;
132 unsigned char *ptr2 = (unsigned char *) &filter[0];
133 for (j = 0; j < sizeof(filter); j++, ptr2++) {
134 if ((j % (sizeof(struct sock_filter))) == 0)
135 printf("\n%u: ", 1 + (unsigned) (j / (sizeof(struct sock_filter))));
136 printf("%02x, ", (*ptr2) & 0xff);
137 }
138 printf("\n");
139}
140printf("whitelist_len %u, struct sock_filter len %u\n", whitelist_len, (unsigned) sizeof(struct sock_filter));
141#endif
142
143
144 // parse list and add commands
145 char *tmplist = strdup(prlist);
146 if (!tmplist)
147 errExit("strdup");
148 char *token = strtok(tmplist, ",");
149 if (!token)
150 errExit("strtok");
151
152 while (token) {
153 struct sock_filter *domain = find_protocol_domain(token);
154 if (domain == NULL) {
155 fprintf(stderr, "Error fseccomp: %s is not a valid protocol\n", token);
156 exit(1);
157 }
158 memcpy(ptr, domain, whitelist_len * sizeof(struct sock_filter));
159 ptr += whitelist_len * sizeof(struct sock_filter);
160 token = strtok(NULL, ",");
161
162#if 0
163printf("entries %u\n", (unsigned) ((uint64_t) ptr - (uint64_t) (filter)) / (unsigned) sizeof(struct sock_filter));
164{
165 unsigned j;
166 unsigned char *ptr2 = (unsigned char *) &filter[0];
167 for (j = 0; j < sizeof(filter); j++, ptr2++) {
168 if ((j % (sizeof(struct sock_filter))) == 0)
169 printf("\n%u: ", 1 + (unsigned) (j / (sizeof(struct sock_filter))));
170 printf("%02x, ", (*ptr2) & 0xff);
171 }
172 printf("\n");
173}
174#endif
175
176
177 }
178 free(tmplist);
179
180 // add end of filter
181 struct sock_filter filter_end[] = {
182 RETURN_ERRNO(ENOTSUP)
183 };
184 memcpy(ptr, &filter_end[0], sizeof(filter_end));
185 ptr += sizeof(filter_end);
186
187#if 0
188printf("entries %u\n", (unsigned) ((uint64_t) ptr - (uint64_t) (filter)) / (unsigned) sizeof(struct sock_filter));
189{
190 unsigned j;
191 unsigned char *ptr2 = (unsigned char *) &filter[0];
192 for (j = 0; j < sizeof(filter); j++, ptr2++) {
193 if ((j % (sizeof(struct sock_filter))) == 0)
194 printf("\n%u: ", 1 + (unsigned) (j / (sizeof(struct sock_filter))));
195 printf("%02x, ", (*ptr2) & 0xff);
196 }
197 printf("\n");
198}
199#endif
200 // save filter to file
201 int dst = open(fname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
202 if (dst < 0) {
203 fprintf(stderr, "Error fseccomp: cannot open %s file\n", fname);
204 exit(1);
205 }
206
207 int size = (int) ((uintptr_t) ptr - (uintptr_t) (filter));
208 int written = 0;
209 while (written < size) {
210 int rv = write(dst, (unsigned char *) filter + written, size - written);
211 if (rv == -1) {
212 fprintf(stderr, "Error fseccomp: cannot write %s file\n", fname);
213 exit(1);
214 }
215 written += rv;
216 }
217 close(dst);
218#endif // SYS_socket
219}
diff --git a/src/fseccomp/syscall.c b/src/fseccomp/syscall.c
new file mode 100644
index 000000000..c67d45598
--- /dev/null
+++ b/src/fseccomp/syscall.c
@@ -0,0 +1,26 @@
1#include "fseccomp.h"
2#include <sys/syscall.h>
3
4typedef struct {
5 char *name;
6 int nr;
7} SyscallEntry;
8
9static SyscallEntry syslist[] = {
10//
11// code generated using tools/extract-syscall
12//
13#include "../include/syscall.h"
14//
15// end of generated code
16//
17}; // end of syslist
18
19void syscall_print(void) {
20 int i;
21 int elems = sizeof(syslist) / sizeof(syslist[0]);
22 for (i = 0; i < elems; i++) {
23 printf("%d\t- %s\n", syslist[i].nr, syslist[i].name);
24 }
25 printf("\n");
26}
diff --git a/src/firejail/syscall.h b/src/include/syscall.h
index 68d4b5736..9a29779c9 100644
--- a/src/firejail/syscall.h
+++ b/src/include/syscall.h
@@ -20,7 +20,6 @@
20 20
21// content extracted from /bits/syscall.h file form glibc 2.22 21// content extracted from /bits/syscall.h file form glibc 2.22
22// using ../tools/extract_syscall tool 22// using ../tools/extract_syscall tool
23
24#if !defined __x86_64__ 23#if !defined __x86_64__
25#ifdef SYS__llseek 24#ifdef SYS__llseek
26#ifdef __NR__llseek 25#ifdef __NR__llseek