aboutsummaryrefslogtreecommitdiffstats
path: root/src/firejail/protocol.c
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@yahoo.com>2015-10-27 12:32:14 -0400
committerLibravatar netblue30 <netblue30@yahoo.com>2015-10-27 12:32:14 -0400
commit9e1e87cedf05eb54df17effdeb8b52b6a4dc2927 (patch)
tree0a42f5a604db856ff6d3fdbb7f2765588c6ed1b0 /src/firejail/protocol.c
parentseccomp refactoring (diff)
downloadfirejail-9e1e87cedf05eb54df17effdeb8b52b6a4dc2927.tar.gz
firejail-9e1e87cedf05eb54df17effdeb8b52b6a4dc2927.tar.zst
firejail-9e1e87cedf05eb54df17effdeb8b52b6a4dc2927.zip
seccomp work
Diffstat (limited to 'src/firejail/protocol.c')
-rw-r--r--src/firejail/protocol.c240
1 files changed, 240 insertions, 0 deletions
diff --git a/src/firejail/protocol.c b/src/firejail/protocol.c
new file mode 100644
index 000000000..098661339
--- /dev/null
+++ b/src/firejail/protocol.c
@@ -0,0 +1,240 @@
1/*
2 * Copyright (C) 2014, 2015 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#ifdef HAVE_SECCOMP
22#include "firejail.h"
23#include "seccomp.h"
24#include <sys/types.h>
25#include <sys/socket.h>
26
27static char *protocol[] = {
28 "unix",
29 "inet",
30 "inet6",
31 "netlink",
32 "packet",
33 NULL
34};
35
36static struct sock_filter protocol_filter_command[] = {
37 WHITELIST(AF_UNIX),
38 WHITELIST(AF_INET),
39 WHITELIST(AF_INET6),
40 WHITELIST(AF_NETLINK),
41 WHITELIST(AF_PACKET)
42};
43// Note: protocol[] and protocol_filter_command are synchronized
44
45// command length
46struct sock_filter whitelist[] = {
47 WHITELIST(AF_UNIX)
48};
49unsigned whitelist_len = sizeof(whitelist) / sizeof(struct sock_filter);
50
51
52
53static int is_protocol(const char *p) {
54 int i = 0;
55 while (protocol[i] != NULL) {
56 if (strcmp(protocol[i], p) == 0)
57 return 1;
58 i++;
59 }
60
61 return 0;
62}
63
64static struct sock_filter *find_protocol_domain(const char *p) {
65 int i = 0;
66 while (protocol[i] != NULL) {
67 if (strcmp(protocol[i], p) == 0)
68 return &protocol_filter_command[i * whitelist_len];
69 i++;
70 }
71
72 return NULL;
73}
74
75// --debug-protocols
76void protocol_list(void) {
77 int i = 0;
78 while (protocol[i] != NULL) {
79 printf("%s, ", protocol[i]);
80 i++;
81 }
82 printf("\n");
83}
84
85// --protocol.print
86void protocol_print_filter_name(const char *name) {
87 (void) name;
88//todo
89}
90
91// --protocol.print
92void protocol_print_filter(pid_t pid) {
93 (void) pid;
94//todo
95}
96
97// check protocol list and store it in cfg structure
98void protocol_store(const char *prlist) {
99 assert(prlist);
100
101 // temporary list
102 char *tmplist = strdup(prlist);
103 if (!tmplist)
104 errExit("strdup");
105
106 // check list
107 char *token = strtok(tmplist, ",");
108 if (!token)
109 goto errout;
110
111 while (token) {
112 if (!is_protocol(token))
113 goto errout;
114 token = strtok(NULL, ",");
115 }
116 free(tmplist);
117
118 // store list
119 cfg.protocol = strdup(prlist);
120 if (!cfg.protocol)
121 errExit("strdup");
122 return;
123
124errout:
125 fprintf(stderr, "Error: invalid protocol list\n");
126 exit(1);
127}
128
129// install protocol filter
130void protocol_filter(void) {
131 assert(cfg.protocol);
132
133 // build the filter
134
135 struct sock_filter filter[32]; // big enough
136 memset(&filter[0], 0, sizeof(filter));
137 uint8_t *ptr = (uint8_t *) &filter[0];
138
139 // header
140 struct sock_filter filter_start[] = {
141 VALIDATE_ARCHITECTURE,
142 EXAMINE_SYSCALL,
143 ONLY(SYS_socket),
144 EXAMINE_ARGUMENT(0)
145 };
146 memcpy(ptr, &filter_start[0], sizeof(filter_start));
147 ptr += sizeof(filter_start);
148
149#if 0
150printf("entries %u\n", (unsigned) (sizeof(filter_start) / sizeof(struct sock_filter)));
151{
152 unsigned j;
153 unsigned char *ptr2 = (unsigned char *) &filter[0];
154 for (j = 0; j < sizeof(filter); j++, ptr2++) {
155 if ((j % (sizeof(struct sock_filter))) == 0)
156 printf("\n%u: ", 1 + (unsigned) (j / (sizeof(struct sock_filter))));
157 printf("%02x, ", (*ptr2) & 0xff);
158 }
159 printf("\n");
160}
161#endif
162
163printf("whitelist_len %u, struct sock_filter len %u\n", whitelist_len, (unsigned) sizeof(struct sock_filter));
164
165 // parse list and add commands
166 char *tmplist = strdup(cfg.protocol);
167 if (!tmplist)
168 errExit("strdup");
169 char *token = strtok(tmplist, ",");
170 if (!token)
171 errExit("strtok");
172
173 while (token) {
174 struct sock_filter *domain = find_protocol_domain(token);
175 assert(domain);
176 memcpy(ptr, domain, whitelist_len * sizeof(struct sock_filter));
177 ptr += whitelist_len * sizeof(struct sock_filter);
178 token = strtok(NULL, ",");
179
180#if 0
181printf("entries %u\n", (unsigned) ((uint64_t) ptr - (uint64_t) (filter)) / (unsigned) sizeof(struct sock_filter));
182{
183 unsigned j;
184 unsigned char *ptr2 = (unsigned char *) &filter[0];
185 for (j = 0; j < sizeof(filter); j++, ptr2++) {
186 if ((j % (sizeof(struct sock_filter))) == 0)
187 printf("\n%u: ", 1 + (unsigned) (j / (sizeof(struct sock_filter))));
188 printf("%02x, ", (*ptr2) & 0xff);
189 }
190 printf("\n");
191}
192#endif
193
194
195 }
196 free(tmplist);
197
198 // add end of filter
199 struct sock_filter filter_end[] = {
200 RETURN_ERRNO(ENOTSUP)
201 };
202 memcpy(ptr, &filter_end[0], sizeof(filter_end));
203 ptr += sizeof(filter_end);
204
205#if 0
206printf("entries %u\n", (unsigned) ((uint64_t) ptr - (uint64_t) (filter)) / (unsigned) sizeof(struct sock_filter));
207{
208 unsigned j;
209 unsigned char *ptr2 = (unsigned char *) &filter[0];
210 for (j = 0; j < sizeof(filter); j++, ptr2++) {
211 if ((j % (sizeof(struct sock_filter))) == 0)
212 printf("\n%u: ", 1 + (unsigned) (j / (sizeof(struct sock_filter))));
213 printf("%02x, ", (*ptr2) & 0xff);
214 }
215 printf("\n");
216}
217#endif
218
219 // install filter
220 unsigned short entries = (unsigned short) ((uint64_t) ptr - (uint64_t) (filter)) / (unsigned) sizeof(struct sock_filter);
221 struct sock_fprog prog = {
222 .len = entries,
223 .filter = filter,
224 };
225
226 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) || prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
227 fprintf(stderr, "Warning: seccomp disabled, it requires a Linux kernel version 3.5 or newer.\n");
228 return;
229 }
230 else if (arg_debug) {
231 printf("seccomp protocol filter enabled\n");
232 }
233
234#if defined(__x86_64__)
235
236#endif
237
238}
239
240#endif