aboutsummaryrefslogtreecommitdiffstats
path: root/src/fseccomp/protocol.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fseccomp/protocol.c')
-rw-r--r--src/fseccomp/protocol.c219
1 files changed, 219 insertions, 0 deletions
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}