aboutsummaryrefslogtreecommitdiffstats
path: root/src/fseccomp
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@yahoo.com>2016-10-29 08:25:47 -0400
committerLibravatar netblue30 <netblue30@yahoo.com>2016-10-29 08:25:47 -0400
commita4da83cae8c7542d0fa1c2733bcf230754425bbb (patch)
tree978ccf26d9d30e2c3d95492e96f45834884f4e04 /src/fseccomp
parentcompile cleanup (diff)
downloadfirejail-a4da83cae8c7542d0fa1c2733bcf230754425bbb.tar.gz
firejail-a4da83cae8c7542d0fa1c2733bcf230754425bbb.tar.zst
firejail-a4da83cae8c7542d0fa1c2733bcf230754425bbb.zip
sbox/fseccomp
Diffstat (limited to 'src/fseccomp')
-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
6 files changed, 509 insertions, 0 deletions
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}