aboutsummaryrefslogtreecommitdiffstats
path: root/src/firejail
diff options
context:
space:
mode:
Diffstat (limited to 'src/firejail')
-rw-r--r--src/firejail/Makefile.in28
-rw-r--r--src/firejail/arg-checking.txt85
-rw-r--r--src/firejail/arp.c474
-rw-r--r--src/firejail/bandwidth.c483
-rw-r--r--src/firejail/caps.c453
-rw-r--r--src/firejail/cgroup.c118
-rw-r--r--src/firejail/cpu.c141
-rw-r--r--src/firejail/firejail.h354
-rw-r--r--src/firejail/fs.c825
-rw-r--r--src/firejail/fs_dev.c163
-rw-r--r--src/firejail/fs_home.c494
-rw-r--r--src/firejail/fs_hostname.c157
-rw-r--r--src/firejail/fs_trace.c76
-rw-r--r--src/firejail/fs_var.c388
-rw-r--r--src/firejail/join.c364
-rw-r--r--src/firejail/list.c65
-rw-r--r--src/firejail/main.c1168
-rw-r--r--src/firejail/netfilter.c164
-rw-r--r--src/firejail/network.c362
-rw-r--r--src/firejail/network.txt95
-rw-r--r--src/firejail/network_main.c268
-rw-r--r--src/firejail/output.c84
-rw-r--r--src/firejail/profile.c444
-rw-r--r--src/firejail/restricted_shell.c96
-rw-r--r--src/firejail/rlimit.c62
-rw-r--r--src/firejail/sandbox.c490
-rw-r--r--src/firejail/seccomp.c658
-rw-r--r--src/firejail/shutdown.c98
-rw-r--r--src/firejail/syscall.c4942
-rw-r--r--src/firejail/usage.c312
-rw-r--r--src/firejail/util.c480
-rw-r--r--src/firejail/veth.c191
32 files changed, 14582 insertions, 0 deletions
diff --git a/src/firejail/Makefile.in b/src/firejail/Makefile.in
new file mode 100644
index 000000000..1f7b563c4
--- /dev/null
+++ b/src/firejail/Makefile.in
@@ -0,0 +1,28 @@
1all: firejail
2
3PREFIX=@prefix@
4VERSION=@PACKAGE_VERSION@
5NAME=@PACKAGE_NAME@
6HAVE_SECCOMP_H=@HAVE_SECCOMP_H@
7HAVE_SECCOMP=@HAVE_SECCOMP@
8HAVE_CHROOT=@HAVE_CHROOT@
9HAVE_BIND=@HAVE_BIND@
10
11H_FILE_LIST = $(wildcard *.[h])
12C_FILE_LIST = $(wildcard *.c)
13OBJS = $(C_FILE_LIST:.c=.o)
14BINOBJS = $(foreach file, $(OBJS), $file)
15CFLAGS += -ggdb -O2 -DVERSION='"$(VERSION)"' -DPREFIX='"$(PREFIX)"' $(HAVE_SECCOMP) $(HAVE_SECCOMP_H) $(HAVE_CHROOT) $(HAVE_BIND) -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security
16LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread
17
18%.o : %.c $(H_FILE_LIST)
19 $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
20
21firejail: $(OBJS) ../lib/libnetlink.o ../lib/common.o
22 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/libnetlink.o ../lib/common.o $(LIBS)
23
24clean:; rm -f *.o firejail firejail.1 firejail.1.gz
25
26distclean: clean
27 rm -fr Makefile
28
diff --git a/src/firejail/arg-checking.txt b/src/firejail/arg-checking.txt
new file mode 100644
index 000000000..c1ab2cb21
--- /dev/null
+++ b/src/firejail/arg-checking.txt
@@ -0,0 +1,85 @@
1arg checking:
2
31. --output=filename
4 - not supported in profiles
5 - checking no "..",
6 - checking no link,
7 - checking no dir,
8 - checking same permissions,
9 - checking no hard links
10 - unit test
11
122. --chroot=dirname
13 - not supported in profiles
14 - expand "~"
15 - checking no "..",
16 - checking is dir,
17 - checking no link
18 - checking directory structure
19 - unit test
20
213. --bind=dirname1,dirname2, --bind=filename1,filenam2
22 - supported in profiles
23 - accepted only when running as root
24 - checking string chars
25 - checking no ".."
26 - unit test non root
27
284. --tmpfs=dirname
29 - supported in profiles
30 - checking string chars
31 - checking no ".."
32 - unit test
33
345. --blacklist=filename, --blacklist=dirname
35 - supported in profiles
36 - checking string chars
37 - checking no ".."
38 - unit test
39
406. --read-only=filename, --read-only=dirname
41 - supported in profiles
42 - checking string chars
43 - checking no ".."
44 - unit test
45
467. --profile=filename
47 - check access as real GID/UID
48 - checking no dir
49 - checking no link
50 - checking no ".."
51 - unit test
52
538. --private=dirname
54 - supported in profiles
55 - expand "~"
56 - check is dir
57 - check no link
58 - checking no ".."
59 - check same owner
60 - unit test
61
629. --private.keep=filelist
63 - supported in profiles
64 - checking no ".."
65 - checking file found
66 - checking same owner
67 - checking no link
68 - unit test
69
7010. --netfilter=filename
71 - supported in profiles
72 - check access as real GID/UID
73 - checking no dir
74 - checking no link
75 - checking no ".."
76 - unit test
77
7811. --shell=filename
79 - not supported in profiles
80 - check access as real GID/UID
81 - checking no dir
82 - checking no link
83 - checking no ".."
84 - unit test
85
diff --git a/src/firejail/arp.c b/src/firejail/arp.c
new file mode 100644
index 000000000..37f8716e7
--- /dev/null
+++ b/src/firejail/arp.c
@@ -0,0 +1,474 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
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#include "firejail.h"
21#include <sys/socket.h>
22#include <sys/ioctl.h>
23#include <linux/if_ether.h> //TCP/IP Protocol Suite for Linux
24#include <net/if.h>
25#include <netinet/in.h>
26#include <linux/ip.h>
27#include <linux/udp.h>
28#include <linux/tcp.h>
29#include <linux/if_packet.h>
30
31typedef struct arp_hdr_t {
32 uint16_t htype;
33 uint16_t ptype;
34 uint8_t hlen;
35 uint8_t plen;
36 uint16_t opcode;
37 uint8_t sender_mac[6];
38 uint8_t sender_ip[4];
39 uint8_t target_mac[6];
40 uint8_t target_ip[4];
41} ArpHdr;
42
43// returns 0 if the address is not in use, -1 otherwise
44int arp_check(const char *dev, uint32_t destaddr, uint32_t srcaddr) {
45 if (strlen(dev) > IFNAMSIZ) {
46 fprintf(stderr, "Error: invalid network device name %s\n", dev);
47 exit(1);
48 }
49
50 if (arg_debug)
51 printf("Trying %d.%d.%d.%d ...\n", PRINT_IP(destaddr));
52
53 // find interface address
54 int sock;
55 if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
56 errExit("socket");
57
58 srcaddr = htonl(srcaddr);
59 destaddr = htonl(destaddr);
60
61 // Find interface MAC address
62 struct ifreq ifr;
63 memset(&ifr, 0, sizeof (ifr));
64 strncpy(ifr.ifr_name, dev, IFNAMSIZ);
65 if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0)
66 errExit("ioctl");
67 close(sock);
68
69 // configure layer2 socket address information
70 struct sockaddr_ll addr;
71 memset(&addr, 0, sizeof(addr));
72 if ((addr.sll_ifindex = if_nametoindex(dev)) == 0)
73 errExit("if_nametoindex");
74 addr.sll_family = AF_PACKET;
75 memcpy (addr.sll_addr, ifr.ifr_hwaddr.sa_data, 6);
76 addr.sll_halen = htons(6);
77
78 // build the arp packet header
79 ArpHdr hdr;
80 memset(&hdr, 0, sizeof(hdr));
81 hdr.htype = htons(1);
82 hdr.ptype = htons(ETH_P_IP);
83 hdr.hlen = 6;
84 hdr.plen = 4;
85 hdr.opcode = htons(1); //ARPOP_REQUEST
86 memcpy(hdr.sender_mac, ifr.ifr_hwaddr.sa_data, 6);
87 memcpy(hdr.sender_ip, (uint8_t *)&srcaddr, 4);
88 memcpy(hdr.target_ip, (uint8_t *)&destaddr, 4);
89
90 // buiild ethernet frame
91 uint8_t frame[ETH_FRAME_LEN]; // includes eht header, vlan, and crc
92 memset(frame, 0, sizeof(frame));
93 frame[0] = frame[1] = frame[2] = frame[3] = frame[4] = frame[5] = 0xff;
94 memcpy(frame + 6, ifr.ifr_hwaddr.sa_data, 6);
95 frame[12] = ETH_P_ARP / 256;
96 frame[13] = ETH_P_ARP % 256;
97 memcpy (frame + 14, &hdr, sizeof(hdr));
98
99 // open layer2 socket
100 if ((sock = socket(PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0)
101 errExit("socket");
102
103 int len;
104 if ((len = sendto (sock, frame, 14 + sizeof(ArpHdr), 0, (struct sockaddr *) &addr, sizeof (addr))) <= 0)
105 errExit("send");
106 fflush(0);
107
108 // wait not more than one second for an answer
109 fd_set fds;
110 FD_ZERO(&fds);
111 FD_SET(sock, &fds);
112 int maxfd = sock;
113 struct timeval ts;
114 ts.tv_sec = 1; // 1 second wait time
115 ts.tv_usec = 0;
116 while (1) {
117 int nready = select(maxfd + 1, &fds, (fd_set *) 0, (fd_set *) 0, &ts);
118 if (nready < 0)
119 errExit("select");
120 else if (nready == 0) { // timeout
121 close(sock);
122 return 0;
123 }
124 else {
125 // read the incoming packet
126 int len = recvfrom(sock, frame, ETH_FRAME_LEN, 0, NULL, NULL);
127 if (len < 0) {
128 perror("recvfrom");
129 close(sock);
130 return -1;
131 }
132
133 // parse the incomming packet
134 if (len < 14 + sizeof(ArpHdr))
135 continue;
136 if (frame[12] != (ETH_P_ARP / 256) || frame[13] != (ETH_P_ARP % 256))
137 continue;
138 memcpy(&hdr, frame + 14, sizeof(ArpHdr));
139 if (hdr.opcode == htons(1))
140 continue;
141 if (hdr.opcode == htons(2)) {
142 // check my mac and my address
143 if (memcmp(ifr.ifr_hwaddr.sa_data, hdr.target_mac, 6) != 0)
144 continue;
145 uint32_t ip;
146 memcpy(&ip, hdr.target_ip, 4);
147 if (ip != srcaddr) {
148 continue;
149 }
150 close(sock);
151 return -1;
152 }
153 }
154 }
155
156 // it will never get here!
157 close(sock);
158 return -1;
159}
160
161// assign a random IP address and check it
162// the address needs to be in the range if it --iprange was specified
163static uint32_t arp_random(const char *dev, Bridge *br) {
164 assert(dev);
165 assert(br);
166 uint32_t ifip = br->ip;
167 uint32_t ifmask = br->mask;
168 assert(ifip);
169 assert(ifmask);
170
171 if (arg_debug)
172 printf("ARP-scan %s, %d.%d.%d.%d/%d\n",
173 dev, PRINT_IP(ifip), mask2bits(ifmask));
174
175 // determine the range based on network address
176 uint32_t range = ~ifmask + 1; // the number of potential addresses
177 // this software is not supported for /31 networks
178 if (range < 4)
179 return 0; // the user will have to set the IP address manually
180 range -= 2; // subtract the network address and the broadcast address
181 uint32_t start = (ifip & ifmask) + 1;
182
183 // adjust range based on --iprange params
184 if (br->iprange_start && br->iprange_end) {
185 start = br->iprange_start;
186 range = br->iprange_end - br->iprange_start;
187 }
188
189 if (arg_debug)
190 printf("IP address range from %d.%d.%d.%d to %d.%d.%d.%d\n",
191 PRINT_IP(start), PRINT_IP(start + range));
192
193 // generate a random address - 10 tries
194 uint32_t dest = 0;
195 int i = 0;
196 for (i = 0; i < 10; i++) {
197 dest = start + ((uint32_t) rand()) % range;
198 if (dest == ifip) // do not allow the interface address
199 continue; // try again
200
201 // if we've made it up to here, we have a valid address
202 break;
203 }
204 if (i == 10) // we failed 10 times
205 return 0;
206
207 // check address
208 uint32_t rv = arp_check(dev, dest, ifip);
209 if (!rv)
210 return dest;
211 return 0;
212}
213
214// go sequentially trough all IP addresses and assign the first one not in use
215static uint32_t arp_sequential(const char *dev, Bridge *br) {
216 assert(dev);
217 assert(br);
218 uint32_t ifip = br->ip;
219 uint32_t ifmask = br->mask;
220 assert(ifip);
221 assert(ifmask);
222
223 // range based on network address
224 uint32_t range = ~ifmask + 1; // the number of potential addresses
225 // this software is not supported for /31 networks
226 if (range < 4)
227 return 0; // the user will have to set the IP address manually
228 range -= 2; // subtract the network address and the broadcast address
229
230 // try all possible ip addresses in ascending order
231 // start address
232 uint32_t dest = (ifip & ifmask) + 1;
233 if (br->iprange_start)
234 dest = br->iprange_start;
235 // end address
236 uint32_t last = dest + range - 1;
237 if (br->iprange_end)
238 last = br->iprange_end;
239
240 if (arg_debug)
241 printf("Trying IP address range from %d.%d.%d.%d to %d.%d.%d.%d\n",
242 PRINT_IP(dest), PRINT_IP(last));
243
244 // loop through addresses and stop as soon as you find an unused one
245 while (dest <= last) {
246 if (dest == ifip) {
247 dest++;
248 continue;
249 }
250 uint32_t rv = arp_check(dev, dest, ifip);
251 if (!rv)
252 return dest;
253 dest++;
254 }
255
256 return 0;
257}
258
259// assign an IP address first trying some random addresses, and if this fails
260// by doing an arp scan.
261//
262// dev is the name of the device to use in scanning,
263// br is bridge structure holding the ip address and mask to use in
264// arp packets. It also holds values for for the range of addresses
265// if --iprange was set by the user
266uint32_t arp_assign(const char *dev, Bridge *br) {
267 assert(br);
268 uint32_t ip = 0;
269
270 // try two random IP addresses
271 ip = arp_random(dev, br);
272 if (!ip)
273 ip = arp_random(dev, br);
274
275 // try all possible IP addresses one by one
276 if (!ip)
277 ip = arp_sequential(dev, br);
278
279 // print result
280 if (!ip) {
281 fprintf(stderr, "Error: cannot assign an IP address; it looks like all of them are in use.\n");
282 logerr("Cannot assign an IP address; it looks like all of them are in use.");
283 exit(1);
284 }
285
286 return ip;
287}
288
289// scan interface (--scan option)
290void arp_scan(const char *dev, uint32_t ifip, uint32_t ifmask) {
291 assert(dev);
292 assert(ifip);
293
294// printf("Scanning interface %s (%d.%d.%d.%d/%d)\n",
295// dev, PRINT_IP(ifip & ifmask), mask2bits(ifmask));
296
297 if (strlen(dev) > IFNAMSIZ) {
298 fprintf(stderr, "Error: invalid network device name %s\n", dev);
299 exit(1);
300 }
301
302 // find interface mac address
303 int sock;
304 if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
305 errExit("socket");
306 struct ifreq ifr;
307 memset(&ifr, 0, sizeof (ifr));
308 strncpy(ifr.ifr_name, dev, IFNAMSIZ);
309 if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0)
310 errExit("ioctl");
311 close(sock);
312 uint8_t mac[6];
313 memcpy (mac, ifr.ifr_hwaddr.sa_data, 6);
314
315 // open layer2 socket
316 if ((sock = socket(PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0)
317 errExit("socket");
318
319 // try all possible ip addresses in ascending order
320 uint32_t range = ~ifmask + 1; // the number of potential addresses
321 // this software is not supported for /31 networks
322 if (range < 4) {
323 fprintf(stderr, "Warning: this option is not supported for /31 networks\n");
324 close(sock);
325 return;
326 }
327
328 uint32_t dest = (ifip & ifmask) + 1;
329 uint32_t last = dest + range - 1;
330 uint32_t src = htonl(ifip);
331
332 // wait not more than one second for an answer
333 int header_printed = 0;
334 int last_ip = 0;
335 struct timeval ts;
336 ts.tv_sec = 2; // 2 seconds receive timeout
337 ts.tv_usec = 0;
338
339 while (1) {
340 fd_set rfds;
341 FD_ZERO(&rfds);
342 FD_SET(sock, &rfds);
343 fd_set wfds;
344 FD_ZERO(&wfds);
345 FD_SET(sock, &wfds);
346 int maxfd = sock;
347
348 uint8_t frame[ETH_FRAME_LEN]; // includes eht header, vlan, and crc
349 memset(frame, 0, ETH_FRAME_LEN);
350
351 int nready;
352 if (dest < last)
353 nready = select(maxfd + 1, &rfds, &wfds, (fd_set *) 0, NULL);
354 else
355 nready = select(maxfd + 1, &rfds, (fd_set *) 0, (fd_set *) 0, &ts);
356
357 if (nready < 0)
358 errExit("select");
359
360 if (nready == 0) { // timeout
361 break;
362 }
363
364 if (FD_ISSET(sock, &wfds) && dest < last) {
365 // configure layer2 socket address information
366 struct sockaddr_ll addr;
367 memset(&addr, 0, sizeof(addr));
368 if ((addr.sll_ifindex = if_nametoindex(dev)) == 0)
369 errExit("if_nametoindex");
370 addr.sll_family = AF_PACKET;
371 memcpy (addr.sll_addr, mac, 6);
372 addr.sll_halen = htons(6);
373
374 // build the arp packet header
375 ArpHdr hdr;
376 memset(&hdr, 0, sizeof(hdr));
377 hdr.htype = htons(1);
378 hdr.ptype = htons(ETH_P_IP);
379 hdr.hlen = 6;
380 hdr.plen = 4;
381 hdr.opcode = htons(1); //ARPOP_REQUEST
382 memcpy(hdr.sender_mac, mac, 6);
383 memcpy(hdr.sender_ip, (uint8_t *)&src, 4);
384 uint32_t dst = htonl(dest);
385 memcpy(hdr.target_ip, (uint8_t *)&dst, 4);
386
387 // buiild ethernet frame
388 uint8_t frame[ETH_FRAME_LEN]; // includes eht header, vlan, and crc
389 memset(frame, 0, sizeof(frame));
390 frame[0] = frame[1] = frame[2] = frame[3] = frame[4] = frame[5] = 0xff;
391 memcpy(frame + 6, mac, 6);
392 frame[12] = ETH_P_ARP / 256;
393 frame[13] = ETH_P_ARP % 256;
394 memcpy (frame + 14, &hdr, sizeof(hdr));
395
396 // send packet
397 int len;
398 if ((len = sendto (sock, frame, 14 + sizeof(ArpHdr), 0, (struct sockaddr *) &addr, sizeof (addr))) <= 0)
399 errExit("send");
400//printf("send %d bytes to %d.%d.%d.%d\n", len, PRINT_IP(dest));
401 fflush(0);
402 dest++;
403 }
404
405 if (FD_ISSET(sock, &rfds)) {
406 // read the incoming packet
407 int len = recvfrom(sock, frame, ETH_FRAME_LEN, 0, NULL, NULL);
408 if (len < 0) {
409 perror("recvfrom");
410 }
411
412 // parse the incomming packet
413 if (len < 14 + sizeof(ArpHdr))
414 continue;
415
416 // look only at ARP packets
417 if (frame[12] != (ETH_P_ARP / 256) || frame[13] != (ETH_P_ARP % 256))
418 continue;
419
420 ArpHdr hdr;
421 memcpy(&hdr, frame + 14, sizeof(ArpHdr));
422
423 if (hdr.opcode == htons(2)) {
424 // check my mac and my address
425 if (memcmp(mac, hdr.target_mac, 6) != 0)
426 continue;
427 uint32_t ip;
428 memcpy(&ip, hdr.target_ip, 4);
429 if (ip != src)
430 continue;
431 memcpy(&ip, hdr.sender_ip, 4);
432 ip = ntohl(ip);
433
434 if (ip == last_ip) // filter duplicates
435 continue;
436 last_ip = ip;
437
438 // printing
439 if (header_printed == 0) {
440 printf(" Network scan:\n");
441
442 // print parent interface
443 if (cfg.bridge0.configured && cfg.bridge0.ip && cfg.bridge0.macvlan &&
444 (cfg.bridge0.ip & cfg.bridge0.mask) == (ifip & cfg.bridge0.mask))
445 printf(" %02x:%02x:%02x:%02x:%02x:%02x\t%d.%d.%d.%d\n",
446 PRINT_MAC(cfg.bridge0.mac), PRINT_IP(cfg.bridge0.ip));
447
448 if (cfg.bridge1.configured && cfg.bridge1.ip && cfg.bridge1.macvlan &&
449 (cfg.bridge1.ip & cfg.bridge1.mask) == (ifip & cfg.bridge1.mask))
450 printf(" %02x:%02x:%02x:%02x:%02x:%02x\t%d.%d.%d.%d\n",
451 PRINT_MAC(cfg.bridge1.mac), PRINT_IP(cfg.bridge1.ip));
452
453 if (cfg.bridge2.configured && cfg.bridge2.ip && cfg.bridge2.macvlan &&
454 (cfg.bridge2.ip & cfg.bridge2.mask) == (ifip & cfg.bridge2.mask))
455 printf(" %02x:%02x:%02x:%02x:%02x:%02x\t%d.%d.%d.%d\n",
456 PRINT_MAC(cfg.bridge2.mac), PRINT_IP(cfg.bridge2.ip));
457
458 if (cfg.bridge3.configured && cfg.bridge3.ip && cfg.bridge3.macvlan &&
459 (cfg.bridge3.ip & cfg.bridge3.mask) == (ifip & cfg.bridge3.mask))
460 printf(" %02x:%02x:%02x:%02x:%02x:%02x\t%d.%d.%d.%d\n",
461 PRINT_MAC(cfg.bridge3.mac), PRINT_IP(cfg.bridge3.ip));
462
463 header_printed = 1;
464 }
465 printf(" %02x:%02x:%02x:%02x:%02x:%02x\t%d.%d.%d.%d\n",
466 PRINT_MAC(hdr.sender_mac), PRINT_IP(ip));
467 }
468 }
469 }
470
471 close(sock);
472}
473
474
diff --git a/src/firejail/bandwidth.c b/src/firejail/bandwidth.c
new file mode 100644
index 000000000..25dd7a0fb
--- /dev/null
+++ b/src/firejail/bandwidth.c
@@ -0,0 +1,483 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
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#define _GNU_SOURCE
21#include <stdio.h>
22#include <sys/types.h>
23#include <sys/stat.h>
24#include <unistd.h>
25#include <net/if.h>
26#include "firejail.h"
27
28//***********************************
29// interface bandwidth linked list
30//***********************************
31typedef struct ifbw_t {
32 struct ifbw_t *next;
33 char *txt;
34} IFBW;
35IFBW *ifbw = NULL;
36
37
38#if 0
39static void ifbw_print(void) {
40 IFBW *ptr = ifbw;
41 while (ptr) {
42 printf("#%s#\n", ptr->txt);
43 ptr = ptr->next;
44 }
45}
46#endif
47
48static void ifbw_add(IFBW *ptr) {
49 assert(ptr);
50
51 if (ifbw != NULL)
52 ptr->next = ifbw;
53 ifbw = ptr;
54}
55
56
57IFBW *ifbw_find(const char *dev) {
58 assert(dev);
59 int len = strlen(dev);
60 assert(len);
61
62 if (ifbw == NULL)
63 return NULL;
64
65 IFBW *ptr = ifbw;
66 while (ptr) {
67 if (strncmp(ptr->txt, dev, len) == 0 && ptr->txt[len] == ':')
68 return ptr;
69 ptr = ptr->next;
70 }
71
72 return NULL;
73}
74
75void ifbw_remove(IFBW *r) {
76 if (ifbw == NULL)
77 return;
78
79 // remove the first element
80 if (ifbw == r) {
81 ifbw = ifbw->next;
82 return;
83 }
84
85 // walk the list
86 IFBW *ptr = ifbw->next;
87 IFBW *prev = ifbw;
88 while (ptr) {
89 if (ptr == r) {
90 prev->next = ptr->next;
91 return;
92 }
93
94 prev = ptr;
95 ptr = ptr->next;
96 }
97
98 return;
99}
100
101int fibw_count(viod) {
102 int rv = 0;
103 IFBW *ptr = ifbw;
104
105 while (ptr) {
106 rv++;
107 ptr = ptr->next;
108 }
109
110 return rv;
111}
112
113
114//***********************************
115// shm file handling
116//***********************************
117void shm_create_firejail_dir(void) {
118 struct stat s;
119 if (stat("/dev/shm/firejail", &s) == -1) {
120 /* coverity[toctou] */
121 if (mkdir("/dev/shm/firejail", 0777) == -1)
122 errExit("mkdir");
123 if (chown("/dev/shm/firejail", 0, 0) == -1)
124 errExit("chown");
125 }
126 else { // check /dev/shm/firejail directory belongs to root end exit if doesn't!
127 if (s.st_uid != 0 || s.st_gid != 0) {
128 fprintf(stderr, "Error: non-root %s directory, exiting...\n", "/dev/shm/firejail");
129 exit(1);
130 }
131 }
132}
133
134static void shm_create_bandwidth_file(pid_t pid) {
135 char *fname;
136 if (asprintf(&fname, "/dev/shm/firejail/%d-bandwidth", (int) pid) == -1)
137 errExit("asprintf");
138
139 // if the file already exists, do nothing
140 struct stat s;
141 if (stat(fname, &s) == 0) {
142 free(fname);
143 return;
144 }
145
146 // create an empty file and set mod and ownership
147 /* coverity[toctou] */
148 FILE *fp = fopen(fname, "w");
149 if (fp) {
150 fclose(fp);
151
152 /* coverity[toctou] */
153 if (chmod(fname, 0644) == -1)
154 errExit("chmod");
155 /* coverity[toctou] */
156 if (chown(fname, 0, 0) == -1)
157 errExit("chown");
158 }
159 else {
160 fprintf(stderr, "Error: cannot create bandwidth file in /dev/shm/firejail directory\n");
161 exit(1);
162 }
163
164 free(fname);
165}
166
167// delete shm bandwidth file
168void bandwidth_shm_del_file(pid_t pid) {
169 char *fname;
170 if (asprintf(&fname, "/dev/shm/firejail/%d-bandwidth", (int) pid) == -1)
171 errExit("asprintf");
172 unlink(fname);
173 free(fname);
174}
175
176void network_shm_del_file(pid_t pid) {
177 char *fname;
178 if (asprintf(&fname, "/dev/shm/firejail/%d-netmap", (int) pid) == -1)
179 errExit("asprintf");
180 unlink(fname);
181 free(fname);
182}
183
184void network_shm_set_file(pid_t pid) {
185 char *fname;
186 if (asprintf(&fname, "/dev/shm/firejail/%d-netmap", (int) pid) == -1)
187 errExit("asprintf");
188
189 // create an empty file and set mod and ownership
190 FILE *fp = fopen(fname, "w");
191 if (fp) {
192 if (cfg.bridge0.configured)
193 fprintf(fp, "%s:%s\n", cfg.bridge0.dev, cfg.bridge0.devsandbox);
194 if (cfg.bridge1.configured)
195 fprintf(fp, "%s:%s\n", cfg.bridge1.dev, cfg.bridge1.devsandbox);
196 if (cfg.bridge2.configured)
197 fprintf(fp, "%s:%s\n", cfg.bridge2.dev, cfg.bridge2.devsandbox);
198 if (cfg.bridge3.configured)
199 fprintf(fp, "%s:%s\n", cfg.bridge3.dev, cfg.bridge3.devsandbox);
200 fclose(fp);
201
202 if (chmod(fname, 0644) == -1)
203 errExit("chmod");
204 if (chown(fname, 0, 0) == -1)
205 errExit("chown");
206 }
207 else {
208 fprintf(stderr, "Error: cannot create network map file in /dev/shm/firejail directory\n");
209 exit(1);
210 }
211
212 free(fname);
213}
214
215
216void shm_read_bandwidth_file(pid_t pid) {
217 assert(ifbw == NULL);
218
219 char *fname;
220 if (asprintf(&fname, "/dev/shm/firejail/%d-bandwidth", (int) pid) == -1)
221 errExit("asprintf");
222
223 FILE *fp = fopen(fname, "r");
224 if (fp) {
225 char buf[1024];
226 while (fgets(buf, 1024,fp)) {
227 // remove '\n'
228 char *ptr = strchr(buf, '\n');
229 if (ptr)
230 *ptr = '\0';
231 if (strlen(buf) == 0)
232 continue;
233
234 // create a new IFBW entry
235 IFBW *ifbw_new = malloc(sizeof(IFBW));
236 if (!ifbw_new)
237 errExit("malloc");
238 memset(ifbw_new, 0, sizeof(IFBW));
239 ifbw_new->txt = strdup(buf);
240 if (!ifbw_new->txt)
241 errExit("strdup");
242
243 // add it to the linked list
244 ifbw_add(ifbw_new);
245 }
246
247 fclose(fp);
248 }
249}
250
251void shm_write_bandwidth_file(pid_t pid) {
252 if (ifbw == NULL)
253 return; // nothing to do
254
255 char *fname;
256 if (asprintf(&fname, "/dev/shm/firejail/%d-bandwidth", (int) pid) == -1)
257 errExit("asprintf");
258
259 FILE *fp = fopen(fname, "w");
260 if (fp) {
261 IFBW *ptr = ifbw;
262 while (ptr) {
263 fprintf(fp, "%s\n", ptr->txt);
264 ptr = ptr->next;
265 }
266 fclose(fp);
267 }
268 else {
269 fprintf(stderr, "Error: cannot write bandwidht file %s\n", fname);
270 exit(1);
271 }
272}
273
274//***********************************
275// add or remove interfaces
276//***********************************
277
278// remove interface from shm file
279void bandwidth_shm_remove(pid_t pid, const char *dev) {
280 // create bandwidth directory & file in case they are not in the filesystem yet
281 shm_create_firejail_dir();
282 shm_create_bandwidth_file(pid);
283
284 // read bandwidth file
285 shm_read_bandwidth_file(pid);
286
287 // find the element and remove it
288 IFBW *elem = ifbw_find(dev);
289 if (elem) {
290 ifbw_remove(elem);
291 shm_write_bandwidth_file(pid) ;
292 }
293
294 // remove the file if there are no entries in the list
295 if (ifbw == NULL) {
296 bandwidth_shm_del_file(pid);
297 }
298}
299
300// add interface to shm file
301void bandwidth_shm_set(pid_t pid, const char *dev, int down, int up) {
302 // create bandwidth directory & file in case they are not in the filesystem yet
303 shm_create_firejail_dir();
304 shm_create_bandwidth_file(pid);
305
306 // create the new text entry
307 char *txt;
308 if (asprintf(&txt, "%s: RX %dKB/s, TX %dKB/s", dev, down, up) == -1)
309 errExit("asprintf");
310
311 // read bandwidth file
312 shm_read_bandwidth_file(pid);
313
314 // look for an existing entry and replace the text
315 IFBW *ptr = ifbw_find(dev);
316 if (ptr) {
317 assert(ptr->txt);
318 free(ptr->txt);
319 ptr->txt = txt;
320 }
321 // ... or add a new entry
322 else {
323 IFBW *ifbw_new = malloc(sizeof(IFBW));
324 if (!ifbw_new)
325 errExit("malloc");
326 memset(ifbw_new, 0, sizeof(IFBW));
327 ifbw_new->txt = txt;
328
329 // add it to the linked list
330 ifbw_add(ifbw_new);
331 }
332 shm_write_bandwidth_file(pid) ;
333}
334
335
336//***********************************
337// command execution
338//***********************************
339void bandwidth_name(const char *name, const char *command, const char *dev, int down, int up) {
340 if (!name || strlen(name) == 0) {
341 fprintf(stderr, "Error: invalid sandbox name\n");
342 exit(1);
343 }
344 pid_t pid;
345 if (name2pid(name, &pid)) {
346 fprintf(stderr, "Error: cannot find sandbox %s\n", name);
347 exit(1);
348 }
349
350 bandwidth_pid(pid, command, dev, down, up);
351}
352
353void bandwidth_pid(pid_t pid, const char *command, const char *dev, int down, int up) {
354 //************************
355 // verify sandbox
356 //************************
357 char *comm = pid_proc_comm(pid);
358 if (!comm) {
359 fprintf(stderr, "Error: cannot find sandbox\n");
360 exit(1);
361 }
362
363 // remove \n and check for firejail sandbox
364 char *ptr = strchr(comm, '\n');
365 if (ptr)
366 *ptr = '\0';
367 if (strcmp(comm, "firejail") != 0) {
368 fprintf(stderr, "Error: cannot find sandbox\n");
369 exit(1);
370 }
371 free(comm);
372
373 // check network namespace
374 char *cmd = pid_proc_cmdline(pid);
375 if (!cmd || strstr(cmd, "--net") == NULL) {
376 fprintf(stderr, "Error: the sandbox doesn't use a new network namespace\n");
377 exit(1);
378 }
379 free(cmd);
380
381
382 //************************
383 // join the network namespace
384 //************************
385 pid_t child;
386 if (find_child(pid, &child) == -1) {
387 fprintf(stderr, "Error: cannot join the network namespace\n");
388 exit(1);
389 }
390 if (join_namespace(child, "net")) {
391 fprintf(stderr, "Error: cannot join the network namespace\n");
392 exit(1);
393 }
394
395 // set shm file
396 if (strcmp(command, "set") == 0)
397 bandwidth_shm_set(pid, dev, down, up);
398 else if (strcmp(command, "clear") == 0)
399 bandwidth_shm_remove(pid, dev);
400
401 //************************
402 // build command
403 //************************
404 char *devname = NULL;
405 if (dev) {
406 // read shm network map file
407 char *fname;
408 if (asprintf(&fname, "/dev/shm/firejail/%d-netmap", (int) pid) == -1)
409 errExit("asprintf");
410 FILE *fp = fopen(fname, "r");
411 if (!fp) {
412 fprintf(stderr, "Error: cannot read netowk map filel %s\n", fname);
413 exit(1);
414 }
415
416 char buf[1024];
417 int len = strlen(dev);
418 while (fgets(buf, 1024, fp)) {
419 // remove '\n'
420 char *ptr = strchr(buf, '\n');
421 if (ptr)
422 *ptr = '\0';
423 if (*buf == '\0')
424 break;
425
426 if (strncmp(buf, dev, len) == 0 && buf[len] == ':') {
427 devname = strdup(buf + len + 1);
428 if (!devname)
429 errExit("strdup");
430 // check device in namespace
431 if (if_nametoindex(devname) == 0) {
432 fprintf(stderr, "Error: cannot find network device %s\n", devname);
433 exit(1);
434 }
435 break;
436 }
437 }
438 free(fname);
439 fclose(fp);
440 }
441
442 // build fshaper.sh command
443 cmd = NULL;
444 if (devname) {
445 if (strcmp(command, "set") == 0) {
446 if (asprintf(&cmd, "%s/lib/firejail/fshaper.sh --%s %s %d %d",
447 PREFIX, command, devname, down, up) == -1)
448 errExit("asprintf");
449 }
450 else {
451 if (asprintf(&cmd, "%s/lib/firejail/fshaper.sh --%s %s",
452 PREFIX, command, devname) == -1)
453 errExit("asprintf");
454 }
455 }
456 else {
457 if (asprintf(&cmd, "%s/lib/firejail/fshaper.sh --%s", PREFIX, command) == -1)
458 errExit("asprintf");
459 }
460 assert(cmd);
461
462 // wipe out environment variables
463 environ = NULL;
464
465 //************************
466 // build command
467 //************************
468 // elevate privileges
469 if (setreuid(0, 0))
470 errExit("setreuid");
471 if (setregid(0, 0))
472 errExit("setregid");
473
474 char *arg[4];
475 arg[0] = "/bin/bash";
476 arg[1] = "-c";
477 arg[2] = cmd;
478 arg[3] = NULL;
479 execvp("/bin/bash", arg);
480
481 // it will never get here
482 exit(0);
483}
diff --git a/src/firejail/caps.c b/src/firejail/caps.c
new file mode 100644
index 000000000..d8777c0db
--- /dev/null
+++ b/src/firejail/caps.c
@@ -0,0 +1,453 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
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#include "firejail.h"
22#include <errno.h>
23#include <linux/filter.h>
24#include <stddef.h>
25#include <linux/capability.h>
26#include <linux/audit.h>
27#include <sys/prctl.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <unistd.h>
31
32extern int capget(cap_user_header_t hdrp, cap_user_data_t datap);
33extern int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
34
35
36typedef struct {
37 char *name;
38 int nr;
39} CapsEntry;
40
41static CapsEntry capslist[] = {
42//
43// code generated using tools/extract-caps
44// updated manually based on kernel 3.18/include/linux/capability.h (added block suspend and audit_read
45//
46#ifdef CAP_CHOWN
47 {"chown", CAP_CHOWN },
48#endif
49#ifdef CAP_DAC_OVERRIDE
50 {"dac_override", CAP_DAC_OVERRIDE },
51#endif
52#ifdef CAP_DAC_READ_SEARCH
53 {"dac_read_search", CAP_DAC_READ_SEARCH },
54#endif
55#ifdef CAP_FOWNER
56 {"fowner", CAP_FOWNER },
57#endif
58#ifdef CAP_FSETID
59 {"fsetid", CAP_FSETID },
60#endif
61#ifdef CAP_KILL
62 {"kill", CAP_KILL },
63#endif
64#ifdef CAP_SETGID
65 {"setgid", CAP_SETGID },
66#endif
67#ifdef CAP_SETUID
68 {"setuid", CAP_SETUID },
69#endif
70#ifdef CAP_SETPCAP
71 {"setpcap", CAP_SETPCAP },
72#endif
73#ifdef CAP_LINUX_IMMUTABLE
74 {"linux_immutable", CAP_LINUX_IMMUTABLE },
75#endif
76#ifdef CAP_NET_BIND_SERVICE
77 {"net_bind_service", CAP_NET_BIND_SERVICE },
78#endif
79#ifdef CAP_NET_BROADCAST
80 {"net_broadcast", CAP_NET_BROADCAST },
81#endif
82#ifdef CAP_NET_ADMIN
83 {"net_admin", CAP_NET_ADMIN },
84#endif
85#ifdef CAP_NET_RAW
86 {"net_raw", CAP_NET_RAW },
87#endif
88#ifdef CAP_IPC_LOCK
89 {"ipc_lock", CAP_IPC_LOCK },
90#endif
91#ifdef CAP_IPC_OWNER
92 {"ipc_owner", CAP_IPC_OWNER },
93#endif
94#ifdef CAP_SYS_MODULE
95 {"sys_module", CAP_SYS_MODULE },
96#endif
97#ifdef CAP_SYS_RAWIO
98 {"sys_rawio", CAP_SYS_RAWIO },
99#endif
100#ifdef CAP_SYS_CHROOT
101 {"sys_chroot", CAP_SYS_CHROOT },
102#endif
103#ifdef CAP_SYS_PTRACE
104 {"sys_ptrace", CAP_SYS_PTRACE },
105#endif
106#ifdef CAP_SYS_PACCT
107 {"sys_pacct", CAP_SYS_PACCT },
108#endif
109#ifdef CAP_SYS_ADMIN
110 {"sys_admin", CAP_SYS_ADMIN },
111#endif
112#ifdef CAP_SYS_BOOT
113 {"sys_boot", CAP_SYS_BOOT },
114#endif
115#ifdef CAP_SYS_NICE
116 {"sys_nice", CAP_SYS_NICE },
117#endif
118#ifdef CAP_SYS_RESOURCE
119 {"sys_resource", CAP_SYS_RESOURCE },
120#endif
121#ifdef CAP_SYS_TIME
122 {"sys_time", CAP_SYS_TIME },
123#endif
124#ifdef CAP_SYS_TTY_CONFIG
125 {"sys_tty_config", CAP_SYS_TTY_CONFIG },
126#endif
127#ifdef CAP_MKNOD
128 {"mknod", CAP_MKNOD },
129#endif
130#ifdef CAP_LEASE
131 {"lease", CAP_LEASE },
132#endif
133#ifdef CAP_AUDIT_WRITE
134 {"audit_write", CAP_AUDIT_WRITE },
135#endif
136#ifdef CAP_AUDIT_CONTROL
137 {"audit_control", CAP_AUDIT_CONTROL },
138#endif
139#ifdef CAP_SETFCAP
140 {"setfcap", CAP_SETFCAP },
141#endif
142#ifdef CAP_MAC_OVERRIDE
143 {"mac_override", CAP_MAC_OVERRIDE },
144#endif
145#ifdef CAP_MAC_ADMIN
146 {"mac_admin", CAP_MAC_ADMIN },
147#endif
148#ifdef CAP_SYSLOG
149 {"syslog", CAP_SYSLOG },
150#endif
151#ifdef CAP_WAKE_ALARM
152 {"wake_alarm", CAP_WAKE_ALARM },
153#endif
154// not in Debian 7
155#ifdef CAP_BLOCK_SUSPEND
156 {"block_suspend", CAP_BLOCK_SUSPEND },
157#else
158 {"block_suspend", 36 },
159#endif
160#ifdef CAP_AUDIT_READ
161 {"audit_read", CAP_AUDIT_READ },
162#else
163 {"audit_read", 37 },
164#endif
165
166//
167// end of generated code
168//
169}; // end of capslist
170
171const char *caps_find_nr(int nr) {
172 int i;
173 int elems = sizeof(capslist) / sizeof(capslist[0]);
174 for (i = 0; i < elems; i++) {
175 if (nr == capslist[i].nr)
176 return capslist[i].name;
177 }
178
179 return "unknown";
180}
181
182// return -1 if error, or syscall number
183static int caps_find_name(const char *name) {
184 int i;
185 int elems = sizeof(capslist) / sizeof(capslist[0]);
186 for (i = 0; i < elems; i++) {
187 if (strcmp(name, capslist[i].name) == 0)
188 return capslist[i].nr;
189 }
190
191 return -1;
192}
193
194// return 1 if error, 0 if OK
195int caps_check_list(const char *clist, void (*callback)(int)) {
196 // don't allow empty lists
197 if (clist == NULL || *clist == '\0') {
198 fprintf(stderr, "Error: empty capabilities lists are not allowed\n");
199 return -1;
200 }
201
202 // work on a copy of the string
203 char *str = strdup(clist);
204 if (!str)
205 errExit("strdup");
206
207 char *ptr = str;
208 char *start = str;
209 while (*ptr != '\0') {
210 if (islower(*ptr) || isdigit(*ptr) || *ptr == '_')
211 ;
212 else if (*ptr == ',') {
213 *ptr = '\0';
214 int nr = caps_find_name(start);
215 if (nr == -1) {
216 fprintf(stderr, "Error: capability %s not found\n", start);
217 free(str);
218 return -1;
219 }
220 else if (callback != NULL)
221 callback(nr);
222
223 start = ptr + 1;
224 }
225 ptr++;
226 }
227 if (*start != '\0') {
228 int nr = caps_find_name(start);
229 if (nr == -1) {
230 fprintf(stderr, "Error: capability %s not found\n", start);
231 free(str);
232 return -1;
233 }
234 else if (callback != NULL)
235 callback(nr);
236 }
237
238 free(str);
239 return 0;
240}
241
242void caps_print(void) {
243 int i;
244 int elems = sizeof(capslist) / sizeof(capslist[0]);
245
246 // check current caps supported by the kernel
247 int cnt = 0;
248 unsigned long cap;
249 for (cap=0; cap <= 63; cap++) {
250 int code = prctl(PR_CAPBSET_DROP, cap, 0, 0, 0);
251 if (code == 0)
252 cnt++;
253 }
254 printf("Your kernel supports %d capabilities.\n", cnt);
255
256 for (i = 0; i < elems; i++) {
257 printf("%d\t- %s\n", capslist[i].nr, capslist[i].name);
258 }
259}
260
261
262
263
264// enabled by default
265int caps_default_filter(void) {
266 // drop capabilities
267 if (prctl(PR_CAPBSET_DROP, CAP_SYS_MODULE, 0, 0, 0) && arg_debug)
268 fprintf(stderr, "Warning: cannot drop CAP_SYS_MODULE");
269 else if (arg_debug)
270 printf("Drop CAP_SYS_MODULE\n");
271
272 if (prctl(PR_CAPBSET_DROP, CAP_SYS_RAWIO, 0, 0, 0) && arg_debug)
273 fprintf(stderr, "Warning: cannot drop CAP_SYS_RAWIO");
274 else if (arg_debug)
275 printf("Drop CAP_SYS_RAWIO\n");
276
277 if (prctl(PR_CAPBSET_DROP, CAP_SYS_BOOT, 0, 0, 0) && arg_debug)
278 fprintf(stderr, "Warning: cannot drop CAP_SYS_BOOT");
279 else if (arg_debug)
280 printf("Drop CAP_SYS_BOOT\n");
281
282 if (prctl(PR_CAPBSET_DROP, CAP_SYS_NICE, 0, 0, 0) && arg_debug)
283 fprintf(stderr, "Warning: cannot drop CAP_SYS_NICE");
284 else if (arg_debug)
285 printf("Drop CAP_SYS_NICE\n");
286
287 if (prctl(PR_CAPBSET_DROP, CAP_SYS_TTY_CONFIG, 0, 0, 0) && arg_debug)
288 fprintf(stderr, "Warning: cannot drop CAP_SYS_TTY_CONFIG");
289 else if (arg_debug)
290 printf("Drop CAP_SYS_TTY_CONFIG\n");
291
292 if (prctl(PR_CAPBSET_DROP, CAP_SYSLOG, 0, 0, 0) && arg_debug)
293 fprintf(stderr, "Warning: cannot drop CAP_SYSLOG");
294 else if (arg_debug)
295 printf("Drop CAP_SYSLOG\n");
296
297 if (prctl(PR_CAPBSET_DROP, CAP_MKNOD, 0, 0, 0) && arg_debug)
298 fprintf(stderr, "Warning: cannot drop CAP_MKNOD");
299 else if (arg_debug)
300 printf("Drop CAP_MKNOD\n");
301
302 if (prctl(PR_CAPBSET_DROP, CAP_SYS_ADMIN, 0, 0, 0) && arg_debug)
303 fprintf(stderr, "Warning: cannot drop CAP_SYS_ADMIN");
304 else if (arg_debug)
305 printf("Drop CAP_SYS_ADMIN\n");
306
307 return 0;
308}
309
310void caps_drop_all(void) {
311 if (arg_debug)
312 printf("Droping all capabilities\n");
313
314 unsigned long cap;
315 for (cap=0; cap <= 63; cap++) {
316 int code = prctl(PR_CAPBSET_DROP, cap, 0, 0, 0);
317 if (code == -1 && errno != EINVAL)
318 errExit("PR_CAPBSET_DROP");
319 }
320}
321
322
323void caps_set(uint64_t caps) {
324 if (arg_debug)
325 printf("Set caps filter %llx\n", (unsigned long long) caps);
326
327 unsigned long i;
328 uint64_t mask = 1LLU;
329 for (i = 0; i < 64; i++, mask <<= 1) {
330 if ((mask & caps) == 0) {
331 int code = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
332 if (code == -1 && errno != EINVAL)
333 errExit("PR_CAPBSET_DROP");
334 }
335 }
336}
337
338
339static uint64_t filter;
340
341static void caps_set_bit(int nr) {
342 uint64_t mask = 1LLU << nr;
343 filter |= mask;
344}
345static void caps_reset_bit(int nr) {
346 uint64_t mask = 1LLU << nr;
347 filter &= ~mask;
348}
349
350void caps_drop_list(const char *clist) {
351 filter = 0;
352 filter--;
353 caps_check_list(clist, caps_reset_bit);
354 caps_set(filter);
355}
356
357void caps_keep_list(const char *clist) {
358 filter = 0;
359 caps_check_list(clist, caps_set_bit);
360 caps_set(filter);
361}
362
363#define MAXBUF 4098
364static uint64_t extract_caps(int pid) {
365 char *file;
366 if (asprintf(&file, "/proc/%d/status", pid) == -1) {
367 errExit("asprintf");
368 exit(1);
369 }
370
371 FILE *fp = fopen(file, "r");
372 if (!fp) {
373 printf("Error: cannot open %s\n", file);
374 free(file);
375 exit(1);
376 }
377
378 char buf[MAXBUF];
379 while (fgets(buf, MAXBUF, fp)) {
380 if (strncmp(buf, "CapBnd:", 7) == 0) {
381 char *ptr = buf + 8;
382 unsigned long long val;
383 sscanf(ptr, "%llx", &val);
384 free(file);
385 fclose(fp);
386 return val;
387 }
388 }
389 fclose(fp);
390 free(file);
391 printf("Error: cannot read caps configuration\n");
392 exit(1);
393}
394
395
396void caps_print_filter_name(const char *name) {
397 if (!name || strlen(name) == 0) {
398 fprintf(stderr, "Error: invalid sandbox name\n");
399 exit(1);
400 }
401 pid_t pid;
402 if (name2pid(name, &pid)) {
403 fprintf(stderr, "Error: cannot find sandbox %s\n", name);
404 exit(1);
405 }
406
407 caps_print_filter(pid);
408}
409
410void caps_print_filter(pid_t pid) {
411 // if the pid is that of a firejail process, use the pid of the first child process
412 char *comm = pid_proc_comm(pid);
413 if (comm) {
414 // remove \n
415 char *ptr = strchr(comm, '\n');
416 if (ptr)
417 *ptr = '\0';
418 if (strcmp(comm, "firejail") == 0) {
419 pid_t child;
420 if (find_child(pid, &child) == 0) {
421 pid = child;
422 }
423 }
424 free(comm);
425 }
426
427 // check privileges for non-root users
428 uid_t uid = getuid();
429 if (uid != 0) {
430 struct stat s;
431 char *dir;
432 if (asprintf(&dir, "/proc/%u/ns", pid) == -1)
433 errExit("asprintf");
434 if (stat(dir, &s) < 0)
435 errExit("stat");
436 if (s.st_uid != uid) {
437 printf("Error: permission denied.\n");
438 exit(1);
439 }
440 }
441
442 uint64_t caps = extract_caps(pid);
443 drop_privs(1);
444
445 int i;
446 uint64_t mask;
447 int elems = sizeof(capslist) / sizeof(capslist[0]);
448 for (i = 0, mask = 1; i < elems; i++, mask <<= 1) {
449 printf("%-18.18s - %s\n", capslist[i].name, (mask & caps)? "enabled": "disabled");
450 }
451
452 exit(0);
453}
diff --git a/src/firejail/cgroup.c b/src/firejail/cgroup.c
new file mode 100644
index 000000000..7366a6699
--- /dev/null
+++ b/src/firejail/cgroup.c
@@ -0,0 +1,118 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
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#include "firejail.h"
21#include <sys/stat.h>
22
23#define MAXBUF 4096
24
25void save_cgroup(void) {
26 if (cfg.cgroup == NULL)
27 return;
28
29 char *fname;
30 if (asprintf(&fname, "%s/cgroup", MNT_DIR) == -1)
31 errExit(fname);
32
33 FILE *fp = fopen(fname, "w");
34 if (fp) {
35 fprintf(fp, "%s", cfg.cgroup);
36 fflush(0);
37 fclose(fp);
38 if (chown(fname, 0, 0) < 0)
39 errExit("chown");
40 }
41 else {
42 fprintf(stderr, "Error: cannot save cgroup\n");
43 free(fname);
44 exit(1);
45 }
46
47 free(fname);
48}
49
50void load_cgroup(const char *fname) {
51 if (!fname)
52 return;
53
54 FILE *fp = fopen(fname, "r");
55 if (fp) {
56 char buf[MAXBUF];
57 if (fgets(buf, MAXBUF, fp)) {
58 cfg.cgroup = strdup(buf);
59 if (!cfg.cgroup)
60 errExit("strdup");
61 }
62 else
63 goto errout;
64
65 fclose(fp);
66 return;
67 }
68errout:
69 fprintf(stderr, "Warrning: cannot load control group\n");
70 if (fp)
71 fclose(fp);
72}
73
74
75void set_cgroup(const char *path) {
76 // path starts with /sys/fs/cgroup
77 if (strncmp(path, "/sys/fs/cgroup", 14) != 0)
78 goto errout;
79
80 // path ends in tasks
81 char *ptr = strstr(path, "tasks");
82 if (!ptr)
83 goto errout;
84 if (*(ptr + 5) != '\0')
85 goto errout;
86
87 // no .. traversal
88 ptr = strstr(path, "..");
89 if (ptr)
90 goto errout;
91
92 // tasks file exists
93 struct stat s;
94 if (stat(path, &s) == -1)
95 goto errout;
96
97 // task file belongs to the user running the sandbox
98 if (s.st_uid != getuid() && s.st_gid != getgid())
99 goto errout2;
100
101 // add the task to cgroup
102 /* coverity[toctou] */
103 FILE *fp = fopen(path, "a");
104 if (!fp)
105 goto errout;
106 pid_t pid = getpid();
107 int rv = fprintf(fp, "%d\n", pid);
108 (void) rv;
109 fclose(fp);
110 return;
111
112errout:
113 fprintf(stderr, "Error: invalid cgroup\n");
114 exit(1);
115errout2:
116 fprintf(stderr, "Error: you don't have permissions to use this control group\n");
117 exit(1);
118}
diff --git a/src/firejail/cpu.c b/src/firejail/cpu.c
new file mode 100644
index 000000000..633081a3f
--- /dev/null
+++ b/src/firejail/cpu.c
@@ -0,0 +1,141 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
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#include "firejail.h"
21#include <sched.h>
22
23// converts a numeric cpu value in the corresponding bit mask
24static void set_cpu(const char *str) {
25 if (strlen(str) == 0)
26 return;
27
28 int val = atoi(str);
29 if (val < 0 || val >= 32) {
30 fprintf(stderr, "Error: invalid cpu number. Accepted values are between 0 and 31.\n");
31 exit(1);
32 }
33
34 uint32_t mask = 1;
35 int i;
36 for (i = 0; i < val; i++, mask <<= 1);
37 cfg.cpus |= mask;
38}
39
40void read_cpu_list(const char *str) {
41 char *tmp = strdup(str);
42 if (tmp == NULL)
43 errExit("strdup");
44
45 char *ptr = tmp;
46 while (*ptr != '\0') {
47 if (*ptr == ',' || isdigit(*ptr))
48 ;
49 else {
50 fprintf(stderr, "Error: invalid cpu list\n");
51 exit(1);
52 }
53 ptr++;
54 }
55
56 char *start = tmp;
57 ptr = tmp;
58 while (*ptr != '\0') {
59 if (*ptr == ',') {
60 *ptr = '\0';
61 set_cpu(start);
62 start = ptr + 1;
63 }
64 ptr++;
65 }
66 set_cpu(start);
67 free(tmp);
68}
69
70void save_cpu(void) {
71 if (cfg.cpus == 0)
72 return;
73
74 char *fname;
75 if (asprintf(&fname, "%s/cpu", MNT_DIR) == -1)
76 errExit("asprintf");
77 FILE *fp = fopen(fname, "w");
78 if (fp) {
79 fprintf(fp, "%x\n", cfg.cpus);
80 fclose(fp);
81 if (chown(fname, 0, 0) < 0)
82 errExit("chown");
83 }
84 else {
85 fprintf(stderr, "Error: cannot save cpu affinity mask\n");
86 free(fname);
87 exit(1);
88 }
89
90 free(fname);
91}
92
93void load_cpu(const char *fname) {
94 if (!fname)
95 return;
96
97 FILE *fp = fopen(fname, "r");
98 if (fp) {
99 unsigned tmp;
100 int rv = fscanf(fp, "%x", &tmp);
101 if (rv)
102 cfg.cpus = (uint32_t) tmp;
103 fclose(fp);
104 }
105 else
106 fprintf(stderr, "Warning: cannot load cpu affinity mask\n");
107}
108
109void set_cpu_affinity(void) {
110 // set cpu affinity
111 cpu_set_t mask;
112 CPU_ZERO(&mask);
113
114 int i;
115 uint32_t m = 1;
116 for (i = 0; i < 32; i++, m <<= 1) {
117 if (cfg.cpus & m)
118 CPU_SET(i, &mask);
119 }
120
121 if (sched_setaffinity(0, sizeof(mask), &mask) == -1) {
122 fprintf(stderr, "Warning: cannot set cpu affinity\n");
123 fprintf(stderr, " ");
124 perror("sched_setaffinity");
125 }
126
127 // verify cpu affinity
128 cpu_set_t mask2;
129 CPU_ZERO(&mask2);
130 if (sched_getaffinity(0, sizeof(mask2), &mask2) == -1) {
131 fprintf(stderr, "Warning: cannot verify cpu affinity\n");
132 fprintf(stderr, " ");
133 perror("sched_getaffinity");
134 }
135 else {
136 if (CPU_EQUAL(&mask, &mask2))
137 printf("CPU affinity set\n");
138 else
139 printf("CPU affinity not set\n");
140 }
141}
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
new file mode 100644
index 000000000..2ec6e54c9
--- /dev/null
+++ b/src/firejail/firejail.h
@@ -0,0 +1,354 @@
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#ifndef FIREJAIL_H
21#define FIREJAIL_H
22#include "../include/common.h"
23
24#define USELOCK
25#define FIREJAIL_DIR "/tmp/firejail"
26#define RO_DIR "/tmp/firejail/firejail.ro.dir"
27#define RO_FILE "/tmp/firejail/firejail.ro.file"
28#define MNT_DIR "/tmp/firejail/mnt"
29#define OVERLAY_DIR "/tmp/firejail/overlay"
30#define HOME_DIR "/tmp/firejail/mnt/home"
31#define MAX_INCLUDE_LEVEL 6
32
33// main.c
34typedef struct bridge_t {
35 // on the host
36 char *dev; // interface device name: bridge or regular ethernet
37 uint32_t ip; // interface device IP address
38 uint32_t mask; // interface device mask
39 uint8_t mac[6]; // interface mac address
40
41 // inside the sandbox
42 char *devsandbox; // name of the device inside the sandbox
43 uint32_t ipsandbox; // ip address inside the sandbox
44 uint8_t macsandbox[6]; // mac address inside the sandbox
45 uint32_t iprange_start;// iprange arp scan start range
46 uint32_t iprange_end; // iprange arp scan end range
47
48 // flags
49 uint8_t arg_ip_none; // --ip=none
50 uint8_t macvlan; // set by --net=eth0 (or eth1, ...); reset by --net=br0 (or br1, ...)
51 uint8_t configured;
52 uint8_t scan; // set by --scan
53} Bridge;
54
55typedef struct profile_entry_t {
56 struct profile_entry_t *next;
57 char *data;
58}ProfileEntry;
59
60typedef struct config_t {
61 // user data
62 char *username;
63 char *homedir;
64
65 // filesystem
66 ProfileEntry *profile;
67 char *chrootdir; // chroot directory
68 char *home_private; // private home directory
69 char *home_private_keep; // keep list for private home directory
70 char *cwd; // current working directory
71
72 // networking
73 char *hostname;
74 uint32_t defaultgw; // default gateway
75 Bridge bridge0;
76 Bridge bridge1;
77 Bridge bridge2;
78 Bridge bridge3;
79 uint32_t dns1; // up to 3 IP addresses for dns servers
80 uint32_t dns2;
81 uint32_t dns3;
82
83 // rlimits
84 unsigned rlimit_nofile;
85 unsigned rlimit_nproc;
86 unsigned rlimit_fsize;
87 unsigned rlimit_sigpending;
88
89 // cpu affinity and control groups
90 uint32_t cpus;
91 char *cgroup;
92
93
94 // command line
95 char *command_line;
96 char *command_name;
97 char *shell;
98 char **original_argv;
99 int original_argc;
100 int original_program_index;
101} Config;
102extern Config cfg;
103
104static inline int any_bridge_configured(void) {
105 if (cfg.bridge3.configured || cfg.bridge2.configured || cfg.bridge1.configured || cfg.bridge0.configured)
106 return 1;
107 else
108 return 0;
109}
110extern int arg_private; // mount private /home and /tmp directory
111extern int arg_debug; // print debug messages
112extern int arg_nonetwork; // --net=none
113extern int arg_command; // -c
114extern int arg_overlay; // --overlay
115extern int arg_zsh; // use zsh as default shell
116extern int arg_csh; // use csh as default shell
117
118extern int arg_seccomp; // enable default seccomp filter
119extern char *arg_seccomp_list;// optional seccomp list on top of default filter
120extern char *arg_seccomp_list_drop; // seccomp drop list
121extern char *arg_seccomp_list_keep; // seccomp keep list
122
123extern int arg_caps_default_filter; // enable default capabilities filter
124extern int arg_caps_drop; // drop list
125extern int arg_caps_drop_all; // drop all capabilities
126extern int arg_caps_keep; // keep list
127extern char *arg_caps_list; // optional caps list
128
129extern int arg_trace; // syscall tracing support
130extern int arg_rlimit_nofile; // rlimit nofile
131extern int arg_rlimit_nproc; // rlimit nproc
132extern int arg_rlimit_fsize; // rlimit fsize
133extern int arg_rlimit_sigpending;// rlimit sigpending
134extern int arg_nox11; // kill the program if x11 unix domain socket is accessed
135extern int arg_nodbus; // kill the program if D-Bus is accessed
136extern int arg_nogroups; // disable supplementary groups
137extern int arg_noroot; // create a new user namespace and disable root user
138extern int arg_netfilter; // enable netfilter
139extern char *arg_netfilter_file; // netfilter file
140extern int arg_doubledash; // double dash
141extern int arg_shell_none; // run the program directly without a shell
142extern int arg_private_dev; // private dev directory
143extern int arg_scan; // arp-scan all interfaces
144
145extern int parent_to_child_fds[2];
146extern int child_to_parent_fds[2];
147extern pid_t sandbox_pid;
148
149
150
151#define MAX_ARGS 128 // maximum number of command arguments (argc)
152extern char *fullargv[MAX_ARGS];
153extern int fullargc;
154
155// main.c
156void check_user_namespace(void);
157
158// sandbox.c
159int sandbox(void* sandbox_arg);
160
161// network_main.c
162void net_configure_bridge(Bridge *br, char *dev_name);
163void net_configure_sandbox_ip(Bridge *br);
164void net_configure_veth_pair(Bridge *br, const char *ifname, pid_t child);
165void net_check_cfg(void);
166void net_dns_print_name(const char *name);
167void net_dns_print(pid_t pid);
168
169// network.c
170void net_if_up(const char *ifname);
171void net_if_ip(const char *ifname, uint32_t ip, uint32_t mask);
172int net_get_if_addr(const char *bridge, uint32_t *ip, uint32_t *mask, uint8_t mac[6]);
173int net_add_route(uint32_t dest, uint32_t mask, uint32_t gw);
174void net_ifprint(void);
175void net_bridge_add_interface(const char *bridge, const char *dev);
176uint32_t network_get_defaultgw(void);
177int net_config_mac(const char *ifname, const unsigned char mac[6]);
178int net_get_mac(const char *ifname, unsigned char mac[6]);
179
180// fs.c
181// build /tmp/firejail directory
182void fs_build_firejail_dir(void);
183// build /tmp/firejail/mnt directory
184void fs_build_mnt_dir(void);
185// blacklist files or directoies by mounting empty files on top of them
186void fs_blacklist(const char *homedir);
187//void fs_blacklist(char **blacklist, const char *homedir);
188// remount a directory read-only
189void fs_rdonly(const char *dir);
190// mount /proc and /sys directories
191void fs_proc_sys_dev_boot(void);
192// build a basic read-only filesystem
193void fs_basic_fs(void);
194// mount overlayfs on top of / directory
195void fs_overlayfs(void);
196// chroot into an existing directory; mount exiting /dev and update /etc/resolv.conf
197void fs_chroot(const char *rootdir);
198int fs_check_chroot_dir(const char *rootdir);
199
200// profile.c
201// find and read the profile specified by name from dir directory
202int profile_find(const char *name, const char *dir);
203// read a profile file
204void profile_read(const char *fname, const char *skip1, const char *skip2);
205// check profile line; if line == 0, this was generated from a command line option
206// return 1 if the command is to be added to the linked list of profile commands
207// return 0 if the command was already executed inside the function
208int profile_check_line(char *ptr, int lineno);
209// add a profile entry in cfg.profile list; use str to populate the list
210void profile_add(char *str);
211
212// list.c
213void list(void);
214void tree(void);
215void top(void);
216void netstats(void);
217
218// usage.c
219void usage(void);
220
221// join.c
222void join(pid_t pid, const char *homedir, int argc, char **argv, int index);
223void join_name(const char *name, const char *homedir, int argc, char **argv, int index);
224void shut(pid_t pid);
225void shut_name(const char *name);
226
227// restricted_shell.c
228extern char *restricted_user;
229int restricted_shell(const char *user);
230
231// arp.c
232// returns 0 if the address is not in use, -1 otherwise
233int arp_check(const char *dev, uint32_t destaddr, uint32_t srcaddr);
234// assign an IP address using arp scanning
235uint32_t arp_assign(const char *dev, Bridge *br);
236// scan interface (--scan option)
237void arp_scan(const char *dev, uint32_t srcaddr, uint32_t srcmask);
238
239// veth.c
240int net_create_veth(const char *dev, const char *nsdev, unsigned pid);
241int net_create_macvlan(const char *dev, const char *parent, unsigned pid);
242
243// util.c
244void drop_privs(int nogroups);
245void extract_command_name(const char *str);
246void logsignal(int s);
247void logmsg(const char *msg);
248void logargs(int argc, char **argv) ;
249void logerr(const char *msg);
250int copy_file(const char *srcname, const char *destname);
251char *get_link(const char *fname);
252int is_dir(const char *fname);
253int is_link(const char *fname);
254char *line_remove_spaces(const char *buf);
255char *split_comma(char *str);
256int not_unsigned(const char *str);
257int find_child(pid_t parent, pid_t *child);
258void check_private_dir(void);
259void update_map(char *mapping, char *map_file);
260void wait_for_other(int fd);
261void notify_other(int fd);
262
263// fs_var.c
264void fs_var_log(void); // mounting /var/log
265void fs_var_lib(void); // various other fixes for software in /var directory
266void fs_var_cache(void); // various other fixes for software in /var/cache directory
267void fs_var_run(void);
268void fs_var_lock(void);
269void fs_var_tmp(void);
270void fs_var_utmp(void);
271void dbg_test_dir(const char *dir);
272
273// fs_dev.c
274void fs_dev_shm(void);
275void fs_private_dev(void);
276
277// fs_home.c
278// private mode (--private)
279void fs_private(void);
280// private mode (--private=homedir)
281void fs_private_homedir(void);
282// private mode (--private.keep=list)
283void fs_private_home_list(void);
284// check directory linst specified by user (--private.keep option) - exit if it fails
285void fs_check_home_list(void);
286// check new private home directory (--private= option) - exit if it fails
287void fs_check_private_dir(void);
288
289
290// seccomp.c
291int seccomp_filter_drop(void);
292int seccomp_filter_keep(void);
293void seccomp_set(void);
294void seccomp_print_filter_name(const char *name);
295void seccomp_print_filter(pid_t pid);
296
297// caps.c
298int caps_default_filter(void);
299void caps_print(void);
300void caps_drop_all(void);
301void caps_set(uint64_t caps);
302int caps_check_list(const char *clist, void (*callback)(int));
303void caps_drop_list(const char *clist);
304void caps_keep_list(const char *clist);
305void caps_print_filter(pid_t pid);
306void caps_print_filter_name(const char *name);
307
308// syscall.c
309const char *syscall_find_nr(int nr);
310// return -1 if error, 0 if no error
311int syscall_check_list(const char *slist, void (*callback)(int));
312// print all available syscalls
313void syscall_print(void);
314
315// fs_trace.c
316void fs_trace_preload(void);
317void fs_trace(void);
318
319// fs_hostname.c
320void fs_hostname(const char *hostname);
321void fs_resolvconf(void);
322
323// rlimit.c
324void set_rlimits(void);
325
326// cpu.c
327void read_cpu_list(const char *str);
328void set_cpu_affinity(void);
329void load_cpu(const char *fname);
330void save_cpu(void);
331
332// cgroup.c
333void save_cgroup(void);
334void load_cgroup(const char *fname);
335void set_cgroup(const char *path);
336
337// output.c
338void check_output(int argc, char **argv);
339
340// netfilter.c
341void check_netfilter_file(const char *fname);
342void netfilter(const char *fname);
343
344// bandwidth.c
345void shm_create_firejail_dir(void);
346void bandwidth_shm_del_file(pid_t pid);
347void bandwidth_shm_set(pid_t pid, const char *dev, int down, int up);
348void bandwidth_name(const char *name, const char *command, const char *dev, int down, int up);
349void bandwidth_pid(pid_t pid, const char *command, const char *dev, int down, int up);
350void network_shm_del_file(pid_t pid);
351void network_shm_set_file(pid_t pid);
352
353
354#endif \ No newline at end of file
diff --git a/src/firejail/fs.c b/src/firejail/fs.c
new file mode 100644
index 000000000..1fc1c0942
--- /dev/null
+++ b/src/firejail/fs.c
@@ -0,0 +1,825 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
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#include "firejail.h"
21#include <sys/mount.h>
22#include <sys/stat.h>
23#include <linux/limits.h>
24#include <glob.h>
25#include <dirent.h>
26#include <fcntl.h>
27#include <errno.h>
28
29// build /tmp/firejail directory
30void fs_build_firejail_dir(void) {
31 struct stat s;
32
33 if (stat(FIREJAIL_DIR, &s)) {
34 if (arg_debug)
35 printf("Creating %s directory\n", FIREJAIL_DIR);
36 /* coverity[toctou] */
37 int rv = mkdir(FIREJAIL_DIR, S_IRWXU | S_IRWXG | S_IRWXO);
38 if (rv == -1)
39 errExit("mkdir");
40 if (chown(FIREJAIL_DIR, 0, 0) < 0)
41 errExit("chown");
42 if (chmod(FIREJAIL_DIR, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0)
43 errExit("chmod");
44 }
45 else { // check /tmp/firejail directory belongs to root end exit if doesn't!
46 if (s.st_uid != 0 || s.st_gid != 0) {
47 fprintf(stderr, "Error: non-root %s directory, exiting...\n", FIREJAIL_DIR);
48 exit(1);
49 }
50 }
51}
52
53
54// build /tmp/firejail/mnt directory
55static int tmpfs_mounted = 0;
56void fs_build_mnt_dir(void) {
57 struct stat s;
58 fs_build_firejail_dir();
59
60 // create /tmp/firejail directory
61 if (stat(MNT_DIR, &s)) {
62 if (arg_debug)
63 printf("Creating %s directory\n", MNT_DIR);
64 /* coverity[toctou] */
65 int rv = mkdir(MNT_DIR, S_IRWXU | S_IRWXG | S_IRWXO);
66 if (rv == -1)
67 errExit("mkdir");
68 if (chown(MNT_DIR, 0, 0) < 0)
69 errExit("chown");
70 if (chmod(MNT_DIR, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0)
71 errExit("chmod");
72 }
73
74 // ... and mount tmpfs on top of it
75 if (!tmpfs_mounted) {
76 // mount tmpfs on top of /tmp/firejail/mnt
77 if (arg_debug)
78 printf("Mounting tmpfs on %s directory\n", MNT_DIR);
79 if (mount("tmpfs", MNT_DIR, "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
80 errExit("mounting /tmp/firejail/mnt");
81 tmpfs_mounted = 1;
82 }
83}
84
85// build /tmp/firejail/overlay directory
86void fs_build_overlay_dir(void) {
87 struct stat s;
88 fs_build_firejail_dir();
89
90 // create /tmp/firejail directory
91 if (stat(OVERLAY_DIR, &s)) {
92 if (arg_debug)
93 printf("Creating %s directory\n", MNT_DIR);
94 /* coverity[toctou] */
95 int rv = mkdir(OVERLAY_DIR, S_IRWXU | S_IRWXG | S_IRWXO);
96 if (rv == -1)
97 errExit("mkdir");
98 if (chown(OVERLAY_DIR, 0, 0) < 0)
99 errExit("chown");
100 if (chmod(OVERLAY_DIR, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0)
101 errExit("chmod");
102 }
103}
104
105
106
107
108
109//***********************************************
110// process profile file
111//***********************************************
112typedef enum {
113 BLACKLIST_FILE,
114 MOUNT_READONLY,
115 MOUNT_TMPFS,
116 OPERATION_MAX
117} OPERATION;
118
119
120static char *create_empty_dir(void) {
121 struct stat s;
122 fs_build_firejail_dir();
123
124 if (stat(RO_DIR, &s)) {
125 /* coverity[toctou] */
126 int rv = mkdir(RO_DIR, S_IRUSR | S_IXUSR);
127 if (rv == -1)
128 errExit("mkdir");
129 if (chown(RO_DIR, 0, 0) < 0)
130 errExit("chown");
131 }
132
133 return RO_DIR;
134}
135
136static char *create_empty_file(void) {
137 struct stat s;
138 fs_build_firejail_dir();
139
140 if (stat(RO_FILE, &s)) {
141 /* coverity[toctou] */
142 FILE *fp = fopen(RO_FILE, "w");
143 if (!fp)
144 errExit("fopen");
145 fclose(fp);
146 if (chown(RO_FILE, 0, 0) < 0)
147 errExit("chown");
148 if (chmod(RO_FILE, S_IRUSR) < 0)
149 errExit("chown");
150 }
151
152 return RO_FILE;
153}
154
155static void disable_file(OPERATION op, const char *fname, const char *emptydir, const char *emptyfile) {
156 assert(fname);
157 assert(emptydir);
158 assert(emptyfile);
159 assert(op <OPERATION_MAX);
160
161 // if the file is a link, follow the link
162 char *lnk = NULL;
163 if (is_link(fname)) {
164 lnk = get_link(fname);
165 if (lnk)
166 fname = lnk;
167 else
168 fprintf(stderr, "Warning: cannot follow link %s, skipping...\n", fname);
169 }
170
171 // if the file is not present, do nothing
172 struct stat s;
173 if (stat(fname, &s) == -1) {
174 if (lnk)
175 free(lnk);
176 return;
177 }
178
179 // modify the file
180 if (op == BLACKLIST_FILE) {
181 if (arg_debug)
182 printf("Disable %s\n", fname);
183 if (S_ISDIR(s.st_mode)) {
184 if (mount(emptydir, fname, "none", MS_BIND, "mode=400,gid=0") < 0)
185 errExit("disable file");
186 }
187 else {
188 if (mount(emptyfile, fname, "none", MS_BIND, "mode=400,gid=0") < 0)
189 errExit("disable file");
190 }
191 }
192 else if (op == MOUNT_READONLY) {
193 if (arg_debug)
194 printf("Mounting read-only %s\n", fname);
195 fs_rdonly(fname);
196 }
197 else if (op == MOUNT_TMPFS) {
198 if (S_ISDIR(s.st_mode)) {
199 if (arg_debug)
200 printf("Mounting tmpfs on %s\n", fname);
201 // preserve owner and mode for the directory
202 if (mount("tmpfs", fname, "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, 0) < 0)
203 errExit("mounting tmpfs");
204 /* coverity[toctou] */
205 if (chown(fname, s.st_uid, s.st_gid) == -1)
206 errExit("mounting tmpfs chmod");
207 }
208 else
209 printf("Warning: %s is not a directory; cannot mount a tmpfs on top of it.\n", fname);
210 }
211 else
212 assert(0);
213
214 if (lnk)
215 free(lnk);
216}
217
218static void globbing(OPERATION op, const char *fname, const char *emptydir, const char *emptyfile) {
219 assert(fname);
220 assert(emptydir);
221 assert(emptyfile);
222
223 // filename globbing: expand * macro and continue processing for every single file
224 if (strchr(fname, '*')) {
225 glob_t globbuf;
226 globbuf.gl_offs = 0;
227 glob(fname, GLOB_DOOFFS, NULL, &globbuf);
228 int i;
229 for (i = 0; i < globbuf.gl_pathc; i++) {
230 assert(globbuf.gl_pathv[i]);
231 disable_file(op, globbuf.gl_pathv[i], emptydir, emptyfile);
232 }
233 }
234 else
235 disable_file(op, fname, emptydir, emptyfile);
236}
237
238static void expand_path(OPERATION op, const char *path, const char *fname, const char *emptydir, const char *emptyfile) {
239 assert(path);
240 assert(fname);
241 assert(emptydir);
242 assert(emptyfile);
243 char newname[strlen(path) + strlen(fname) + 1];
244 sprintf(newname, "%s%s", path, fname);
245
246 globbing(op, newname, emptydir, emptyfile);
247}
248
249// blacklist files or directoies by mounting empty files on top of them
250void fs_blacklist(const char *homedir) {
251 ProfileEntry *entry = cfg.profile;
252 if (!entry)
253 return;
254
255 char *emptydir = create_empty_dir();
256 char *emptyfile = create_empty_file();
257
258 while (entry) {
259 OPERATION op = OPERATION_MAX;
260 char *ptr;
261
262 // process blacklist command
263 if (strncmp(entry->data, "bind", 4) == 0) {
264 char *dname1 = entry->data + 5;
265 char *dname2 = split_comma(dname1);
266 if (dname2 == NULL) {
267 fprintf(stderr, "Error: second directory missing in bind command\n");
268 entry = entry->next;
269 continue;
270 }
271 struct stat s;
272 if (stat(dname1, &s) == -1) {
273 fprintf(stderr, "Error: cannot find directories for bind command\n");
274 entry = entry->next;
275 continue;
276 }
277 if (stat(dname2, &s) == -1) {
278 fprintf(stderr, "Error: cannot find directories for bind command\n");
279 entry = entry->next;
280 continue;
281 }
282
283 // mount --bind olddir newdir
284 if (arg_debug)
285 printf("Mount-bind %s on top of %s\n", dname1, dname2);
286 // preserve dname2 mode and ownership
287 if (mount(dname1, dname2, NULL, MS_BIND|MS_REC, NULL) < 0)
288 errExit("mount bind");
289 /* coverity[toctou] */
290 if (chown(dname2, s.st_uid, s.st_gid) == -1)
291 errExit("mount-bind chown");
292 /* coverity[toctou] */
293 if (chmod(dname2, s.st_mode) == -1)
294 errExit("mount-bind chmod");
295
296 entry = entry->next;
297 continue;
298 }
299
300 // process blacklist command
301 if (strncmp(entry->data, "blacklist", 9) == 0) {
302 ptr = entry->data + 10;
303 op = BLACKLIST_FILE;
304 }
305 else if (strncmp(entry->data, "read-only", 9) == 0) {
306 ptr = entry->data + 10;
307 op = MOUNT_READONLY;
308 }
309 else if (strncmp(entry->data, "tmpfs", 5) == 0) {
310 ptr = entry->data + 6;
311 op = MOUNT_TMPFS;
312 }
313 else {
314 fprintf(stderr, "Error: invalid profile line %s\n", entry->data);
315 entry = entry->next;
316 continue;
317 }
318
319 // replace home macro in blacklist array
320 char *new_name = NULL;
321 if (strncmp(ptr, "${HOME}", 7) == 0) {
322 if (asprintf(&new_name, "%s%s", homedir, ptr + 7) == -1)
323 errExit("asprintf");
324 ptr = new_name;
325 }
326
327 // expand path macro - look for the file in /bin, /usr/bin, /sbin and /usr/sbin directories
328 if (strncmp(ptr, "${PATH}", 7) == 0) {
329 expand_path(op, "/bin", ptr + 7, emptydir, emptyfile);
330 expand_path(op, "/sbin", ptr + 7, emptydir, emptyfile);
331 expand_path(op, "/usr/bin", ptr + 7, emptydir, emptyfile);
332 expand_path(op, "/usr/sbin", ptr + 7, emptydir, emptyfile);
333 }
334 else
335 globbing(op, ptr, emptydir, emptyfile);
336
337 if (new_name)
338 free(new_name);
339 entry = entry->next;
340 }
341}
342
343//***********************************************
344// mount namespace
345//***********************************************
346
347// remount a directory read-only
348void fs_rdonly(const char *dir) {
349 assert(dir);
350 // check directory exists
351 struct stat s;
352 int rv = stat(dir, &s);
353 if (rv == 0) {
354 // mount --bind /bin /bin
355 if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0)
356 errExit("mount read-only");
357 // mount --bind -o remount,ro /bin
358 if (mount(NULL, dir, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_REC, NULL) < 0)
359 errExit("mount read-only");
360 }
361}
362void fs_rdonly_noexit(const char *dir) {
363 assert(dir);
364 // check directory exists
365 struct stat s;
366 int rv = stat(dir, &s);
367 if (rv == 0) {
368 int merr = 0;
369 // mount --bind /bin /bin
370 if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0)
371 merr = 1;
372 // mount --bind -o remount,ro /bin
373 if (mount(NULL, dir, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_REC, NULL) < 0)
374 merr = 1;
375 if (merr)
376 fprintf(stderr, "Warning: cannot mount %s read-only\n", dir);
377 }
378}
379
380// mount /proc and /sys directories
381void fs_proc_sys_dev_boot(void) {
382 struct stat s;
383
384 if (arg_debug)
385 printf("Remounting /proc and /proc/sys filesystems\n");
386 if (mount("proc", "/proc", "proc", MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_REC, NULL) < 0)
387 errExit("mounting /proc");
388
389 // remount /proc/sys readonly
390 if (mount("/proc/sys", "/proc/sys", NULL, MS_BIND | MS_REC, NULL) < 0)
391 errExit("mounting /proc/sys");
392
393 if (mount(NULL, "/proc/sys", NULL, MS_BIND | MS_REMOUNT | MS_RDONLY | MS_REC, NULL) < 0)
394 errExit("mounting /proc/sys");
395
396
397 /* Mount a version of /sys that describes the network namespace */
398 if (arg_debug)
399 printf("Remounting /sys directory\n");
400 if (umount2("/sys", MNT_DETACH) < 0)
401 fprintf(stderr, "Warning: failed to unmount /sys\n");
402 if (mount("sysfs", "/sys", "sysfs", MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REC, NULL) < 0)
403 fprintf(stderr, "Warning: failed to mount /sys\n");
404
405// if (mount("sysfs", "/sys", "sysfs", MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REC, NULL) < 0)
406// errExit("mounting /sys");
407
408
409 // mounting firejail kernel module files
410 if (stat("/proc/firejail-uptime", &s) == 0) {
411 errno = 0;
412 FILE *fp = fopen("/proc/firejail", "w");
413 int cnt = 0;
414 while (errno == EBUSY && cnt < 10) {
415 if (!fp) {
416 int s = random();
417 s /= 200000;
418 usleep(s);
419 fp = fopen("/proc/firejail", "w");
420 }
421 else
422 break;
423 }
424 if (!fp) {
425 fprintf(stderr, "Error: cannot register sandbox with firejail-lkm\n");
426 exit(1);
427 }
428 if (fp) {
429 // registration
430 fprintf(fp, "register\n");
431 fflush(0);
432 // filtering x11 connect calls
433 if (arg_nox11) {
434 fprintf(fp, "no connect unix /tmp/.X11\n");
435 fflush(0);
436 printf("X11 access disabled\n");
437 }
438 if (arg_nodbus) {
439 fprintf(fp, "no connect unix /var/run/dbus/system_bus_socket\n");
440 fflush(0);
441 fprintf(fp, "no connect unix /tmp/dbus\n");
442 fflush(0);
443 printf("D-Bus access disabled\n");
444 }
445 fclose(fp);
446 if (mount("/proc/firejail-uptime", "/proc/uptime", NULL, MS_BIND|MS_REC, NULL) < 0)
447 fprintf(stderr, "Warning: cannot mount /proc/firejail-uptime\n");
448 }
449 }
450
451 // Disable SysRq
452 // a linux box can be shut down easily using the following commands (as root):
453 // # echo 1 > /proc/sys/kernel/sysrq
454 // #echo b > /proc/sysrq-trigger
455 // for more information see https://www.kernel.org/doc/Documentation/sysrq.txt
456 if (arg_debug)
457 printf("Disable /proc/sysrq-trigger\n");
458 fs_rdonly_noexit("/proc/sysrq-trigger");
459
460 // disable hotplug and uevent_helper
461 if (arg_debug)
462 printf("Disable /proc/sys/kernel/hotplug\n");
463 fs_rdonly_noexit("/proc/sys/kernel/hotplug");
464 if (arg_debug)
465 printf("Disable /sys/kernel/uevent_helper\n");
466 fs_rdonly_noexit("/sys/kernel/uevent_helper");
467
468 // read-only /proc/irq and /proc/bus
469 if (arg_debug)
470 printf("Disable /proc/irq\n");
471 fs_rdonly_noexit("/proc/irq");
472 if (arg_debug)
473 printf("Disable /proc/bus\n");
474 fs_rdonly_noexit("/proc/bus");
475
476 // disable /proc/kcore
477 disable_file(BLACKLIST_FILE, "/proc/kcore", "not used", "/dev/null");
478
479 // disable /proc/kallsyms
480 disable_file(BLACKLIST_FILE, "/proc/kallsyms", "not used", "/dev/null");
481
482 // disable /boot
483 if (stat("/boot", &s) == 0) {
484 if (arg_debug)
485 printf("Mounting a new /boot directory\n");
486 if (mount("tmpfs", "/boot", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=777,gid=0") < 0)
487 errExit("mounting /boot directory");
488 }
489
490 // disable /dev/port
491 if (stat("/dev/port", &s) == 0) {
492 disable_file(BLACKLIST_FILE, "/dev/port", "not used", "/dev/null");
493 }
494}
495
496static void sanitize_home(void) {
497 // extract current /home directory data
498 struct dirent *dir;
499 DIR *d = opendir("/home");
500 if (d == NULL)
501 return;
502
503 char *emptydir = create_empty_dir();
504 while ((dir = readdir(d))) {
505 if(strcmp(dir->d_name, "." ) == 0 || strcmp(dir->d_name, ".." ) == 0)
506 continue;
507
508 if (dir->d_type == DT_DIR ) {
509 // get properties
510 struct stat s;
511 char *name;
512 if (asprintf(&name, "/home/%s", dir->d_name) == -1)
513 continue;
514 if (stat(name, &s) == -1)
515 continue;
516 if (S_ISLNK(s.st_mode)) {
517 free(name);
518 continue;
519 }
520
521 if (strcmp(name, cfg.homedir) == 0)
522 continue;
523
524// printf("directory %u %u:%u #%s#\n",
525// s.st_mode,
526// s.st_uid,
527// s.st_gid,
528// name);
529
530 // disable directory
531 disable_file(BLACKLIST_FILE, name, emptydir, "not used");
532 free(name);
533 }
534 }
535 closedir(d);
536}
537
538
539
540
541
542
543// build a basic read-only filesystem
544void fs_basic_fs(void) {
545 if (arg_debug)
546 printf("Mounting read-only /bin, /sbin, /lib, /lib64, /usr, /etc, /var\n");
547 fs_rdonly("/bin");
548 fs_rdonly("/sbin");
549 fs_rdonly("/lib");
550 fs_rdonly("/lib64");
551 fs_rdonly("/usr");
552 fs_rdonly("/etc");
553 fs_rdonly("/var");
554
555 // update /var directory in order to support multiple sandboxes running on the same root directory
556 if (!arg_private_dev)
557 fs_dev_shm();
558 fs_var_lock();
559 fs_var_tmp();
560 fs_var_log();
561 fs_var_lib();
562 fs_var_cache();
563 fs_var_utmp();
564
565 // only in user mode
566 if (getuid())
567 sanitize_home();
568}
569
570
571// mount overlayfs on top of / directory
572// mounting an overlay and chrooting into it:
573//
574// Old Ubuntu kernel
575// # cd ~
576// # mkdir -p overlay/root
577// # mkdir -p overlay/diff
578// # mount -t overlayfs -o lowerdir=/,upperdir=/root/overlay/diff overlayfs /root/overlay/root
579// # chroot /root/overlay/root
580// to shutdown, first exit the chroot and then unmount the overlay
581// # exit
582// # umount /root/overlay/root
583//
584// Kernels 3.18+
585// # cd ~
586// # mkdir -p overlay/root
587// # mkdir -p overlay/diff
588// # mkdir -p overlay/work
589// # mount -t overlay -o lowerdir=/,upperdir=/root/overlay/diff,workdir=/root/overlay/work overlay /root/overlay/root
590// # cat /etc/mtab | grep overlay
591// /root/overlay /root/overlay/root overlay rw,relatime,lowerdir=/,upperdir=/root/overlay/diff,workdir=/root/overlay/work 0 0
592// # chroot /root/overlay/root
593// to shutdown, first exit the chroot and then unmount the overlay
594// # exit
595// # umount /root/overlay/root
596
597
598// to do: fix the code below; also, it might work without /dev; impose seccomp/caps filters when not root
599#include <sys/utsname.h>
600void fs_overlayfs(void) {
601 // check kernel version
602 struct utsname u;
603 int rv = uname(&u);
604 if (rv != 0)
605 errExit("uname");
606 int major;
607 int minor;
608 if (2 != sscanf(u.release, "%d.%d", &major, &minor)) {
609 fprintf(stderr, "Error: cannot extract Linux kernel version: %s\n", u.version);
610 exit(1);
611 }
612
613 if (arg_debug)
614 printf("Linux kernel version %d.%d\n", major, minor);
615 int oldkernel = 0;
616 if (major < 3) {
617 fprintf(stderr, "Error: minimum kernel version required 3.x\n");
618 exit(1);
619 }
620 if (major == 3 && minor < 18)
621 oldkernel = 1;
622
623 // build overlay directories
624 fs_build_mnt_dir();
625
626 char *oroot;
627 if(asprintf(&oroot, "%s/oroot", MNT_DIR) == -1)
628 errExit("asprintf");
629 if (mkdir(oroot, S_IRWXU | S_IRWXG | S_IRWXO))
630 errExit("mkdir");
631 if (chown(oroot, 0, 0) < 0)
632 errExit("chown");
633 if (chmod(oroot, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0)
634 errExit("chmod");
635
636 char *odiff;
637 if(asprintf(&odiff, "%s/odiff", MNT_DIR) == -1)
638 errExit("asprintf");
639 if (mkdir(odiff, S_IRWXU | S_IRWXG | S_IRWXO))
640 errExit("mkdir");
641 if (chown(odiff, 0, 0) < 0)
642 errExit("chown");
643 if (chmod(odiff, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0)
644 errExit("chmod");
645
646 char *owork;
647 if(asprintf(&owork, "%s/owork", MNT_DIR) == -1)
648 errExit("asprintf");
649 if (mkdir(owork, S_IRWXU | S_IRWXG | S_IRWXO))
650 errExit("mkdir");
651 if (chown(owork, 0, 0) < 0)
652 errExit("chown");
653 if (chmod(owork, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0)
654 errExit("chmod");
655
656 // mount overlayfs
657 if (arg_debug)
658 printf("Mounting OverlayFS\n");
659 char *option;
660 if (oldkernel) { // old Ubuntu/OpenSUSE kernels
661 if (asprintf(&option, "lowerdir=/,upperdir=%s", odiff) == -1)
662 errExit("asprintf");
663 if (mount("overlayfs", oroot, "overlayfs", MS_MGC_VAL, option) < 0)
664 errExit("mounting overlayfs");
665 }
666 else { // kernel 3.18 or newer
667 if (asprintf(&option, "lowerdir=/,upperdir=%s,workdir=%s", odiff, owork) == -1)
668 errExit("asprintf");
669 if (mount("overlay", oroot, "overlay", MS_MGC_VAL, option) < 0)
670 errExit("mounting overlayfs");
671 }
672
673 // mount-bind dev directory
674 if (arg_debug)
675 printf("Mounting /dev\n");
676 char *dev;
677 if (asprintf(&dev, "%s/dev", oroot) == -1)
678 errExit("asprintf");
679 if (mount("/dev", dev, NULL, MS_BIND|MS_REC, NULL) < 0)
680 errExit("mounting /dev");
681
682 // chroot in the new filesystem
683 if (chroot(oroot) == -1)
684 errExit("chroot");
685 // update /var directory in order to support multiple sandboxes running on the same root directory
686 if (!arg_private_dev)
687 fs_dev_shm();
688 fs_var_lock();
689 fs_var_tmp();
690 fs_var_log();
691 fs_var_lib();
692 fs_var_cache();
693 fs_var_utmp();
694
695 // only in user mode
696 if (getuid())
697 sanitize_home();
698
699 // cleanup and exit
700 free(option);
701 free(oroot);
702 free(odiff);
703}
704
705
706
707#ifdef HAVE_CHROOT
708// return 1 if error
709int fs_check_chroot_dir(const char *rootdir) {
710 assert(rootdir);
711 struct stat s;
712 char *name;
713
714 // check /dev
715 if (asprintf(&name, "%s/dev", rootdir) == -1)
716 errExit("asprintf");
717 if (stat(name, &s) == -1) {
718 fprintf(stderr, "Error: cannot find /dev in chroot directory\n");
719 return 1;
720 }
721 free(name);
722
723 // check /var/tmp
724 if (asprintf(&name, "%s/var/tmp", rootdir) == -1)
725 errExit("asprintf");
726 if (stat(name, &s) == -1) {
727 fprintf(stderr, "Error: cannot find /var/tmp in chroot directory\n");
728 return 1;
729 }
730 free(name);
731
732 // check /proc
733 if (asprintf(&name, "%s/proc", rootdir) == -1)
734 errExit("asprintf");
735 if (stat(name, &s) == -1) {
736 fprintf(stderr, "Error: cannot find /proc in chroot directory\n");
737 return 1;
738 }
739 free(name);
740
741 // check /proc
742 if (asprintf(&name, "%s/tmp", rootdir) == -1)
743 errExit("asprintf");
744 if (stat(name, &s) == -1) {
745 fprintf(stderr, "Error: cannot find /tmp in chroot directory\n");
746 return 1;
747 }
748 free(name);
749
750 // check /bin/bash
751 if (asprintf(&name, "%s/bin/bash", rootdir) == -1)
752 errExit("asprintf");
753 if (stat(name, &s) == -1) {
754 fprintf(stderr, "Error: cannot find /bin/bash in chroot directory\n");
755 return 1;
756 }
757 free(name);
758
759 return 0;
760}
761
762// chroot into an existing directory; mount exiting /dev and update /etc/resolv.conf
763void fs_chroot(const char *rootdir) {
764 assert(rootdir);
765
766 //***********************************
767 // mount-bind a /dev in rootdir
768 //***********************************
769 // mount /dev
770 char *newdev;
771 if (asprintf(&newdev, "%s/dev", rootdir) == -1)
772 errExit("asprintf");
773 if (arg_debug)
774 printf("Mounting /dev on %s\n", newdev);
775 if (mount("/dev", newdev, NULL, MS_BIND|MS_REC, NULL) < 0)
776 errExit("mounting /dev");
777
778 // some older distros don't have a /run directory
779 // create one by default
780 // no exit on error, let the user deal with any problems
781 char *rundir;
782 if (asprintf(&rundir, "%s/run", rootdir) == -1)
783 errExit("asprintf");
784 if (!is_dir(rundir)) {
785 int rv = mkdir(rundir, S_IRWXU | S_IRWXG | S_IRWXO);
786 (void) rv;
787 rv = chown(rundir, 0, 0);
788 (void) rv;
789 }
790
791 // copy /etc/resolv.conf in chroot directory
792 // if resolv.conf in chroot is a symbolic link, this will fail
793 // no exit on error, let the user deal with the problem
794 char *fname;
795 if (asprintf(&fname, "%s/etc/resolv.conf", rootdir) == -1)
796 errExit("asprintf");
797 if (arg_debug)
798 printf("Updating /etc/resolv.conf in %s\n", fname);
799 if (copy_file("/etc/resolv.conf", fname) == -1)
800 fprintf(stderr, "Warning: /etc/resolv.conf not initialized\n");
801
802 // chroot into the new directory
803 if (arg_debug)
804 printf("Chrooting into %s\n", rootdir);
805 if (chroot(rootdir) < 0)
806 errExit("chroot");
807
808 // update /var directory in order to support multiple sandboxes running on the same root directory
809 if (!arg_private_dev)
810 fs_dev_shm();
811 fs_var_lock();
812 fs_var_tmp();
813 fs_var_log();
814 fs_var_lib();
815 fs_var_cache();
816 fs_var_utmp();
817
818 // only in user mode
819 if (getuid())
820 sanitize_home();
821
822}
823#endif
824
825
diff --git a/src/firejail/fs_dev.c b/src/firejail/fs_dev.c
new file mode 100644
index 000000000..80bd11582
--- /dev/null
+++ b/src/firejail/fs_dev.c
@@ -0,0 +1,163 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
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#include "firejail.h"
21#include <sys/mount.h>
22#include <sys/stat.h>
23#include <linux/limits.h>
24#include <glob.h>
25#include <dirent.h>
26#include <fcntl.h>
27#include <pwd.h>
28#ifndef _BSD_SOURCE
29#define _BSD_SOURCE
30#endif
31#include <sys/types.h>
32
33static void create_char_dev(const char *path, mode_t mode, int major, int minor) {
34 dev_t dev = makedev(major, minor);
35 int rv = mknod(path, S_IFCHR | mode, dev);
36 if (rv == -1)
37 goto errexit;
38
39
40 if (chmod(path, mode) < 0)
41 goto errexit;
42 if (chown(path, 0, 0) < 0)
43 goto errexit;
44
45 return;
46
47errexit:
48 fprintf(stderr, "Error: cannot create %s device\n", path);
49 exit(1);
50}
51
52static void create_link(const char *oldpath, const char *newpath) {
53 if (symlink(oldpath, newpath) == -1)
54 goto errexit;
55 if (chown(newpath, 0, 0) < 0)
56 goto errexit;
57 return;
58
59errexit:
60 fprintf(stderr, "Error: cannot create %s device\n", newpath);
61 exit(1);
62}
63
64void fs_private_dev(void){
65 // install a new /dev directory
66 if (arg_debug)
67 printf("Mounting tmpfs on /dev\n");
68 if (mount("tmpfs", "/dev", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=777,gid=0") < 0)
69 errExit("mounting /dev");
70
71 // create /dev/shm
72 if (arg_debug)
73 printf("Create /dev/shm directory\n");
74 int rv = mkdir("/dev/shm", S_IRWXU | S_IRWXG | S_IRWXO);
75 if (rv == -1)
76 errExit("mkdir");
77 if (chown("/dev/shm", 0, 0) < 0)
78 errExit("chown");
79 if (chmod("/dev/shm", S_IRWXU | S_IRWXG | S_IRWXO) < 0)
80 errExit("chmod");
81
82 // create devices
83 create_char_dev("/dev/zero", 0666, 1, 5); // mknod -m 666 /dev/zero c 1 5
84 create_char_dev("/dev/null", 0666, 1, 3); // mknod -m 666 /dev/null c 1 3
85 create_char_dev("/dev/full", 0666, 1, 7); // mknod -m 666 /dev/full c 1 7
86 create_char_dev("/dev/random", 0666, 1, 8); // Mknod -m 666 /dev/random c 1 8
87 create_char_dev("/dev/urandom", 0666, 1, 9); // mknod -m 666 /dev/urandom c 1 9
88 create_char_dev("/dev/tty", 0666, 5, 0); // mknod -m 666 /dev/tty c 5 0
89#if 0
90 create_dev("/dev/tty0", "mknod -m 666 /dev/tty0 c 4 0");
91 create_dev("/dev/console", "mknod -m 622 /dev/console c 5 1");
92#endif
93
94 // pseudo-terminal
95 rv = mkdir("/dev/pts", 0755);
96 if (rv == -1)
97 errExit("mkdir");
98 if (chown("/dev/pts", 0, 0) < 0)
99 errExit("chown");
100 if (chmod("/dev/pts", 0755) < 0)
101 errExit("chmod");
102 create_char_dev("/dev/pts/ptmx", 0666, 5, 2); //"mknod -m 666 /dev/pts/ptmx c 5 2");
103 create_link("/dev/pts/ptmx", "/dev/ptmx");
104 // mount -vt devpts -o newinstance -o ptmxmode=0666 devpts //dev/pts
105 if (mount("devpts", "/dev/pts", "devpts", MS_MGC_VAL, "newinstance,ptmxmode=0666") < 0)
106 errExit("mounting /dev/pts");
107
108#if 0
109 // stdin, stdout, stderr
110 create_link("/proc/self/fd", "/dev/fd");
111 create_link("/proc/self/fd/0", "/dev/stdin");
112 create_link("/proc/self/fd/1", "/dev/stdout");
113 create_link("/proc/self/fd/2", "/dev/stderr");
114#endif
115}
116
117
118void fs_dev_shm(void) {
119 uid_t uid = getuid(); // set a new shm only if we started as root
120 if (uid)
121 return;
122
123 if (is_dir("/dev/shm")) {
124 if (arg_debug)
125 printf("Mounting tmpfs on /dev/shm\n");
126 if (mount("tmpfs", "/dev/shm", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=777,gid=0") < 0)
127 errExit("mounting /dev/shm");
128 }
129 else {
130 char *lnk = get_link("/dev/shm");
131 if (lnk) {
132 // convert a link such as "../shm" into "/shm"
133 char *lnk2 = lnk;
134 int cnt = 0;
135 while (strncmp(lnk2, "../", 3) == 0) {
136 cnt++;
137 lnk2 = lnk2 + 3;
138 }
139 if (cnt != 0)
140 lnk2 = lnk + (cnt - 1) * 3 + 2;
141
142 if (!is_dir(lnk2)) {
143 // create directory
144 if (mkdir(lnk2, S_IRWXU|S_IRWXG|S_IRWXO))
145 errExit("mkdir");
146 if (chown(lnk2, 0, 0))
147 errExit("chown");
148 if (chmod(lnk2, S_IRWXU|S_IRWXG|S_IRWXO))
149 errExit("chmod");
150 }
151 if (arg_debug)
152 printf("Mounting tmpfs on %s on behalf of /dev/shm\n", lnk2);
153 if (mount("tmpfs", lnk2, "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=777,gid=0") < 0)
154 errExit("mounting /var/tmp");
155 free(lnk);
156 }
157 else {
158 fprintf(stderr, "Warning: /dev/shm not mounted\n");
159 dbg_test_dir("/dev/shm");
160 }
161
162 }
163}
diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c
new file mode 100644
index 000000000..853e3930b
--- /dev/null
+++ b/src/firejail/fs_home.c
@@ -0,0 +1,494 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
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#include "firejail.h"
21#include <sys/mount.h>
22#include <linux/limits.h>
23#include <glob.h>
24#include <dirent.h>
25#include <fcntl.h>
26#include <sys/stat.h>
27#include <sys/types.h>
28#include <sys/wait.h>
29#include <unistd.h>
30#include <grp.h>
31
32static void skel(const char *homedir, uid_t u, gid_t g) {
33 char *fname;
34 // zsh
35 if (arg_zsh) {
36 // copy skel files
37 if (asprintf(&fname, "%s/.zshrc", homedir) == -1)
38 errExit("asprintf");
39 struct stat s;
40 // don't copy it if we already have the file
41 if (stat(fname, &s) == 0)
42 return;
43 if (stat("/etc/skel/.zshrc", &s) == 0) {
44 if (copy_file("/etc/skel/.zshrc", fname) == 0) {
45 if (chown(fname, u, g) == -1)
46 errExit("chown");
47 }
48 }
49 else { //
50 FILE *fp = fopen(fname, "w");
51 if (fp) {
52 fprintf(fp, "\n");
53 fclose(fp);
54 if (chown(fname, u, g) == -1)
55 errExit("chown");
56 if (chmod(fname, S_IRUSR | S_IWUSR) < 0)
57 errExit("chown");
58 }
59 }
60 free(fname);
61 }
62 // csh
63 else if (arg_csh) {
64 // copy skel files
65 if (asprintf(&fname, "%s/.cshrc", homedir) == -1)
66 errExit("asprintf");
67 struct stat s;
68 // don't copy it if we already have the file
69 if (stat(fname, &s) == 0)
70 return;
71 if (stat("/etc/skel/.cshrc", &s) == 0) {
72 if (copy_file("/etc/skel/.cshrc", fname) == 0) {
73 if (chown(fname, u, g) == -1)
74 errExit("chown");
75 }
76 }
77 else { //
78 /* coverity[toctou] */
79 FILE *fp = fopen(fname, "w");
80 if (fp) {
81 fprintf(fp, "\n");
82 fclose(fp);
83 if (chown(fname, u, g) == -1)
84 errExit("chown");
85 if (chmod(fname, S_IRUSR | S_IWUSR) < 0)
86 errExit("chown");
87 }
88 }
89 free(fname);
90 }
91 // bash etc.
92 else {
93 // copy skel files
94 if (asprintf(&fname, "%s/.bashrc", homedir) == -1)
95 errExit("asprintf");
96 struct stat s;
97 // don't copy it if we already have the file
98 if (stat(fname, &s) == 0)
99 return;
100 if (stat("/etc/skel/.bashrc", &s) == 0) {
101 if (copy_file("/etc/skel/.bashrc", fname) == 0) {
102 /* coverity[toctou] */
103 if (chown(fname, u, g) == -1)
104 errExit("chown");
105 }
106 }
107 free(fname);
108 }
109}
110
111static int store_xauthority(void) {
112 // put a copy of .Xauthority in MNT_DIR
113 fs_build_mnt_dir();
114
115 char *src;
116 char *dest;
117 if (asprintf(&src, "%s/.Xauthority", cfg.homedir) == -1)
118 errExit("asprintf");
119 if (asprintf(&dest, "%s/.Xauthority", MNT_DIR) == -1)
120 errExit("asprintf");
121
122 struct stat s;
123 if (stat(src, &s) == 0) {
124 int rv = copy_file(src, dest);
125 if (rv) {
126 fprintf(stderr, "Warning: cannot transfer .Xauthority in private home directory\n");
127 return 0;
128 }
129 return 1; // file copied
130 }
131
132 return 0;
133}
134
135static void copy_xauthority(void) {
136 // put a copy of .Xauthority in MNT_DIR
137 fs_build_mnt_dir();
138
139 char *src;
140 char *dest;
141 if (asprintf(&dest, "%s/.Xauthority", cfg.homedir) == -1)
142 errExit("asprintf");
143 if (asprintf(&src, "%s/.Xauthority", MNT_DIR) == -1)
144 errExit("asprintf");
145 int rv = copy_file(src, dest);
146 if (rv)
147 fprintf(stderr, "Warning: cannot transfer .Xauthority in private home directory\n");
148
149 // set permissions and ownership
150 if (chown(dest, getuid(), getgid()) < 0)
151 errExit("chown");
152 if (chmod(dest, S_IRUSR | S_IWUSR) < 0)
153 errExit("chmod");
154
155 // delete the temporary file
156 unlink(src);
157}
158
159// private mode (--private=homedir):
160// mount homedir on top of /home/user,
161// tmpfs on top of /root in nonroot mode,
162// tmpfs on top of /tmp in root mode,
163// set skel files,
164// restore .Xauthority
165void fs_private_homedir(void) {
166 char *homedir = cfg.homedir;
167 char *private_homedir = cfg.home_private;
168 assert(homedir);
169 assert(private_homedir);
170
171 int xflag = store_xauthority();
172
173 uid_t u = getuid();
174 gid_t g = getgid();
175 struct stat s;
176 if (stat(homedir, &s) == -1) {
177 fprintf(stderr, "Error: cannot find user home directory\n");
178 exit(1);
179 }
180
181
182 // mount bind private_homedir on top of homedir
183 if (arg_debug)
184 printf("Mount-bind %s on top of %s\n", private_homedir, homedir);
185 if (mount(private_homedir, homedir, NULL, MS_BIND|MS_REC, NULL) < 0)
186 errExit("mount bind");
187// preserve mode and ownership
188// if (chown(homedir, s.st_uid, s.st_gid) == -1)
189// errExit("mount-bind chown");
190// if (chmod(homedir, s.st_mode) == -1)
191// errExit("mount-bind chmod");
192
193 if (u != 0) {
194 // mask /root
195 if (arg_debug)
196 printf("Mounting a new /root directory\n");
197 if (mount("tmpfs", "/root", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=700,gid=0") < 0)
198 errExit("mounting home directory");
199 }
200 else {
201 // mask /home
202 if (arg_debug)
203 printf("Mounting a new /home directory\n");
204 if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
205 errExit("mounting home directory");
206
207 // mask /tmp only in root mode; KDE keeps all kind of sockets in /tmp!
208 if (arg_debug)
209 printf("Mounting a new /tmp directory\n");
210 if (mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=777,gid=0") < 0)
211 errExit("mounting tmp directory");
212 }
213
214
215 skel(homedir, u, g);
216 if (xflag)
217 copy_xauthority();
218}
219
220// private mode (--private):
221// mount tmpfs over /home/user,
222// tmpfs on top of /root in nonroot mode,
223// tmpfs on top of /tmp in root mode
224// set skel files,
225// restore .Xauthority
226void fs_private(void) {
227 char *homedir = cfg.homedir;
228 assert(homedir);
229 uid_t u = getuid();
230 gid_t g = getgid();
231
232 int xflag = store_xauthority();
233
234 // mask /home
235 if (arg_debug)
236 printf("Mounting a new /home directory\n");
237 if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
238 errExit("mounting home directory");
239
240 // mask /root
241 if (arg_debug)
242 printf("Mounting a new /root directory\n");
243 if (mount("tmpfs", "/root", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=700,gid=0") < 0)
244 errExit("mounting home directory");
245
246 if (u != 0) {
247 // create /home/user
248 if (arg_debug)
249 printf("Create a new user directory\n");
250 int rv = mkdir(homedir, S_IRWXU);
251 if (rv == -1)
252 errExit("mkdir");
253 if (chown(homedir, u, g) < 0)
254 errExit("chown");
255 }
256 else {
257 // mask tmp only in root mode; KDE keeps all kind of sockets in /tmp!
258 if (arg_debug)
259 printf("Mounting a new /tmp directory\n");
260 if (mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=777,gid=0") < 0)
261 errExit("mounting tmp directory");
262 }
263
264 skel(homedir, u, g);
265 if (xflag)
266 copy_xauthority();
267}
268
269static void check_dir_or_file(const char *name) {
270 assert(name);
271 struct stat s;
272 char *fname;
273 if (asprintf(&fname, "%s/%s", cfg.homedir, name) == -1)
274 errExit("asprintf");
275 if (arg_debug)
276 printf("***************Checking %s\n", fname);
277 if (stat(fname, &s) == -1) {
278 fprintf(stderr, "Error: file %s not found.\n", fname);
279 exit(1);
280 }
281
282 // check uid
283 uid_t uid = getuid();
284 gid_t gid = getgid();
285 if (s.st_uid != uid || s.st_gid != gid) {
286 fprintf(stderr, "Error: only files or directories created by the current user are allowed.\n");
287 exit(1);
288 }
289
290 // dir or regular file
291 if (S_ISDIR(s.st_mode) || S_ISREG(s.st_mode)) {
292 free(fname);
293 return;
294 }
295
296 if (!is_link(fname)) {
297 free(fname);
298 return;
299 }
300
301 fprintf(stderr, "Error: invalid file type, %s.\n", fname);
302 exit(1);
303}
304
305// check directory linst specified by user (--private.keep option) - exit if it fails
306void fs_check_home_list(void) {
307 if (strstr(cfg.home_private_keep, "..")) {
308 fprintf(stderr, "Error: invalid private.keep list\n");
309 exit(1);
310 }
311
312 char *dlist = strdup(cfg.home_private_keep);
313 if (!dlist)
314 errExit("strdup");
315
316 char *ptr = strtok(dlist, ",");
317 check_dir_or_file(ptr);
318 while ((ptr = strtok(NULL, ",")) != NULL)
319 check_dir_or_file(ptr);
320
321 free(dlist);
322}
323
324// check new private home directory (--private= option) - exit if it fails
325void fs_check_private_dir(void) {
326 // if the directory starts with ~, expand the home directory
327 if (*cfg.home_private == '~') {
328 char *tmp;
329 if (asprintf(&tmp, "%s%s", cfg.homedir, cfg.home_private + 1) == -1)
330 errExit("asprintf");
331 cfg.home_private = tmp;
332 }
333
334 if (!is_dir(cfg.home_private) || is_link(cfg.home_private) || strstr(cfg.home_private, "..")) {
335 fprintf(stderr, "Error: invalid private directory\n");
336 exit(1);
337 }
338
339 // check home directory and chroot home directory have the same owner
340 struct stat s2;
341 int rv = stat(cfg.home_private, &s2);
342 if (rv < 0) {
343 fprintf(stderr, "Error: cannot find %s directory\n", cfg.home_private);
344 exit(1);
345 }
346
347 struct stat s1;
348 rv = stat(cfg.homedir, &s1);
349 if (rv < 0) {
350 fprintf(stderr, "Error: cannot find %s directory, full path name required\n", cfg.homedir);
351 exit(1);
352 }
353 if (s1.st_uid != s2.st_uid) {
354 printf("Error: the two home directories must have the same owner\n");
355 exit(1);
356 }
357}
358
359#if 0
360static int mkpath(char* file_path, mode_t mode) {
361 assert(file_path && *file_path);
362 char* p;
363 for (p=strchr(file_path+1, '/'); p; p=strchr(p+1, '/')) {
364 *p='\0';
365 if (mkdir(file_path, mode)==-1) {
366 if (errno!=EEXIST) { *p='/'; return -1; }
367 }
368 *p='/';
369 }
370 return 0;
371}
372#endif
373
374static void duplicate(char *fname) {
375 char *cmd;
376
377 // copy the file
378 if (asprintf(&cmd, "cp -a --parents %s/%s %s", cfg.homedir, fname, HOME_DIR) == -1)
379 errExit("asprintf");
380 if (arg_debug)
381 printf("%s\n", cmd);
382 if (system(cmd))
383 errExit("system cp -a --parents");
384 free(cmd);
385}
386
387
388// private mode (--private.keep=list):
389// mount homedir on top of /home/user,
390// tmpfs on top of /root in nonroot mode,
391// tmpfs on top of /tmp in root mode,
392// set skel files,
393// restore .Xauthority
394void fs_private_home_list(void) {
395 char *homedir = cfg.homedir;
396 char *private_list = cfg.home_private_keep;
397 assert(homedir);
398 assert(private_list);
399
400 int xflag = store_xauthority();
401
402 uid_t u = getuid();
403 gid_t g = getgid();
404 struct stat s;
405 if (stat(homedir, &s) == -1) {
406 fprintf(stderr, "Error: cannot find user home directory\n");
407 exit(1);
408 }
409
410 // create /tmp/firejail/mnt/home directory
411 fs_build_mnt_dir();
412 int rv = mkdir(HOME_DIR, S_IRWXU | S_IRWXG | S_IRWXO);
413 if (rv == -1)
414 errExit("mkdir");
415 if (chown(HOME_DIR, u, g) < 0)
416 errExit("chown");
417 if (chmod(HOME_DIR, 0755) < 0)
418 errExit("chmod");
419
420 // copy the list of files in the new home directory
421 // using a new child process without root privileges
422 pid_t child = fork();
423 if (child < 0)
424 errExit("fork");
425 if (child == 0) {
426 if (arg_debug)
427 printf("Copying files in the new home:\n");
428
429 // drop privileges
430 if (setgroups(0, NULL) < 0)
431 errExit("setgroups");
432 if (setgid(getgid()) < 0)
433 errExit("setgid/getgid");
434 if (setuid(getuid()) < 0)
435 errExit("setuid/getuid");
436
437 // copy the list of files in the new home directory
438 char *dlist = strdup(cfg.home_private_keep);
439 if (!dlist)
440 errExit("strdup");
441
442 char *ptr = strtok(dlist, ",");
443 duplicate(ptr);
444
445 while ((ptr = strtok(NULL, ",")) != NULL)
446 duplicate(ptr);
447 free(dlist);
448 exit(0);
449 }
450 // wait for the child to finish
451 waitpid(child, NULL, 0);
452
453 // mount bind private_homedir on top of homedir
454 char *newhome;
455 if (asprintf(&newhome, "%s%s", HOME_DIR, cfg.homedir) == -1)
456 errExit("asprintf");
457
458 if (arg_debug)
459 printf("Mount-bind %s on top of %s\n", newhome, homedir);
460 if (mount(newhome, homedir, NULL, MS_BIND|MS_REC, NULL) < 0)
461 errExit("mount bind");
462// preserve mode and ownership
463// if (chown(homedir, s.st_uid, s.st_gid) == -1)
464// errExit("mount-bind chown");
465// if (chmod(homedir, s.st_mode) == -1)
466// errExit("mount-bind chmod");
467
468 if (u != 0) {
469 // mask /root
470 if (arg_debug)
471 printf("Mounting a new /root directory\n");
472 if (mount("tmpfs", "/root", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=700,gid=0") < 0)
473 errExit("mounting home directory");
474 }
475 else {
476 // mask /home
477 if (arg_debug)
478 printf("Mounting a new /home directory\n");
479 if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
480 errExit("mounting home directory");
481
482 // mask /tmp only in root mode; KDE keeps all kind of sockets in /tmp!
483 if (arg_debug)
484 printf("Mounting a new /tmp directory\n");
485 if (mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=777,gid=0") < 0)
486 errExit("mounting tmp directory");
487 }
488
489 skel(homedir, u, g);
490 if (xflag)
491 copy_xauthority();
492
493}
494
diff --git a/src/firejail/fs_hostname.c b/src/firejail/fs_hostname.c
new file mode 100644
index 000000000..fb3fc530e
--- /dev/null
+++ b/src/firejail/fs_hostname.c
@@ -0,0 +1,157 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
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#include "firejail.h"
21#include <sys/mount.h>
22#include <sys/stat.h>
23#include <linux/limits.h>
24#include <glob.h>
25#include <dirent.h>
26#include <fcntl.h>
27
28void fs_hostname(const char *hostname) {
29 struct stat s;
30 fs_build_mnt_dir();
31
32 // create a new /etc/hostname
33 if (stat("/etc/hostname", &s) == 0) {
34 if (arg_debug)
35 printf("Creating a new /etc/hostname file\n");
36 char *fhost;
37 if (asprintf(&fhost, "%s/hostname", MNT_DIR) == -1)
38 errExit("asprintf");
39 FILE *fp = fopen(fhost, "w");
40 if (!fp) {
41 fprintf(stderr, "Error: cannot create %s\n", fhost);
42 free(fhost);
43 exit(1);
44 }
45 fprintf(fp, "%s\n", hostname);
46 fclose(fp);
47
48 // mode and owner
49 if (chown(fhost, 0, 0) < 0)
50 errExit("chown");
51 if (chmod(fhost, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH ) < 0)
52 errExit("chmod");
53
54 // bind-mount the file on top of /etc/hostname
55 if (mount(fhost, "/etc/hostname", NULL, MS_BIND|MS_REC, NULL) < 0)
56 errExit("mount bind /etc/hostname");
57 free(fhost);
58 }
59
60 // create a new /etc/hosts
61 if (stat("/etc/hosts", &s) == 0) {
62 if (arg_debug)
63 printf("Creating a new /etc/hosts file\n");
64 char *fhost;
65 if (asprintf(&fhost, "%s/hosts", MNT_DIR) == -1)
66 errExit("asprintf");
67 // copy /etc/host into our new file, and modify it on the fly
68 /* coverity[toctou] */
69 FILE *fp1 = fopen("/etc/hosts", "r");
70 if (!fp1) {
71 fprintf(stderr, "Error: cannot open /etc/hosts\n");
72 free(fhost);
73 exit(1);
74 }
75 FILE *fp2 = fopen(fhost, "w");
76 if (!fp2) {
77 fprintf(stderr, "Error: cannot create %s\n", fhost);
78 free(fhost);
79 exit(1);
80 }
81
82 char buf[4096];
83 while (fgets(buf, sizeof(buf), fp1)) {
84 // remove '\n'
85 char *ptr = strchr(buf, '\n');
86 if (ptr)
87 *ptr = '\0';
88
89 // copy line
90 if (strstr(buf, "127.0.0.1"))
91 fprintf(fp2, "%s %s\n", buf, hostname);
92 else
93 fprintf(fp2, "%s\n", buf);
94 }
95 fclose(fp1);
96 fclose(fp2);
97
98 // mode and owner
99 if (chown(fhost, 0, 0) < 0)
100 errExit("chown");
101 if (chmod(fhost, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH ) < 0)
102 errExit("chmod");
103
104 // bind-mount the file on top of /etc/hostname
105 if (mount(fhost, "/etc/hosts", NULL, MS_BIND|MS_REC, NULL) < 0)
106 errExit("mount bind /etc/hosts");
107 free(fhost);
108 }
109}
110
111void fs_resolvconf(void) {
112 if (cfg.dns1 == 0)
113 return;
114
115 struct stat s;
116 fs_build_mnt_dir();
117
118 // create a new /etc/hostname
119 if (stat("/etc/resolv.conf", &s) == 0) {
120 if (arg_debug)
121 printf("Creating a new /etc/resolv.conf file\n");
122 char *fname;
123 if (asprintf(&fname, "%s/resolv.conf", MNT_DIR) == -1)
124 errExit("asprintf");
125 FILE *fp = fopen(fname, "w");
126 if (!fp) {
127 fprintf(stderr, "Error: cannot create %s\n", fname);
128 free(fname);
129 exit(1);
130 }
131
132 if (cfg.dns1)
133 fprintf(fp, "nameserver %d.%d.%d.%d\n", PRINT_IP(cfg.dns1));
134 if (cfg.dns2)
135 fprintf(fp, "nameserver %d.%d.%d.%d\n", PRINT_IP(cfg.dns2));
136 if (cfg.dns3)
137 fprintf(fp, "nameserver %d.%d.%d.%d\n", PRINT_IP(cfg.dns3));
138 fclose(fp);
139
140 // mode and owner
141 if (chown(fname, 0, 0) < 0)
142 errExit("chown");
143 if (chmod(fname, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH ) < 0)
144 errExit("chmod");
145
146 // bind-mount the file on top of /etc/hostname
147 if (mount(fname, "/etc/resolv.conf", NULL, MS_BIND|MS_REC, NULL) < 0)
148 errExit("mount bind /etc/resolv.conf");
149 free(fname);
150 }
151 else {
152 fprintf(stderr, "Error: cannot set DNS servers, /etc/resolv.conf file is missing\n");
153 exit(1);
154 }
155}
156
157
diff --git a/src/firejail/fs_trace.c b/src/firejail/fs_trace.c
new file mode 100644
index 000000000..1c7ef5cbe
--- /dev/null
+++ b/src/firejail/fs_trace.c
@@ -0,0 +1,76 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
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#include "firejail.h"
21#include <sys/mount.h>
22#include <sys/stat.h>
23#include <linux/limits.h>
24#include <glob.h>
25#include <dirent.h>
26#include <fcntl.h>
27#include <pwd.h>
28
29void fs_trace_preload(void) {
30 struct stat s;
31
32 // create an empty /etc/ld.so.preload
33 if (stat("/etc/ld.so.preload", &s)) {
34 if (arg_debug)
35 printf("Creating an empty /etc/ld.so.preload file\n");
36 /* coverity[toctou] */
37 FILE *fp = fopen("/etc/ld.so.preload", "w");
38 if (!fp)
39 errExit("fopen");
40 fclose(fp);
41 if (chown("/etc/ld.so.preload", 0, 0) < 0)
42 errExit("chown");
43 if (chmod("/etc/ld.so.preload", S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH ) < 0)
44 errExit("chmod");
45 }
46}
47
48void fs_trace(void) {
49 // create /tmp/firejail/mnt directory
50 fs_build_mnt_dir();
51
52 // create the new ld.so.preload file and mount-bind it
53 if (arg_debug)
54 printf("Create the new ld.so.preload file\n");
55 char *preload;
56 if (asprintf(&preload, "%s/ld.so.preload", MNT_DIR) == -1)
57 errExit("asprintf");
58 FILE *fp = fopen(preload, "w");
59 if (!fp)
60 errExit("fopen");
61 fprintf(fp, "%s/lib/firejail/libtrace.so\n", PREFIX);
62 fclose(fp);
63 if (chown(preload, 0, 0) < 0)
64 errExit("chown");
65 if (chmod(preload, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH ) < 0)
66 errExit("chmod");
67
68 // mount the new preload file
69 if (arg_debug)
70 printf("Mount the new ld.so.preload file\n");
71 if (mount(preload, "/etc/ld.so.preload", NULL, MS_BIND|MS_REC, NULL) < 0)
72 errExit("mount bind ls.so.preload");
73}
74
75
76 \ No newline at end of file
diff --git a/src/firejail/fs_var.c b/src/firejail/fs_var.c
new file mode 100644
index 000000000..ee0f81828
--- /dev/null
+++ b/src/firejail/fs_var.c
@@ -0,0 +1,388 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
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#include "firejail.h"
21#include <sys/mount.h>
22#include <sys/stat.h>
23#include <linux/limits.h>
24#include <glob.h>
25#include <dirent.h>
26#include <fcntl.h>
27#include <pwd.h>
28#include <utmp.h>
29#include <time.h>
30
31typedef struct dirdata_t{
32 struct dirdata_t *next;
33 char *name;
34 mode_t st_mode;
35 uid_t st_uid;
36 gid_t st_gid;
37} DirData;
38
39static DirData *dirlist = NULL;
40
41static void release_all(void) {
42 DirData *ptr = dirlist;
43 while (ptr) {
44 DirData *next = ptr->next;
45 free(ptr->name);
46 free(ptr);
47 ptr = next;
48 }
49 dirlist = NULL;
50}
51
52static void build_list(const char *srcdir) {
53 // extract current /var/log directory data
54 struct dirent *dir;
55 DIR *d = opendir(srcdir);
56 if (d == NULL)
57 return;
58
59 while ((dir = readdir(d))) {
60 if(strcmp(dir->d_name, "." ) == 0 || strcmp(dir->d_name, ".." ) == 0)
61 continue;
62
63 if (dir->d_type == DT_DIR ) {
64 // get properties
65 struct stat s;
66 char *name;
67 if (asprintf(&name, "%s/%s", srcdir, dir->d_name) == -1)
68 continue;
69 if (stat(name, &s) == -1)
70 continue;
71 if (S_ISLNK(s.st_mode)) {
72 free(name);
73 continue;
74 }
75
76// printf("directory %u %u:%u %s\n",
77// s.st_mode,
78// s.st_uid,
79// s.st_gid,
80// dir->d_name);
81
82 DirData *ptr = malloc(sizeof(DirData));
83 if (ptr == NULL)
84 errExit("malloc");
85 memset(ptr, 0, sizeof(DirData));
86 ptr->name = name;
87 ptr->st_mode = s.st_mode;
88 ptr->st_uid = s.st_uid;
89 ptr->st_gid = s.st_gid;
90 ptr->next = dirlist;
91 dirlist = ptr;
92 }
93 }
94 closedir(d);
95}
96
97static void build_dirs(void) {
98 // create directories under /var/log
99 DirData *ptr = dirlist;
100 while (ptr) {
101 if (mkdir(ptr->name, ptr->st_mode))
102 errExit("mkdir");
103 if (chown(ptr->name, ptr->st_uid, ptr->st_gid))
104 errExit("chown");
105 ptr = ptr->next;
106 }
107}
108
109void fs_var_log(void) {
110 build_list("/var/log");
111
112 // create /var/log if it does't exit
113 if (is_dir("/var/log")) {
114 // extract group id for /var/log/wtmp
115 struct stat s;
116 gid_t wtmp_group = 0;
117 if (stat("/var/log/wtmp", &s) == 0)
118 wtmp_group = s.st_gid;
119
120 // mount a tmpfs on top of /var/log
121 if (arg_debug)
122 printf("Mounting tmpfs on /var/log\n");
123 if (mount("tmpfs", "/var/log", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
124 errExit("mounting /var/log");
125
126 build_dirs();
127 release_all();
128
129 // create an empty /var/log/wtmp file
130 /* coverity[toctou] */
131 FILE *fp = fopen("/var/log/wtmp", "w");
132 if (fp)
133 fclose(fp);
134 if (chown("/var/log/wtmp", 0, wtmp_group) < 0)
135 errExit("chown");
136 if (chmod("/var/log/wtmp", S_IRUSR | S_IWRITE | S_IRGRP | S_IWGRP | S_IROTH ) < 0)
137 errExit("chmod");
138
139 // create an empty /var/log/btmp file
140 fp = fopen("/var/log/btmp", "w");
141 if (fp)
142 fclose(fp);
143 if (chown("/var/log/btmp", 0, wtmp_group) < 0)
144 errExit("chown");
145 if (chmod("/var/log/btmp", S_IRUSR | S_IWRITE | S_IRGRP | S_IWGRP) < 0)
146 errExit("chmod");
147 }
148 else
149 fprintf(stderr, "Warning: cannot mount tmpfs in top of /var/log\n");
150}
151
152void fs_var_lib(void) {
153 struct stat s;
154
155 // ISC DHCP multiserver
156 if (stat("/var/lib/dhcp", &s) == 0) {
157 if (arg_debug)
158 printf("Mounting tmpfs on /var/lib/dhcp\n");
159 if (mount("tmpfs", "/var/lib/dhcp", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
160 errExit("mounting /var/lib/dhcp");
161
162 // isc dhcp server requires a /var/lib/dhcp/dhcpd.leases file
163 FILE *fp = fopen("/var/lib/dhcp/dhcpd.leases", "w");
164
165 if (fp) {
166 fprintf(fp, "\n");
167 fclose(fp);
168 if (chown("/var/lib/dhcp/dhcpd.leases", 0, 0) == -1)
169 errExit("chown");
170 if (chmod("/var/lib/dhcp/dhcpd.leases", S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH))
171 errExit("chmod");
172 }
173 }
174
175 // nginx multiserver
176 if (stat("/var/lib/nginx", &s) == 0) {
177 if (arg_debug)
178 printf("Mounting tmpfs on /var/lib/nginx\n");
179 if (mount("tmpfs", "/var/lib/nginx", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
180 errExit("mounting /var/lib/nginx");
181 }
182
183 // net-snmp multiserver
184 if (stat("/var/lib/snmp", &s) == 0) {
185 if (arg_debug)
186 printf("Mounting tmpfs on /var/lib/snmp\n");
187 if (mount("tmpfs", "/var/lib/snmp", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
188 errExit("mounting /var/lib/snmp");
189 }
190
191 // this is where sudo remembers its state
192 if (stat("/var/lib/sudo", &s) == 0) {
193 if (arg_debug)
194 printf("Mounting tmpfs on /var/lib/sudo\n");
195 if (mount("tmpfs", "/var/lib/sudo", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
196 errExit("mounting /var/lib/sudo");
197 }
198}
199
200void fs_var_cache(void) {
201 struct stat s;
202
203 if (stat("/var/cache/apache2", &s) == 0) {
204 if (arg_debug)
205 printf("Mounting tmpfs on /var/cache/apache2\n");
206 if (mount("tmpfs", "/var/cache/apache2", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
207 errExit("mounting /var/cahce/apache2");
208 }
209
210 if (stat("/var/cache/lighttpd", &s) == 0) {
211 if (arg_debug)
212 printf("Mounting tmpfs on /var/cache/lighttpd\n");
213 if (mount("tmpfs", "/var/cache/lighttpd", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
214 errExit("mounting /var/cache/lighttpd");
215
216 struct passwd *p = getpwnam("www-data");
217 uid_t uid = 0;
218 gid_t gid = 0;
219 if (p) {
220 uid = p->pw_uid;
221 gid = p->pw_gid;
222 }
223
224 int rv = mkdir("/var/cache/lighttpd/compress", S_IRWXU | S_IRWXG | S_IRWXO);
225 if (rv == -1)
226 errExit("mkdir");
227 if (chown("/var/cache/lighttpd/compress", uid, gid) < 0)
228 errExit("chown");
229
230 rv = mkdir("/var/cache/lighttpd/uploads", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
231 if (rv == -1)
232 errExit("mkdir");
233 if (chown("/var/cache/lighttpd/uploads", uid, gid) < 0)
234 errExit("chown");
235 }
236}
237
238void dbg_test_dir(const char *dir) {
239 if (arg_debug) {
240 if (is_dir(dir))
241 printf("%s is a directory\n", dir);
242 if (is_link(dir)) {
243 char *lnk = get_link(dir);
244 if (lnk) {
245 printf("%s is a symbolic link to %s\n", dir, lnk);
246 free(lnk);
247 }
248 }
249 }
250}
251
252
253void fs_var_lock(void) {
254
255 if (is_dir("/var/lock")) {
256 if (arg_debug)
257 printf("Mounting tmpfs on /var/lock\n");
258 if (mount("tmpfs", "/var/lock", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=777,gid=0") < 0)
259 errExit("mounting /lock");
260 }
261 else {
262 char *lnk = get_link("/var/lock");
263 if (lnk) {
264 // convert a link such as "../shm" into "/shm"
265 char *lnk2 = lnk;
266 int cnt = 0;
267 while (strncmp(lnk2, "../", 3) == 0) {
268 cnt++;
269 lnk2 = lnk2 + 3;
270 }
271 if (cnt != 0)
272 lnk2 = lnk + (cnt - 1) * 3 + 2;
273
274 if (!is_dir(lnk2)) {
275 // create directory
276 if (mkdir(lnk2, S_IRWXU|S_IRWXG|S_IRWXO))
277 errExit("mkdir");
278 if (chown(lnk2, 0, 0))
279 errExit("chown");
280 if (chmod(lnk2, S_IRWXU|S_IRWXG|S_IRWXO))
281 errExit("chmod");
282 }
283 if (arg_debug)
284 printf("Mounting tmpfs on %s on behalf of /var/lock\n", lnk2);
285 if (mount("tmpfs", lnk2, "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=777,gid=0") < 0)
286 errExit("mounting /var/lock");
287 free(lnk);
288 }
289 else {
290 fprintf(stderr, "Warning: /var/lock not mounted\n");
291 dbg_test_dir("/var/lock");
292 }
293 }
294}
295
296void fs_var_tmp(void) {
297
298 if (!is_link("/var/tmp")) {
299 if (arg_debug)
300 printf("Mounting tmpfs on /var/tmp\n");
301 if (mount("tmpfs", "/var/tmp", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=777,gid=0") < 0)
302 errExit("mounting /var/tmp");
303 }
304 else {
305 fprintf(stderr, "Warning: /var/tmp not mounted\n");
306 dbg_test_dir("/var/tmp");
307 }
308}
309
310void fs_var_utmp(void) {
311 struct stat s;
312
313 // extract utmp group id
314 gid_t utmp_group = 0;
315 if (stat("/var/run/utmp", &s) == 0)
316 utmp_group = s.st_gid;
317 else {
318 fprintf(stderr, "Warning: cannot find /var/run/utmp\n");
319 return;
320 }
321
322 // create /tmp/firejail/mnt directory
323 fs_build_mnt_dir();
324
325 // create a new utmp file
326 if (arg_debug)
327 printf("Create the new utmp file\n");
328 char *utmp;
329 if (asprintf(&utmp, "%s/utmp", MNT_DIR) == -1)
330 errExit("asprintf");
331 FILE *fp = fopen(utmp, "w");
332 if (!fp)
333 errExit("fopen");
334
335 // read current utmp
336 struct utmp *u;
337 struct utmp u_boot;
338 setutent();
339 while ((u = getutent()) != NULL) {
340 if (u->ut_type == BOOT_TIME) {
341 memcpy(&u_boot, u, sizeof(u_boot));
342 u_boot.ut_tv.tv_sec = (unsigned) time(NULL);
343 }
344 }
345 endutent();
346
347 // save new utmp file
348 fwrite(&u_boot, sizeof(u_boot), 1, fp);
349 fclose(fp);
350 if (chown(utmp, 0, utmp_group) < 0)
351 errExit("chown");
352 if (chmod(utmp, S_IRUSR | S_IWRITE | S_IRGRP | S_IWGRP | S_IROTH ) < 0)
353 errExit("chmod");
354
355 // mount the new utmp file
356 if (arg_debug)
357 printf("Mount the new utmp file\n");
358 if (mount(utmp, "/var/run/utmp", NULL, MS_BIND|MS_REC, NULL) < 0)
359 errExit("mount bind utmp");
360}
361
362
363#if 0
364Testing servers:
365
366brctl addbr br0
367ifconfig br0 10.10.20.1/24
368
369apt-get install snmpd
370insserv -r snmpd
371sudo firejail --net=br0 --ip=10.10.20.10 "/etc/init.d/rsyslog start; /etc/init.d/ssh start; /etc/init.d/snmpd start; sleep inf"
372
373apt-get install apache2
374insserv -r apache2
375sudo firejail --net=br0 --ip=10.10.20.10 "/etc/init.d/rsyslog start; /etc/init.d/ssh start; /etc/init.d/apache2 start; sleep inf"
376
377apt-get install nginx
378insserv -r nginx
379sudo firejail --net=br0 --ip=10.10.20.10 "/etc/init.d/rsyslog start; /etc/init.d/ssh start; /etc/init.d/nginx start; sleep inf"
380
381apt-get install lighttpd
382insserv -r lighttpd
383sudo firejail --net=br0 --ip=10.10.20.10 "/etc/init.d/rsyslog start; /etc/init.d/ssh start; /etc/init.d/lighttpd start; sleep inf"
384
385apt-get install isc-dhcp-server
386insserv -r isc-dhcp-server
387sudo firejail --net=br0 --ip=10.10.20.10 "/etc/init.d/rsyslog start; /etc/init.d/ssh start; /etc/init.d/isc-dhcp-server start; sleep inf"
388#endif
diff --git a/src/firejail/join.c b/src/firejail/join.c
new file mode 100644
index 000000000..e2d2ca7fc
--- /dev/null
+++ b/src/firejail/join.c
@@ -0,0 +1,364 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
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#include "firejail.h"
21#include <sys/stat.h>
22#include <sys/wait.h>
23#include <fcntl.h>
24#include <unistd.h>
25#include <sys/prctl.h>
26
27static int apply_caps = 0;
28static uint64_t caps = 0;
29static int apply_seccomp = 0;
30#define BUFLEN 4096
31
32static void extract_command(int argc, char **argv, int index) {
33 if (index >= argc)
34 return;
35
36 // doubledash followed by positional parameters
37 if (strcmp(argv[index], "--") == 0) {
38 arg_doubledash = 1;
39 index++;
40 if (index >= argc)
41 return;
42 }
43
44 // first argv needs to be a valid command
45 if (arg_doubledash == 0 && *argv[index] == '-') {
46 fprintf(stderr, "Error: invalid option %s after --join\n", argv[index]);
47 exit(1);
48 }
49
50
51 int len = 0;
52 int i;
53 // calculate command length
54 for (i = index; i < argc; i++) {
55 len += strlen(argv[i]) + 1;
56 }
57 assert(len > 0);
58
59 // build command
60 cfg.command_line = malloc(len + 1);
61 *cfg.command_line = '\0';
62 for (i = index; i < argc; i++) {
63 strcat(cfg.command_line, argv[i]);
64 strcat(cfg.command_line, " ");
65 }
66 if (arg_debug)
67 printf("Extracted command #%s#\n", cfg.command_line);
68}
69
70static void extract_nogroups(pid_t pid) {
71 char *fname;
72 if (asprintf(&fname, "/proc/%d/root%s/groups", pid, MNT_DIR) == -1)
73 errExit("asprintf");
74
75 struct stat s;
76 if (stat(fname, &s) == -1)
77 return;
78
79 arg_nogroups = 1;
80 free(fname);
81}
82
83static void extract_cpu(pid_t pid) {
84 char *fname;
85 if (asprintf(&fname, "/proc/%d/root%s/cpu", pid, MNT_DIR) == -1)
86 errExit("asprintf");
87
88 struct stat s;
89 if (stat(fname, &s) == -1)
90 return;
91
92 // there is a cpu file in MNT_DIR; load the information from the file
93 load_cpu(fname);
94 free(fname);
95}
96
97static void extract_cgroup(pid_t pid) {
98 char *fname;
99 if (asprintf(&fname, "/proc/%d/root%s/cgroup", pid, MNT_DIR) == -1)
100 errExit("asprintf");
101
102 struct stat s;
103 if (stat(fname, &s) == -1)
104 return;
105
106 // there is a cgroup file in MNT_DIR; load the information from the file
107 load_cgroup(fname);
108 free(fname);
109}
110
111static void extract_caps_seccomp(pid_t pid) {
112 // open stat file
113 char *file;
114 if (asprintf(&file, "/proc/%u/status", pid) == -1) {
115 perror("asprintf");
116 exit(1);
117 }
118 FILE *fp = fopen(file, "r");
119 if (!fp) {
120 free(file);
121 fprintf(stderr, "Error: cannot open stat file for process %u\n", pid);
122 exit(1);
123 }
124
125 char buf[BUFLEN];
126 while (fgets(buf, BUFLEN - 1, fp)) {
127 if (strncmp(buf, "Seccomp:", 8) == 0) {
128 char *ptr = buf + 8;
129 int val;
130 sscanf(ptr, "%d", &val);
131 if (val == 2)
132 apply_seccomp = 1;
133 break;
134 }
135 else if (strncmp(buf, "CapBnd:", 7) == 0) {
136 char *ptr = buf + 8;
137 unsigned long long val;
138 sscanf(ptr, "%llx", &val);
139 apply_caps = 1;
140 caps = val;
141 }
142 }
143 fclose(fp);
144 free(file);
145}
146
147void extract_user_namespace(pid_t pid) {
148 // test user namespaces available in the kernel
149 struct stat s1;
150 struct stat s2;
151 struct stat s3;
152 if (stat("/proc/self/ns/user", &s1) == 0 &&
153 stat("/proc/self/uid_map", &s2) == 0 &&
154 stat("/proc/self/gid_map", &s3) == 0);
155 else
156 return;
157
158 // read uid map
159 char *uidmap;
160 if (asprintf(&uidmap, "/proc/%u/uid_map", pid) == -1)
161 errExit("asprintf");
162 FILE *fp = fopen(uidmap, "r");
163 if (!fp) {
164 free(uidmap);
165 return;
166 }
167
168 // check uid map
169 int u1;
170 int u2;
171 if (fscanf(fp, "%d %d", &u1, &u2) == 2) {
172 if (arg_debug)
173 printf("User namespace detected: %s, %d, %d\n", uidmap, u1, u2);
174 if (u1 != 0 || u2 != 0)
175 arg_noroot = 1;
176 }
177 fclose(fp);
178 free(uidmap);
179}
180
181void join_name(const char *name, const char *homedir, int argc, char **argv, int index) {
182 if (!name || strlen(name) == 0) {
183 fprintf(stderr, "Error: invalid sandbox name\n");
184 exit(1);
185 }
186 pid_t pid;
187 if (name2pid(name, &pid)) {
188 fprintf(stderr, "Error: cannot find sandbox %s\n", name);
189 exit(1);
190 }
191
192 join(pid, homedir, argc, argv, index);
193}
194
195void join(pid_t pid, const char *homedir, int argc, char **argv, int index) {
196 extract_command(argc, argv, index);
197
198 // if the pid is that of a firejail process, use the pid of the first child process
199 char *comm = pid_proc_comm(pid);
200 if (comm) {
201 // remove \n
202 char *ptr = strchr(comm, '\n');
203 if (ptr)
204 *ptr = '\0';
205 if (strcmp(comm, "firejail") == 0) {
206 pid_t child;
207 if (find_child(pid, &child) == 0) {
208 pid = child;
209 printf("Switching to pid %u, the first child process inside the sandbox\n", (unsigned) pid);
210 }
211 }
212 free(comm);
213 }
214
215 // check privileges for non-root users
216 uid_t uid = getuid();
217 if (uid != 0) {
218 struct stat s;
219 char *dir;
220 if (asprintf(&dir, "/proc/%u/ns", pid) == -1)
221 errExit("asprintf");
222 if (stat(dir, &s) < 0)
223 errExit("stat");
224 if (s.st_uid != uid) {
225 fprintf(stderr, "Error: permission is denied to join a sandbox created by a different user.\n");
226 exit(1);
227 }
228 }
229
230 // in user mode set caps seccomp, cpu, cgroup, etc
231 if (getuid() != 0) {
232 extract_caps_seccomp(pid);
233 extract_cpu(pid);
234 extract_cgroup(pid);
235 extract_nogroups(pid);
236 extract_user_namespace(pid);
237 }
238
239 // set cgroup
240 if (cfg.cgroup)
241 set_cgroup(cfg.cgroup);
242
243 // join namespaces
244 if (join_namespace(pid, "ipc"))
245 exit(1);
246 if (join_namespace(pid, "net"))
247 exit(1);
248 if (join_namespace(pid, "pid"))
249 exit(1);
250 if (join_namespace(pid, "uts"))
251 exit(1);
252 if (join_namespace(pid, "mnt"))
253 exit(1);
254
255 pid_t child = fork();
256 if (child < 0)
257 errExit("fork");
258 if (child == 0) {
259 // chroot into /proc/PID/root directory
260 char *rootdir;
261 if (asprintf(&rootdir, "/proc/%d/root", pid) == -1)
262 errExit("asprintf");
263
264 int rv = chroot(rootdir); // this will fail for processes in sandboxes not started with --chroot option
265 if (rv == 0)
266 printf("changing root to %s\n", rootdir);
267
268 prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died
269 if (chdir("/") < 0)
270 errExit("chdir");
271 if (homedir) {
272 struct stat s;
273 if (stat(homedir, &s) == 0) {
274 /* coverity[toctou] */
275 if (chdir(homedir) < 0)
276 errExit("chdir");
277 }
278 }
279
280 // set cpu affinity
281 if (cfg.cpus)
282 set_cpu_affinity();
283
284 // set caps filter
285 if (apply_caps == 1)
286 caps_set(caps);
287#ifdef HAVE_SECCOMP
288 // set seccomp filter
289 if (apply_seccomp == 1)
290 seccomp_set();
291#endif
292
293 // fix qt 4.8
294 if (setenv("QT_X11_NO_MITSHM", "1", 1) < 0)
295 errExit("setenv");
296 if (setenv("container", "firejail", 1) < 0) // LXC sets container=lxc,
297 errExit("setenv");
298
299 // mount user namespace or drop privileges
300 if (arg_noroot) {
301 if (arg_debug)
302 printf("Joining user namespace\n");
303 if (join_namespace(1, "user"))
304 exit(1);
305 }
306 else
307 drop_privs(arg_nogroups);
308
309 // set prompt color to green
310 //export PS1='\[\e[1;32m\][\u@\h \W]\$\[\e[0m\] '
311 if (setenv("PROMPT_COMMAND", "export PS1=\"\\[\\e[1;32m\\][\\u@\\h \\W]\\$\\[\\e[0m\\] \"", 1) < 0)
312 errExit("setenv");
313
314 // run icmdline trough /bin/bash
315 if (cfg.command_line == NULL)
316 // replace the process with a regular bash session
317 execlp("/bin/bash", "/bin/bash", NULL);
318 else {
319 // run the command supplied by the user
320 int cwd = 0;
321 if (cfg.cwd) {
322 if (chdir(cfg.cwd) == 0)
323 cwd = 1;
324 }
325
326 if (!cwd) {
327 if (chdir("/") < 0)
328 errExit("chdir");
329 if (cfg.homedir) {
330 struct stat s;
331 if (stat(cfg.homedir, &s) == 0) {
332 if (chdir(cfg.homedir) < 0)
333 errExit("chdir");
334 }
335 }
336 }
337
338 char *arg[5];
339 arg[0] = "/bin/bash";
340 arg[1] = "-c";
341 if (arg_debug)
342 printf("Starting %s\n", cfg.command_line);
343 if (!arg_doubledash) {
344 arg[2] = cfg.command_line;
345 arg[3] = NULL;
346 }
347 else {
348 arg[2] = "--";
349 arg[3] = cfg.command_line;
350 arg[4] = NULL;
351 }
352 execvp("/bin/bash", arg);
353 }
354
355 // it will never get here!!!
356 }
357
358 // wait for the child to finish
359 waitpid(child, NULL, 0);
360 exit(0);
361}
362
363
364
diff --git a/src/firejail/list.c b/src/firejail/list.c
new file mode 100644
index 000000000..c2c4e801f
--- /dev/null
+++ b/src/firejail/list.c
@@ -0,0 +1,65 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
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#include "firejail.h"
21
22void top(void) {
23 drop_privs(1);
24
25 char *arg[4];
26 arg[0] = "bash";
27 arg[1] = "-c";
28 arg[2] = "firemon --top";
29 arg[3] = NULL;
30 execvp("/bin/bash", arg);
31}
32
33void netstats(void) {
34 drop_privs(1);
35
36 char *arg[4];
37 arg[0] = "bash";
38 arg[1] = "-c";
39 arg[2] = "firemon --netstats";
40 arg[3] = NULL;
41 execvp("/bin/bash", arg);
42}
43
44void list(void) {
45 drop_privs(1);
46
47 char *arg[4];
48 arg[0] = "bash";
49 arg[1] = "-c";
50 arg[2] = "firemon --list";
51 arg[3] = NULL;
52 execvp("/bin/bash", arg);
53}
54
55void tree(void) {
56 drop_privs(1);
57
58 char *arg[4];
59 arg[0] = "bash";
60 arg[1] = "-c";
61 arg[2] = "firemon --tree";
62 arg[3] = NULL;
63 execvp("/bin/bash", arg);
64}
65
diff --git a/src/firejail/main.c b/src/firejail/main.c
new file mode 100644
index 000000000..78971aa86
--- /dev/null
+++ b/src/firejail/main.c
@@ -0,0 +1,1168 @@
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#include "firejail.h"
21#include "../include/pid.h"
22#define _GNU_SOURCE
23#include <sys/utsname.h>
24#include <sched.h>
25#include <sys/mount.h>
26#include <sys/wait.h>
27#include <sys/stat.h>
28#include <fcntl.h>
29#include <dirent.h>
30#include <pwd.h>
31#include <errno.h>
32#include <limits.h>
33#include <sys/file.h>
34#include <sys/prctl.h>
35#include <signal.h>
36#include <time.h>
37#include <net/if.h>
38
39#if 0
40#include <sys/times.h>
41{
42struct tms tm;
43clock_t systick = times(&tm);
44printf("time %s:%d %u\n", __FILE__, __LINE__, (uint32_t) systick);
45}
46#endif
47
48#define STACK_SIZE (1024 * 1024)
49static char child_stack[STACK_SIZE]; // space for child's stack
50Config cfg; // configuration
51int arg_private = 0; // mount private /home and /tmp directoryu
52int arg_debug = 0; // print debug messages
53int arg_nonetwork = 0; // --net=none
54int arg_command = 0; // -c
55int arg_overlay = 0; // --overlay
56int arg_zsh = 0; // use zsh as default shell
57int arg_csh = 0; // use csh as default shell
58
59int arg_seccomp = 0; // enable default seccomp filter
60char *arg_seccomp_list = NULL; // optional seccomp list on top of default filter
61char *arg_seccomp_list_drop = NULL; // seccomp drop list
62char *arg_seccomp_list_keep = NULL; // seccomp keep list
63
64int arg_caps_default_filter = 0; // enable default capabilities filter
65int arg_caps_drop = 0; // drop list
66int arg_caps_drop_all = 0; // drop all capabilities
67int arg_caps_keep = 0; // keep list
68char *arg_caps_list = NULL; // optional caps list
69
70int arg_trace = 0; // syscall tracing support
71int arg_rlimit_nofile = 0; // rlimit nofile
72int arg_rlimit_nproc = 0; // rlimit nproc
73int arg_rlimit_fsize = 0; // rlimit fsize
74int arg_rlimit_sigpending = 0; // rlimit fsize
75int arg_nox11 = 0; // kill the program if x11 unix domain socket is accessed
76int arg_nodbus = 0; // kill the program if D-Bus is accessed
77int arg_nogroups = 0; // disable supplementary groups
78int arg_noroot = 0; // create a new user namespace and disable root user
79int arg_netfilter; // enable netfilter
80char *arg_netfilter_file = NULL; // netfilter file
81int arg_doubledash = 0; // double dash
82int arg_shell_none = 0; // run the program directly without a shell
83int arg_private_dev = 0; // private dev directory
84int arg_scan = 0; // arp-scan all interfaces
85
86int parent_to_child_fds[2];
87int child_to_parent_fds[2];
88
89char *fullargv[MAX_ARGS]; // expanded argv for restricted shell
90int fullargc = 0;
91static pid_t child = 0;
92pid_t sandbox_pid;
93
94static void myexit(int rv) {
95 logmsg("exiting...");
96 if (!arg_command)
97 printf("\nparent is shutting down, bye...\n");
98
99 struct stat s;
100 if (stat("/proc/firejail", &s) == 0) {
101 /* coverity[toctou] */
102 FILE *fp = fopen("/proc/firejail", "w");
103 if (fp) {
104 // deregistration
105 fprintf(fp, "release\n");
106 fflush(0);
107 fclose(fp);
108 }
109 }
110
111 // delete sandbox files in shared memory
112 bandwidth_shm_del_file(sandbox_pid); // bandwidht file
113 network_shm_del_file(sandbox_pid); // network map file
114
115 exit(rv);
116}
117
118static void my_handler(int s){
119 printf("\nSignal %d caught, shutting down the child process\n", s);
120 logsignal(s);
121 kill(child, SIGKILL);
122 myexit(1);
123}
124
125static void extract_user_data(void) {
126 // check suid
127 if (geteuid()) {
128 fprintf(stderr, "Error: the sandbox is not setuid root\n");
129 exit(1);
130 }
131
132 struct passwd *pw = getpwuid(getuid());
133 if (!pw)
134 errExit("getpwuid");
135 cfg.username = strdup(pw->pw_name);
136 if (!cfg.username)
137 errExit("strdup");
138
139 // build home directory name
140 cfg.homedir = NULL;
141 if (pw->pw_dir != NULL) {
142 cfg.homedir = strdup(pw->pw_dir);
143 if (!cfg.homedir)
144 errExit("strdup");
145 }
146 else {
147 fprintf(stderr, "Error: user %s doesn't have a user directory assigned\n", cfg.username);
148 exit(1);
149 }
150
151 cfg.cwd = getcwd(NULL, 0);
152}
153
154
155
156
157static inline Bridge *last_bridge_configured(void) {
158 if (cfg.bridge3.configured)
159 return &cfg.bridge3;
160 else if (cfg.bridge2.configured)
161 return &cfg.bridge2;
162 else if (cfg.bridge1.configured)
163 return &cfg.bridge1;
164 else if (cfg.bridge0.configured)
165 return &cfg.bridge0;
166 else
167 return NULL;
168}
169
170
171
172// return 1 if error, 0 if a valid pid was found
173static int read_pid(char *str, pid_t *pid) {
174 char *endptr;
175 errno = 0;
176 pid_t pidtmp = strtol(str, &endptr, 10);
177 if ((errno == ERANGE && (pidtmp == LONG_MAX || pidtmp == LONG_MIN))
178 || (errno != 0 && pidtmp == 0)) {
179 return 1;
180 }
181 if (endptr == str) {
182 return 1;
183 }
184 *pid = pidtmp;
185 return 0;
186}
187
188static void init_cfg(void) {
189 memset(&cfg, 0, sizeof(cfg));
190
191 cfg.bridge0.devsandbox = "eth0";
192 cfg.bridge1.devsandbox = "eth1";
193 cfg.bridge2.devsandbox = "eth2";
194 cfg.bridge3.devsandbox = "eth3";
195
196 extract_user_data();
197}
198
199static void check_network(Bridge *br) {
200 assert(br);
201 if (br->macvlan == 0) // for bridge devices check network range or arp-scan and assign address
202 net_configure_sandbox_ip(br);
203 else if (br->ipsandbox) { // for macvlan check network range
204 char *rv = in_netrange(br->ipsandbox, br->ip, br->mask);
205 if (rv) {
206 fprintf(stderr, "%s", rv);
207 exit(1);
208 }
209 }
210}
211
212
213void check_user_namespace(void) {
214 if (getuid() == 0) {
215 fprintf(stderr, "Error: --noroot option cannot be used when starting the sandbox as root.\n");
216 exit(1);
217 }
218
219 // test user namespaces available in the kernel
220 struct stat s1;
221 struct stat s2;
222 struct stat s3;
223 if (stat("/proc/self/ns/user", &s1) == 0 &&
224 stat("/proc/self/uid_map", &s2) == 0 &&
225 stat("/proc/self/gid_map", &s3) == 0)
226 arg_noroot = 1;
227 else {
228 fprintf(stderr, "Warning: user namespaces not available in the current kernel.\n");
229 arg_noroot = 0;
230 }
231}
232
233//*******************************************
234// Main program
235//*******************************************
236int main(int argc, char **argv) {
237 int i;
238 int prog_index = -1; // index in argv where the program command starts
239 int lockfd = -1;
240 int arg_ipc = 0;
241 int arg_cgroup = 0;
242 int custom_profile = 0; // custom profile loaded
243
244 // initialize globals
245 init_cfg();
246 cfg.original_argv = argv;
247 cfg.original_argc = argc;
248
249
250 // initialize random number generator
251 sandbox_pid = getpid();
252 time_t t = time(NULL);
253 srand(t ^ sandbox_pid);
254
255 // check firejail directories
256 fs_build_firejail_dir();
257 shm_create_firejail_dir();
258 bandwidth_shm_del_file(sandbox_pid);
259
260 // is this a login shell?
261 if (*argv[0] == '-') {
262 fullargc = restricted_shell(cfg.username);
263 if (fullargc) {
264 int j;
265 for (i = 1, j = fullargc; i < argc && j < MAX_ARGS; i++, j++, fullargc++)
266 fullargv[j] = argv[i];
267
268 // replace argc/argv with fullargc/fullargv
269 argv = fullargv;
270 argc = j;
271 }
272 }
273 else {
274 // check --output option and execute it;
275 check_output(argc, argv); // the function will not return if --output option was found
276 }
277
278 // parse arguments
279 for (i = 1; i < argc; i++) {
280 //*************************************
281 // basic arguments
282 //*************************************
283 if (strcmp(argv[i], "--help") == 0 ||
284 strcmp(argv[i], "-?") == 0) {
285 usage();
286 exit(0);
287 }
288 else if (strcmp(argv[i], "--version") == 0) {
289 printf("firejail version %s\n", VERSION);
290 exit(0);
291 }
292 else if (strcmp(argv[i], "--debug") == 0)
293 arg_debug = 1;
294
295 else if (strncmp(argv[i], "--bandwidth=", 12) == 0) {
296 logargs(argc, argv);
297
298 // extract the command
299 if ((i + 1) == argc) {
300 fprintf(stderr, "Error: command expected after --bandwidth option\n");
301 exit(1);
302 }
303 char *cmd = argv[i + 1];
304 if (strcmp(cmd, "status") && strcmp(cmd, "clear") && strcmp(cmd, "set")) {
305 fprintf(stderr, "Error: invalid --bandwidth command\n");
306 exit(1);
307 }
308
309 // extract network name
310 char *dev = NULL;
311 int down = 0;
312 int up = 0;
313 if (strcmp(cmd, "set") == 0 || strcmp(cmd, "clear") == 0) {
314 // extract device name
315 if ((i + 2) == argc) {
316 fprintf(stderr, "Error: network name expected after --bandwidth %s option\n", cmd);
317 exit(1);
318 }
319 dev = argv[i + 2];
320
321 // check device name
322 if (if_nametoindex(dev) == 0) {
323 fprintf(stderr, "Error: network device %s not found\n", dev);
324 exit(1);
325 }
326
327 // extract bandwidth
328 if (strcmp(cmd, "set") == 0) {
329 if ((i + 4) >= argc) {
330 fprintf(stderr, "Error: invalid --bandwidth set command\n");
331 exit(1);
332 }
333
334 down = atoi(argv[i + 3]);
335 if (down < 0) {
336 fprintf(stderr, "Error: invalid download speed\n");
337 exit(1);
338 }
339 up = atoi(argv[i + 4]);
340 if (up < 0) {
341 fprintf(stderr, "Error: invalid upload speed\n");
342 exit(1);
343 }
344 }
345 }
346
347 // extract pid or sandbox name
348 pid_t pid;
349 if (read_pid(argv[i] + 12, &pid) == 0)
350 bandwidth_pid(pid, cmd, dev, down, up);
351 else
352 bandwidth_name(argv[i] + 12, cmd, dev, down, up);
353
354 // it will never get here
355 exit(0);
356 }
357
358 //*************************************
359 // independent commands - the program will exit!
360 //*************************************
361#ifdef HAVE_SECCOMP
362 else if (strcmp(argv[i], "--debug-syscalls") == 0) {
363 syscall_print();
364 exit(0);
365 }
366 else if (strncmp(argv[i], "--seccomp.print=", 16) == 0) {
367 // join sandbox by pid or by name
368 pid_t pid;
369 if (read_pid(argv[i] + 16, &pid) == 0)
370 seccomp_print_filter(pid);
371 else
372 seccomp_print_filter_name(argv[i] + 16);
373
374 // it will never get here!!!
375 exit(0);
376 }
377#endif
378 else if (strncmp(argv[i], "--caps.print=", 13) == 0) {
379 // join sandbox by pid or by name
380 pid_t pid;
381 if (read_pid(argv[i] + 13, &pid) == 0)
382 caps_print_filter(pid);
383 else
384 caps_print_filter_name(argv[i] + 13);
385
386 // it will never get here!!!
387 exit(0);
388 }
389
390 else if (strncmp(argv[i], "--dns.print=", 12) == 0) {
391 // join sandbox by pid or by name
392 pid_t pid;
393 if (read_pid(argv[i] + 12, &pid) == 0)
394 net_dns_print(pid);
395 else
396 net_dns_print_name(argv[i] + 12);
397
398 // it will never get here!!!
399 exit(0);
400 }
401 else if (strcmp(argv[i], "--debug-caps") == 0) {
402 caps_print();
403 exit(0);
404 }
405 else if (strcmp(argv[i], "--list") == 0) {
406 list();
407 exit(0);
408 }
409 else if (strcmp(argv[i], "--tree") == 0) {
410 tree();
411 exit(0);
412 }
413 else if (strcmp(argv[i], "--top") == 0) {
414 top();
415 exit(0);
416 }
417 else if (strcmp(argv[i], "--netstats") == 0) {
418 netstats();
419 exit(0);
420 }
421 else if (strncmp(argv[i], "--join=", 7) == 0) {
422 logargs(argc, argv);
423
424 // join sandbox by pid or by name
425 pid_t pid;
426 if (read_pid(argv[i] + 7, &pid) == 0)
427 join(pid, cfg.homedir, argc, argv, i + 1);
428 else
429 join_name(argv[i] + 7, cfg.homedir, argc, argv, i + 1);
430
431 // it will never get here!!!
432 exit(0);
433 }
434 else if (strncmp(argv[i], "--shutdown=", 11) == 0) {
435 logargs(argc, argv);
436
437 // shutdown sandbox by pid or by name
438 pid_t pid;
439 if (read_pid(argv[i] + 11, &pid) == 0)
440 shut(pid);
441 else
442 shut_name(argv[i] + 11);
443
444 // it will never get here!!!
445 exit(0);
446 }
447
448 //*************************************
449 // filtering
450 //*************************************
451#ifdef HAVE_SECCOMP
452 else if (strcmp(argv[i], "--seccomp") == 0) {
453 if (arg_seccomp) {
454 fprintf(stderr, "Error: seccomp already enabled\n");
455 exit(1);
456 }
457 arg_seccomp = 1;
458 }
459 else if (strncmp(argv[i], "--seccomp=", 10) == 0) {
460 if (arg_seccomp) {
461 fprintf(stderr, "Error: seccomp already enabled\n");
462 exit(1);
463 }
464 arg_seccomp = 1;
465 arg_seccomp_list = strdup(argv[i] + 10);
466 if (!arg_seccomp_list)
467 errExit("strdup");
468 }
469 else if (strncmp(argv[i], "--seccomp.drop=", 15) == 0) {
470 if (arg_seccomp) {
471 fprintf(stderr, "Error: seccomp already enabled\n");
472 exit(1);
473 }
474 arg_seccomp = 1;
475 arg_seccomp_list_drop = strdup(argv[i] + 15);
476 if (!arg_seccomp_list_drop)
477 errExit("strdup");
478 }
479 else if (strncmp(argv[i], "--seccomp.keep=", 15) == 0) {
480 if (arg_seccomp) {
481 fprintf(stderr, "Error: seccomp already enabled\n");
482 exit(1);
483 }
484 arg_seccomp = 1;
485 arg_seccomp_list_keep = strdup(argv[i] + 15);
486 if (!arg_seccomp_list_keep)
487 errExit("strdup");
488 }
489#endif
490 else if (strcmp(argv[i], "--caps") == 0)
491 arg_caps_default_filter = 1;
492 else if (strcmp(argv[i], "--caps.drop=all") == 0)
493 arg_caps_drop_all = 1;
494 else if (strncmp(argv[i], "--caps.drop=", 12) == 0) {
495 arg_caps_drop = 1;
496 arg_caps_list = strdup(argv[i] + 12);
497 if (!arg_caps_list)
498 errExit("strdup");
499 // verify caps list and exit if problems
500 if (caps_check_list(arg_caps_list, NULL))
501 return 1;
502 }
503 else if (strncmp(argv[i], "--caps.keep=", 12) == 0) {
504 arg_caps_keep = 1;
505 arg_caps_list = strdup(argv[i] + 12);
506 if (!arg_caps_list)
507 errExit("strdup");
508 // verify caps list and exit if problems
509 if (caps_check_list(arg_caps_list, NULL))
510 return 1;
511 }
512
513
514 else if (strcmp(argv[i], "--trace") == 0)
515 arg_trace = 1;
516 else if (strncmp(argv[i], "--rlimit-nofile=", 16) == 0) {
517 if (not_unsigned(argv[i] + 16)) {
518 fprintf(stderr, "Error: invalid rlimt nofile\n");
519 exit(1);
520 }
521 sscanf(argv[i] + 16, "%u", &cfg.rlimit_nofile);
522 arg_rlimit_nofile = 1;
523 }
524 else if (strncmp(argv[i], "--rlimit-nproc=", 15) == 0) {
525 if (not_unsigned(argv[i] + 15)) {
526 fprintf(stderr, "Error: invalid rlimt nproc\n");
527 exit(1);
528 }
529 sscanf(argv[i] + 15, "%u", &cfg.rlimit_nproc);
530 arg_rlimit_nproc = 1;
531 }
532 else if (strncmp(argv[i], "--rlimit-fsize=", 15) == 0) {
533 if (not_unsigned(argv[i] + 15)) {
534 fprintf(stderr, "Error: invalid rlimt fsize\n");
535 exit(1);
536 }
537 sscanf(argv[i] + 15, "%u", &cfg.rlimit_fsize);
538 arg_rlimit_fsize = 1;
539 }
540 else if (strncmp(argv[i], "--rlimit-sigpending=", 20) == 0) {
541 if (not_unsigned(argv[i] + 20)) {
542 fprintf(stderr, "Error: invalid rlimt sigpending\n");
543 exit(1);
544 }
545 sscanf(argv[i] + 20, "%u", &cfg.rlimit_sigpending);
546 arg_rlimit_sigpending = 1;
547 }
548 else if (strncmp(argv[i], "--ipc-namespace", 15) == 0)
549 arg_ipc = 1;
550 else if (strncmp(argv[i], "--cpu=", 6) == 0)
551 read_cpu_list(argv[i] + 6);
552 else if (strcmp(argv[i], "--nox11") == 0) {
553 // check if firejail lkm is present
554 struct stat s;
555 if (stat("/proc/firejail", &s) < 0) {
556 fprintf(stderr, "Error: firejail Linux kernel module not found. The module"
557 " is required for --nox11 option to work.\n");
558 exit(1);
559 }
560 arg_nox11 = 1;
561 }
562 else if (strcmp(argv[i], "--nodbus") == 0) {
563 // check if firejail lkm is present
564 struct stat s;
565 if (stat("/proc/firejail", &s) < 0) {
566 fprintf(stderr, "Error: firejail Linux kernel module not found. The module"
567 " is required for --nodbus option to work.\n");
568 exit(1);
569 }
570 arg_nodbus = 1;
571 }
572 else if (strncmp(argv[i], "--cgroup=", 9) == 0) {
573 if (arg_cgroup) {
574 fprintf(stderr, "Error: only a cgroup can be defined\n");
575 exit(1);
576 }
577 arg_cgroup = 1;
578 cfg.cgroup = strdup(argv[i] + 9);
579 if (!cfg.cgroup)
580 errExit("strdup");
581 set_cgroup(cfg.cgroup);
582 }
583
584 //*************************************
585 // filesystem
586 //*************************************
587#ifdef HAVE_BIND
588 else if (strncmp(argv[i], "--bind=", 7) == 0) {
589 char *line;
590 if (asprintf(&line, "bind %s", argv[i] + 7) == -1)
591 errExit("asprintf");
592
593 profile_check_line(line, 0); // will exit if something wrong
594 profile_add(line);
595 }
596#endif
597 else if (strncmp(argv[i], "--tmpfs=", 8) == 0) {
598 char *line;
599 if (asprintf(&line, "tmpfs %s", argv[i] + 8) == -1)
600 errExit("asprintf");
601
602 profile_check_line(line, 0); // will exit if something wrong
603 profile_add(line);
604 }
605 else if (strncmp(argv[i], "--blacklist=", 12) == 0) {
606 char *line;
607 if (asprintf(&line, "blacklist %s", argv[i] + 12) == -1)
608 errExit("asprintf");
609
610 profile_check_line(line, 0); // will exit if something wrong
611 profile_add(line);
612 }
613 else if (strncmp(argv[i], "--read-only=", 12) == 0) {
614 char *line;
615 if (asprintf(&line, "read-only %s", argv[i] + 12) == -1)
616 errExit("asprintf");
617
618 profile_check_line(line, 0); // will exit if something wrong
619 profile_add(line);
620 }
621 else if (strcmp(argv[i], "--overlay") == 0) {
622 if (cfg.chrootdir) {
623 fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n");
624 exit(1);
625 }
626 arg_overlay = 1;
627 }
628 else if (strncmp(argv[i], "--profile=", 10) == 0) {
629 // multiple profile files are allowed!
630 char *ptr = argv[i] + 10;
631 if (is_dir(ptr) || is_link(ptr) || strstr(ptr, "..")) {
632 fprintf(stderr, "Error: invalid profile file\n");
633 exit(1);
634 }
635
636 // access call checks as real UID/GID, not as effective UID/GID
637 if (access(argv[i] + 10, R_OK)) {
638 fprintf(stderr, "Error: cannot access profile file\n");
639 return 1;
640 }
641
642 profile_read(argv[i] + 10, NULL, NULL);
643 custom_profile = 1;
644 }
645#ifdef HAVE_CHROOT
646 else if (strncmp(argv[i], "--chroot=", 9) == 0) {
647 if (arg_overlay) {
648 fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n");
649 exit(1);
650 }
651
652 // extract chroot dirname
653 cfg.chrootdir = argv[i] + 9;
654 // if the directory starts with ~, expand the home directory
655 if (*cfg.chrootdir == '~') {
656 char *tmp;
657 if (asprintf(&tmp, "%s%s", cfg.homedir, cfg.chrootdir + 1) == -1)
658 errExit("asprintf");
659 cfg.chrootdir = tmp;
660 }
661
662 // check chroot dirname exists
663 if (strstr(cfg.chrootdir, "..") || !is_dir(cfg.chrootdir) || is_link(cfg.chrootdir)) {
664 fprintf(stderr, "Error: invalid directory %s\n", cfg.chrootdir);
665 return 1;
666 }
667
668 // check chroot directory structure
669 if (fs_check_chroot_dir(cfg.chrootdir)) {
670 fprintf(stderr, "Error: invalid chroot\n");
671 exit(1);
672 }
673 }
674#endif
675 else if (strcmp(argv[i], "--private") == 0)
676 arg_private = 1;
677 else if (strncmp(argv[i], "--private=", 10) == 0) {
678 if (cfg.home_private_keep) {
679 fprintf(stderr, "Error: a private list of files was already defined with --private.keep option.\n");
680 exit(1);
681 }
682
683 // extract private home dirname
684 cfg.home_private = argv[i] + 10;
685 fs_check_private_dir();
686 arg_private = 1;
687 }
688 else if (strncmp(argv[i], "--private.keep=", 15) == 0) {
689 if (cfg.home_private) {
690 fprintf(stderr, "Error: a private home directory was already defined with --private option.\n");
691 exit(1);
692 }
693
694 // extract private home dirname
695 cfg.home_private_keep = argv[i] + 15;
696 fs_check_home_list();
697 arg_private = 1;
698 }
699 else if (strcmp(argv[i], "--private-dev") == 0) {
700 arg_private_dev = 1;
701 }
702
703
704
705 //*************************************
706 // hostname, etc
707 //*************************************
708 else if (strncmp(argv[i], "--name=", 7) == 0) {
709 cfg.hostname = argv[i] + 7;
710 if (strlen(cfg.hostname) == 0) {
711 fprintf(stderr, "Error: please provide a name for sandbox\n");
712 return 1;
713 }
714 }
715 else if (strcmp(argv[i], "--nogroups") == 0)
716 arg_nogroups = 1;
717 else if (strcmp(argv[i], "--noroot") == 0) {
718 check_user_namespace();
719 }
720
721 //*************************************
722 // network
723 //*************************************
724 else if (strncmp(argv[i], "--net=", 6) == 0) {
725 if (strcmp(argv[i] + 6, "none") == 0) {
726 arg_nonetwork = 1;
727 cfg.bridge0.configured = 0;
728 cfg.bridge1.configured = 0;
729 cfg.bridge2.configured = 0;
730 cfg.bridge3.configured = 0;
731 continue;
732 }
733 if (strcmp(argv[i] + 6, "lo") == 0) {
734 fprintf(stderr, "Error: cannot attach to lo device\n");
735 exit(1);
736 }
737
738 Bridge *br;
739 if (cfg.bridge0.configured == 0)
740 br = &cfg.bridge0;
741 else if (cfg.bridge1.configured == 0)
742 br = &cfg.bridge1;
743 else if (cfg.bridge2.configured == 0)
744 br = &cfg.bridge2;
745 else if (cfg.bridge3.configured == 0)
746 br = &cfg.bridge3;
747 else {
748 fprintf(stderr, "Error: maximum 4 network devices allowed\n");
749 return 1;
750 }
751 net_configure_bridge(br, argv[i] + 6);
752 }
753 else if (strcmp(argv[i], "--scan") == 0) {
754 arg_scan = 1;
755 }
756 else if (strncmp(argv[i], "--iprange=", 10) == 0) {
757 Bridge *br = last_bridge_configured();
758 if (br == NULL) {
759 fprintf(stderr, "Error: no network device configured\n");
760 return 1;
761 }
762 if (br->iprange_start || br->iprange_end) {
763 fprintf(stderr, "Error: cannot configure the IP range twice for the same interface\n");
764 return 1;
765 }
766
767 // parse option arguments
768 char *firstip = argv[i] + 10;
769 char *secondip = firstip;
770 while (*secondip != '\0') {
771 if (*secondip == ',')
772 break;
773 secondip++;
774 }
775 if (*secondip == '\0') {
776 fprintf(stderr, "Error: invalid IP range\n");
777 return 1;
778 }
779 *secondip = '\0';
780 secondip++;
781
782 // check addresses
783 if (atoip(firstip, &br->iprange_start) || atoip(secondip, &br->iprange_end) ||
784 br->iprange_start >= br->iprange_end) {
785 fprintf(stderr, "Error: invalid IP range\n");
786 return 1;
787 }
788 if (in_netrange(br->iprange_start, br->ip, br->mask) || in_netrange(br->iprange_end, br->ip, br->mask)) {
789 fprintf(stderr, "Error: IP range addresses not in network range\n");
790 return 1;
791 }
792 }
793 else if (strncmp(argv[i], "--mac=", 6) == 0) {
794 Bridge *br = last_bridge_configured();
795 if (br == NULL) {
796 fprintf(stderr, "Error: no network device configured\n");
797 return 1;
798 }
799 if (mac_not_zero(br->macsandbox)) {
800 fprintf(stderr, "Error: cannot configure the MAC address twice for the same interface\n");
801 return 1;
802 }
803
804 // read the address
805 if (atomac(argv[i] + 6, br->macsandbox)) {
806 fprintf(stderr, "Error: invalid MAC address\n");
807 return 1;
808 }
809 }
810 else if (strncmp(argv[i], "--ip=", 5) == 0) {
811 Bridge *br = last_bridge_configured();
812 if (br == NULL) {
813 fprintf(stderr, "Error: no network device configured\n");
814 return 1;
815 }
816 if (br->arg_ip_none || br->ipsandbox) {
817 fprintf(stderr, "Error: cannot configure the IP address twice for the same interface\n");
818 return 1;
819 }
820
821 // configure this IP address for the last bridge defined
822 if (strcmp(argv[i] + 5, "none") == 0)
823 br->arg_ip_none = 1;
824 else {
825 if (atoip(argv[i] + 5, &br->ipsandbox)) {
826 fprintf(stderr, "Error: invalid IP address\n");
827 return 1;
828 }
829 }
830 }
831 else if (strncmp(argv[i], "--defaultgw=", 12) == 0) {
832 if (atoip(argv[i] + 12, &cfg.defaultgw)) {
833 fprintf(stderr, "Error: invalid IP address\n");
834 return 1;
835 }
836 }
837 else if (strncmp(argv[i], "--dns=", 6) == 0) {
838 uint32_t dns;
839 if (atoip(argv[i] + 6, &dns)) {
840 fprintf(stderr, "Error: invalid DNS server IP address\n");
841 return 1;
842 }
843
844 if (cfg.dns1 == 0)
845 cfg.dns1 = dns;
846 else if (cfg.dns2 == 0)
847 cfg.dns2 = dns;
848 else if (cfg.dns3 == 0)
849 cfg.dns3 = dns;
850 else {
851 fprintf(stderr, "Error: up to 3 DNS servers can be specified\n");
852 return 1;
853 }
854 }
855 else if (strcmp(argv[i], "--netfilter") == 0)
856 arg_netfilter = 1;
857 else if (strncmp(argv[i], "--netfilter=", 12) == 0) {
858 arg_netfilter = 1;
859 arg_netfilter_file = argv[i] + 12;
860 check_netfilter_file(arg_netfilter_file);
861 }
862
863 //*************************************
864 // command
865 //*************************************
866 else if (strcmp(argv[i], "--csh") == 0) {
867 if (arg_shell_none) {
868 fprintf(stderr, "Error: --shell=none was already specified.\n");
869 return 1;
870 }
871 if (arg_zsh || cfg.shell ) {
872 fprintf(stderr, "Error: only one default user shell can be specified\n");
873 return 1;
874 }
875 arg_csh = 1;
876 }
877 else if (strcmp(argv[i], "--zsh") == 0) {
878 if (arg_shell_none) {
879 fprintf(stderr, "Error: --shell=none was already specified.\n");
880 return 1;
881 }
882 if (arg_csh || cfg.shell ) {
883 fprintf(stderr, "Error: only one default user shell can be specified\n");
884 return 1;
885 }
886 arg_zsh = 1;
887 }
888 else if (strcmp(argv[i], "--shell=none") == 0) {
889 arg_shell_none = 1;
890 if (arg_csh || arg_zsh || cfg.shell) {
891 fprintf(stderr, "Error: a shell was already specified\n");
892 return 1;
893 }
894 }
895 else if (strncmp(argv[i], "--shell=", 8) == 0) {
896 if (arg_shell_none) {
897 fprintf(stderr, "Error: --shell=none was already specified.\n");
898 return 1;
899 }
900 if (arg_csh || arg_zsh || cfg.shell) {
901 fprintf(stderr, "Error: only one user shell can be specified\n");
902 return 1;
903 }
904 cfg.shell = argv[i] + 8;
905
906 if (is_dir(cfg.shell) || is_link(cfg.shell) || strstr(cfg.shell, "..")) {
907 fprintf(stderr, "Error: invalid shell\n");
908 exit(1);
909 }
910
911 // access call checks as real UID/GID, not as effective UID/GID
912 if (access(cfg.shell, R_OK)) {
913 fprintf(stderr, "Error: cannot access shell file\n");
914 exit(1);
915 }
916 }
917 else if (strcmp(argv[i], "-c") == 0) {
918 arg_command = 1;
919 if (i == (argc - 1)) {
920 fprintf(stderr, "Error: option -c requires an argument\n");
921 return 1;
922 }
923 }
924 else if (strcmp(argv[i], "--") == 0) {
925 // double dash - positional params to follow
926 arg_doubledash = 1;
927 i++;
928 if (i >= argc) {
929 fprintf(stderr, "Error: program name not found\n");
930 exit(1);
931 }
932 extract_command_name(argv[i]);
933 prog_index = i;
934 cfg.original_program_index = i;
935 break;
936 }
937 else {
938 // is this an invalid option?
939 if (*argv[i] == '-') {
940 fprintf(stderr, "Error: invalid %s command line option\n", argv[i]);
941 return 1;
942 }
943
944 // we have a program name coming
945 extract_command_name(argv[i]);
946 prog_index = i;
947 cfg.original_program_index = i;
948 break;
949 }
950 }
951
952 // check network configuration options - it will exit if anything went wrong
953 net_check_cfg();
954
955 // check user namespace (--noroot) options
956 if (arg_noroot) {
957 if (arg_overlay) {
958 fprintf(stderr, "Error: --overlay and --noroot are mutually exclusive.\n");
959 exit(1);
960 }
961 else if (cfg.chrootdir) {
962 fprintf(stderr, "Error: --chroot and --noroot are mutually exclusive.\n");
963 exit(1);
964 }
965 }
966
967 // log command
968 logargs(argc, argv);
969 if (fullargc) {
970 char *msg;
971 if (asprintf(&msg, "user %s entering restricted shell", cfg.username) == -1)
972 errExit("asprintf");
973 logmsg(msg);
974 free(msg);
975 }
976
977 // build the sandbox command
978 if (prog_index == -1 && arg_zsh) {
979 cfg.command_line = "/usr/bin/zsh";
980 cfg.command_name = "zsh";
981 }
982 else if (prog_index == -1 && arg_csh) {
983 cfg.command_line = "/bin/csh";
984 cfg.command_name = "csh";
985 }
986 else if (prog_index == -1 && cfg.shell) {
987 cfg.command_line = cfg.shell;
988 cfg.command_name = cfg.shell;
989 }
990 else if (prog_index == -1) {
991 cfg.command_line = "/bin/bash";
992 cfg.command_name = "bash";
993 }
994 else {
995 // calculate the length of the command
996 int i;
997 int len = 0;
998 int argcnt = argc - prog_index;
999 for (i = 0; i < argcnt; i++)
1000 len += strlen(argv[i + prog_index]) + 1; // + ' '
1001
1002 // build the string
1003 cfg.command_line = malloc(len + 1); // + '\0'
1004 if (!cfg.command_line)
1005 errExit("malloc");
1006 char *ptr = cfg.command_line;
1007 for (i = 0; i < argcnt; i++) {
1008 sprintf(ptr, "%s ", argv[i + prog_index]);
1009 ptr += strlen(ptr);
1010 }
1011 }
1012
1013 // load the profile
1014 {
1015 assert(cfg.command_name);
1016 if (arg_debug)
1017 printf("Command name #%s#\n", cfg.command_name);
1018 if (!custom_profile) {
1019 // look for a profile in ~/.config/firejail directory
1020 char *usercfgdir;
1021 if (asprintf(&usercfgdir, "%s/.config/firejail", cfg.homedir) == -1)
1022 errExit("asprintf");
1023 int rv = profile_find(cfg.command_name, usercfgdir);
1024 free(usercfgdir);
1025 custom_profile = rv;
1026 }
1027 if (!custom_profile) {
1028 // look for a user profile in /etc/firejail directory
1029 int rv = profile_find(cfg.command_name, "/etc/firejail");
1030 custom_profile = rv;
1031 }
1032 }
1033
1034 // check and assign an IP address - for macvlan it will be done again in the sandbox!
1035 if (any_bridge_configured()) {
1036 lockfd = open("/tmp/firejail/firejail.lock", O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
1037 if (lockfd != -1) {
1038 int rv = fchown(lockfd, 0, 0);
1039 (void) rv;
1040 flock(lockfd, LOCK_EX);
1041 }
1042
1043 check_network(&cfg.bridge0);
1044 check_network(&cfg.bridge1);
1045 check_network(&cfg.bridge2);
1046 check_network(&cfg.bridge3);
1047
1048 // save network mapping in shared memory
1049 network_shm_set_file(sandbox_pid);
1050 }
1051
1052 // create the parent-child communication pipe
1053 if (pipe(parent_to_child_fds) < 0)
1054 errExit("pipe");
1055 if (pipe(child_to_parent_fds) < 0)
1056 errExit("pipe");
1057
1058 // clone environment
1059 int flags = CLONE_NEWNS | CLONE_NEWPID | CLONE_NEWUTS | SIGCHLD;
1060
1061 // in root mode also enable CLONE_NEWIPC
1062 // in user mode CLONE_NEWIPC will break MIT Shared Memory Extension (MIT-SHM)
1063 if (getuid() == 0 || arg_ipc)
1064 flags |= CLONE_NEWIPC;
1065
1066 if (any_bridge_configured() || arg_nonetwork) {
1067 flags |= CLONE_NEWNET;
1068 }
1069 else if (arg_debug)
1070 printf("Using the local network stack\n");
1071
1072 child = clone(sandbox,
1073 child_stack + STACK_SIZE,
1074 flags,
1075 NULL);
1076 if (child == -1)
1077 errExit("clone");
1078
1079 if (!arg_command) {
1080 printf("Parent pid %u, child pid %u\n", sandbox_pid, child);
1081 // print the path of the new log directory
1082 if (getuid() == 0) // only for root
1083 printf("The new log directory is /proc/%d/root/var/log\n", child);
1084 }
1085
1086
1087
1088 // create veth pair or macvlan device
1089 if (cfg.bridge0.configured && !arg_nonetwork) {
1090 if (cfg.bridge0.macvlan == 0)
1091 net_configure_veth_pair(&cfg.bridge0, "eth0", child);
1092 else
1093 net_create_macvlan(cfg.bridge0.devsandbox, cfg.bridge0.dev, child);
1094 }
1095
1096 if (cfg.bridge1.configured && !arg_nonetwork) {
1097 if (cfg.bridge1.macvlan == 0)
1098 net_configure_veth_pair(&cfg.bridge1, "eth1", child);
1099 else
1100 net_create_macvlan(cfg.bridge1.devsandbox, cfg.bridge1.dev, child);
1101 }
1102
1103 if (cfg.bridge2.configured && !arg_nonetwork) {
1104 if (cfg.bridge2.macvlan == 0)
1105 net_configure_veth_pair(&cfg.bridge2, "eth2", child);
1106 else
1107 net_create_macvlan(cfg.bridge2.devsandbox, cfg.bridge2.dev, child);
1108 }
1109
1110 if (cfg.bridge3.configured && !arg_nonetwork) {
1111 if (cfg.bridge3.macvlan == 0)
1112 net_configure_veth_pair(&cfg.bridge3, "eth3", child);
1113 else
1114 net_create_macvlan(cfg.bridge3.devsandbox, cfg.bridge3.dev, child);
1115 }
1116
1117 // close each end of the unused pipes
1118 close(parent_to_child_fds[0]);
1119 close(child_to_parent_fds[1]);
1120
1121 // notify child that base setup is complete
1122 notify_other(parent_to_child_fds[1]);
1123
1124 // wait for child to create new user namespace with CLONE_NEWUSER
1125 wait_for_other(child_to_parent_fds[0]);
1126 close(child_to_parent_fds[0]);
1127
1128 if (arg_noroot) {
1129 // update the UID and GID maps in the new child user namespace
1130 // uid
1131 char *map_path;
1132 if (asprintf(&map_path, "/proc/%d/uid_map", child) == -1)
1133 errExit("asprintf");
1134 char *map;
1135 uid_t uid = getuid();
1136 if (asprintf(&map, "%d %d 1", uid, uid) == -1)
1137 errExit("asprintf");
1138 update_map(map, map_path);
1139 free(map);
1140 free(map_path);
1141
1142 //gid
1143 if (asprintf(&map_path, "/proc/%d/gid_map", child) == -1)
1144 errExit("asprintf");
1145 gid_t gid = getgid();
1146 if (asprintf(&map, "%d %d 1", gid, gid) == -1)
1147 errExit("asprintf");
1148 update_map(map, map_path);
1149 free(map);
1150 free(map_path);
1151 }
1152
1153 // notify child that UID/GID mapping is complete
1154 notify_other(parent_to_child_fds[1]);
1155 close(parent_to_child_fds[1]);
1156
1157 if (lockfd != -1)
1158 flock(lockfd, LOCK_UN);
1159
1160 // handle CTRL-C in parent
1161 signal (SIGINT, my_handler);
1162 signal (SIGTERM, my_handler);
1163
1164 // wait for the child to finish
1165 waitpid(child, NULL, 0);
1166 myexit(0);
1167 return 0;
1168}
diff --git a/src/firejail/netfilter.c b/src/firejail/netfilter.c
new file mode 100644
index 000000000..dbed4ac30
--- /dev/null
+++ b/src/firejail/netfilter.c
@@ -0,0 +1,164 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
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#include "firejail.h"
21#include <sys/mount.h>
22#include <sys/stat.h>
23#include <sys/types.h>
24#include <sys/wait.h>
25#include <fcntl.h>
26
27static char *client_filter =
28"*filter\n"
29":INPUT DROP [0:0]\n"
30":FORWARD DROP [0:0]\n"
31":OUTPUT ACCEPT [0:0]\n"
32"-A INPUT -i lo -j ACCEPT\n"
33"# echo replay is handled by -m state RELEATED/ESTABLISHED below\n"
34"#-A INPUT -p icmp --icmp-type echo-reply -j ACCEPT\n"
35"-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n"
36"-A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT\n"
37"-A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT\n"
38"-A INPUT -p icmp --icmp-type echo-request -j ACCEPT \n"
39"COMMIT\n";
40
41void check_netfilter_file(const char *fname) {
42 if (is_dir(fname) || is_link(fname) || strstr(fname, "..")) {
43 fprintf(stderr, "Error: invalid network filter file\n");
44 exit(1);
45 }
46
47 // access call checks as real UID/GID, not as effective UID/GID
48 if (access(fname, R_OK)) {
49 fprintf(stderr, "Error: cannot access network filter file\n");
50 exit(1);
51 }
52}
53
54
55void netfilter(const char *fname) {
56 // default filter
57 char *filter = client_filter;
58
59 // custom filter
60 int allocated = 0;
61 if (fname) {
62 // buffer the filter
63 struct stat s;
64 if (stat(fname, &s) == -1) {
65 fprintf(stderr, "Error: cannot find network filter file\n");
66 exit(1);
67 }
68
69 filter = malloc(s.st_size + 1); // + '\0'
70 memset(filter, 0, s.st_size + 1);
71 if (!filter)
72 errExit("malloc");
73
74 /* coverity[toctou] */
75 FILE *fp = fopen(fname, "r");
76 if (!fp) {
77 fprintf(stderr, "Error: cannot open network filter file\n");
78 exit(1);
79 }
80
81 size_t sz = fread(filter, 1, s.st_size, fp);
82 if (sz != s.st_size) {
83 fprintf(stderr, "Error: cannot read network filter file\n");
84 exit(1);
85 }
86 fclose(fp);
87 allocated = 1;
88 }
89
90 // mount a tempfs on top of /tmp directory
91 if (mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
92 errExit("mounting /tmp");
93
94 // create the filter file
95 FILE *fp = fopen("/tmp/netfilter", "w");
96 if (!fp) {
97 fprintf(stderr, "Error: cannot open /tmp/netfilter file\n");
98 exit(1);
99 }
100 fprintf(fp, "%s\n", filter);
101 fclose(fp);
102
103 // find iptables command
104 struct stat s;
105 char *iptables = NULL;
106 char *iptables_restore = NULL;
107 if (stat("/sbin/iptables", &s) == 0) {
108 iptables = "/sbin/iptables";
109 iptables_restore = "/sbin/iptables-restore";
110 }
111 else if (stat("/usr/sbin/iptables", &s) == 0) {
112 iptables = "/usr/sbin/iptables";
113 iptables_restore = "/usr/sbin/iptables-restore";
114 }
115 if (iptables == NULL || iptables_restore == NULL) {
116 fprintf(stderr, "Error: iptables command not found\n");
117 goto doexit;
118 }
119
120 // push filter
121 pid_t child = fork();
122 if (child < 0)
123 errExit("fork");
124 if (child == 0) {
125 if (arg_debug)
126 printf("Installing network filter:\n%s\n", filter);
127
128 int fd;
129 if((fd = open("/tmp/netfilter", O_RDONLY)) == -1) {
130 fprintf(stderr,"Error: cannot open /tmp/netfilter\n");
131 exit(1);
132 }
133 dup2(fd,STDIN_FILENO);
134 close(fd);
135
136 // wipe out environment variables
137 environ = NULL;
138 execl(iptables_restore, iptables_restore, NULL);
139 // it will never get here!!!
140 }
141 // wait for the child to finish
142 waitpid(child, NULL, 0);
143
144 // debug
145 if (arg_debug) {
146 child = fork();
147 if (child < 0)
148 errExit("fork");
149 if (child == 0) {
150 environ = NULL;
151 execl(iptables, iptables, "-vL", NULL);
152 // it will never get here!!!
153 }
154 // wait for the child to finish
155 waitpid(child, NULL, 0);
156 }
157
158doexit:
159 // unmount /tmp
160 umount("/tmp");
161
162 if (allocated)
163 free(filter);
164}
diff --git a/src/firejail/network.c b/src/firejail/network.c
new file mode 100644
index 000000000..6a1d52744
--- /dev/null
+++ b/src/firejail/network.c
@@ -0,0 +1,362 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
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#include "firejail.h"
21#include <arpa/inet.h>
22#include <sys/socket.h>
23#include <sys/ioctl.h>
24#include <netdb.h>
25#include <ifaddrs.h>
26#include <net/if.h>
27#include <net/if_arp.h>
28#include <net/route.h>
29#include <linux/if_bridge.h>
30
31// scan interfaces in current namespace and print IP address/mask for each interface
32void net_ifprint(void) {
33 uint32_t ip;
34 uint32_t mask;
35 struct ifaddrs *ifaddr, *ifa;
36
37 if (getifaddrs(&ifaddr) == -1)
38 errExit("getifaddrs");
39
40 printf("%-17.17s%-19.19s%-17.17s%-17.17s%-6.6s\n",
41 "Interface", "MAC", "IP", "Mask", "Status");
42 // walk through the linked list
43 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
44 if (ifa->ifa_addr == NULL)
45 continue;
46
47 if (ifa->ifa_addr->sa_family == AF_INET) {
48 struct sockaddr_in *si = (struct sockaddr_in *) ifa->ifa_netmask;
49 mask = ntohl(si->sin_addr.s_addr);
50 si = (struct sockaddr_in *) ifa->ifa_addr;
51 ip = ntohl(si->sin_addr.s_addr);
52
53 // interface status
54 char *status;
55 if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP)
56 status = "UP";
57 else
58 status = "DOWN";
59
60 // ip address and mask
61 char ipstr[30];
62 sprintf(ipstr, "%d.%d.%d.%d", PRINT_IP(ip));
63 char maskstr[30];
64 sprintf(maskstr, "%d.%d.%d.%d", PRINT_IP(mask));
65
66 // mac address
67 unsigned char mac[6];
68 net_get_mac(ifa->ifa_name, mac);
69 char macstr[30];
70 if (strcmp(ifa->ifa_name, "lo") == 0)
71 macstr[0] = '\0';
72 else
73 sprintf(macstr, "%02x:%02x:%02x:%02x:%02x:%02x", PRINT_MAC(mac));
74
75 // print
76 printf("%-17.17s%-19.19s%-17.17s%-17.17s%-6.6s\n",
77 ifa->ifa_name, macstr, ipstr, maskstr, status);
78
79 // network scanning
80 if (!arg_scan) // scanning disabled
81 continue;
82 if (strcmp(ifa->ifa_name, "lo") == 0) // no loopbabck scanning
83 continue;
84 if (mask2bits(mask) < 16) // not scanning large networks
85 continue;
86 if (!ip) // if not configured
87 continue;
88 // only if the interface is up and running
89 if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP)
90 arp_scan(ifa->ifa_name, ip, mask);
91 }
92 }
93 freeifaddrs(ifaddr);
94}
95
96
97// return -1 if the interface was not found; if the interface was found retrn 0 and fill in IP address and mask
98int net_get_if_addr(const char *bridge, uint32_t *ip, uint32_t *mask, uint8_t mac[6]) {
99 assert(bridge);
100 assert(ip);
101 assert(mask);
102 int rv = -1;
103 struct ifaddrs *ifaddr, *ifa;
104
105 if (getifaddrs(&ifaddr) == -1)
106 errExit("getifaddrs");
107
108 // walk through the linked list; if the interface is found, extract IP address and mask
109 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
110 if (ifa->ifa_addr == NULL)
111 continue;
112 if (strcmp(ifa->ifa_name, bridge) != 0)
113 continue;
114
115 if (ifa->ifa_addr->sa_family == AF_INET) {
116 struct sockaddr_in *si = (struct sockaddr_in *) ifa->ifa_netmask;
117 *mask = ntohl(si->sin_addr.s_addr);
118 si = (struct sockaddr_in *) ifa->ifa_addr;
119 *ip = ntohl(si->sin_addr.s_addr);
120 if (strcmp(ifa->ifa_name, "lo") != 0)
121 net_get_mac(ifa->ifa_name, mac);
122
123 rv = 0;
124 break;
125 }
126 }
127
128 freeifaddrs(ifaddr);
129 return rv;
130}
131
132// bring interface up
133void net_if_up(const char *ifname) {
134 if (strlen(ifname) > IFNAMSIZ) {
135 fprintf(stderr, "Error: invalid network device name %s\n", ifname);
136 exit(1);
137 }
138
139 int sock = socket(AF_INET,SOCK_DGRAM,0);
140 if (sock < 0)
141 errExit("socket");
142
143 // get the existing interface flags
144 struct ifreq ifr;
145 memset(&ifr, 0, sizeof(ifr));
146 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
147 ifr.ifr_addr.sa_family = AF_INET;
148
149 // read the existing flags
150 if (ioctl(sock, SIOCGIFFLAGS, &ifr ) < 0) {
151 close(sock);
152 errExit("ioctl");
153 }
154
155 ifr.ifr_flags |= IFF_UP;
156
157 // set the new flags
158 if (ioctl( sock, SIOCSIFFLAGS, &ifr ) < 0) {
159 close(sock);
160 errExit("ioctl");
161 }
162
163 // checking
164 // read the existing flags
165 if (ioctl(sock, SIOCGIFFLAGS, &ifr ) < 0) {
166 close(sock);
167 errExit("ioctl");
168 }
169
170 // wait not more than 500ms for the interface to come up
171 int cnt = 0;
172 while (cnt < 50) {
173 usleep(10000); // sleep 10ms
174
175 // read the existing flags
176 if (ioctl(sock, SIOCGIFFLAGS, &ifr ) < 0) {
177 close(sock);
178 errExit("ioctl");
179 }
180 if (ifr.ifr_flags & IFF_RUNNING)
181 break;
182 cnt++;
183 }
184
185 close(sock);
186}
187
188// configure interface
189void net_if_ip(const char *ifname, uint32_t ip, uint32_t mask) {
190 if (strlen(ifname) > IFNAMSIZ) {
191 fprintf(stderr, "Error: invalid network device name %s\n", ifname);
192 exit(1);
193 }
194
195 int sock = socket(AF_INET,SOCK_DGRAM,0);
196 if (sock < 0)
197 errExit("socket");
198
199 struct ifreq ifr;
200 memset(&ifr, 0, sizeof(ifr));
201 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
202 ifr.ifr_addr.sa_family = AF_INET;
203
204 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr = htonl(ip);
205 if (ioctl( sock, SIOCSIFADDR, &ifr ) < 0) {
206 close(sock);
207 errExit("ioctl");
208 }
209
210 if (ip != 0) {
211 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr = htonl(mask);
212 if (ioctl( sock, SIOCSIFNETMASK, &ifr ) < 0) {
213 close(sock);
214 errExit("ioctl");
215 }
216 }
217
218 close(sock);
219 usleep(10000); // sleep 10ms
220}
221
222
223// add an IP route, return -1 if error, 0 if the route was added
224int net_add_route(uint32_t ip, uint32_t mask, uint32_t gw) {
225 int sock;
226 struct rtentry route;
227 struct sockaddr_in *addr;
228 int err = 0;
229
230 // create the socket
231 if((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
232 errExit("socket");
233
234 memset(&route, 0, sizeof(route));
235
236 addr = (struct sockaddr_in*) &route.rt_gateway;
237 addr->sin_family = AF_INET;
238 addr->sin_addr.s_addr = htonl(gw);
239
240 addr = (struct sockaddr_in*) &route.rt_dst;
241 addr->sin_family = AF_INET;
242 addr->sin_addr.s_addr = htonl(ip);
243
244 addr = (struct sockaddr_in*) &route.rt_genmask;
245 addr->sin_family = AF_INET;
246 addr->sin_addr.s_addr = htonl(mask);
247
248 route.rt_flags = RTF_UP | RTF_GATEWAY;
249 route.rt_metric = 0;
250 if ((err = ioctl(sock, SIOCADDRT, &route)) != 0) {
251 close(sock);
252 return -1;
253 }
254
255 close(sock);
256 return 0;
257}
258
259
260// add a veth device to a bridge
261void net_bridge_add_interface(const char *bridge, const char *dev) {
262 if (strlen(bridge) > IFNAMSIZ) {
263 fprintf(stderr, "Error: invalid network device name %s\n", bridge);
264 exit(1);
265 }
266
267 struct ifreq ifr;
268 int err;
269 int ifindex = if_nametoindex(dev);
270
271 if (ifindex <= 0)
272 errExit("if_nametoindex");
273
274 int sock;
275 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
276 errExit("socket");
277
278 memset(&ifr, 0, sizeof(ifr));
279 strncpy(ifr.ifr_name, bridge, IFNAMSIZ);
280#ifdef SIOCBRADDIF
281 ifr.ifr_ifindex = ifindex;
282 err = ioctl(sock, SIOCBRADDIF, &ifr);
283 if (err < 0)
284#endif
285 {
286 unsigned long args[4] = { BRCTL_ADD_IF, ifindex, 0, 0 };
287
288 ifr.ifr_data = (char *) args;
289 err = ioctl(sock, SIOCDEVPRIVATE, &ifr);
290 }
291 (void) err;
292 close(sock);
293}
294
295#define BUFSIZE 1024
296uint32_t network_get_defaultgw(void) {
297 FILE *fp = fopen("/proc/self/net/route", "r");
298 if (!fp)
299 errExit("fopen");
300
301 char buf[BUFSIZE];
302 uint32_t retval = 0;
303 while (fgets(buf, BUFSIZE, fp)) {
304 if (strncmp(buf, "Iface", 5) == 0)
305 continue;
306
307 char *ptr = buf;
308 while (*ptr != ' ' && *ptr != '\t')
309 ptr++;
310 while (*ptr == ' ' || *ptr == '\t')
311 ptr++;
312
313 unsigned dest;
314 unsigned gw;
315 int rv = sscanf(ptr, "%x %x", &dest, &gw);
316 if (rv == 2 && dest == 0) {
317 retval = ntohl(gw);
318 break;
319 }
320 }
321
322 fclose(fp);
323 return retval;
324}
325
326int net_config_mac(const char *ifname, const unsigned char mac[6]) {
327 struct ifreq ifr;
328 int sock;
329
330 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
331 errExit("socket");
332
333 memset(&ifr, 0, sizeof(ifr));
334 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
335 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
336 memcpy(ifr.ifr_hwaddr.sa_data, mac, 6);
337
338 if (ioctl(sock, SIOCSIFHWADDR, &ifr) == -1)
339 errExit("ioctl");
340 close(sock);
341 return 0;
342}
343
344int net_get_mac(const char *ifname, unsigned char mac[6]) {
345
346 struct ifreq ifr;
347 int sock;
348
349 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
350 errExit("socket");
351
352 memset(&ifr, 0, sizeof(ifr));
353 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
354 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
355
356 if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1)
357 errExit("ioctl");
358 memcpy(mac, ifr.ifr_hwaddr.sa_data, 6);
359
360 close(sock);
361 return 0;
362}
diff --git a/src/firejail/network.txt b/src/firejail/network.txt
new file mode 100644
index 000000000..673d5b941
--- /dev/null
+++ b/src/firejail/network.txt
@@ -0,0 +1,95 @@
1struct Bridge {
2 char *dev; // bridge device name
3 uint32_t ip; // bridge device IP address
4 uint32_t mask; // bridge device mask
5 uint32_t ipsandbox // sandbox interface IP address
6}
7
8net_configure_bridge(br, device) {
9 br->dev = devname;
10 br->ip = extracted from kernel device - using net_get_if_addr() in network.c
11 br->mask = extracted from kernel device - using net_get_if_addr() in network.c
12 check available network range; /31 networks are not supported
13}
14
15net_configure_sandbox_ip(br) {
16 if br->ip_snadbox
17 check br->ipsandbox inside the bridge network
18 arp_check(br->ipsandbox) // send an arp req to check if anybody else is using this address
19 else
20 br->ipsandbox = arp_assign();
21}
22
23net_configure_veth_pair {
24 create a veth pair
25 place one interface end in the bridge
26 place the other end in the namespace of the child process
27}
28
29net_bridge_wait_ip {
30 arp_check br->ipsandbox address to come up
31 wait for not more than 5 seconds
32}
33
34main() {
35
36 foreach argv[i] {
37 if --net
38 br = next bridge available
39 net_configure_bridge(br, device name from argv[i]);
40 else if --ip
41 br = last bridge configured
42 br->ipsandbox = ip address extracted from argv[i]
43 else if --defaultgw
44 cfg.defaultgw = ip address extracted from argv[i]
45 }
46
47 net_check_cfg(); // check the validity of network configuration so far
48
49 if (any bridge configured) {
50 lock /var/lock/firejail.lock file
51 for each bridge
52 net_configure_sandbox_ip(br)
53 }
54
55 clone (new network namespace if any bridge configured or --net=none)
56
57 if (any bridge configured) {
58 for each bridge
59 net_configure_veth_pair
60 }
61
62 notify child init is done
63
64 if (any bridge configured) {
65 for each bridge
66 net_bridge_wait_ip
67 unlock /var/lock/firejail.lock file
68 }
69
70 wait on child
71 exit
72}
73
74
75******************************************************
76* macvlan notes
77******************************************************
78Configure a macvlan interface
79
80# ip link add virtual0 link eth0 type macvlan mode bridge
81(you can configure it with # ifconfig virtual0 192.168.1.52/24 up)
82
83Create a new network namespace and move the interface in the new network namespace
84
85# ip netns add dummy0
86# ip link set virtual0 netns dummy0
87
88Join the namespace and configure the interfaces
89
90# ip netns exec dummy0 bash
91# ifconfig lo up
92# ifconfig virtual0 192.168.1.52/24
93
94Investigate ipvlan interface - added to linux kernel 3.19
95https://github.com/torvalds/linux/blob/master/Documentation/networking/ipvlan.txt
diff --git a/src/firejail/network_main.c b/src/firejail/network_main.c
new file mode 100644
index 000000000..c2459b0cd
--- /dev/null
+++ b/src/firejail/network_main.c
@@ -0,0 +1,268 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
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#include "firejail.h"
22#include <sys/types.h>
23#include <sys/stat.h>
24#include <unistd.h>
25#include <net/if.h>
26
27// configure bridge structure
28// - extract ip address and mask from the bridge interface
29void net_configure_bridge(Bridge *br, char *dev_name) {
30 assert(br);
31 assert(dev_name);
32
33 br->dev = dev_name;
34
35 // check the bridge device exists
36 char sysbridge[30 + strlen(br->dev)];
37 sprintf(sysbridge, "/sys/class/net/%s/bridge", br->dev);
38 struct stat s;
39 int rv = stat(sysbridge, &s);
40 if (rv == 0) {
41 // this is a bridge device
42 br->macvlan = 0;
43 }
44 else {
45 // is this a regular Ethernet interface
46 if (if_nametoindex(br->dev) > 0) {
47 br->macvlan = 1;
48 char *newname;
49 if (asprintf(&newname, "%s-%u", br->devsandbox, getpid()) == -1)
50 errExit("asprintf");
51 br->devsandbox = newname;
52 }
53 else {
54 fprintf(stderr, "Error: cannot find network device %s\n", br->dev);
55 exit(1);
56 }
57 }
58
59 if (net_get_if_addr(br->dev, &br->ip, &br->mask, br->mac)) {
60 fprintf(stderr, "Error: interface %s is not configured\n", br->dev);
61 exit(1);
62 }
63 if (arg_debug) {
64 if (br->macvlan == 0)
65 printf("Bridge device %s at %d.%d.%d.%d/%d\n",
66 br->dev, PRINT_IP(br->ip), mask2bits(br->mask));
67 else
68 printf("macvlan parent device %s at %d.%d.%d.%d/%d\n",
69 br->dev, PRINT_IP(br->ip), mask2bits(br->mask));
70 }
71
72 uint32_t range = ~br->mask + 1; // the number of potential addresses
73 // this software is not supported for /31 networks
74 if (range < 4) {
75 fprintf(stderr, "Error: the software is not supported for /31 networks\n");
76 exit(1);
77 }
78 br->configured = 1;
79}
80
81
82void net_configure_sandbox_ip(Bridge *br) {
83 assert(br);
84 if (br->configured == 0)
85 return;
86
87 if (br->arg_ip_none)
88 br->ipsandbox = 0;
89 else if (br->ipsandbox) {
90 // check network range
91 char *rv = in_netrange(br->ipsandbox, br->ip, br->mask);
92 if (rv) {
93 fprintf(stderr, "%s", rv);
94 exit(1);
95 }
96 // send an ARP request and check if there is anybody on this IP address
97 if (arp_check(br->dev, br->ipsandbox, br->ip)) {
98 fprintf(stderr, "Error: IP address %d.%d.%d.%d is already in use\n", PRINT_IP(br->ipsandbox));
99 exit(1);
100 }
101 }
102 else
103 // ip address assigned by arp-scan for a bridge device
104 br->ipsandbox = arp_assign(br->dev, br); //br->ip, br->mask);
105}
106
107
108// create a veth pair
109// - br - bridge device
110// - ifname - interface name in sandbox namespace
111// - child - child process running the namespace
112
113void net_configure_veth_pair(Bridge *br, const char *ifname, pid_t child) {
114 assert(br);
115 if (br->configured == 0)
116 return;
117
118 // create a veth pair
119 char *dev;
120 if (asprintf(&dev, "veth%u%s", getpid(), ifname) < 0)
121 errExit("asprintf");
122 net_create_veth(dev, ifname, child);
123
124 // bring up the interface
125 net_if_up(dev);
126
127 // add interface to the bridge
128 net_bridge_add_interface(br->dev, dev);
129
130 char *msg;
131 if (asprintf(&msg, "%d.%d.%d.%d address assigned to sandbox", PRINT_IP(br->ipsandbox)) == -1)
132 errExit("asprintf");
133 logmsg(msg);
134 fflush(0);
135 free(msg);
136}
137
138// the default address should be in the range of at least on of the bridge devices
139void check_default_gw(uint32_t defaultgw) {
140 assert(defaultgw);
141
142 if (cfg.bridge0.configured) {
143 char *rv = in_netrange(defaultgw, cfg.bridge0.ip, cfg.bridge0.mask);
144 if (rv == 0)
145 return;
146 }
147 if (cfg.bridge1.configured) {
148 char *rv = in_netrange(defaultgw, cfg.bridge1.ip, cfg.bridge1.mask);
149 if (rv == 0)
150 return;
151 }
152 if (cfg.bridge2.configured) {
153 char *rv = in_netrange(defaultgw, cfg.bridge2.ip, cfg.bridge2.mask);
154 if (rv == 0)
155 return;
156 }
157 if (cfg.bridge3.configured) {
158 char *rv = in_netrange(defaultgw, cfg.bridge3.ip, cfg.bridge3.mask);
159 if (rv == 0)
160 return;
161 }
162
163 fprintf(stderr, "Error: default gateway %d.%d.%d.%d is not in the range of any network\n", PRINT_IP(defaultgw));
164 exit(1);
165}
166
167void net_check_cfg(void) {
168 int net_configured = 0;
169 if (cfg.bridge0.configured)
170 net_configured++;
171 if (cfg.bridge1.configured)
172 net_configured++;
173 if (cfg.bridge2.configured)
174 net_configured++;
175 if (cfg.bridge3.configured)
176 net_configured++;
177
178 // --defaultgw requires a network
179 if (cfg.defaultgw && net_configured == 0) {
180 fprintf(stderr, "Error: option --defaultgw requires at least one network to be configured\n");
181 exit(1);
182 }
183
184 if (net_configured == 0) // nothing to check
185 return;
186
187 // --net=none
188 if (arg_nonetwork && net_configured) {
189 fprintf(stderr, "Error: --net and --net=none are mutually exclusive\n");
190 exit(1);
191 }
192
193 // check default gateway address or assign one
194 assert(cfg.bridge0.configured);
195 if (cfg.defaultgw)
196 check_default_gw(cfg.defaultgw);
197 else {
198 // first network is a regular bridge
199 if (cfg.bridge0.macvlan == 0)
200 cfg.defaultgw = cfg.bridge0.ip;
201 // first network is a mac device
202 else {
203 // get the host default gw
204 uint32_t gw = network_get_defaultgw();
205 // check the gateway is network range
206 if (in_netrange(gw, cfg.bridge0.ip, cfg.bridge0.mask))
207 gw = 0;
208 cfg.defaultgw = gw;
209 }
210 }
211}
212
213
214
215void net_dns_print_name(const char *name) {
216 if (!name || strlen(name) == 0) {
217 fprintf(stderr, "Error: invalid sandbox name\n");
218 exit(1);
219 }
220 pid_t pid;
221 if (name2pid(name, &pid)) {
222 fprintf(stderr, "Error: cannot find sandbox %s\n", name);
223 exit(1);
224 }
225
226 net_dns_print(pid);
227}
228
229#define MAXBUF 4096
230void net_dns_print(pid_t pid) {
231 // drop privileges - will not be able to read /etc/resolv.conf for --noroot option
232// drop_privs(1);
233
234 // if the pid is that of a firejail process, use the pid of the first child process
235 char *comm = pid_proc_comm(pid);
236 if (comm) {
237 // remove \n
238 char *ptr = strchr(comm, '\n');
239 if (ptr)
240 *ptr = '\0';
241 if (strcmp(comm, "firejail") == 0) {
242 pid_t child;
243 if (find_child(pid, &child) == 0) {
244 pid = child;
245 }
246 }
247 free(comm);
248 }
249
250 char *fname;
251 if (asprintf(&fname, "/proc/%d/root/etc/resolv.conf", pid) == -1)
252 errExit("asprintf");
253
254 // access /etc/resolv.conf
255 FILE *fp = fopen(fname, "r");
256 if (!fp) {
257 fprintf(stderr, "Error: cannot access /etc/resolv.conf\n");
258 exit(1);
259 }
260
261 char buf[MAXBUF];
262 while (fgets(buf, MAXBUF, fp))
263 printf("%s", buf);
264 printf("\n");
265 fclose(fp);
266 free(fname);
267 exit(0);
268}
diff --git a/src/firejail/output.c b/src/firejail/output.c
new file mode 100644
index 000000000..32adac108
--- /dev/null
+++ b/src/firejail/output.c
@@ -0,0 +1,84 @@
1#include "firejail.h"
2#include <sys/types.h>
3#include <sys/stat.h>
4#include <unistd.h>
5
6void check_output(int argc, char **argv) {
7 int i;
8 char *outfile = NULL;
9// drop_privs(0);
10
11 int found = 0;
12 for (i = 1; i < argc; i++) {
13 if (strncmp(argv[i], "--output=", 9) == 0) {
14 found = 1;
15 outfile = argv[i] + 9;
16
17 // do not accept directories, links, and files with ".."
18 if (strstr(outfile, "..") || is_link(outfile) || is_dir(outfile)) {
19 fprintf(stderr, "Error: invalid output file. Links, directories and files with \"..\" are not allowed.\n");
20 exit(1);
21 }
22
23 struct stat s;
24 if (stat(outfile, &s) == 0) {
25 // check permissions
26 if (s.st_uid != getuid() || s.st_gid != getgid()) {
27 fprintf(stderr, "Error: the output file needs to be owned by the current user.\n");
28 exit(1);
29 }
30
31 // check hard links
32 if (s.st_nlink != 1) {
33 fprintf(stderr, "Error: no hard links allowed.\n");
34 exit(1);
35 }
36 }
37
38 // drop privileges and try to open the file for writing
39 drop_privs(0);
40 /* coverity[toctou] */
41 FILE *fp = fopen(outfile, "a");
42 if (!fp) {
43 fprintf(stderr, "Error: cannot open output file %s\n", outfile);
44 exit(1);
45 }
46 fclose(fp);
47 break;
48 }
49 }
50 if (!found)
51 return;
52
53
54 // build the new command line
55 int len = 0;
56 for (i = 0; i < argc; i++) {
57 len += strlen(argv[i]) + 1; // + ' '
58 }
59 len += 50 + strlen(outfile); // tee command
60
61 char *cmd = malloc(len + 1); // + '\0'
62 if (!cmd)
63 errExit("malloc");
64
65 char *ptr = cmd;
66 for (i = 0; i < argc; i++) {
67 if (strncmp(argv[i], "--output=", 9) == 0)
68 continue;
69 ptr += sprintf(ptr, "%s ", argv[i]);
70 }
71 sprintf(ptr, "| %s/lib/firejail/ftee %s", PREFIX, outfile);
72
73 // run command
74 char *a[4];
75 a[0] = "/bin/bash";
76 a[1] = "-c";
77 a[2] = cmd;
78 a[3] = NULL;
79
80 execvp(a[0], a);
81
82 perror("execvp");
83 exit(1);
84}
diff --git a/src/firejail/profile.c b/src/firejail/profile.c
new file mode 100644
index 000000000..343907584
--- /dev/null
+++ b/src/firejail/profile.c
@@ -0,0 +1,444 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
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#include "firejail.h"
21#include <dirent.h>
22#include <sys/stat.h>
23
24#define MAX_READ 8192 // line buffer for profile files
25
26// find and read the profile specified by name from dir directory
27int profile_find(const char *name, const char *dir) {
28 assert(name);
29 assert(dir);
30
31 int rv = 0;
32 DIR *dp;
33 char *pname;
34 if (asprintf(&pname, "%s.profile", name) == -1)
35 errExit("asprintf");
36
37 dp = opendir (dir);
38 if (dp != NULL) {
39 struct dirent *ep;
40 while ((ep = readdir(dp)) != NULL) {
41 if (strcmp(ep->d_name, pname) == 0) {
42 if (arg_debug)
43 printf("Found %s profile in %s directory\n", name, dir);
44 char *etcpname;
45 if (asprintf(&etcpname, "%s/%s", dir, pname) == -1)
46 errExit("asprintf");
47 profile_read(etcpname, NULL, NULL);
48 free(etcpname);
49 rv = 1;
50 break;
51 }
52 }
53 (void) closedir (dp);
54 }
55
56 free(pname);
57 return rv;
58}
59
60
61//***************************************************
62// run-time profiles
63//***************************************************
64static void check_file_name(char *ptr, int lineno) {
65 if (strncmp(ptr, "${HOME}", 7) == 0)
66 ptr += 7;
67 else if (strncmp(ptr, "${PATH}", 7) == 0)
68 ptr += 7;
69
70 int len = strlen(ptr);
71 // file globbing ('*') is allowed
72 if (strcspn(ptr, "\\&!?\"'<>%^(){}[];, ") != len) {
73 if (lineno == 0)
74 fprintf(stderr, "Error: \"%s\" is an invalid filename\n", ptr);
75 else
76 fprintf(stderr, "Error: line %d in the custom profile is invalid\n", lineno);
77 exit(1);
78 }
79}
80
81
82// check profile line; if line == 0, this was generated from a command line option
83// return 1 if the command is to be added to the linked list of profile commands
84// return 0 if the command was already executed inside the function
85int profile_check_line(char *ptr, int lineno) {
86 // seccomp, caps, private, user namespace
87 if (strcmp(ptr, "noroot") == 0) {
88 check_user_namespace();
89 return 0;
90 }
91 else if (strcmp(ptr, "seccomp") == 0) {
92 arg_seccomp = 1;
93 return 0;
94 }
95 else if (strcmp(ptr, "caps") == 0) {
96 arg_caps_default_filter = 1;
97 return 0;
98 }
99 else if (strcmp(ptr, "caps.drop all") == 0) {
100 arg_caps_drop_all = 1;
101 return 0;
102 }
103 else if (strcmp(ptr, "shell none") == 0) {
104 arg_shell_none = 1;
105 return 0;
106 }
107 else if (strcmp(ptr, "private") == 0) {
108 arg_private = 1;
109 return 0;
110 }
111 else if (strcmp(ptr, "private-dev") == 0) {
112 arg_private_dev = 1;
113 return 0;
114 }
115 else if (strcmp(ptr, "nogroups") == 0) {
116 arg_nogroups = 1;
117 return 0;
118 }
119 else if (strcmp(ptr, "netfilter") == 0) {
120 arg_netfilter = 1;
121 return 0;
122 }
123 else if (strncmp(ptr, "netfilter ", 10) == 0) {
124 arg_netfilter = 1;
125 arg_netfilter_file = strdup(ptr + 10);
126 if (!arg_netfilter_file)
127 errExit("strdup");
128 check_netfilter_file(arg_netfilter_file);
129 return 0;
130 }
131
132 // seccomp drop list on top of default list
133 if (strncmp(ptr, "seccomp ", 8) == 0) {
134 arg_seccomp = 1;
135#ifdef HAVE_SECCOMP
136 arg_seccomp_list = strdup(ptr + 8);
137 if (!arg_seccomp_list)
138 errExit("strdup");
139#endif
140 return 0;
141 }
142
143 // seccomp drop list without default list
144 if (strncmp(ptr, "seccomp.drop ", 13) == 0) {
145 arg_seccomp = 1;
146#ifdef HAVE_SECCOMP
147 arg_seccomp_list_drop = strdup(ptr + 13);
148 if (!arg_seccomp_list_drop)
149 errExit("strdup");
150#endif
151 return 0;
152 }
153
154 // seccomp keep list
155 if (strncmp(ptr, "seccomp.keep ", 13) == 0) {
156 arg_seccomp = 1;
157#ifdef HAVE_SECCOMP
158 arg_seccomp_list_keep= strdup(ptr + 13);
159 if (!arg_seccomp_list_keep)
160 errExit("strdup");
161#endif
162 return 0;
163 }
164
165 // caps drop list
166 if (strncmp(ptr, "caps.drop ", 10) == 0) {
167 arg_caps_drop = 1;
168 arg_caps_list = strdup(ptr + 10);
169 if (!arg_caps_list)
170 errExit("strdup");
171 // verify seccomp list and exit if problems
172 if (caps_check_list(arg_caps_list, NULL))
173 exit(1);
174 return 0;
175 }
176
177 // caps keep list
178 if (strncmp(ptr, "caps.keep ", 10) == 0) {
179 arg_caps_keep = 1;
180 arg_caps_list = strdup(ptr + 10);
181 if (!arg_caps_list)
182 errExit("strdup");
183 // verify seccomp list and exit if problems
184 if (caps_check_list(arg_caps_list, NULL))
185 exit(1);
186 return 0;
187 }
188
189 // dns
190 if (strncmp(ptr, "dns ", 4) == 0) {
191 uint32_t dns;
192 if (atoip(ptr + 4, &dns)) {
193 fprintf(stderr, "Error: invalid DNS server IP address\n");
194 return 1;
195 }
196
197 if (cfg.dns1 == 0)
198 cfg.dns1 = dns;
199 else if (cfg.dns2 == 0)
200 cfg.dns2 = dns;
201 else if (cfg.dns3 == 0)
202 cfg.dns3 = dns;
203 else {
204 fprintf(stderr, "Error: up to 3 DNS servers can be specified\n");
205 return 1;
206 }
207 return 0;
208 }
209
210 // cpu affinity
211 if (strncmp(ptr, "cpu ", 4) == 0) {
212 read_cpu_list(ptr + 4);
213 return 0;
214 }
215
216 // cgroup
217 if (strncmp(ptr, "cgroup ", 7) == 0) {
218 set_cgroup(ptr + 7);
219 return 0;
220 }
221
222 // private directory
223 if (strncmp(ptr, "private ", 8) == 0) {
224 cfg.home_private = ptr + 8;
225 fs_check_private_dir();
226 arg_private = 1;
227 return 0;
228 }
229
230 // private list of files and directories
231 if (strncmp(ptr, "private.keep ", 13) == 0) {
232 cfg.home_private_keep = ptr + 13;
233 fs_check_home_list();
234 arg_private = 1;
235 return 0;
236 }
237
238 // filesystem bind
239 if (strncmp(ptr, "bind ", 5) == 0) {
240 if (getuid() != 0) {
241 fprintf(stderr, "Error: --bind option is available only if running as root\n");
242 exit(1);
243 }
244
245 // extract two directories
246 char *dname1 = ptr + 5;
247 char *dname2 = split_comma(dname1); // this inserts a '0 to separate the two dierctories
248 if (dname2 == NULL) {
249 fprintf(stderr, "Error: mising second directory for bind\n");
250 exit(1);
251 }
252
253 // check directories
254 check_file_name(dname1, lineno);
255 check_file_name(dname2, lineno);
256 if (strstr(dname1, "..") || strstr(dname2, "..")) {
257 fprintf(stderr, "Error: invalid file name.\n");
258 exit(1);
259 }
260
261 // insert comma back
262 *(dname2 - 1) = ',';
263 return 1;
264 }
265
266 // rlimit
267 if (strncmp(ptr, "rlimit", 6) == 0) {
268 if (strncmp(ptr, "rlimit-nofile ", 14) == 0) {
269 ptr += 14;
270 if (not_unsigned(ptr)) {
271 fprintf(stderr, "Invalid rlimit option on line %d\n", lineno);
272 exit(1);
273 }
274 sscanf(ptr, "%u", &cfg.rlimit_nofile);
275 arg_rlimit_nofile = 1;
276 }
277 else if (strncmp(ptr, "rlimit-nproc ", 13) == 0) {
278 ptr += 13;
279 if (not_unsigned(ptr)) {
280 fprintf(stderr, "Invalid rlimit option on line %d\n", lineno);
281 exit(1);
282 }
283 sscanf(ptr, "%u", &cfg.rlimit_nproc);
284 arg_rlimit_nproc = 1;
285 }
286 else if (strncmp(ptr, "rlimit-fsize ", 13) == 0) {
287 ptr += 13;
288 if (not_unsigned(ptr)) {
289 fprintf(stderr, "Invalid rlimit option on line %d\n", lineno);
290 exit(1);
291 }
292 sscanf(ptr, "%u", &cfg.rlimit_fsize);
293 arg_rlimit_fsize = 1;
294 }
295 else if (strncmp(ptr, "rlimit-sigpending ", 18) == 0) {
296 ptr += 18;
297 if (not_unsigned(ptr)) {
298 fprintf(stderr, "Invalid rlimit option on line %d\n", lineno);
299 exit(1);
300 }
301 sscanf(ptr, "%u", &cfg.rlimit_sigpending);
302 arg_rlimit_sigpending = 1;
303 }
304 else {
305 fprintf(stderr, "Invalid rlimit option on line %d\n", lineno);
306 exit(1);
307 }
308
309 return 0;
310 }
311
312 // rest of filesystem
313 if (strncmp(ptr, "blacklist ", 10) == 0)
314 ptr += 10;
315 else if (strncmp(ptr, "read-only ", 10) == 0)
316 ptr += 10;
317 else if (strncmp(ptr, "tmpfs ", 6) == 0)
318 ptr += 6;
319 else {
320 if (lineno == 0)
321 fprintf(stderr, "Error: \"%s\" as a command line option is invalid\n", ptr);
322 else
323 fprintf(stderr, "Error: line %d in the custom profile is invalid\n", lineno);
324 exit(1);
325 }
326
327 // some characters just don't belong in filenames
328 check_file_name(ptr, lineno);
329 if (strstr(ptr, "..")) {
330 if (lineno == 0)
331 fprintf(stderr, "Error: \"%s\" is an invalid filename\n", ptr);
332 else
333 fprintf(stderr, "Error: line %d in the custom profile is invalid\n", lineno);
334 exit(1);
335 }
336 return 1;
337}
338
339// add a profile entry in cfg.profile list; use str to populate the list
340void profile_add(char *str) {
341 ProfileEntry *prf = malloc(sizeof(ProfileEntry));
342 if (!prf)
343 errExit("malloc");
344 prf->next = NULL;
345 prf->data = str;
346
347 // add prf to the list
348 if (cfg.profile == NULL) {
349 cfg.profile = prf;
350 return;
351 }
352 ProfileEntry *ptr = cfg.profile;
353 while (ptr->next != NULL)
354 ptr = ptr->next;
355 ptr->next = prf;
356}
357
358// read a profile file
359static int include_level = 0;
360// skip1, skip2 - if the string is found in the line, the line is not interpreted
361void profile_read(const char *fname, const char *skip1, const char *skip2) {
362 // exit program if maximum include level was reached
363 if (include_level > MAX_INCLUDE_LEVEL) {
364 fprintf(stderr, "Error: maximum profile include level was reached\n");
365 exit(1);
366 }
367
368 if (strlen(fname) == 0) {
369 fprintf(stderr, "Error: invalid profile file\n");
370 exit(1);
371 }
372
373 // open profile file:
374 FILE *fp = fopen(fname, "r");
375 if (fp == NULL) {
376 fprintf(stderr, "Error: cannot open profile file\n");
377 exit(1);
378 }
379
380 fprintf(stderr, "Reading profile %s\n", fname);
381
382 // read the file line by line
383 char buf[MAX_READ + 1];
384 int lineno = 0;
385 while (fgets(buf, MAX_READ, fp)) {
386 ++lineno;
387 // remove empty space - ptr in allocated memory
388 char *ptr = line_remove_spaces(buf);
389 if (ptr == NULL)
390 continue;
391
392 // comments
393 if (*ptr == '#' || *ptr == '\0') {
394 free(ptr);
395 continue;
396 }
397
398 // process include
399 if (strncmp(ptr, "include ", 8) == 0) {
400 include_level++;
401
402 // extract profile filename and new skip params
403 char *newprofile = ptr + 8; // profile name
404 char *newskip1 = NULL; // new skip1
405 char *newskip2 = NULL; // new skip2
406 char *p = newprofile;
407 while (*p != '\0') {
408 if (*p == ' ') {
409 *p = '\0';
410 if (newskip1 == NULL)
411 newskip1 = p + 1;
412 else if (newskip2 == NULL)
413 newskip2 = p + 1;
414 }
415 p++;
416 }
417
418 // recursivity
419 profile_read(newprofile, newskip1, newskip2);
420 include_level--;
421 free(ptr);
422 continue;
423 }
424
425 // skip
426 if (skip1) {
427 if (strstr(ptr, skip1)) {
428 free(ptr);
429 continue;
430 }
431 }
432 if (skip2) {
433 if (strstr(ptr, skip2)) {
434 free(ptr);
435 continue;
436 }
437 }
438
439 // verify syntax, exit in case of error
440 if (profile_check_line(ptr, lineno))
441 profile_add(ptr);
442 }
443 fclose(fp);
444}
diff --git a/src/firejail/restricted_shell.c b/src/firejail/restricted_shell.c
new file mode 100644
index 000000000..ba3aae759
--- /dev/null
+++ b/src/firejail/restricted_shell.c
@@ -0,0 +1,96 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
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#include "firejail.h"
21
22#define MAX_READ 4096 // maximum line length
23char *restricted_user = NULL;
24
25
26int restricted_shell(const char *user) {
27 assert(user);
28
29 // open profile file:
30 FILE *fp = fopen("/etc/firejail/login.users", "r");
31 if (fp == NULL)
32 return 0;
33
34 int lineno = 0;
35 char buf[MAX_READ];
36 while (fgets(buf, MAX_READ, fp)) {
37 lineno++;
38
39 // remove empty spaces at the beginning of the line
40 char *ptr = buf;
41 while (*ptr == ' ' || *ptr == '\t') {
42 ptr++;
43 }
44 if (*ptr == '\n' || *ptr == '#')
45 continue;
46
47 // parse line
48 char *usr = ptr;
49 char *args = strchr(usr, ':');
50 if (args == NULL) {
51 fprintf(stderr, "Error: users.conf line %d\n", lineno);
52 exit(1);
53 }
54 *args = '\0';
55 args++;
56 ptr = strchr(args, '\n');
57 if (ptr)
58 *ptr = '\0';
59
60 if (strcmp(user, usr) == 0) {
61 restricted_user = strdup(user);
62 // extract program arguments
63
64 fullargv[0] = "firejail";
65 int i;
66 ptr = args;
67 for (i = 1; i < MAX_ARGS; i++) {
68 fullargv[i] = ptr;
69 while (*ptr != ' ' && *ptr != '\t' && *ptr != '\0')
70 ptr++;
71 if (*ptr != '\0') {
72 *ptr ='\0';
73 fullargv[i] = strdup(fullargv[i]);
74 if (fullargv[i] == NULL) {
75 fprintf(stderr, "Error: cannot allocate memory\n");
76 exit(1);
77 }
78 ptr++;
79 while (*ptr == ' ' || *ptr == '\t')
80 ptr++;
81 if (*ptr != '\0')
82 continue;
83 }
84 fullargv[i] = strdup(fullargv[i]);
85 fclose(fp);
86 return i + 1;
87 }
88 fprintf(stderr, "Error: too many program arguments in users.conf line %d\n", lineno);
89 exit(1);
90 }
91 }
92 fclose(fp);
93
94 return 0;
95}
96
diff --git a/src/firejail/rlimit.c b/src/firejail/rlimit.c
new file mode 100644
index 000000000..6c755a08d
--- /dev/null
+++ b/src/firejail/rlimit.c
@@ -0,0 +1,62 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
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#include "firejail.h"
21#include <sys/time.h>
22#include <sys/resource.h>
23
24void set_rlimits(void) {
25 // resource limits
26 struct rlimit rl;
27 if (arg_rlimit_nofile) {
28 rl.rlim_cur = (rlim_t) cfg.rlimit_nofile;
29 rl.rlim_max = (rlim_t) cfg.rlimit_nofile;
30 if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
31 errExit("setrlimit");
32 if (arg_debug)
33 printf("Config rlimit: number of open file descriptors %u\n", cfg.rlimit_nofile);
34 }
35
36 if (arg_rlimit_nproc) {
37 rl.rlim_cur = (rlim_t) cfg.rlimit_nproc;
38 rl.rlim_max = (rlim_t) cfg.rlimit_nproc;
39 if (setrlimit(RLIMIT_NPROC, &rl) == -1)
40 errExit("setrlimit");
41 if (arg_debug)
42 printf("Config rlimit: number of processes %u\n", cfg.rlimit_nproc);
43 }
44
45 if (arg_rlimit_fsize) {
46 rl.rlim_cur = (rlim_t) cfg.rlimit_fsize;
47 rl.rlim_max = (rlim_t) cfg.rlimit_fsize;
48 if (setrlimit(RLIMIT_FSIZE, &rl) == -1)
49 errExit("setrlimit");
50 if (arg_debug)
51 printf("Config rlimit: maximum file size %u\n", cfg.rlimit_fsize);
52 }
53
54 if (arg_rlimit_sigpending) {
55 rl.rlim_cur = (rlim_t) cfg.rlimit_sigpending;
56 rl.rlim_max = (rlim_t) cfg.rlimit_sigpending;
57 if (setrlimit(RLIMIT_SIGPENDING, &rl) == -1)
58 errExit("setrlimit");
59 if (arg_debug)
60 printf("Config rlimit: maximum number of signals pending %u\n", cfg.rlimit_sigpending);
61 }
62}
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c
new file mode 100644
index 000000000..3f5fb51fa
--- /dev/null
+++ b/src/firejail/sandbox.c
@@ -0,0 +1,490 @@
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#include "firejail.h"
22#include <sys/mount.h>
23#include <sys/wait.h>
24#include <sys/stat.h>
25#include <sys/prctl.h>
26#include <sys/time.h>
27#include <sys/resource.h>
28
29#include <sched.h>
30#ifndef CLONE_NEWUSER
31#define CLONE_NEWUSER 0x10000000
32#endif
33
34static void set_caps(void) {
35 if (arg_caps_drop_all)
36 caps_drop_all();
37 else if (arg_caps_drop)
38 caps_drop_list(arg_caps_list);
39 else if (arg_caps_keep)
40 caps_keep_list(arg_caps_list);
41 else if (arg_caps_default_filter)
42 caps_default_filter();
43}
44
45void save_nogroups(void) {
46 if (arg_nogroups == 0)
47 return;
48
49 char *fname;
50 if (asprintf(&fname, "%s/groups", MNT_DIR) == -1)
51 errExit("asprintf");
52 FILE *fp = fopen(fname, "w");
53 if (fp) {
54 fprintf(fp, "\n");
55 fclose(fp);
56 if (chown(fname, 0, 0) < 0)
57 errExit("chown");
58 }
59 else {
60 fprintf(stderr, "Error: cannot save nogroups state\n");
61 free(fname);
62 exit(1);
63 }
64
65 free(fname);
66}
67
68static void sandbox_if_up(Bridge *br) {
69 assert(br);
70 if (!br->configured)
71 return;
72
73 char *dev = br->devsandbox;
74 net_if_up(dev);
75
76 if (br->arg_ip_none == 1); // do nothing
77 else if (br->arg_ip_none == 0 && br->macvlan == 0) {
78 if (br->ipsandbox == br->ip) {
79 fprintf(stderr, "Error: %d.%d.%d.%d is interface %s address.\n", PRINT_IP(br->ipsandbox), br->dev);
80 exit(1);
81 }
82
83 // just assign the address
84 assert(br->ipsandbox);
85 if (arg_debug)
86 printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(br->ipsandbox), dev);
87 net_if_ip(dev, br->ipsandbox, br->mask);
88 net_if_up(dev);
89 }
90 else if (br->arg_ip_none == 0 && br->macvlan == 1) {
91 // reassign the macvlan address
92 if (br->ipsandbox == 0)
93 // ip address assigned by arp-scan for a macvlan device
94 br->ipsandbox = arp_assign(dev, br); //br->ip, br->mask);
95 else {
96 if (br->ipsandbox == br->ip) {
97 fprintf(stderr, "Error: %d.%d.%d.%d is interface %s address.\n", PRINT_IP(br->ipsandbox), br->dev);
98 exit(1);
99 }
100
101 uint32_t rv = arp_check(dev, br->ipsandbox, br->ip);
102 if (rv) {
103 fprintf(stderr, "Error: the address %d.%d.%d.%d is already in use.\n", PRINT_IP(br->ipsandbox));
104 exit(1);
105 }
106 }
107
108 if (arg_debug)
109 printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(br->ipsandbox), dev);
110 net_if_ip(dev, br->ipsandbox, br->mask);
111 net_if_up(dev);
112 }
113}
114
115static void chk_chroot(void) {
116 // if we are starting firejail inside some other container technology, we don't care about this
117 char *mycont = getenv("container");
118 if (mycont)
119 return;
120
121 // check if this is a regular chroot
122 struct stat s;
123 if (stat("/", &s) == 0) {
124 if (s.st_ino != 2)
125 return;
126 }
127
128 fprintf(stderr, "Error: cannot mount filesystem as slave\n");
129 exit(1);
130}
131
132int sandbox(void* sandbox_arg) {
133 pid_t child_pid = getpid();
134 if (arg_debug)
135 printf("Initializing child process\n");
136
137 // close each end of the unused pipes
138 close(parent_to_child_fds[1]);
139 close(child_to_parent_fds[0]);
140
141 // wait for parent to do base setup
142 wait_for_other(parent_to_child_fds[0]);
143
144 if (arg_debug && child_pid == 1)
145 printf("PID namespace installed\n");
146
147 //****************************
148 // set hostname
149 //****************************
150 if (cfg.hostname) {
151 if (sethostname(cfg.hostname, strlen(cfg.hostname)) < 0)
152 errExit("sethostname");
153 }
154
155 //****************************
156 // mount namespace
157 //****************************
158 // mount events are not forwarded between the host the sandbox
159 if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) {
160 chk_chroot();
161 }
162
163 //****************************
164 // netfilter
165 //****************************
166 if (arg_netfilter && any_bridge_configured()) { // assuming by default the client filter
167 netfilter(arg_netfilter_file);
168 }
169
170 //****************************
171 // trace pre-install
172 //****************************
173 if (arg_trace)
174 fs_trace_preload();
175
176 //****************************
177 // configure filesystem
178 //****************************
179#ifdef HAVE_CHROOT
180 if (cfg.chrootdir) {
181 fs_chroot(cfg.chrootdir);
182 // force caps and seccomp if not started as root
183 if (getuid() != 0) {
184 // force default seccomp inside the chroot, no keep or drop list
185 // the list build on top of the default drop list is kept intact
186 arg_seccomp = 1;
187 if (arg_seccomp_list_drop) {
188 free(arg_seccomp_list_drop);
189 arg_seccomp_list_drop = NULL;
190 }
191 if (arg_seccomp_list_keep) {
192 free(arg_seccomp_list_keep);
193 arg_seccomp_list_keep = NULL;
194 }
195
196 // disable all capabilities
197 if (arg_caps_default_filter || arg_caps_list)
198 fprintf(stderr, "Warning: all capabilities disabled for a regular user during chroot\n");
199 arg_caps_drop_all = 1;
200
201 // drop all supplementary groups; /etc/group file inside chroot
202 // is controlled by a regular usr
203 arg_nogroups = 1;
204 printf("Dropping all Linux capabilities and enforcing default seccomp filter\n");
205 }
206
207 //****************************
208 // trace pre-install, this time inside chroot
209 //****************************
210 if (arg_trace)
211 fs_trace_preload();
212 }
213 else
214#endif
215 if (arg_overlay)
216 fs_overlayfs();
217 else
218 fs_basic_fs();
219
220
221 //****************************
222 // set hostname in /etc/hostname
223 //****************************
224 if (cfg.hostname) {
225 fs_hostname(cfg.hostname);
226 }
227
228 //****************************
229 // apply the profile file
230 //****************************
231 if (cfg.profile)
232 fs_blacklist(cfg.homedir);
233
234 //****************************
235 // private mode
236 //****************************
237 if (arg_private) {
238 if (cfg.home_private) // --private=
239 fs_private_homedir();
240 else if (cfg.home_private_keep) // --private.keep=
241 fs_private_home_list();
242 else // --private
243 fs_private();
244 }
245
246 if (arg_private_dev)
247 fs_private_dev();
248
249 //****************************
250 // install trace
251 //****************************
252 if (arg_trace)
253 fs_trace();
254
255 //****************************
256 // update /proc, /dev, /boot directorymy
257 //****************************
258 fs_proc_sys_dev_boot();
259
260 //****************************
261 // networking
262 //****************************
263 if (arg_nonetwork) {
264 net_if_up("lo");
265 }
266 else if (any_bridge_configured()) {
267 // configure lo and eth0...eth3
268 net_if_up("lo");
269
270 if (mac_not_zero(cfg.bridge0.macsandbox))
271 net_config_mac(cfg.bridge0.devsandbox, cfg.bridge0.macsandbox);
272 sandbox_if_up(&cfg.bridge0);
273
274 if (mac_not_zero(cfg.bridge1.macsandbox))
275 net_config_mac(cfg.bridge1.devsandbox, cfg.bridge1.macsandbox);
276 sandbox_if_up(&cfg.bridge1);
277
278 if (mac_not_zero(cfg.bridge2.macsandbox))
279 net_config_mac(cfg.bridge2.devsandbox, cfg.bridge2.macsandbox);
280 sandbox_if_up(&cfg.bridge2);
281
282 if (mac_not_zero(cfg.bridge3.macsandbox))
283 net_config_mac(cfg.bridge3.devsandbox, cfg.bridge3.macsandbox);
284 sandbox_if_up(&cfg.bridge3);
285
286 // add a default route
287 if (cfg.defaultgw) {
288 // set the default route
289 if (net_add_route(0, 0, cfg.defaultgw))
290 fprintf(stderr, "Warning: cannot configure default route\n");
291 }
292
293 if (arg_debug)
294 printf("Network namespace enabled\n");
295 }
296
297 // if any dns server is configured, it is time to set it now
298 fs_resolvconf();
299
300 // print network configuration
301 if (any_bridge_configured() || cfg.defaultgw || cfg.dns1) {
302 printf("\n");
303 if (any_bridge_configured())
304 net_ifprint();
305 if (cfg.defaultgw != 0)
306 printf("Default gateway %d.%d.%d.%d\n", PRINT_IP(cfg.defaultgw));
307 if (cfg.dns1 != 0)
308 printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns1));
309 if (cfg.dns2 != 0)
310 printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns2));
311 if (cfg.dns3 != 0)
312 printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns3));
313 printf("\n");
314 }
315
316
317
318 //****************************
319 // start executable
320 //****************************
321 prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died
322 int cwd = 0;
323 if (cfg.cwd) {
324 if (chdir(cfg.cwd) == 0)
325 cwd = 1;
326 }
327
328 if (!cwd) {
329 if (chdir("/") < 0)
330 errExit("chdir");
331 if (cfg.homedir) {
332 struct stat s;
333 if (stat(cfg.homedir, &s) == 0) {
334 /* coverity[toctou] */
335 if (chdir(cfg.homedir) < 0)
336 errExit("chdir");
337 }
338 }
339 }
340
341 // set environment
342 // fix qt 4.8
343 if (setenv("QT_X11_NO_MITSHM", "1", 1) < 0)
344 errExit("setenv");
345 if (setenv("container", "firejail", 1) < 0) // LXC sets container=lxc,
346 errExit("setenv");
347 if (arg_zsh && setenv("SHELL", "/usr/bin/zsh", 1) < 0)
348 errExit("setenv");
349 if (arg_csh && setenv("SHELL", "/bin/csh", 1) < 0)
350 errExit("setenv");
351 if (cfg.shell && setenv("SHELL", cfg.shell, 1) < 0)
352 errExit("setenv");
353 // set prompt color to green
354 //export PS1='\[\e[1;32m\][\u@\h \W]\$\[\e[0m\] '
355 if (setenv("PROMPT_COMMAND", "export PS1=\"\\[\\e[1;32m\\][\\u@\\h \\W]\\$\\[\\e[0m\\] \"", 1) < 0)
356 errExit("setenv");
357
358
359 // set capabilities
360 if (!arg_noroot)
361 set_caps();
362
363 // set rlimits
364 set_rlimits();
365
366 // set seccomp
367#ifdef HAVE_SECCOMP
368 // if a keep list is available, disregard the drop list
369 if (arg_seccomp == 1) {
370 if (arg_seccomp_list_keep)
371 seccomp_filter_keep(); // this will also save the fmyilter to MNT_DIR/seccomp file
372 else
373 seccomp_filter_drop(); // this will also save the filter to MNT_DIR/seccomp file
374 }
375#endif
376
377 // set cpu affinity
378 if (cfg.cpus) {
379 save_cpu(); // save cpu affinity mask to MNT_DIR/cpu file
380 set_cpu_affinity();
381 }
382
383 // save cgroup in MNT_DIR/cgroup file
384 if (cfg.cgroup)
385 save_cgroup();
386
387 //****************************************
388 // drop privileges or create a new user namespace
389 //****************************************
390 save_nogroups();
391 if (arg_noroot) {
392 int rv = unshare(CLONE_NEWUSER);
393 if (rv == -1) {
394 fprintf(stderr, "Warning: cannot mount a new user namespace\n");
395 perror("unshare");
396 drop_privs(arg_nogroups);
397 }
398 }
399 else
400 drop_privs(arg_nogroups);
401
402 // notify parent that new user namespace has been created so a proper
403 // UID/GID map can be setup
404 notify_other(child_to_parent_fds[1]);
405 close(child_to_parent_fds[1]);
406
407 // wait for parent to finish setting up a proper UID/GID map
408 wait_for_other(parent_to_child_fds[0]);
409 close(parent_to_child_fds[0]);
410
411 // somehow, the new user namespace resets capabilities;
412 // we need to do them again
413 if (arg_noroot) {
414 set_caps();
415 if (arg_debug)
416 printf("User namespace (noroot) installed\n");
417 }
418
419
420 //****************************************
421 // start the program without using a shell
422 //****************************************
423 if (arg_shell_none) {
424 if (arg_debug) {
425 int i;
426 for (i = cfg.original_program_index; i < cfg.original_argc; i++) {
427 if (cfg.original_argv[i] == NULL)
428 break;
429 printf("execvp argument %d: %s\n", i - cfg.original_program_index, cfg.original_argv[i]);
430 }
431 }
432
433 if (!arg_command)
434 printf("Child process initialized\n");
435 execvp(cfg.original_argv[cfg.original_program_index], &cfg.original_argv[cfg.original_program_index + 1]);
436 }
437 //****************************************
438 // start the program using a shell
439 //****************************************
440 else {
441 // choose the shell requested by the user, or use bash as default
442 char *sh;
443 if (cfg.shell)
444 sh = cfg.shell;
445 else if (arg_zsh)
446 sh = "/usr/bin/zsh";
447 else if (arg_csh)
448 sh = "/bin/csh";
449 else
450 sh = "/bin/bash";
451
452 char *arg[5];
453 int index = 0;
454 arg[index++] = sh;
455 arg[index++] = "-c";
456 assert(cfg.command_line);
457 if (arg_debug)
458 printf("Starting %s\n", cfg.command_line);
459 if (arg_doubledash)
460 arg[index++] = "--";
461 arg[index++] = cfg.command_line;
462 arg[index] = NULL;
463 assert(index < 5);
464
465 if (arg_debug) {
466 char *msg;
467 if (asprintf(&msg, "sandbox %d, execvp into %s", sandbox_pid, cfg.command_line) == -1)
468 errExit("asprintf");
469 logmsg(msg);
470 free(msg);
471 }
472
473 if (arg_debug) {
474 int i;
475 for (i = 0; i < 5; i++) {
476 if (arg[i] == NULL)
477 break;
478 printf("execvp argument %d: %s\n", i, arg[i]);
479 }
480 }
481
482 if (!arg_command)
483 printf("Child process initialized\n");
484 execvp(sh, arg);
485 }
486
487
488 perror("execvp");
489 return 0;
490}
diff --git a/src/firejail/seccomp.c b/src/firejail/seccomp.c
new file mode 100644
index 000000000..c03eb6848
--- /dev/null
+++ b/src/firejail/seccomp.c
@@ -0,0 +1,658 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
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/* default seccomp filter
22 // seccomp
23 struct sock_filter filter[] = {
24 VALIDATE_ARCHITECTURE,
25 EXAMINE_SYSCALL,
26 BLACKLIST(SYS_mount), // mount/unmount filesystems
27 BLACKLIST(SYS_umount2),
28 BLACKLIST(SYS_ptrace), // trace processes
29 BLACKLIST(SYS_kexec_load), // loading a different kernel
30 BLACKLIST(SYS_open_by_handle_at), // open by handle
31 BLACKLIST(SYS_init_module), // kernel module handling
32#ifdef SYS_finit_module // introduced in 2013
33 BLACKLIST(SYS_finit_module),
34#endif
35 BLACKLIST(SYS_delete_module),
36 BLACKLIST(SYS_iopl), // io permisions
37#ifdef SYS_ioperm
38 BLACKLIST(SYS_ioperm),
39#endif
40SYS_iopl
41 BLACKLIST(SYS_iopl), // io permisions
42#endif
43#ifdef SYS_ni_syscall), // new io permisions call on arm devices
44 BLACKLIST(SYS_ni_syscall),
45#endif
46 BLACKLIST(SYS_swapon), // swap on/off
47 BLACKLIST(SYS_swapoff),
48 BLACKLIST(SYS_syslog), // kernel printk control
49 RETURN_ALLOW
50 };
51*/
52#ifdef HAVE_SECCOMP
53#include "firejail.h"
54#include <errno.h>
55#include <linux/filter.h>
56#include <sys/syscall.h>
57#include <linux/capability.h>
58#include <linux/audit.h>
59#include <sys/stat.h>
60#include <fcntl.h>
61
62#include <sys/prctl.h>
63#ifndef PR_SET_NO_NEW_PRIVS
64# define PR_SET_NO_NEW_PRIVS 38
65#endif
66
67#if HAVE_SECCOMP_H
68#include <linux/seccomp.h>
69#else
70#define SECCOMP_MODE_FILTER 2
71#define SECCOMP_RET_KILL 0x00000000U
72#define SECCOMP_RET_TRAP 0x00030000U
73#define SECCOMP_RET_ALLOW 0x7fff0000U
74#define SECCOMP_RET_ERRNO 0x00050000U
75#define SECCOMP_RET_DATA 0x0000ffffU
76struct seccomp_data {
77 int nr;
78 __u32 arch;
79 __u64 instruction_pointer;
80 __u64 args[6];
81};
82#endif
83
84#if defined(__i386__)
85# define ARCH_NR AUDIT_ARCH_I386
86#elif defined(__x86_64__)
87# define ARCH_NR AUDIT_ARCH_X86_64
88#elif defined(__arm__)
89# define ARCH_NR AUDIT_ARCH_ARM
90#else
91# warning "Platform does not support seccomp filter yet"
92# define ARCH_NR 0
93#endif
94
95
96#define VALIDATE_ARCHITECTURE \
97 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, (offsetof(struct seccomp_data, arch))), \
98 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARCH_NR, 1, 0), \
99 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
100
101#define EXAMINE_SYSCALL BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \
102 (offsetof(struct seccomp_data, nr)))
103
104#define BLACKLIST(syscall_nr) \
105 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, syscall_nr, 0, 1), \
106 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
107
108#define WHITELIST(syscall_nr) \
109 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, syscall_nr, 0, 1), \
110 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
111
112#define RETURN_ALLOW \
113 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
114
115#define KILL_PROCESS \
116 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
117
118#define SECSIZE 128 // initial filter size
119static struct sock_filter *sfilter = NULL;
120static int sfilter_alloc_size = 0;
121static int sfilter_index = 0;
122
123// debug filter
124void filter_debug(void) {
125 // start filter
126 struct sock_filter filter[] = {
127 VALIDATE_ARCHITECTURE,
128 EXAMINE_SYSCALL
129 };
130
131 // print sizes
132 printf("SECCOMP Filter:\n");
133 if (sfilter == NULL) {
134 printf("SECCOMP filter not allocated\n");
135 return;
136 }
137 if (sfilter_index < 4)
138 return;
139
140 // test the start of the filter
141 if (memcmp(sfilter, filter, sizeof(filter)) == 0) {
142 printf(" VALIDATE_ARCHITECTURE\n");
143 printf(" EXAMINE_SYSCAL\n");
144 }
145
146 // loop trough blacklists
147 int i = 4;
148 while (i < sfilter_index) {
149 // minimal parsing!
150 unsigned char *ptr = (unsigned char *) &sfilter[i];
151 int *nr = (int *) (ptr + 4);
152 if (*ptr == 0x15 && *(ptr +14) == 0xff && *(ptr + 15) == 0x7f ) {
153 printf(" WHITELIST %d %s\n", *nr, syscall_find_nr(*nr));
154 i += 2;
155 }
156 else if (*ptr == 0x15 && *(ptr +14) == 0 && *(ptr + 15) == 0) {
157 printf(" BLACKLIST %d %s\n", *nr, syscall_find_nr(*nr));
158 i += 2;
159 }
160 else if (*ptr == 0x06 && *(ptr +6) == 0 && *(ptr + 7) == 0 ) {
161 printf(" KILL_PROCESS\n");
162 i++;
163 }
164 else if (*ptr == 0x06 && *(ptr +6) == 0xff && *(ptr + 7) == 0x7f ) {
165 printf(" RETURN_ALLOW\n");
166 i++;
167 }
168 else {
169 printf(" UNKNOWN ENTRY!!!\n");
170 i++;
171 }
172 }
173}
174
175// initialize filter
176static void filter_init(void) {
177 if (sfilter) {
178 assert(0);
179 return;
180 }
181
182 if (arg_debug)
183 printf("Initialize seccomp filter\n");
184 // allocate a filter of SECSIZE
185 sfilter = malloc(sizeof(struct sock_filter) * SECSIZE);
186 if (!sfilter)
187 errExit("malloc");
188 memset(sfilter, 0, sizeof(struct sock_filter) * SECSIZE);
189 sfilter_alloc_size = SECSIZE;
190
191 // copy the start entries
192 struct sock_filter filter[] = {
193 VALIDATE_ARCHITECTURE,
194 EXAMINE_SYSCALL
195 };
196 sfilter_index = sizeof(filter) / sizeof(struct sock_filter);
197 memcpy(sfilter, filter, sizeof(filter));
198}
199
200static void filter_realloc(void) {
201 assert(sfilter);
202 assert(sfilter_alloc_size);
203 assert(sfilter_index);
204 if (arg_debug)
205 printf("Allocating more seccomp filter entries\n");
206
207 // allocate the new memory
208 struct sock_filter *old = sfilter;
209 sfilter = malloc(sizeof(struct sock_filter) * (sfilter_alloc_size + SECSIZE));
210 if (!sfilter)
211 errExit("malloc");
212 memset(sfilter, 0, sizeof(struct sock_filter) * (sfilter_alloc_size + SECSIZE));
213
214 // copy old filter
215 memcpy(sfilter, old, sizeof(struct sock_filter) * sfilter_alloc_size);
216 sfilter_alloc_size += SECSIZE;
217}
218
219static void filter_add_whitelist(int syscall) {
220 assert(sfilter);
221 assert(sfilter_alloc_size);
222 assert(sfilter_index);
223 if (arg_debug)
224 printf("Whitelisting syscall %d %s\n", syscall, syscall_find_nr(syscall));
225
226 if ((sfilter_index + 2) > sfilter_alloc_size)
227 filter_realloc();
228
229 struct sock_filter filter[] = {
230 WHITELIST(syscall)
231 };
232#if 0
233{
234 int i;
235 unsigned char *ptr = (unsigned char *) &filter[0];
236 for (i = 0; i < sizeof(filter); i++, ptr++)
237 printf("%x, ", (*ptr) & 0xff);
238 printf("\n");
239}
240#endif
241 memcpy(&sfilter[sfilter_index], filter, sizeof(filter));
242 sfilter_index += sizeof(filter) / sizeof(struct sock_filter);
243}
244
245static void filter_add_blacklist(int syscall) {
246 assert(sfilter);
247 assert(sfilter_alloc_size);
248 assert(sfilter_index);
249 if (arg_debug)
250 printf("Blacklisting syscall %d %s\n", syscall, syscall_find_nr(syscall));
251
252 if ((sfilter_index + 2) > sfilter_alloc_size)
253 filter_realloc();
254
255 struct sock_filter filter[] = {
256 BLACKLIST(syscall)
257 };
258#if 0
259{
260 int i;
261 unsigned char *ptr = (unsigned char *) &filter[0];
262 for (i = 0; i < sizeof(filter); i++, ptr++)
263 printf("%x, ", (*ptr) & 0xff);
264 printf("\n");
265}
266#endif
267 memcpy(&sfilter[sfilter_index], filter, sizeof(filter));
268 sfilter_index += sizeof(filter) / sizeof(struct sock_filter);
269}
270
271static void filter_end_blacklist(void) {
272 assert(sfilter);
273 assert(sfilter_alloc_size);
274 assert(sfilter_index);
275 if (arg_debug)
276 printf("Ending syscall filter\n");
277
278 if ((sfilter_index + 2) > sfilter_alloc_size)
279 filter_realloc();
280
281 struct sock_filter filter[] = {
282 RETURN_ALLOW
283 };
284#if 0
285{
286 int i;
287 unsigned char *ptr = (unsigned char *) &filter[0];
288 for (i = 0; i < sizeof(filter); i++, ptr++)
289 printf("%x, ", (*ptr) & 0xff);
290 printf("\n");
291}
292#endif
293 memcpy(&sfilter[sfilter_index], filter, sizeof(filter));
294 sfilter_index += sizeof(filter) / sizeof(struct sock_filter);
295}
296
297static void filter_end_whitelist(void) {
298 assert(sfilter);
299 assert(sfilter_alloc_size);
300 assert(sfilter_index);
301 if (arg_debug)
302 printf("Ending syscall filter\n");
303
304 if ((sfilter_index + 2) > sfilter_alloc_size)
305 filter_realloc();
306
307 struct sock_filter filter[] = {
308 KILL_PROCESS
309 };
310#if 0
311{
312 int i;
313 unsigned char *ptr = (unsigned char *) &filter[0];
314 for (i = 0; i < sizeof(filter); i++, ptr++)
315 printf("%x, ", (*ptr) & 0xff);
316 printf("\n");
317}
318#endif
319 memcpy(&sfilter[sfilter_index], filter, sizeof(filter));
320 sfilter_index += sizeof(filter) / sizeof(struct sock_filter);
321}
322
323
324// save seccomp filter in /tmp/firejail/mnt/seccomp
325static void write_seccomp_file(void) {
326 fs_build_mnt_dir();
327 assert(sfilter);
328
329 char *fname;
330 if (asprintf(&fname, "%s/seccomp", MNT_DIR) == -1)
331 errExit("asprintf");
332 int fd = open(fname, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
333 if (fd == -1)
334 errExit("open");
335
336 if (arg_debug)
337 printf("Save seccomp filter, size %lu bytes\n", sfilter_index * sizeof(struct sock_filter));
338 errno = 0;
339 ssize_t sz = write(fd, sfilter, sfilter_index * sizeof(struct sock_filter));
340 if (sz != (sfilter_index * sizeof(struct sock_filter))) {
341 fprintf(stderr, "Error: cannot save seccomp filter\n");
342 exit(1);
343 }
344 close(fd);
345 if (chown(fname, 0, 0) < 0)
346 errExit("chown");
347 free(fname);
348}
349
350// read seccomp filter from /tmp/firejail/mnt/seccomp
351static void read_seccomp_file(char *file_name) {
352 assert(sfilter == NULL && sfilter_index == 0);
353
354 char *fname;
355 if (file_name)
356 fname = file_name;
357 else {
358 if (asprintf(&fname, "%s/seccomp", MNT_DIR) == -1)
359 errExit("asprintf");
360 }
361
362 // check file
363 struct stat s;
364 if (stat(fname, &s) == -1) {
365 fprintf(stderr, "Error: seccomp file not found\n");
366 exit(1);
367 }
368 ssize_t sz = s.st_size;
369 if (sz == 0 || (sz % sizeof(struct sock_filter)) != 0) {
370 fprintf(stderr, "Error: invalid seccomp file\n");
371 exit(1);
372 }
373 sfilter = malloc(sz);
374 if (!sfilter)
375 errExit("malloc");
376
377 // read file
378 /* coverity[toctou] */
379 int fd = open(fname,O_RDONLY);
380 if (fd == -1)
381 errExit("open");
382 errno = 0;
383 ssize_t size = read(fd, sfilter, sz);
384 if (size != sz) {
385 fprintf(stderr, "Error: invalid seccomp file\n");
386 exit(1);
387 }
388 sfilter_index = sz / sizeof(struct sock_filter);
389
390 if (arg_debug)
391 printf("Read seccomp filter, size %lu bytes\n", sfilter_index * sizeof(struct sock_filter));
392
393 close(fd);
394 free(fname);
395
396 if (arg_debug)
397 filter_debug();
398}
399
400
401// drop filter for seccomp option
402int seccomp_filter_drop(void) {
403 filter_init();
404
405 // default seccomp
406 if (arg_seccomp_list_drop == NULL) {
407#ifdef SYS_mount
408 filter_add_blacklist(SYS_mount);
409#endif
410#ifdef SYS_umount2
411 filter_add_blacklist(SYS_umount2);
412#endif
413#ifdef SYS_ptrace
414 filter_add_blacklist(SYS_ptrace);
415#endif
416#ifdef SYS_kexec_load
417 filter_add_blacklist(SYS_kexec_load);
418#endif
419#ifdef SYS_open_by_handle_at
420 filter_add_blacklist(SYS_open_by_handle_at);
421#endif
422#ifdef SYS_init_module
423 filter_add_blacklist(SYS_init_module);
424#endif
425#ifdef SYS_finit_module // introduced in 2013
426 filter_add_blacklist(SYS_finit_module);
427#endif
428#ifdef SYS_delete_module
429 filter_add_blacklist(SYS_delete_module);
430#endif
431#ifdef SYS_iopl
432 filter_add_blacklist(SYS_iopl);
433#endif
434#ifdef SYS_ioperm
435 filter_add_blacklist(SYS_ioperm);
436#endif
437#ifdef SYS_ni_syscall // new io permisions call on arm devices
438 filter_add_blacklist(SYS_ni_syscall);
439#endif
440#ifdef SYS_swapon
441 filter_add_blacklist(SYS_swapon);
442#endif
443#ifdef SYS_swapoff
444 filter_add_blacklist(SYS_swapoff);
445#endif
446#ifdef SYS_syslog
447 filter_add_blacklist(SYS_syslog);
448#endif
449#ifdef SYS_process_vm_readv
450 filter_add_blacklist(SYS_process_vm_readv);
451#endif
452#ifdef SYS_process_vm_writev
453 filter_add_blacklist(SYS_process_vm_writev);
454#endif
455#ifdef SYS_mknod
456 filter_add_blacklist(SYS_mknod);
457#endif
458
459 // new syscalls in 0.9,23
460#ifdef SYS_sysfs
461 filter_add_blacklist(SYS_sysfs);
462#endif
463#ifdef SYS__sysctl
464 filter_add_blacklist(SYS__sysctl);
465#endif
466#ifdef SYS_adjtimex
467 filter_add_blacklist(SYS_adjtimex);
468#endif
469#ifdef SYS_clock_adjtime
470 filter_add_blacklist(SYS_clock_adjtime);
471#endif
472#ifdef SYS_lookup_dcookie
473 filter_add_blacklist(SYS_lookup_dcookie);
474#endif
475#ifdef SYS_perf_event_open
476 filter_add_blacklist(SYS_perf_event_open);
477#endif
478#ifdef SYS_fanotify_init
479 filter_add_blacklist(SYS_fanotify_init);
480#endif
481#ifdef SYS_kcmp
482 filter_add_blacklist(SYS_kcmp);
483#endif
484 }
485
486 // default seccomp filter with additional drop list
487 if (arg_seccomp_list && arg_seccomp_list_drop == NULL) {
488 if (syscall_check_list(arg_seccomp_list, filter_add_blacklist)) {
489 fprintf(stderr, "Error: cannot load seccomp filter\n");
490 exit(1);
491 }
492 }
493 // drop list
494 else if (arg_seccomp_list == NULL && arg_seccomp_list_drop) {
495 if (syscall_check_list(arg_seccomp_list_drop, filter_add_blacklist)) {
496 fprintf(stderr, "Error: cannot load seccomp filter\n");
497 exit(1);
498 }
499 }
500
501
502 filter_end_blacklist();
503 if (arg_debug)
504 filter_debug();
505
506 // save seccomp filter in /tmp/firejail/mnt/seccomp
507 // in order to use it in --join operations
508 write_seccomp_file();
509
510
511 struct sock_fprog prog = {
512 .len = sfilter_index,
513 .filter = sfilter,
514 };
515
516 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) || prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
517 fprintf(stderr, "Warning: seccomp disabled, it requires a Linux kernel version 3.5 or newer.\n");
518 return 1;
519 }
520 else if (arg_debug) {
521 printf("seccomp enabled\n");
522 }
523
524 return 0;
525}
526
527// keep filter for seccomp option
528int seccomp_filter_keep(void) {
529 filter_init();
530
531 // these 4 syscalls are used by firejail after the seccomp filter is initialized
532 filter_add_whitelist(SYS_setuid);
533 filter_add_whitelist(SYS_setgid);
534 filter_add_whitelist(SYS_setgroups);
535 filter_add_whitelist(SYS_dup);
536
537 // apply keep list
538 if (arg_seccomp_list_keep) {
539 if (syscall_check_list(arg_seccomp_list_keep, filter_add_whitelist)) {
540 fprintf(stderr, "Error: cannot load seccomp filter\n");
541 exit(1);
542 }
543 }
544
545 filter_end_whitelist();
546 if (arg_debug)
547 filter_debug();
548
549 // save seccomp filter in /tmp/firejail/mnt/seccomp
550 // in order to use it in --join operations
551 write_seccomp_file();
552
553
554 struct sock_fprog prog = {
555 .len = sfilter_index,
556 .filter = sfilter,
557 };
558
559 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) || prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
560 fprintf(stderr, "Warning: seccomp disabled, it requires a Linux kernel version 3.5 or newer.\n");
561 return 1;
562 }
563 else if (arg_debug) {
564 printf("seccomp enabled\n");
565 }
566
567 return 0;
568}
569
570
571
572void seccomp_set(void) {
573 // read seccomp filter from /tmp/firejail/mnt/seccomp
574 read_seccomp_file(NULL);
575
576 // apply filter
577 struct sock_fprog prog = {
578 .len = sfilter_index,
579 .filter = sfilter,
580 };
581
582 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) || prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
583 fprintf(stderr, "Warning: seccomp disabled, it requires a Linux kernel version 3.5 or newer.\n");
584 return;
585 }
586 else if (arg_debug) {
587 printf("seccomp enabled\n");
588 }
589}
590
591void seccomp_print_filter_name(const char *name) {
592 if (!name || strlen(name) == 0) {
593 fprintf(stderr, "Error: invalid sandbox name\n");
594 exit(1);
595 }
596 pid_t pid;
597 if (name2pid(name, &pid)) {
598 fprintf(stderr, "Error: cannot find sandbox %s\n", name);
599 exit(1);
600 }
601
602 seccomp_print_filter(pid);
603}
604
605void seccomp_print_filter(pid_t pid) {
606 // if the pid is that of a firejail process, use the pid of the first child process
607 char *comm = pid_proc_comm(pid);
608 if (comm) {
609 // remove \n
610 char *ptr = strchr(comm, '\n');
611 if (ptr)
612 *ptr = '\0';
613 if (strcmp(comm, "firejail") == 0) {
614 pid_t child;
615 if (find_child(pid, &child) == 0) {
616 pid = child;
617 }
618 }
619 free(comm);
620 }
621
622 // check privileges for non-root users
623 uid_t uid = getuid();
624 if (uid != 0) {
625 struct stat s;
626 char *dir;
627 if (asprintf(&dir, "/proc/%u/ns", pid) == -1)
628 errExit("asprintf");
629 if (stat(dir, &s) < 0)
630 errExit("stat");
631 if (s.st_uid != uid) {
632 printf("Error: permission denied.\n");
633 exit(1);
634 }
635 }
636
637
638 // find the seccomp filter
639 char *fname;
640 if (asprintf(&fname, "/proc/%d/root/tmp/firejail/mnt/seccomp", pid) == -1)
641 errExit("asprintf");
642
643 struct stat s;
644 if (stat(fname, &s) == -1) {
645 printf("Cannot access seccomp filter.\n");
646 exit(1);
647 }
648
649 // read and print the filter
650 read_seccomp_file(fname);
651 drop_privs(1);
652 filter_debug();
653
654 exit(0);
655}
656
657#endif // HAVE_SECCOMP
658
diff --git a/src/firejail/shutdown.c b/src/firejail/shutdown.c
new file mode 100644
index 000000000..b666996df
--- /dev/null
+++ b/src/firejail/shutdown.c
@@ -0,0 +1,98 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
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#include "firejail.h"
21#include <sys/stat.h>
22#include <sys/wait.h>
23#include <fcntl.h>
24#include <sys/prctl.h>
25
26void shut_name(const char *name) {
27 if (!name || strlen(name) == 0) {
28 fprintf(stderr, "Error: invalid sandbox name\n");
29 exit(1);
30 }
31
32 pid_t pid;
33 if (name2pid(name, &pid)) {
34 fprintf(stderr, "Error: cannot find sandbox %s\n", name);
35 exit(1);
36 }
37
38 shut(pid);
39}
40
41void shut(pid_t pid) {
42 pid_t parent = pid;
43 // if the pid is that of a firejail process, use the pid of a child process inside the sandbox
44 char *comm = pid_proc_comm(pid);
45 if (comm) {
46 // remove \n
47 char *ptr = strchr(comm, '\n');
48 if (ptr)
49 *ptr = '\0';
50 if (strcmp(comm, "firejail") == 0) {
51 pid_t child;
52 if (find_child(pid, &child) == 0) {
53 pid = child;
54 printf("Switching to pid %u, the first child process inside the sandbox\n", (unsigned) pid);
55 }
56 }
57 free(comm);
58 }
59
60 // check privileges for non-root users
61 uid_t uid = getuid();
62 if (uid != 0) {
63 struct stat s;
64 char *dir;
65 if (asprintf(&dir, "/proc/%u/ns", pid) == -1)
66 errExit("asprintf");
67 if (stat(dir, &s) < 0)
68 errExit("stat");
69 if (s.st_uid != uid) {
70 fprintf(stderr, "Error: permission is denied to shutdown a sandbox created by a different user.\n");
71 exit(1);
72 }
73 }
74
75 printf("Sending SIGTERM to %u\n", pid);
76 kill(pid, SIGTERM);
77 sleep(2);
78
79 // if the process is still running, terminate it using SIGKILL
80 // try to open stat file
81 char *file;
82 if (asprintf(&file, "/proc/%u/status", pid) == -1) {
83 perror("asprintf");
84 exit(1);
85 }
86 FILE *fp = fopen(file, "r");
87 if (!fp)
88 return;
89 fclose(fp);
90
91 // kill the process and also the parent
92 printf("Sending SIGKILL to %u\n", pid);
93 kill(pid, SIGKILL);
94 if (parent != pid) {
95 printf("Sending SIGKILL to %u\n", parent);
96 kill(parent, SIGKILL);
97 }
98}
diff --git a/src/firejail/syscall.c b/src/firejail/syscall.c
new file mode 100644
index 000000000..50bff7f5a
--- /dev/null
+++ b/src/firejail/syscall.c
@@ -0,0 +1,4942 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
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 <sys/syscall.h>
24
25typedef struct {
26 char *name;
27 int nr;
28} SyscallEntry;
29
30static SyscallEntry syslist[] = {
31//
32// code generated using tools/extract-syscall
33//
34#ifndef _SYSCALL_H
35#endif
36#if !defined __x86_64__
37#ifdef SYS__llseek
38#ifdef __NR__llseek
39 {"_llseek", __NR__llseek},
40#endif
41#endif
42#ifdef SYS__newselect
43#ifdef __NR__newselect
44 {"_newselect", __NR__newselect},
45#endif
46#endif
47#ifdef SYS__sysctl
48#ifdef __NR__sysctl
49 {"_sysctl", __NR__sysctl},
50#endif
51#endif
52#ifdef SYS_access
53#ifdef __NR_access
54 {"access", __NR_access},
55#endif
56#endif
57#ifdef SYS_acct
58#ifdef __NR_acct
59 {"acct", __NR_acct},
60#endif
61#endif
62#ifdef SYS_add_key
63#ifdef __NR_add_key
64 {"add_key", __NR_add_key},
65#endif
66#endif
67#ifdef SYS_adjtimex
68#ifdef __NR_adjtimex
69 {"adjtimex", __NR_adjtimex},
70#endif
71#endif
72#ifdef SYS_afs_syscall
73#ifdef __NR_afs_syscall
74 {"afs_syscall", __NR_afs_syscall},
75#endif
76#endif
77#ifdef SYS_alarm
78#ifdef __NR_alarm
79 {"alarm", __NR_alarm},
80#endif
81#endif
82#ifdef SYS_bdflush
83#ifdef __NR_bdflush
84 {"bdflush", __NR_bdflush},
85#endif
86#endif
87#ifdef SYS_break
88#ifdef __NR_break
89 {"break", __NR_break},
90#endif
91#endif
92#ifdef SYS_brk
93#ifdef __NR_brk
94 {"brk", __NR_brk},
95#endif
96#endif
97#ifdef SYS_capget
98#ifdef __NR_capget
99 {"capget", __NR_capget},
100#endif
101#endif
102#ifdef SYS_capset
103#ifdef __NR_capset
104 {"capset", __NR_capset},
105#endif
106#endif
107#ifdef SYS_chdir
108#ifdef __NR_chdir
109 {"chdir", __NR_chdir},
110#endif
111#endif
112#ifdef SYS_chmod
113#ifdef __NR_chmod
114 {"chmod", __NR_chmod},
115#endif
116#endif
117#ifdef SYS_chown
118#ifdef __NR_chown
119 {"chown", __NR_chown},
120#endif
121#endif
122#ifdef SYS_chown32
123#ifdef __NR_chown32
124 {"chown32", __NR_chown32},
125#endif
126#endif
127#ifdef SYS_chroot
128#ifdef __NR_chroot
129 {"chroot", __NR_chroot},
130#endif
131#endif
132#ifdef SYS_clock_adjtime
133#ifdef __NR_clock_adjtime
134 {"clock_adjtime", __NR_clock_adjtime},
135#endif
136#endif
137#ifdef SYS_clock_getres
138#ifdef __NR_clock_getres
139 {"clock_getres", __NR_clock_getres},
140#endif
141#endif
142#ifdef SYS_clock_gettime
143#ifdef __NR_clock_gettime
144 {"clock_gettime", __NR_clock_gettime},
145#endif
146#endif
147#ifdef SYS_clock_nanosleep
148#ifdef __NR_clock_nanosleep
149 {"clock_nanosleep", __NR_clock_nanosleep},
150#endif
151#endif
152#ifdef SYS_clock_settime
153#ifdef __NR_clock_settime
154 {"clock_settime", __NR_clock_settime},
155#endif
156#endif
157#ifdef SYS_clone
158#ifdef __NR_clone
159 {"clone", __NR_clone},
160#endif
161#endif
162#ifdef SYS_close
163#ifdef __NR_close
164 {"close", __NR_close},
165#endif
166#endif
167#ifdef SYS_creat
168#ifdef __NR_creat
169 {"creat", __NR_creat},
170#endif
171#endif
172#ifdef SYS_create_module
173#ifdef __NR_create_module
174 {"create_module", __NR_create_module},
175#endif
176#endif
177#ifdef SYS_delete_module
178#ifdef __NR_delete_module
179 {"delete_module", __NR_delete_module},
180#endif
181#endif
182#ifdef SYS_dup
183#ifdef __NR_dup
184 {"dup", __NR_dup},
185#endif
186#endif
187#ifdef SYS_dup2
188#ifdef __NR_dup2
189 {"dup2", __NR_dup2},
190#endif
191#endif
192#ifdef SYS_dup3
193#ifdef __NR_dup3
194 {"dup3", __NR_dup3},
195#endif
196#endif
197#ifdef SYS_epoll_create
198#ifdef __NR_epoll_create
199 {"epoll_create", __NR_epoll_create},
200#endif
201#endif
202#ifdef SYS_epoll_create1
203#ifdef __NR_epoll_create1
204 {"epoll_create1", __NR_epoll_create1},
205#endif
206#endif
207#ifdef SYS_epoll_ctl
208#ifdef __NR_epoll_ctl
209 {"epoll_ctl", __NR_epoll_ctl},
210#endif
211#endif
212#ifdef SYS_epoll_pwait
213#ifdef __NR_epoll_pwait
214 {"epoll_pwait", __NR_epoll_pwait},
215#endif
216#endif
217#ifdef SYS_epoll_wait
218#ifdef __NR_epoll_wait
219 {"epoll_wait", __NR_epoll_wait},
220#endif
221#endif
222#ifdef SYS_eventfd
223#ifdef __NR_eventfd
224 {"eventfd", __NR_eventfd},
225#endif
226#endif
227#ifdef SYS_eventfd2
228#ifdef __NR_eventfd2
229 {"eventfd2", __NR_eventfd2},
230#endif
231#endif
232#ifdef SYS_execve
233#ifdef __NR_execve
234 {"execve", __NR_execve},
235#endif
236#endif
237#ifdef SYS_exit
238#ifdef __NR_exit
239 {"exit", __NR_exit},
240#endif
241#endif
242#ifdef SYS_exit_group
243#ifdef __NR_exit_group
244 {"exit_group", __NR_exit_group},
245#endif
246#endif
247#ifdef SYS_faccessat
248#ifdef __NR_faccessat
249 {"faccessat", __NR_faccessat},
250#endif
251#endif
252#ifdef SYS_fadvise64
253#ifdef __NR_fadvise64
254 {"fadvise64", __NR_fadvise64},
255#endif
256#endif
257#ifdef SYS_fadvise64_64
258#ifdef __NR_fadvise64_64
259 {"fadvise64_64", __NR_fadvise64_64},
260#endif
261#endif
262#ifdef SYS_fallocate
263#ifdef __NR_fallocate
264 {"fallocate", __NR_fallocate},
265#endif
266#endif
267#ifdef SYS_fanotify_init
268#ifdef __NR_fanotify_init
269 {"fanotify_init", __NR_fanotify_init},
270#endif
271#endif
272#ifdef SYS_fanotify_mark
273#ifdef __NR_fanotify_mark
274 {"fanotify_mark", __NR_fanotify_mark},
275#endif
276#endif
277#ifdef SYS_fchdir
278#ifdef __NR_fchdir
279 {"fchdir", __NR_fchdir},
280#endif
281#endif
282#ifdef SYS_fchmod
283#ifdef __NR_fchmod
284 {"fchmod", __NR_fchmod},
285#endif
286#endif
287#ifdef SYS_fchmodat
288#ifdef __NR_fchmodat
289 {"fchmodat", __NR_fchmodat},
290#endif
291#endif
292#ifdef SYS_fchown
293#ifdef __NR_fchown
294 {"fchown", __NR_fchown},
295#endif
296#endif
297#ifdef SYS_fchown32
298#ifdef __NR_fchown32
299 {"fchown32", __NR_fchown32},
300#endif
301#endif
302#ifdef SYS_fchownat
303#ifdef __NR_fchownat
304 {"fchownat", __NR_fchownat},
305#endif
306#endif
307#ifdef SYS_fcntl
308#ifdef __NR_fcntl
309 {"fcntl", __NR_fcntl},
310#endif
311#endif
312#ifdef SYS_fcntl64
313#ifdef __NR_fcntl64
314 {"fcntl64", __NR_fcntl64},
315#endif
316#endif
317#ifdef SYS_fdatasync
318#ifdef __NR_fdatasync
319 {"fdatasync", __NR_fdatasync},
320#endif
321#endif
322#ifdef SYS_fgetxattr
323#ifdef __NR_fgetxattr
324 {"fgetxattr", __NR_fgetxattr},
325#endif
326#endif
327#ifdef SYS_finit_module
328#ifdef __NR_finit_module
329 {"finit_module", __NR_finit_module},
330#endif
331#endif
332#ifdef SYS_flistxattr
333#ifdef __NR_flistxattr
334 {"flistxattr", __NR_flistxattr},
335#endif
336#endif
337#ifdef SYS_flock
338#ifdef __NR_flock
339 {"flock", __NR_flock},
340#endif
341#endif
342#ifdef SYS_fork
343#ifdef __NR_fork
344 {"fork", __NR_fork},
345#endif
346#endif
347#ifdef SYS_fremovexattr
348#ifdef __NR_fremovexattr
349 {"fremovexattr", __NR_fremovexattr},
350#endif
351#endif
352#ifdef SYS_fsetxattr
353#ifdef __NR_fsetxattr
354 {"fsetxattr", __NR_fsetxattr},
355#endif
356#endif
357#ifdef SYS_fstat
358#ifdef __NR_fstat
359 {"fstat", __NR_fstat},
360#endif
361#endif
362#ifdef SYS_fstat64
363#ifdef __NR_fstat64
364 {"fstat64", __NR_fstat64},
365#endif
366#endif
367#ifdef SYS_fstatat64
368#ifdef __NR_fstatat64
369 {"fstatat64", __NR_fstatat64},
370#endif
371#endif
372#ifdef SYS_fstatfs
373#ifdef __NR_fstatfs
374 {"fstatfs", __NR_fstatfs},
375#endif
376#endif
377#ifdef SYS_fstatfs64
378#ifdef __NR_fstatfs64
379 {"fstatfs64", __NR_fstatfs64},
380#endif
381#endif
382#ifdef SYS_fsync
383#ifdef __NR_fsync
384 {"fsync", __NR_fsync},
385#endif
386#endif
387#ifdef SYS_ftime
388#ifdef __NR_ftime
389 {"ftime", __NR_ftime},
390#endif
391#endif
392#ifdef SYS_ftruncate
393#ifdef __NR_ftruncate
394 {"ftruncate", __NR_ftruncate},
395#endif
396#endif
397#ifdef SYS_ftruncate64
398#ifdef __NR_ftruncate64
399 {"ftruncate64", __NR_ftruncate64},
400#endif
401#endif
402#ifdef SYS_futex
403#ifdef __NR_futex
404 {"futex", __NR_futex},
405#endif
406#endif
407#ifdef SYS_futimesat
408#ifdef __NR_futimesat
409 {"futimesat", __NR_futimesat},
410#endif
411#endif
412#ifdef SYS_get_kernel_syms
413#ifdef __NR_get_kernel_syms
414 {"get_kernel_syms", __NR_get_kernel_syms},
415#endif
416#endif
417#ifdef SYS_get_mempolicy
418#ifdef __NR_get_mempolicy
419 {"get_mempolicy", __NR_get_mempolicy},
420#endif
421#endif
422#ifdef SYS_get_robust_list
423#ifdef __NR_get_robust_list
424 {"get_robust_list", __NR_get_robust_list},
425#endif
426#endif
427#ifdef SYS_get_thread_area
428#ifdef __NR_get_thread_area
429 {"get_thread_area", __NR_get_thread_area},
430#endif
431#endif
432#ifdef SYS_getcpu
433#ifdef __NR_getcpu
434 {"getcpu", __NR_getcpu},
435#endif
436#endif
437#ifdef SYS_getcwd
438#ifdef __NR_getcwd
439 {"getcwd", __NR_getcwd},
440#endif
441#endif
442#ifdef SYS_getdents
443#ifdef __NR_getdents
444 {"getdents", __NR_getdents},
445#endif
446#endif
447#ifdef SYS_getdents64
448#ifdef __NR_getdents64
449 {"getdents64", __NR_getdents64},
450#endif
451#endif
452#ifdef SYS_getegid
453#ifdef __NR_getegid
454 {"getegid", __NR_getegid},
455#endif
456#endif
457#ifdef SYS_getegid32
458#ifdef __NR_getegid32
459 {"getegid32", __NR_getegid32},
460#endif
461#endif
462#ifdef SYS_geteuid
463#ifdef __NR_geteuid
464 {"geteuid", __NR_geteuid},
465#endif
466#endif
467#ifdef SYS_geteuid32
468#ifdef __NR_geteuid32
469 {"geteuid32", __NR_geteuid32},
470#endif
471#endif
472#ifdef SYS_getgid
473#ifdef __NR_getgid
474 {"getgid", __NR_getgid},
475#endif
476#endif
477#ifdef SYS_getgid32
478#ifdef __NR_getgid32
479 {"getgid32", __NR_getgid32},
480#endif
481#endif
482#ifdef SYS_getgroups
483#ifdef __NR_getgroups
484 {"getgroups", __NR_getgroups},
485#endif
486#endif
487#ifdef SYS_getgroups32
488#ifdef __NR_getgroups32
489 {"getgroups32", __NR_getgroups32},
490#endif
491#endif
492#ifdef SYS_getitimer
493#ifdef __NR_getitimer
494 {"getitimer", __NR_getitimer},
495#endif
496#endif
497#ifdef SYS_getpgid
498#ifdef __NR_getpgid
499 {"getpgid", __NR_getpgid},
500#endif
501#endif
502#ifdef SYS_getpgrp
503#ifdef __NR_getpgrp
504 {"getpgrp", __NR_getpgrp},
505#endif
506#endif
507#ifdef SYS_getpid
508#ifdef __NR_getpid
509 {"getpid", __NR_getpid},
510#endif
511#endif
512#ifdef SYS_getpmsg
513#ifdef __NR_getpmsg
514 {"getpmsg", __NR_getpmsg},
515#endif
516#endif
517#ifdef SYS_getppid
518#ifdef __NR_getppid
519 {"getppid", __NR_getppid},
520#endif
521#endif
522#ifdef SYS_getpriority
523#ifdef __NR_getpriority
524 {"getpriority", __NR_getpriority},
525#endif
526#endif
527#ifdef SYS_getresgid
528#ifdef __NR_getresgid
529 {"getresgid", __NR_getresgid},
530#endif
531#endif
532#ifdef SYS_getresgid32
533#ifdef __NR_getresgid32
534 {"getresgid32", __NR_getresgid32},
535#endif
536#endif
537#ifdef SYS_getresuid
538#ifdef __NR_getresuid
539 {"getresuid", __NR_getresuid},
540#endif
541#endif
542#ifdef SYS_getresuid32
543#ifdef __NR_getresuid32
544 {"getresuid32", __NR_getresuid32},
545#endif
546#endif
547#ifdef SYS_getrlimit
548#ifdef __NR_getrlimit
549 {"getrlimit", __NR_getrlimit},
550#endif
551#endif
552#ifdef SYS_getrusage
553#ifdef __NR_getrusage
554 {"getrusage", __NR_getrusage},
555#endif
556#endif
557#ifdef SYS_getsid
558#ifdef __NR_getsid
559 {"getsid", __NR_getsid},
560#endif
561#endif
562#ifdef SYS_gettid
563#ifdef __NR_gettid
564 {"gettid", __NR_gettid},
565#endif
566#endif
567#ifdef SYS_gettimeofday
568#ifdef __NR_gettimeofday
569 {"gettimeofday", __NR_gettimeofday},
570#endif
571#endif
572#ifdef SYS_getuid
573#ifdef __NR_getuid
574 {"getuid", __NR_getuid},
575#endif
576#endif
577#ifdef SYS_getuid32
578#ifdef __NR_getuid32
579 {"getuid32", __NR_getuid32},
580#endif
581#endif
582#ifdef SYS_getxattr
583#ifdef __NR_getxattr
584 {"getxattr", __NR_getxattr},
585#endif
586#endif
587#ifdef SYS_gtty
588#ifdef __NR_gtty
589 {"gtty", __NR_gtty},
590#endif
591#endif
592#ifdef SYS_idle
593#ifdef __NR_idle
594 {"idle", __NR_idle},
595#endif
596#endif
597#ifdef SYS_init_module
598#ifdef __NR_init_module
599 {"init_module", __NR_init_module},
600#endif
601#endif
602#ifdef SYS_inotify_add_watch
603#ifdef __NR_inotify_add_watch
604 {"inotify_add_watch", __NR_inotify_add_watch},
605#endif
606#endif
607#ifdef SYS_inotify_init
608#ifdef __NR_inotify_init
609 {"inotify_init", __NR_inotify_init},
610#endif
611#endif
612#ifdef SYS_inotify_init1
613#ifdef __NR_inotify_init1
614 {"inotify_init1", __NR_inotify_init1},
615#endif
616#endif
617#ifdef SYS_inotify_rm_watch
618#ifdef __NR_inotify_rm_watch
619 {"inotify_rm_watch", __NR_inotify_rm_watch},
620#endif
621#endif
622#ifdef SYS_io_cancel
623#ifdef __NR_io_cancel
624 {"io_cancel", __NR_io_cancel},
625#endif
626#endif
627#ifdef SYS_io_destroy
628#ifdef __NR_io_destroy
629 {"io_destroy", __NR_io_destroy},
630#endif
631#endif
632#ifdef SYS_io_getevents
633#ifdef __NR_io_getevents
634 {"io_getevents", __NR_io_getevents},
635#endif
636#endif
637#ifdef SYS_io_setup
638#ifdef __NR_io_setup
639 {"io_setup", __NR_io_setup},
640#endif
641#endif
642#ifdef SYS_io_submit
643#ifdef __NR_io_submit
644 {"io_submit", __NR_io_submit},
645#endif
646#endif
647#ifdef SYS_ioctl
648#ifdef __NR_ioctl
649 {"ioctl", __NR_ioctl},
650#endif
651#endif
652#ifdef SYS_ioperm
653#ifdef __NR_ioperm
654 {"ioperm", __NR_ioperm},
655#endif
656#endif
657#ifdef SYS_iopl
658#ifdef __NR_iopl
659 {"iopl", __NR_iopl},
660#endif
661#endif
662#ifdef SYS_ioprio_get
663#ifdef __NR_ioprio_get
664 {"ioprio_get", __NR_ioprio_get},
665#endif
666#endif
667#ifdef SYS_ioprio_set
668#ifdef __NR_ioprio_set
669 {"ioprio_set", __NR_ioprio_set},
670#endif
671#endif
672#ifdef SYS_ipc
673#ifdef __NR_ipc
674 {"ipc", __NR_ipc},
675#endif
676#endif
677#ifdef SYS_kcmp
678#ifdef __NR_kcmp
679 {"kcmp", __NR_kcmp},
680#endif
681#endif
682#ifdef SYS_kexec_load
683#ifdef __NR_kexec_load
684 {"kexec_load", __NR_kexec_load},
685#endif
686#endif
687#ifdef SYS_keyctl
688#ifdef __NR_keyctl
689 {"keyctl", __NR_keyctl},
690#endif
691#endif
692#ifdef SYS_kill
693#ifdef __NR_kill
694 {"kill", __NR_kill},
695#endif
696#endif
697#ifdef SYS_lchown
698#ifdef __NR_lchown
699 {"lchown", __NR_lchown},
700#endif
701#endif
702#ifdef SYS_lchown32
703#ifdef __NR_lchown32
704 {"lchown32", __NR_lchown32},
705#endif
706#endif
707#ifdef SYS_lgetxattr
708#ifdef __NR_lgetxattr
709 {"lgetxattr", __NR_lgetxattr},
710#endif
711#endif
712#ifdef SYS_link
713#ifdef __NR_link
714 {"link", __NR_link},
715#endif
716#endif
717#ifdef SYS_linkat
718#ifdef __NR_linkat
719 {"linkat", __NR_linkat},
720#endif
721#endif
722#ifdef SYS_listxattr
723#ifdef __NR_listxattr
724 {"listxattr", __NR_listxattr},
725#endif
726#endif
727#ifdef SYS_llistxattr
728#ifdef __NR_llistxattr
729 {"llistxattr", __NR_llistxattr},
730#endif
731#endif
732#ifdef SYS_lock
733#ifdef __NR_lock
734 {"lock", __NR_lock},
735#endif
736#endif
737#ifdef SYS_lookup_dcookie
738#ifdef __NR_lookup_dcookie
739 {"lookup_dcookie", __NR_lookup_dcookie},
740#endif
741#endif
742#ifdef SYS_lremovexattr
743#ifdef __NR_lremovexattr
744 {"lremovexattr", __NR_lremovexattr},
745#endif
746#endif
747#ifdef SYS_lseek
748#ifdef __NR_lseek
749 {"lseek", __NR_lseek},
750#endif
751#endif
752#ifdef SYS_lsetxattr
753#ifdef __NR_lsetxattr
754 {"lsetxattr", __NR_lsetxattr},
755#endif
756#endif
757#ifdef SYS_lstat
758#ifdef __NR_lstat
759 {"lstat", __NR_lstat},
760#endif
761#endif
762#ifdef SYS_lstat64
763#ifdef __NR_lstat64
764 {"lstat64", __NR_lstat64},
765#endif
766#endif
767#ifdef SYS_madvise
768#ifdef __NR_madvise
769 {"madvise", __NR_madvise},
770#endif
771#endif
772#ifdef SYS_mbind
773#ifdef __NR_mbind
774 {"mbind", __NR_mbind},
775#endif
776#endif
777#ifdef SYS_migrate_pages
778#ifdef __NR_migrate_pages
779 {"migrate_pages", __NR_migrate_pages},
780#endif
781#endif
782#ifdef SYS_mincore
783#ifdef __NR_mincore
784 {"mincore", __NR_mincore},
785#endif
786#endif
787#ifdef SYS_mkdir
788#ifdef __NR_mkdir
789 {"mkdir", __NR_mkdir},
790#endif
791#endif
792#ifdef SYS_mkdirat
793#ifdef __NR_mkdirat
794 {"mkdirat", __NR_mkdirat},
795#endif
796#endif
797#ifdef SYS_mknod
798#ifdef __NR_mknod
799 {"mknod", __NR_mknod},
800#endif
801#endif
802#ifdef SYS_mknodat
803#ifdef __NR_mknodat
804 {"mknodat", __NR_mknodat},
805#endif
806#endif
807#ifdef SYS_mlock
808#ifdef __NR_mlock
809 {"mlock", __NR_mlock},
810#endif
811#endif
812#ifdef SYS_mlockall
813#ifdef __NR_mlockall
814 {"mlockall", __NR_mlockall},
815#endif
816#endif
817#ifdef SYS_mmap
818#ifdef __NR_mmap
819 {"mmap", __NR_mmap},
820#endif
821#endif
822#ifdef SYS_mmap2
823#ifdef __NR_mmap2
824 {"mmap2", __NR_mmap2},
825#endif
826#endif
827#ifdef SYS_modify_ldt
828#ifdef __NR_modify_ldt
829 {"modify_ldt", __NR_modify_ldt},
830#endif
831#endif
832#ifdef SYS_mount
833#ifdef __NR_mount
834 {"mount", __NR_mount},
835#endif
836#endif
837#ifdef SYS_move_pages
838#ifdef __NR_move_pages
839 {"move_pages", __NR_move_pages},
840#endif
841#endif
842#ifdef SYS_mprotect
843#ifdef __NR_mprotect
844 {"mprotect", __NR_mprotect},
845#endif
846#endif
847#ifdef SYS_mpx
848#ifdef __NR_mpx
849 {"mpx", __NR_mpx},
850#endif
851#endif
852#ifdef SYS_mq_getsetattr
853#ifdef __NR_mq_getsetattr
854 {"mq_getsetattr", __NR_mq_getsetattr},
855#endif
856#endif
857#ifdef SYS_mq_notify
858#ifdef __NR_mq_notify
859 {"mq_notify", __NR_mq_notify},
860#endif
861#endif
862#ifdef SYS_mq_open
863#ifdef __NR_mq_open
864 {"mq_open", __NR_mq_open},
865#endif
866#endif
867#ifdef SYS_mq_timedreceive
868#ifdef __NR_mq_timedreceive
869 {"mq_timedreceive", __NR_mq_timedreceive},
870#endif
871#endif
872#ifdef SYS_mq_timedsend
873#ifdef __NR_mq_timedsend
874 {"mq_timedsend", __NR_mq_timedsend},
875#endif
876#endif
877#ifdef SYS_mq_unlink
878#ifdef __NR_mq_unlink
879 {"mq_unlink", __NR_mq_unlink},
880#endif
881#endif
882#ifdef SYS_mremap
883#ifdef __NR_mremap
884 {"mremap", __NR_mremap},
885#endif
886#endif
887#ifdef SYS_msync
888#ifdef __NR_msync
889 {"msync", __NR_msync},
890#endif
891#endif
892#ifdef SYS_munlock
893#ifdef __NR_munlock
894 {"munlock", __NR_munlock},
895#endif
896#endif
897#ifdef SYS_munlockall
898#ifdef __NR_munlockall
899 {"munlockall", __NR_munlockall},
900#endif
901#endif
902#ifdef SYS_munmap
903#ifdef __NR_munmap
904 {"munmap", __NR_munmap},
905#endif
906#endif
907#ifdef SYS_name_to_handle_at
908#ifdef __NR_name_to_handle_at
909 {"name_to_handle_at", __NR_name_to_handle_at},
910#endif
911#endif
912#ifdef SYS_nanosleep
913#ifdef __NR_nanosleep
914 {"nanosleep", __NR_nanosleep},
915#endif
916#endif
917#ifdef SYS_nfsservctl
918#ifdef __NR_nfsservctl
919 {"nfsservctl", __NR_nfsservctl},
920#endif
921#endif
922#ifdef SYS_nice
923#ifdef __NR_nice
924 {"nice", __NR_nice},
925#endif
926#endif
927#ifdef SYS_oldfstat
928#ifdef __NR_oldfstat
929 {"oldfstat", __NR_oldfstat},
930#endif
931#endif
932#ifdef SYS_oldlstat
933#ifdef __NR_oldlstat
934 {"oldlstat", __NR_oldlstat},
935#endif
936#endif
937#ifdef SYS_oldolduname
938#ifdef __NR_oldolduname
939 {"oldolduname", __NR_oldolduname},
940#endif
941#endif
942#ifdef SYS_oldstat
943#ifdef __NR_oldstat
944 {"oldstat", __NR_oldstat},
945#endif
946#endif
947#ifdef SYS_olduname
948#ifdef __NR_olduname
949 {"olduname", __NR_olduname},
950#endif
951#endif
952#ifdef SYS_open
953#ifdef __NR_open
954 {"open", __NR_open},
955#endif
956#endif
957#ifdef SYS_open_by_handle_at
958#ifdef __NR_open_by_handle_at
959 {"open_by_handle_at", __NR_open_by_handle_at},
960#endif
961#endif
962#ifdef SYS_openat
963#ifdef __NR_openat
964 {"openat", __NR_openat},
965#endif
966#endif
967#ifdef SYS_pause
968#ifdef __NR_pause
969 {"pause", __NR_pause},
970#endif
971#endif
972#ifdef SYS_perf_event_open
973#ifdef __NR_perf_event_open
974 {"perf_event_open", __NR_perf_event_open},
975#endif
976#endif
977#ifdef SYS_personality
978#ifdef __NR_personality
979 {"personality", __NR_personality},
980#endif
981#endif
982#ifdef SYS_pipe
983#ifdef __NR_pipe
984 {"pipe", __NR_pipe},
985#endif
986#endif
987#ifdef SYS_pipe2
988#ifdef __NR_pipe2
989 {"pipe2", __NR_pipe2},
990#endif
991#endif
992#ifdef SYS_pivot_root
993#ifdef __NR_pivot_root
994 {"pivot_root", __NR_pivot_root},
995#endif
996#endif
997#ifdef SYS_poll
998#ifdef __NR_poll
999 {"poll", __NR_poll},
1000#endif
1001#endif
1002#ifdef SYS_ppoll
1003#ifdef __NR_ppoll
1004 {"ppoll", __NR_ppoll},
1005#endif
1006#endif
1007#ifdef SYS_prctl
1008#ifdef __NR_prctl
1009 {"prctl", __NR_prctl},
1010#endif
1011#endif
1012#ifdef SYS_pread64
1013#ifdef __NR_pread64
1014 {"pread64", __NR_pread64},
1015#endif
1016#endif
1017#ifdef SYS_preadv
1018#ifdef __NR_preadv
1019 {"preadv", __NR_preadv},
1020#endif
1021#endif
1022#ifdef SYS_prlimit64
1023#ifdef __NR_prlimit64
1024 {"prlimit64", __NR_prlimit64},
1025#endif
1026#endif
1027#ifdef SYS_process_vm_readv
1028#ifdef __NR_process_vm_readv
1029 {"process_vm_readv", __NR_process_vm_readv},
1030#endif
1031#endif
1032#ifdef SYS_process_vm_writev
1033#ifdef __NR_process_vm_writev
1034 {"process_vm_writev", __NR_process_vm_writev},
1035#endif
1036#endif
1037#ifdef SYS_prof
1038#ifdef __NR_prof
1039 {"prof", __NR_prof},
1040#endif
1041#endif
1042#ifdef SYS_profil
1043#ifdef __NR_profil
1044 {"profil", __NR_profil},
1045#endif
1046#endif
1047#ifdef SYS_pselect6
1048#ifdef __NR_pselect6
1049 {"pselect6", __NR_pselect6},
1050#endif
1051#endif
1052#ifdef SYS_ptrace
1053#ifdef __NR_ptrace
1054 {"ptrace", __NR_ptrace},
1055#endif
1056#endif
1057#ifdef SYS_putpmsg
1058#ifdef __NR_putpmsg
1059 {"putpmsg", __NR_putpmsg},
1060#endif
1061#endif
1062#ifdef SYS_pwrite64
1063#ifdef __NR_pwrite64
1064 {"pwrite64", __NR_pwrite64},
1065#endif
1066#endif
1067#ifdef SYS_pwritev
1068#ifdef __NR_pwritev
1069 {"pwritev", __NR_pwritev},
1070#endif
1071#endif
1072#ifdef SYS_query_module
1073#ifdef __NR_query_module
1074 {"query_module", __NR_query_module},
1075#endif
1076#endif
1077#ifdef SYS_quotactl
1078#ifdef __NR_quotactl
1079 {"quotactl", __NR_quotactl},
1080#endif
1081#endif
1082#ifdef SYS_read
1083#ifdef __NR_read
1084 {"read", __NR_read},
1085#endif
1086#endif
1087#ifdef SYS_readahead
1088#ifdef __NR_readahead
1089 {"readahead", __NR_readahead},
1090#endif
1091#endif
1092#ifdef SYS_readdir
1093#ifdef __NR_readdir
1094 {"readdir", __NR_readdir},
1095#endif
1096#endif
1097#ifdef SYS_readlink
1098#ifdef __NR_readlink
1099 {"readlink", __NR_readlink},
1100#endif
1101#endif
1102#ifdef SYS_readlinkat
1103#ifdef __NR_readlinkat
1104 {"readlinkat", __NR_readlinkat},
1105#endif
1106#endif
1107#ifdef SYS_readv
1108#ifdef __NR_readv
1109 {"readv", __NR_readv},
1110#endif
1111#endif
1112#ifdef SYS_reboot
1113#ifdef __NR_reboot
1114 {"reboot", __NR_reboot},
1115#endif
1116#endif
1117#ifdef SYS_recvmmsg
1118#ifdef __NR_recvmmsg
1119 {"recvmmsg", __NR_recvmmsg},
1120#endif
1121#endif
1122#ifdef SYS_remap_file_pages
1123#ifdef __NR_remap_file_pages
1124 {"remap_file_pages", __NR_remap_file_pages},
1125#endif
1126#endif
1127#ifdef SYS_removexattr
1128#ifdef __NR_removexattr
1129 {"removexattr", __NR_removexattr},
1130#endif
1131#endif
1132#ifdef SYS_rename
1133#ifdef __NR_rename
1134 {"rename", __NR_rename},
1135#endif
1136#endif
1137#ifdef SYS_renameat
1138#ifdef __NR_renameat
1139 {"renameat", __NR_renameat},
1140#endif
1141#endif
1142#ifdef SYS_request_key
1143#ifdef __NR_request_key
1144 {"request_key", __NR_request_key},
1145#endif
1146#endif
1147#ifdef SYS_restart_syscall
1148#ifdef __NR_restart_syscall
1149 {"restart_syscall", __NR_restart_syscall},
1150#endif
1151#endif
1152#ifdef SYS_rmdir
1153#ifdef __NR_rmdir
1154 {"rmdir", __NR_rmdir},
1155#endif
1156#endif
1157#ifdef SYS_rt_sigaction
1158#ifdef __NR_rt_sigaction
1159 {"rt_sigaction", __NR_rt_sigaction},
1160#endif
1161#endif
1162#ifdef SYS_rt_sigpending
1163#ifdef __NR_rt_sigpending
1164 {"rt_sigpending", __NR_rt_sigpending},
1165#endif
1166#endif
1167#ifdef SYS_rt_sigprocmask
1168#ifdef __NR_rt_sigprocmask
1169 {"rt_sigprocmask", __NR_rt_sigprocmask},
1170#endif
1171#endif
1172#ifdef SYS_rt_sigqueueinfo
1173#ifdef __NR_rt_sigqueueinfo
1174 {"rt_sigqueueinfo", __NR_rt_sigqueueinfo},
1175#endif
1176#endif
1177#ifdef SYS_rt_sigreturn
1178#ifdef __NR_rt_sigreturn
1179 {"rt_sigreturn", __NR_rt_sigreturn},
1180#endif
1181#endif
1182#ifdef SYS_rt_sigsuspend
1183#ifdef __NR_rt_sigsuspend
1184 {"rt_sigsuspend", __NR_rt_sigsuspend},
1185#endif
1186#endif
1187#ifdef SYS_rt_sigtimedwait
1188#ifdef __NR_rt_sigtimedwait
1189 {"rt_sigtimedwait", __NR_rt_sigtimedwait},
1190#endif
1191#endif
1192#ifdef SYS_rt_tgsigqueueinfo
1193#ifdef __NR_rt_tgsigqueueinfo
1194 {"rt_tgsigqueueinfo", __NR_rt_tgsigqueueinfo},
1195#endif
1196#endif
1197#ifdef SYS_sched_get_priority_max
1198#ifdef __NR_sched_get_priority_max
1199 {"sched_get_priority_max", __NR_sched_get_priority_max},
1200#endif
1201#endif
1202#ifdef SYS_sched_get_priority_min
1203#ifdef __NR_sched_get_priority_min
1204 {"sched_get_priority_min", __NR_sched_get_priority_min},
1205#endif
1206#endif
1207#ifdef SYS_sched_getaffinity
1208#ifdef __NR_sched_getaffinity
1209 {"sched_getaffinity", __NR_sched_getaffinity},
1210#endif
1211#endif
1212#ifdef SYS_sched_getparam
1213#ifdef __NR_sched_getparam
1214 {"sched_getparam", __NR_sched_getparam},
1215#endif
1216#endif
1217#ifdef SYS_sched_getscheduler
1218#ifdef __NR_sched_getscheduler
1219 {"sched_getscheduler", __NR_sched_getscheduler},
1220#endif
1221#endif
1222#ifdef SYS_sched_rr_get_interval
1223#ifdef __NR_sched_rr_get_interval
1224 {"sched_rr_get_interval", __NR_sched_rr_get_interval},
1225#endif
1226#endif
1227#ifdef SYS_sched_setaffinity
1228#ifdef __NR_sched_setaffinity
1229 {"sched_setaffinity", __NR_sched_setaffinity},
1230#endif
1231#endif
1232#ifdef SYS_sched_setparam
1233#ifdef __NR_sched_setparam
1234 {"sched_setparam", __NR_sched_setparam},
1235#endif
1236#endif
1237#ifdef SYS_sched_setscheduler
1238#ifdef __NR_sched_setscheduler
1239 {"sched_setscheduler", __NR_sched_setscheduler},
1240#endif
1241#endif
1242#ifdef SYS_sched_yield
1243#ifdef __NR_sched_yield
1244 {"sched_yield", __NR_sched_yield},
1245#endif
1246#endif
1247#ifdef SYS_select
1248#ifdef __NR_select
1249 {"select", __NR_select},
1250#endif
1251#endif
1252#ifdef SYS_sendfile
1253#ifdef __NR_sendfile
1254 {"sendfile", __NR_sendfile},
1255#endif
1256#endif
1257#ifdef SYS_sendfile64
1258#ifdef __NR_sendfile64
1259 {"sendfile64", __NR_sendfile64},
1260#endif
1261#endif
1262#ifdef SYS_sendmmsg
1263#ifdef __NR_sendmmsg
1264 {"sendmmsg", __NR_sendmmsg},
1265#endif
1266#endif
1267#ifdef SYS_set_mempolicy
1268#ifdef __NR_set_mempolicy
1269 {"set_mempolicy", __NR_set_mempolicy},
1270#endif
1271#endif
1272#ifdef SYS_set_robust_list
1273#ifdef __NR_set_robust_list
1274 {"set_robust_list", __NR_set_robust_list},
1275#endif
1276#endif
1277#ifdef SYS_set_thread_area
1278#ifdef __NR_set_thread_area
1279 {"set_thread_area", __NR_set_thread_area},
1280#endif
1281#endif
1282#ifdef SYS_set_tid_address
1283#ifdef __NR_set_tid_address
1284 {"set_tid_address", __NR_set_tid_address},
1285#endif
1286#endif
1287#ifdef SYS_setdomainname
1288#ifdef __NR_setdomainname
1289 {"setdomainname", __NR_setdomainname},
1290#endif
1291#endif
1292#ifdef SYS_setfsgid
1293#ifdef __NR_setfsgid
1294 {"setfsgid", __NR_setfsgid},
1295#endif
1296#endif
1297#ifdef SYS_setfsgid32
1298#ifdef __NR_setfsgid32
1299 {"setfsgid32", __NR_setfsgid32},
1300#endif
1301#endif
1302#ifdef SYS_setfsuid
1303#ifdef __NR_setfsuid
1304 {"setfsuid", __NR_setfsuid},
1305#endif
1306#endif
1307#ifdef SYS_setfsuid32
1308#ifdef __NR_setfsuid32
1309 {"setfsuid32", __NR_setfsuid32},
1310#endif
1311#endif
1312#ifdef SYS_setgid
1313#ifdef __NR_setgid
1314 {"setgid", __NR_setgid},
1315#endif
1316#endif
1317#ifdef SYS_setgid32
1318#ifdef __NR_setgid32
1319 {"setgid32", __NR_setgid32},
1320#endif
1321#endif
1322#ifdef SYS_setgroups
1323#ifdef __NR_setgroups
1324 {"setgroups", __NR_setgroups},
1325#endif
1326#endif
1327#ifdef SYS_setgroups32
1328#ifdef __NR_setgroups32
1329 {"setgroups32", __NR_setgroups32},
1330#endif
1331#endif
1332#ifdef SYS_sethostname
1333#ifdef __NR_sethostname
1334 {"sethostname", __NR_sethostname},
1335#endif
1336#endif
1337#ifdef SYS_setitimer
1338#ifdef __NR_setitimer
1339 {"setitimer", __NR_setitimer},
1340#endif
1341#endif
1342#ifdef SYS_setns
1343#ifdef __NR_setns
1344 {"setns", __NR_setns},
1345#endif
1346#endif
1347#ifdef SYS_setpgid
1348#ifdef __NR_setpgid
1349 {"setpgid", __NR_setpgid},
1350#endif
1351#endif
1352#ifdef SYS_setpriority
1353#ifdef __NR_setpriority
1354 {"setpriority", __NR_setpriority},
1355#endif
1356#endif
1357#ifdef SYS_setregid
1358#ifdef __NR_setregid
1359 {"setregid", __NR_setregid},
1360#endif
1361#endif
1362#ifdef SYS_setregid32
1363#ifdef __NR_setregid32
1364 {"setregid32", __NR_setregid32},
1365#endif
1366#endif
1367#ifdef SYS_setresgid
1368#ifdef __NR_setresgid
1369 {"setresgid", __NR_setresgid},
1370#endif
1371#endif
1372#ifdef SYS_setresgid32
1373#ifdef __NR_setresgid32
1374 {"setresgid32", __NR_setresgid32},
1375#endif
1376#endif
1377#ifdef SYS_setresuid
1378#ifdef __NR_setresuid
1379 {"setresuid", __NR_setresuid},
1380#endif
1381#endif
1382#ifdef SYS_setresuid32
1383#ifdef __NR_setresuid32
1384 {"setresuid32", __NR_setresuid32},
1385#endif
1386#endif
1387#ifdef SYS_setreuid
1388#ifdef __NR_setreuid
1389 {"setreuid", __NR_setreuid},
1390#endif
1391#endif
1392#ifdef SYS_setreuid32
1393#ifdef __NR_setreuid32
1394 {"setreuid32", __NR_setreuid32},
1395#endif
1396#endif
1397#ifdef SYS_setrlimit
1398#ifdef __NR_setrlimit
1399 {"setrlimit", __NR_setrlimit},
1400#endif
1401#endif
1402#ifdef SYS_setsid
1403#ifdef __NR_setsid
1404 {"setsid", __NR_setsid},
1405#endif
1406#endif
1407#ifdef SYS_settimeofday
1408#ifdef __NR_settimeofday
1409 {"settimeofday", __NR_settimeofday},
1410#endif
1411#endif
1412#ifdef SYS_setuid
1413#ifdef __NR_setuid
1414 {"setuid", __NR_setuid},
1415#endif
1416#endif
1417#ifdef SYS_setuid32
1418#ifdef __NR_setuid32
1419 {"setuid32", __NR_setuid32},
1420#endif
1421#endif
1422#ifdef SYS_setxattr
1423#ifdef __NR_setxattr
1424 {"setxattr", __NR_setxattr},
1425#endif
1426#endif
1427#ifdef SYS_sgetmask
1428#ifdef __NR_sgetmask
1429 {"sgetmask", __NR_sgetmask},
1430#endif
1431#endif
1432#ifdef SYS_sigaction
1433#ifdef __NR_sigaction
1434 {"sigaction", __NR_sigaction},
1435#endif
1436#endif
1437#ifdef SYS_sigaltstack
1438#ifdef __NR_sigaltstack
1439 {"sigaltstack", __NR_sigaltstack},
1440#endif
1441#endif
1442#ifdef SYS_signal
1443#ifdef __NR_signal
1444 {"signal", __NR_signal},
1445#endif
1446#endif
1447#ifdef SYS_signalfd
1448#ifdef __NR_signalfd
1449 {"signalfd", __NR_signalfd},
1450#endif
1451#endif
1452#ifdef SYS_signalfd4
1453#ifdef __NR_signalfd4
1454 {"signalfd4", __NR_signalfd4},
1455#endif
1456#endif
1457#ifdef SYS_sigpending
1458#ifdef __NR_sigpending
1459 {"sigpending", __NR_sigpending},
1460#endif
1461#endif
1462#ifdef SYS_sigprocmask
1463#ifdef __NR_sigprocmask
1464 {"sigprocmask", __NR_sigprocmask},
1465#endif
1466#endif
1467#ifdef SYS_sigreturn
1468#ifdef __NR_sigreturn
1469 {"sigreturn", __NR_sigreturn},
1470#endif
1471#endif
1472#ifdef SYS_sigsuspend
1473#ifdef __NR_sigsuspend
1474 {"sigsuspend", __NR_sigsuspend},
1475#endif
1476#endif
1477#ifdef SYS_socketcall
1478#ifdef __NR_socketcall
1479 {"socketcall", __NR_socketcall},
1480#endif
1481#endif
1482#ifdef SYS_splice
1483#ifdef __NR_splice
1484 {"splice", __NR_splice},
1485#endif
1486#endif
1487#ifdef SYS_ssetmask
1488#ifdef __NR_ssetmask
1489 {"ssetmask", __NR_ssetmask},
1490#endif
1491#endif
1492#ifdef SYS_stat
1493#ifdef __NR_stat
1494 {"stat", __NR_stat},
1495#endif
1496#endif
1497#ifdef SYS_stat64
1498#ifdef __NR_stat64
1499 {"stat64", __NR_stat64},
1500#endif
1501#endif
1502#ifdef SYS_statfs
1503#ifdef __NR_statfs
1504 {"statfs", __NR_statfs},
1505#endif
1506#endif
1507#ifdef SYS_statfs64
1508#ifdef __NR_statfs64
1509 {"statfs64", __NR_statfs64},
1510#endif
1511#endif
1512#ifdef SYS_stime
1513#ifdef __NR_stime
1514 {"stime", __NR_stime},
1515#endif
1516#endif
1517#ifdef SYS_stty
1518#ifdef __NR_stty
1519 {"stty", __NR_stty},
1520#endif
1521#endif
1522#ifdef SYS_swapoff
1523#ifdef __NR_swapoff
1524 {"swapoff", __NR_swapoff},
1525#endif
1526#endif
1527#ifdef SYS_swapon
1528#ifdef __NR_swapon
1529 {"swapon", __NR_swapon},
1530#endif
1531#endif
1532#ifdef SYS_symlink
1533#ifdef __NR_symlink
1534 {"symlink", __NR_symlink},
1535#endif
1536#endif
1537#ifdef SYS_symlinkat
1538#ifdef __NR_symlinkat
1539 {"symlinkat", __NR_symlinkat},
1540#endif
1541#endif
1542#ifdef SYS_sync
1543#ifdef __NR_sync
1544 {"sync", __NR_sync},
1545#endif
1546#endif
1547#ifdef SYS_sync_file_range
1548#ifdef __NR_sync_file_range
1549 {"sync_file_range", __NR_sync_file_range},
1550#endif
1551#endif
1552#ifdef SYS_syncfs
1553#ifdef __NR_syncfs
1554 {"syncfs", __NR_syncfs},
1555#endif
1556#endif
1557#ifdef SYS_sysfs
1558#ifdef __NR_sysfs
1559 {"sysfs", __NR_sysfs},
1560#endif
1561#endif
1562#ifdef SYS_sysinfo
1563#ifdef __NR_sysinfo
1564 {"sysinfo", __NR_sysinfo},
1565#endif
1566#endif
1567#ifdef SYS_syslog
1568#ifdef __NR_syslog
1569 {"syslog", __NR_syslog},
1570#endif
1571#endif
1572#ifdef SYS_tee
1573#ifdef __NR_tee
1574 {"tee", __NR_tee},
1575#endif
1576#endif
1577#ifdef SYS_tgkill
1578#ifdef __NR_tgkill
1579 {"tgkill", __NR_tgkill},
1580#endif
1581#endif
1582#ifdef SYS_time
1583#ifdef __NR_time
1584 {"time", __NR_time},
1585#endif
1586#endif
1587#ifdef SYS_timer_create
1588#ifdef __NR_timer_create
1589 {"timer_create", __NR_timer_create},
1590#endif
1591#endif
1592#ifdef SYS_timer_delete
1593#ifdef __NR_timer_delete
1594 {"timer_delete", __NR_timer_delete},
1595#endif
1596#endif
1597#ifdef SYS_timer_getoverrun
1598#ifdef __NR_timer_getoverrun
1599 {"timer_getoverrun", __NR_timer_getoverrun},
1600#endif
1601#endif
1602#ifdef SYS_timer_gettime
1603#ifdef __NR_timer_gettime
1604 {"timer_gettime", __NR_timer_gettime},
1605#endif
1606#endif
1607#ifdef SYS_timer_settime
1608#ifdef __NR_timer_settime
1609 {"timer_settime", __NR_timer_settime},
1610#endif
1611#endif
1612#ifdef SYS_timerfd_create
1613#ifdef __NR_timerfd_create
1614 {"timerfd_create", __NR_timerfd_create},
1615#endif
1616#endif
1617#ifdef SYS_timerfd_gettime
1618#ifdef __NR_timerfd_gettime
1619 {"timerfd_gettime", __NR_timerfd_gettime},
1620#endif
1621#endif
1622#ifdef SYS_timerfd_settime
1623#ifdef __NR_timerfd_settime
1624 {"timerfd_settime", __NR_timerfd_settime},
1625#endif
1626#endif
1627#ifdef SYS_times
1628#ifdef __NR_times
1629 {"times", __NR_times},
1630#endif
1631#endif
1632#ifdef SYS_tkill
1633#ifdef __NR_tkill
1634 {"tkill", __NR_tkill},
1635#endif
1636#endif
1637#ifdef SYS_truncate
1638#ifdef __NR_truncate
1639 {"truncate", __NR_truncate},
1640#endif
1641#endif
1642#ifdef SYS_truncate64
1643#ifdef __NR_truncate64
1644 {"truncate64", __NR_truncate64},
1645#endif
1646#endif
1647#ifdef SYS_ugetrlimit
1648#ifdef __NR_ugetrlimit
1649 {"ugetrlimit", __NR_ugetrlimit},
1650#endif
1651#endif
1652#ifdef SYS_ulimit
1653#ifdef __NR_ulimit
1654 {"ulimit", __NR_ulimit},
1655#endif
1656#endif
1657#ifdef SYS_umask
1658#ifdef __NR_umask
1659 {"umask", __NR_umask},
1660#endif
1661#endif
1662#ifdef SYS_umount
1663#ifdef __NR_umount
1664 {"umount", __NR_umount},
1665#endif
1666#endif
1667#ifdef SYS_umount2
1668#ifdef __NR_umount2
1669 {"umount2", __NR_umount2},
1670#endif
1671#endif
1672#ifdef SYS_uname
1673#ifdef __NR_uname
1674 {"uname", __NR_uname},
1675#endif
1676#endif
1677#ifdef SYS_unlink
1678#ifdef __NR_unlink
1679 {"unlink", __NR_unlink},
1680#endif
1681#endif
1682#ifdef SYS_unlinkat
1683#ifdef __NR_unlinkat
1684 {"unlinkat", __NR_unlinkat},
1685#endif
1686#endif
1687#ifdef SYS_unshare
1688#ifdef __NR_unshare
1689 {"unshare", __NR_unshare},
1690#endif
1691#endif
1692#ifdef SYS_uselib
1693#ifdef __NR_uselib
1694 {"uselib", __NR_uselib},
1695#endif
1696#endif
1697#ifdef SYS_ustat
1698#ifdef __NR_ustat
1699 {"ustat", __NR_ustat},
1700#endif
1701#endif
1702#ifdef SYS_utime
1703#ifdef __NR_utime
1704 {"utime", __NR_utime},
1705#endif
1706#endif
1707#ifdef SYS_utimensat
1708#ifdef __NR_utimensat
1709 {"utimensat", __NR_utimensat},
1710#endif
1711#endif
1712#ifdef SYS_utimes
1713#ifdef __NR_utimes
1714 {"utimes", __NR_utimes},
1715#endif
1716#endif
1717#ifdef SYS_vfork
1718#ifdef __NR_vfork
1719 {"vfork", __NR_vfork},
1720#endif
1721#endif
1722#ifdef SYS_vhangup
1723#ifdef __NR_vhangup
1724 {"vhangup", __NR_vhangup},
1725#endif
1726#endif
1727#ifdef SYS_vm86
1728#ifdef __NR_vm86
1729 {"vm86", __NR_vm86},
1730#endif
1731#endif
1732#ifdef SYS_vm86old
1733#ifdef __NR_vm86old
1734 {"vm86old", __NR_vm86old},
1735#endif
1736#endif
1737#ifdef SYS_vmsplice
1738#ifdef __NR_vmsplice
1739 {"vmsplice", __NR_vmsplice},
1740#endif
1741#endif
1742#ifdef SYS_vserver
1743#ifdef __NR_vserver
1744 {"vserver", __NR_vserver},
1745#endif
1746#endif
1747#ifdef SYS_wait4
1748#ifdef __NR_wait4
1749 {"wait4", __NR_wait4},
1750#endif
1751#endif
1752#ifdef SYS_waitid
1753#ifdef __NR_waitid
1754 {"waitid", __NR_waitid},
1755#endif
1756#endif
1757#ifdef SYS_waitpid
1758#ifdef __NR_waitpid
1759 {"waitpid", __NR_waitpid},
1760#endif
1761#endif
1762#ifdef SYS_write
1763#ifdef __NR_write
1764 {"write", __NR_write},
1765#endif
1766#endif
1767#ifdef SYS_writev
1768#ifdef __NR_writev
1769 {"writev", __NR_writev},
1770#endif
1771#endif
1772#endif
1773#if defined __x86_64__ && defined __LP64__
1774#ifdef SYS__sysctl
1775#ifdef __NR__sysctl
1776 {"_sysctl", __NR__sysctl},
1777#endif
1778#endif
1779#ifdef SYS_accept
1780#ifdef __NR_accept
1781 {"accept", __NR_accept},
1782#endif
1783#endif
1784#ifdef SYS_accept4
1785#ifdef __NR_accept4
1786 {"accept4", __NR_accept4},
1787#endif
1788#endif
1789#ifdef SYS_access
1790#ifdef __NR_access
1791 {"access", __NR_access},
1792#endif
1793#endif
1794#ifdef SYS_acct
1795#ifdef __NR_acct
1796 {"acct", __NR_acct},
1797#endif
1798#endif
1799#ifdef SYS_add_key
1800#ifdef __NR_add_key
1801 {"add_key", __NR_add_key},
1802#endif
1803#endif
1804#ifdef SYS_adjtimex
1805#ifdef __NR_adjtimex
1806 {"adjtimex", __NR_adjtimex},
1807#endif
1808#endif
1809#ifdef SYS_afs_syscall
1810#ifdef __NR_afs_syscall
1811 {"afs_syscall", __NR_afs_syscall},
1812#endif
1813#endif
1814#ifdef SYS_alarm
1815#ifdef __NR_alarm
1816 {"alarm", __NR_alarm},
1817#endif
1818#endif
1819#ifdef SYS_arch_prctl
1820#ifdef __NR_arch_prctl
1821 {"arch_prctl", __NR_arch_prctl},
1822#endif
1823#endif
1824#ifdef SYS_bind
1825#ifdef __NR_bind
1826 {"bind", __NR_bind},
1827#endif
1828#endif
1829#ifdef SYS_brk
1830#ifdef __NR_brk
1831 {"brk", __NR_brk},
1832#endif
1833#endif
1834#ifdef SYS_capget
1835#ifdef __NR_capget
1836 {"capget", __NR_capget},
1837#endif
1838#endif
1839#ifdef SYS_capset
1840#ifdef __NR_capset
1841 {"capset", __NR_capset},
1842#endif
1843#endif
1844#ifdef SYS_chdir
1845#ifdef __NR_chdir
1846 {"chdir", __NR_chdir},
1847#endif
1848#endif
1849#ifdef SYS_chmod
1850#ifdef __NR_chmod
1851 {"chmod", __NR_chmod},
1852#endif
1853#endif
1854#ifdef SYS_chown
1855#ifdef __NR_chown
1856 {"chown", __NR_chown},
1857#endif
1858#endif
1859#ifdef SYS_chroot
1860#ifdef __NR_chroot
1861 {"chroot", __NR_chroot},
1862#endif
1863#endif
1864#ifdef SYS_clock_adjtime
1865#ifdef __NR_clock_adjtime
1866 {"clock_adjtime", __NR_clock_adjtime},
1867#endif
1868#endif
1869#ifdef SYS_clock_getres
1870#ifdef __NR_clock_getres
1871 {"clock_getres", __NR_clock_getres},
1872#endif
1873#endif
1874#ifdef SYS_clock_gettime
1875#ifdef __NR_clock_gettime
1876 {"clock_gettime", __NR_clock_gettime},
1877#endif
1878#endif
1879#ifdef SYS_clock_nanosleep
1880#ifdef __NR_clock_nanosleep
1881 {"clock_nanosleep", __NR_clock_nanosleep},
1882#endif
1883#endif
1884#ifdef SYS_clock_settime
1885#ifdef __NR_clock_settime
1886 {"clock_settime", __NR_clock_settime},
1887#endif
1888#endif
1889#ifdef SYS_clone
1890#ifdef __NR_clone
1891 {"clone", __NR_clone},
1892#endif
1893#endif
1894#ifdef SYS_close
1895#ifdef __NR_close
1896 {"close", __NR_close},
1897#endif
1898#endif
1899#ifdef SYS_connect
1900#ifdef __NR_connect
1901 {"connect", __NR_connect},
1902#endif
1903#endif
1904#ifdef SYS_creat
1905#ifdef __NR_creat
1906 {"creat", __NR_creat},
1907#endif
1908#endif
1909#ifdef SYS_create_module
1910#ifdef __NR_create_module
1911 {"create_module", __NR_create_module},
1912#endif
1913#endif
1914#ifdef SYS_delete_module
1915#ifdef __NR_delete_module
1916 {"delete_module", __NR_delete_module},
1917#endif
1918#endif
1919#ifdef SYS_dup
1920#ifdef __NR_dup
1921 {"dup", __NR_dup},
1922#endif
1923#endif
1924#ifdef SYS_dup2
1925#ifdef __NR_dup2
1926 {"dup2", __NR_dup2},
1927#endif
1928#endif
1929#ifdef SYS_dup3
1930#ifdef __NR_dup3
1931 {"dup3", __NR_dup3},
1932#endif
1933#endif
1934#ifdef SYS_epoll_create
1935#ifdef __NR_epoll_create
1936 {"epoll_create", __NR_epoll_create},
1937#endif
1938#endif
1939#ifdef SYS_epoll_create1
1940#ifdef __NR_epoll_create1
1941 {"epoll_create1", __NR_epoll_create1},
1942#endif
1943#endif
1944#ifdef SYS_epoll_ctl
1945#ifdef __NR_epoll_ctl
1946 {"epoll_ctl", __NR_epoll_ctl},
1947#endif
1948#endif
1949#ifdef SYS_epoll_ctl_old
1950#ifdef __NR_epoll_ctl_old
1951 {"epoll_ctl_old", __NR_epoll_ctl_old},
1952#endif
1953#endif
1954#ifdef SYS_epoll_pwait
1955#ifdef __NR_epoll_pwait
1956 {"epoll_pwait", __NR_epoll_pwait},
1957#endif
1958#endif
1959#ifdef SYS_epoll_wait
1960#ifdef __NR_epoll_wait
1961 {"epoll_wait", __NR_epoll_wait},
1962#endif
1963#endif
1964#ifdef SYS_epoll_wait_old
1965#ifdef __NR_epoll_wait_old
1966 {"epoll_wait_old", __NR_epoll_wait_old},
1967#endif
1968#endif
1969#ifdef SYS_eventfd
1970#ifdef __NR_eventfd
1971 {"eventfd", __NR_eventfd},
1972#endif
1973#endif
1974#ifdef SYS_eventfd2
1975#ifdef __NR_eventfd2
1976 {"eventfd2", __NR_eventfd2},
1977#endif
1978#endif
1979#ifdef SYS_execve
1980#ifdef __NR_execve
1981 {"execve", __NR_execve},
1982#endif
1983#endif
1984#ifdef SYS_exit
1985#ifdef __NR_exit
1986 {"exit", __NR_exit},
1987#endif
1988#endif
1989#ifdef SYS_exit_group
1990#ifdef __NR_exit_group
1991 {"exit_group", __NR_exit_group},
1992#endif
1993#endif
1994#ifdef SYS_faccessat
1995#ifdef __NR_faccessat
1996 {"faccessat", __NR_faccessat},
1997#endif
1998#endif
1999#ifdef SYS_fadvise64
2000#ifdef __NR_fadvise64
2001 {"fadvise64", __NR_fadvise64},
2002#endif
2003#endif
2004#ifdef SYS_fallocate
2005#ifdef __NR_fallocate
2006 {"fallocate", __NR_fallocate},
2007#endif
2008#endif
2009#ifdef SYS_fanotify_init
2010#ifdef __NR_fanotify_init
2011 {"fanotify_init", __NR_fanotify_init},
2012#endif
2013#endif
2014#ifdef SYS_fanotify_mark
2015#ifdef __NR_fanotify_mark
2016 {"fanotify_mark", __NR_fanotify_mark},
2017#endif
2018#endif
2019#ifdef SYS_fchdir
2020#ifdef __NR_fchdir
2021 {"fchdir", __NR_fchdir},
2022#endif
2023#endif
2024#ifdef SYS_fchmod
2025#ifdef __NR_fchmod
2026 {"fchmod", __NR_fchmod},
2027#endif
2028#endif
2029#ifdef SYS_fchmodat
2030#ifdef __NR_fchmodat
2031 {"fchmodat", __NR_fchmodat},
2032#endif
2033#endif
2034#ifdef SYS_fchown
2035#ifdef __NR_fchown
2036 {"fchown", __NR_fchown},
2037#endif
2038#endif
2039#ifdef SYS_fchownat
2040#ifdef __NR_fchownat
2041 {"fchownat", __NR_fchownat},
2042#endif
2043#endif
2044#ifdef SYS_fcntl
2045#ifdef __NR_fcntl
2046 {"fcntl", __NR_fcntl},
2047#endif
2048#endif
2049#ifdef SYS_fdatasync
2050#ifdef __NR_fdatasync
2051 {"fdatasync", __NR_fdatasync},
2052#endif
2053#endif
2054#ifdef SYS_fgetxattr
2055#ifdef __NR_fgetxattr
2056 {"fgetxattr", __NR_fgetxattr},
2057#endif
2058#endif
2059#ifdef SYS_finit_module
2060#ifdef __NR_finit_module
2061 {"finit_module", __NR_finit_module},
2062#endif
2063#endif
2064#ifdef SYS_flistxattr
2065#ifdef __NR_flistxattr
2066 {"flistxattr", __NR_flistxattr},
2067#endif
2068#endif
2069#ifdef SYS_flock
2070#ifdef __NR_flock
2071 {"flock", __NR_flock},
2072#endif
2073#endif
2074#ifdef SYS_fork
2075#ifdef __NR_fork
2076 {"fork", __NR_fork},
2077#endif
2078#endif
2079#ifdef SYS_fremovexattr
2080#ifdef __NR_fremovexattr
2081 {"fremovexattr", __NR_fremovexattr},
2082#endif
2083#endif
2084#ifdef SYS_fsetxattr
2085#ifdef __NR_fsetxattr
2086 {"fsetxattr", __NR_fsetxattr},
2087#endif
2088#endif
2089#ifdef SYS_fstat
2090#ifdef __NR_fstat
2091 {"fstat", __NR_fstat},
2092#endif
2093#endif
2094#ifdef SYS_fstatfs
2095#ifdef __NR_fstatfs
2096 {"fstatfs", __NR_fstatfs},
2097#endif
2098#endif
2099#ifdef SYS_fsync
2100#ifdef __NR_fsync
2101 {"fsync", __NR_fsync},
2102#endif
2103#endif
2104#ifdef SYS_ftruncate
2105#ifdef __NR_ftruncate
2106 {"ftruncate", __NR_ftruncate},
2107#endif
2108#endif
2109#ifdef SYS_futex
2110#ifdef __NR_futex
2111 {"futex", __NR_futex},
2112#endif
2113#endif
2114#ifdef SYS_futimesat
2115#ifdef __NR_futimesat
2116 {"futimesat", __NR_futimesat},
2117#endif
2118#endif
2119#ifdef SYS_get_kernel_syms
2120#ifdef __NR_get_kernel_syms
2121 {"get_kernel_syms", __NR_get_kernel_syms},
2122#endif
2123#endif
2124#ifdef SYS_get_mempolicy
2125#ifdef __NR_get_mempolicy
2126 {"get_mempolicy", __NR_get_mempolicy},
2127#endif
2128#endif
2129#ifdef SYS_get_robust_list
2130#ifdef __NR_get_robust_list
2131 {"get_robust_list", __NR_get_robust_list},
2132#endif
2133#endif
2134#ifdef SYS_get_thread_area
2135#ifdef __NR_get_thread_area
2136 {"get_thread_area", __NR_get_thread_area},
2137#endif
2138#endif
2139#ifdef SYS_getcpu
2140#ifdef __NR_getcpu
2141 {"getcpu", __NR_getcpu},
2142#endif
2143#endif
2144#ifdef SYS_getcwd
2145#ifdef __NR_getcwd
2146 {"getcwd", __NR_getcwd},
2147#endif
2148#endif
2149#ifdef SYS_getdents
2150#ifdef __NR_getdents
2151 {"getdents", __NR_getdents},
2152#endif
2153#endif
2154#ifdef SYS_getdents64
2155#ifdef __NR_getdents64
2156 {"getdents64", __NR_getdents64},
2157#endif
2158#endif
2159#ifdef SYS_getegid
2160#ifdef __NR_getegid
2161 {"getegid", __NR_getegid},
2162#endif
2163#endif
2164#ifdef SYS_geteuid
2165#ifdef __NR_geteuid
2166 {"geteuid", __NR_geteuid},
2167#endif
2168#endif
2169#ifdef SYS_getgid
2170#ifdef __NR_getgid
2171 {"getgid", __NR_getgid},
2172#endif
2173#endif
2174#ifdef SYS_getgroups
2175#ifdef __NR_getgroups
2176 {"getgroups", __NR_getgroups},
2177#endif
2178#endif
2179#ifdef SYS_getitimer
2180#ifdef __NR_getitimer
2181 {"getitimer", __NR_getitimer},
2182#endif
2183#endif
2184#ifdef SYS_getpeername
2185#ifdef __NR_getpeername
2186 {"getpeername", __NR_getpeername},
2187#endif
2188#endif
2189#ifdef SYS_getpgid
2190#ifdef __NR_getpgid
2191 {"getpgid", __NR_getpgid},
2192#endif
2193#endif
2194#ifdef SYS_getpgrp
2195#ifdef __NR_getpgrp
2196 {"getpgrp", __NR_getpgrp},
2197#endif
2198#endif
2199#ifdef SYS_getpid
2200#ifdef __NR_getpid
2201 {"getpid", __NR_getpid},
2202#endif
2203#endif
2204#ifdef SYS_getpmsg
2205#ifdef __NR_getpmsg
2206 {"getpmsg", __NR_getpmsg},
2207#endif
2208#endif
2209#ifdef SYS_getppid
2210#ifdef __NR_getppid
2211 {"getppid", __NR_getppid},
2212#endif
2213#endif
2214#ifdef SYS_getpriority
2215#ifdef __NR_getpriority
2216 {"getpriority", __NR_getpriority},
2217#endif
2218#endif
2219#ifdef SYS_getresgid
2220#ifdef __NR_getresgid
2221 {"getresgid", __NR_getresgid},
2222#endif
2223#endif
2224#ifdef SYS_getresuid
2225#ifdef __NR_getresuid
2226 {"getresuid", __NR_getresuid},
2227#endif
2228#endif
2229#ifdef SYS_getrlimit
2230#ifdef __NR_getrlimit
2231 {"getrlimit", __NR_getrlimit},
2232#endif
2233#endif
2234#ifdef SYS_getrusage
2235#ifdef __NR_getrusage
2236 {"getrusage", __NR_getrusage},
2237#endif
2238#endif
2239#ifdef SYS_getsid
2240#ifdef __NR_getsid
2241 {"getsid", __NR_getsid},
2242#endif
2243#endif
2244#ifdef SYS_getsockname
2245#ifdef __NR_getsockname
2246 {"getsockname", __NR_getsockname},
2247#endif
2248#endif
2249#ifdef SYS_getsockopt
2250#ifdef __NR_getsockopt
2251 {"getsockopt", __NR_getsockopt},
2252#endif
2253#endif
2254#ifdef SYS_gettid
2255#ifdef __NR_gettid
2256 {"gettid", __NR_gettid},
2257#endif
2258#endif
2259#ifdef SYS_gettimeofday
2260#ifdef __NR_gettimeofday
2261 {"gettimeofday", __NR_gettimeofday},
2262#endif
2263#endif
2264#ifdef SYS_getuid
2265#ifdef __NR_getuid
2266 {"getuid", __NR_getuid},
2267#endif
2268#endif
2269#ifdef SYS_getxattr
2270#ifdef __NR_getxattr
2271 {"getxattr", __NR_getxattr},
2272#endif
2273#endif
2274#ifdef SYS_init_module
2275#ifdef __NR_init_module
2276 {"init_module", __NR_init_module},
2277#endif
2278#endif
2279#ifdef SYS_inotify_add_watch
2280#ifdef __NR_inotify_add_watch
2281 {"inotify_add_watch", __NR_inotify_add_watch},
2282#endif
2283#endif
2284#ifdef SYS_inotify_init
2285#ifdef __NR_inotify_init
2286 {"inotify_init", __NR_inotify_init},
2287#endif
2288#endif
2289#ifdef SYS_inotify_init1
2290#ifdef __NR_inotify_init1
2291 {"inotify_init1", __NR_inotify_init1},
2292#endif
2293#endif
2294#ifdef SYS_inotify_rm_watch
2295#ifdef __NR_inotify_rm_watch
2296 {"inotify_rm_watch", __NR_inotify_rm_watch},
2297#endif
2298#endif
2299#ifdef SYS_io_cancel
2300#ifdef __NR_io_cancel
2301 {"io_cancel", __NR_io_cancel},
2302#endif
2303#endif
2304#ifdef SYS_io_destroy
2305#ifdef __NR_io_destroy
2306 {"io_destroy", __NR_io_destroy},
2307#endif
2308#endif
2309#ifdef SYS_io_getevents
2310#ifdef __NR_io_getevents
2311 {"io_getevents", __NR_io_getevents},
2312#endif
2313#endif
2314#ifdef SYS_io_setup
2315#ifdef __NR_io_setup
2316 {"io_setup", __NR_io_setup},
2317#endif
2318#endif
2319#ifdef SYS_io_submit
2320#ifdef __NR_io_submit
2321 {"io_submit", __NR_io_submit},
2322#endif
2323#endif
2324#ifdef SYS_ioctl
2325#ifdef __NR_ioctl
2326 {"ioctl", __NR_ioctl},
2327#endif
2328#endif
2329#ifdef SYS_ioperm
2330#ifdef __NR_ioperm
2331 {"ioperm", __NR_ioperm},
2332#endif
2333#endif
2334#ifdef SYS_iopl
2335#ifdef __NR_iopl
2336 {"iopl", __NR_iopl},
2337#endif
2338#endif
2339#ifdef SYS_ioprio_get
2340#ifdef __NR_ioprio_get
2341 {"ioprio_get", __NR_ioprio_get},
2342#endif
2343#endif
2344#ifdef SYS_ioprio_set
2345#ifdef __NR_ioprio_set
2346 {"ioprio_set", __NR_ioprio_set},
2347#endif
2348#endif
2349#ifdef SYS_kcmp
2350#ifdef __NR_kcmp
2351 {"kcmp", __NR_kcmp},
2352#endif
2353#endif
2354#ifdef SYS_kexec_load
2355#ifdef __NR_kexec_load
2356 {"kexec_load", __NR_kexec_load},
2357#endif
2358#endif
2359#ifdef SYS_keyctl
2360#ifdef __NR_keyctl
2361 {"keyctl", __NR_keyctl},
2362#endif
2363#endif
2364#ifdef SYS_kill
2365#ifdef __NR_kill
2366 {"kill", __NR_kill},
2367#endif
2368#endif
2369#ifdef SYS_lchown
2370#ifdef __NR_lchown
2371 {"lchown", __NR_lchown},
2372#endif
2373#endif
2374#ifdef SYS_lgetxattr
2375#ifdef __NR_lgetxattr
2376 {"lgetxattr", __NR_lgetxattr},
2377#endif
2378#endif
2379#ifdef SYS_link
2380#ifdef __NR_link
2381 {"link", __NR_link},
2382#endif
2383#endif
2384#ifdef SYS_linkat
2385#ifdef __NR_linkat
2386 {"linkat", __NR_linkat},
2387#endif
2388#endif
2389#ifdef SYS_listen
2390#ifdef __NR_listen
2391 {"listen", __NR_listen},
2392#endif
2393#endif
2394#ifdef SYS_listxattr
2395#ifdef __NR_listxattr
2396 {"listxattr", __NR_listxattr},
2397#endif
2398#endif
2399#ifdef SYS_llistxattr
2400#ifdef __NR_llistxattr
2401 {"llistxattr", __NR_llistxattr},
2402#endif
2403#endif
2404#ifdef SYS_lookup_dcookie
2405#ifdef __NR_lookup_dcookie
2406 {"lookup_dcookie", __NR_lookup_dcookie},
2407#endif
2408#endif
2409#ifdef SYS_lremovexattr
2410#ifdef __NR_lremovexattr
2411 {"lremovexattr", __NR_lremovexattr},
2412#endif
2413#endif
2414#ifdef SYS_lseek
2415#ifdef __NR_lseek
2416 {"lseek", __NR_lseek},
2417#endif
2418#endif
2419#ifdef SYS_lsetxattr
2420#ifdef __NR_lsetxattr
2421 {"lsetxattr", __NR_lsetxattr},
2422#endif
2423#endif
2424#ifdef SYS_lstat
2425#ifdef __NR_lstat
2426 {"lstat", __NR_lstat},
2427#endif
2428#endif
2429#ifdef SYS_madvise
2430#ifdef __NR_madvise
2431 {"madvise", __NR_madvise},
2432#endif
2433#endif
2434#ifdef SYS_mbind
2435#ifdef __NR_mbind
2436 {"mbind", __NR_mbind},
2437#endif
2438#endif
2439#ifdef SYS_migrate_pages
2440#ifdef __NR_migrate_pages
2441 {"migrate_pages", __NR_migrate_pages},
2442#endif
2443#endif
2444#ifdef SYS_mincore
2445#ifdef __NR_mincore
2446 {"mincore", __NR_mincore},
2447#endif
2448#endif
2449#ifdef SYS_mkdir
2450#ifdef __NR_mkdir
2451 {"mkdir", __NR_mkdir},
2452#endif
2453#endif
2454#ifdef SYS_mkdirat
2455#ifdef __NR_mkdirat
2456 {"mkdirat", __NR_mkdirat},
2457#endif
2458#endif
2459#ifdef SYS_mknod
2460#ifdef __NR_mknod
2461 {"mknod", __NR_mknod},
2462#endif
2463#endif
2464#ifdef SYS_mknodat
2465#ifdef __NR_mknodat
2466 {"mknodat", __NR_mknodat},
2467#endif
2468#endif
2469#ifdef SYS_mlock
2470#ifdef __NR_mlock
2471 {"mlock", __NR_mlock},
2472#endif
2473#endif
2474#ifdef SYS_mlockall
2475#ifdef __NR_mlockall
2476 {"mlockall", __NR_mlockall},
2477#endif
2478#endif
2479#ifdef SYS_mmap
2480#ifdef __NR_mmap
2481 {"mmap", __NR_mmap},
2482#endif
2483#endif
2484#ifdef SYS_modify_ldt
2485#ifdef __NR_modify_ldt
2486 {"modify_ldt", __NR_modify_ldt},
2487#endif
2488#endif
2489#ifdef SYS_mount
2490#ifdef __NR_mount
2491 {"mount", __NR_mount},
2492#endif
2493#endif
2494#ifdef SYS_move_pages
2495#ifdef __NR_move_pages
2496 {"move_pages", __NR_move_pages},
2497#endif
2498#endif
2499#ifdef SYS_mprotect
2500#ifdef __NR_mprotect
2501 {"mprotect", __NR_mprotect},
2502#endif
2503#endif
2504#ifdef SYS_mq_getsetattr
2505#ifdef __NR_mq_getsetattr
2506 {"mq_getsetattr", __NR_mq_getsetattr},
2507#endif
2508#endif
2509#ifdef SYS_mq_notify
2510#ifdef __NR_mq_notify
2511 {"mq_notify", __NR_mq_notify},
2512#endif
2513#endif
2514#ifdef SYS_mq_open
2515#ifdef __NR_mq_open
2516 {"mq_open", __NR_mq_open},
2517#endif
2518#endif
2519#ifdef SYS_mq_timedreceive
2520#ifdef __NR_mq_timedreceive
2521 {"mq_timedreceive", __NR_mq_timedreceive},
2522#endif
2523#endif
2524#ifdef SYS_mq_timedsend
2525#ifdef __NR_mq_timedsend
2526 {"mq_timedsend", __NR_mq_timedsend},
2527#endif
2528#endif
2529#ifdef SYS_mq_unlink
2530#ifdef __NR_mq_unlink
2531 {"mq_unlink", __NR_mq_unlink},
2532#endif
2533#endif
2534#ifdef SYS_mremap
2535#ifdef __NR_mremap
2536 {"mremap", __NR_mremap},
2537#endif
2538#endif
2539#ifdef SYS_msgctl
2540#ifdef __NR_msgctl
2541 {"msgctl", __NR_msgctl},
2542#endif
2543#endif
2544#ifdef SYS_msgget
2545#ifdef __NR_msgget
2546 {"msgget", __NR_msgget},
2547#endif
2548#endif
2549#ifdef SYS_msgrcv
2550#ifdef __NR_msgrcv
2551 {"msgrcv", __NR_msgrcv},
2552#endif
2553#endif
2554#ifdef SYS_msgsnd
2555#ifdef __NR_msgsnd
2556 {"msgsnd", __NR_msgsnd},
2557#endif
2558#endif
2559#ifdef SYS_msync
2560#ifdef __NR_msync
2561 {"msync", __NR_msync},
2562#endif
2563#endif
2564#ifdef SYS_munlock
2565#ifdef __NR_munlock
2566 {"munlock", __NR_munlock},
2567#endif
2568#endif
2569#ifdef SYS_munlockall
2570#ifdef __NR_munlockall
2571 {"munlockall", __NR_munlockall},
2572#endif
2573#endif
2574#ifdef SYS_munmap
2575#ifdef __NR_munmap
2576 {"munmap", __NR_munmap},
2577#endif
2578#endif
2579#ifdef SYS_name_to_handle_at
2580#ifdef __NR_name_to_handle_at
2581 {"name_to_handle_at", __NR_name_to_handle_at},
2582#endif
2583#endif
2584#ifdef SYS_nanosleep
2585#ifdef __NR_nanosleep
2586 {"nanosleep", __NR_nanosleep},
2587#endif
2588#endif
2589#ifdef SYS_newfstatat
2590#ifdef __NR_newfstatat
2591 {"newfstatat", __NR_newfstatat},
2592#endif
2593#endif
2594#ifdef SYS_nfsservctl
2595#ifdef __NR_nfsservctl
2596 {"nfsservctl", __NR_nfsservctl},
2597#endif
2598#endif
2599#ifdef SYS_open
2600#ifdef __NR_open
2601 {"open", __NR_open},
2602#endif
2603#endif
2604#ifdef SYS_open_by_handle_at
2605#ifdef __NR_open_by_handle_at
2606 {"open_by_handle_at", __NR_open_by_handle_at},
2607#endif
2608#endif
2609#ifdef SYS_openat
2610#ifdef __NR_openat
2611 {"openat", __NR_openat},
2612#endif
2613#endif
2614#ifdef SYS_pause
2615#ifdef __NR_pause
2616 {"pause", __NR_pause},
2617#endif
2618#endif
2619#ifdef SYS_perf_event_open
2620#ifdef __NR_perf_event_open
2621 {"perf_event_open", __NR_perf_event_open},
2622#endif
2623#endif
2624#ifdef SYS_personality
2625#ifdef __NR_personality
2626 {"personality", __NR_personality},
2627#endif
2628#endif
2629#ifdef SYS_pipe
2630#ifdef __NR_pipe
2631 {"pipe", __NR_pipe},
2632#endif
2633#endif
2634#ifdef SYS_pipe2
2635#ifdef __NR_pipe2
2636 {"pipe2", __NR_pipe2},
2637#endif
2638#endif
2639#ifdef SYS_pivot_root
2640#ifdef __NR_pivot_root
2641 {"pivot_root", __NR_pivot_root},
2642#endif
2643#endif
2644#ifdef SYS_poll
2645#ifdef __NR_poll
2646 {"poll", __NR_poll},
2647#endif
2648#endif
2649#ifdef SYS_ppoll
2650#ifdef __NR_ppoll
2651 {"ppoll", __NR_ppoll},
2652#endif
2653#endif
2654#ifdef SYS_prctl
2655#ifdef __NR_prctl
2656 {"prctl", __NR_prctl},
2657#endif
2658#endif
2659#ifdef SYS_pread64
2660#ifdef __NR_pread64
2661 {"pread64", __NR_pread64},
2662#endif
2663#endif
2664#ifdef SYS_preadv
2665#ifdef __NR_preadv
2666 {"preadv", __NR_preadv},
2667#endif
2668#endif
2669#ifdef SYS_prlimit64
2670#ifdef __NR_prlimit64
2671 {"prlimit64", __NR_prlimit64},
2672#endif
2673#endif
2674#ifdef SYS_process_vm_readv
2675#ifdef __NR_process_vm_readv
2676 {"process_vm_readv", __NR_process_vm_readv},
2677#endif
2678#endif
2679#ifdef SYS_process_vm_writev
2680#ifdef __NR_process_vm_writev
2681 {"process_vm_writev", __NR_process_vm_writev},
2682#endif
2683#endif
2684#ifdef SYS_pselect6
2685#ifdef __NR_pselect6
2686 {"pselect6", __NR_pselect6},
2687#endif
2688#endif
2689#ifdef SYS_ptrace
2690#ifdef __NR_ptrace
2691 {"ptrace", __NR_ptrace},
2692#endif
2693#endif
2694#ifdef SYS_putpmsg
2695#ifdef __NR_putpmsg
2696 {"putpmsg", __NR_putpmsg},
2697#endif
2698#endif
2699#ifdef SYS_pwrite64
2700#ifdef __NR_pwrite64
2701 {"pwrite64", __NR_pwrite64},
2702#endif
2703#endif
2704#ifdef SYS_pwritev
2705#ifdef __NR_pwritev
2706 {"pwritev", __NR_pwritev},
2707#endif
2708#endif
2709#ifdef SYS_query_module
2710#ifdef __NR_query_module
2711 {"query_module", __NR_query_module},
2712#endif
2713#endif
2714#ifdef SYS_quotactl
2715#ifdef __NR_quotactl
2716 {"quotactl", __NR_quotactl},
2717#endif
2718#endif
2719#ifdef SYS_read
2720#ifdef __NR_read
2721 {"read", __NR_read},
2722#endif
2723#endif
2724#ifdef SYS_readahead
2725#ifdef __NR_readahead
2726 {"readahead", __NR_readahead},
2727#endif
2728#endif
2729#ifdef SYS_readlink
2730#ifdef __NR_readlink
2731 {"readlink", __NR_readlink},
2732#endif
2733#endif
2734#ifdef SYS_readlinkat
2735#ifdef __NR_readlinkat
2736 {"readlinkat", __NR_readlinkat},
2737#endif
2738#endif
2739#ifdef SYS_readv
2740#ifdef __NR_readv
2741 {"readv", __NR_readv},
2742#endif
2743#endif
2744#ifdef SYS_reboot
2745#ifdef __NR_reboot
2746 {"reboot", __NR_reboot},
2747#endif
2748#endif
2749#ifdef SYS_recvfrom
2750#ifdef __NR_recvfrom
2751 {"recvfrom", __NR_recvfrom},
2752#endif
2753#endif
2754#ifdef SYS_recvmmsg
2755#ifdef __NR_recvmmsg
2756 {"recvmmsg", __NR_recvmmsg},
2757#endif
2758#endif
2759#ifdef SYS_recvmsg
2760#ifdef __NR_recvmsg
2761 {"recvmsg", __NR_recvmsg},
2762#endif
2763#endif
2764#ifdef SYS_remap_file_pages
2765#ifdef __NR_remap_file_pages
2766 {"remap_file_pages", __NR_remap_file_pages},
2767#endif
2768#endif
2769#ifdef SYS_removexattr
2770#ifdef __NR_removexattr
2771 {"removexattr", __NR_removexattr},
2772#endif
2773#endif
2774#ifdef SYS_rename
2775#ifdef __NR_rename
2776 {"rename", __NR_rename},
2777#endif
2778#endif
2779#ifdef SYS_renameat
2780#ifdef __NR_renameat
2781 {"renameat", __NR_renameat},
2782#endif
2783#endif
2784#ifdef SYS_request_key
2785#ifdef __NR_request_key
2786 {"request_key", __NR_request_key},
2787#endif
2788#endif
2789#ifdef SYS_restart_syscall
2790#ifdef __NR_restart_syscall
2791 {"restart_syscall", __NR_restart_syscall},
2792#endif
2793#endif
2794#ifdef SYS_rmdir
2795#ifdef __NR_rmdir
2796 {"rmdir", __NR_rmdir},
2797#endif
2798#endif
2799#ifdef SYS_rt_sigaction
2800#ifdef __NR_rt_sigaction
2801 {"rt_sigaction", __NR_rt_sigaction},
2802#endif
2803#endif
2804#ifdef SYS_rt_sigpending
2805#ifdef __NR_rt_sigpending
2806 {"rt_sigpending", __NR_rt_sigpending},
2807#endif
2808#endif
2809#ifdef SYS_rt_sigprocmask
2810#ifdef __NR_rt_sigprocmask
2811 {"rt_sigprocmask", __NR_rt_sigprocmask},
2812#endif
2813#endif
2814#ifdef SYS_rt_sigqueueinfo
2815#ifdef __NR_rt_sigqueueinfo
2816 {"rt_sigqueueinfo", __NR_rt_sigqueueinfo},
2817#endif
2818#endif
2819#ifdef SYS_rt_sigreturn
2820#ifdef __NR_rt_sigreturn
2821 {"rt_sigreturn", __NR_rt_sigreturn},
2822#endif
2823#endif
2824#ifdef SYS_rt_sigsuspend
2825#ifdef __NR_rt_sigsuspend
2826 {"rt_sigsuspend", __NR_rt_sigsuspend},
2827#endif
2828#endif
2829#ifdef SYS_rt_sigtimedwait
2830#ifdef __NR_rt_sigtimedwait
2831 {"rt_sigtimedwait", __NR_rt_sigtimedwait},
2832#endif
2833#endif
2834#ifdef SYS_rt_tgsigqueueinfo
2835#ifdef __NR_rt_tgsigqueueinfo
2836 {"rt_tgsigqueueinfo", __NR_rt_tgsigqueueinfo},
2837#endif
2838#endif
2839#ifdef SYS_sched_get_priority_max
2840#ifdef __NR_sched_get_priority_max
2841 {"sched_get_priority_max", __NR_sched_get_priority_max},
2842#endif
2843#endif
2844#ifdef SYS_sched_get_priority_min
2845#ifdef __NR_sched_get_priority_min
2846 {"sched_get_priority_min", __NR_sched_get_priority_min},
2847#endif
2848#endif
2849#ifdef SYS_sched_getaffinity
2850#ifdef __NR_sched_getaffinity
2851 {"sched_getaffinity", __NR_sched_getaffinity},
2852#endif
2853#endif
2854#ifdef SYS_sched_getparam
2855#ifdef __NR_sched_getparam
2856 {"sched_getparam", __NR_sched_getparam},
2857#endif
2858#endif
2859#ifdef SYS_sched_getscheduler
2860#ifdef __NR_sched_getscheduler
2861 {"sched_getscheduler", __NR_sched_getscheduler},
2862#endif
2863#endif
2864#ifdef SYS_sched_rr_get_interval
2865#ifdef __NR_sched_rr_get_interval
2866 {"sched_rr_get_interval", __NR_sched_rr_get_interval},
2867#endif
2868#endif
2869#ifdef SYS_sched_setaffinity
2870#ifdef __NR_sched_setaffinity
2871 {"sched_setaffinity", __NR_sched_setaffinity},
2872#endif
2873#endif
2874#ifdef SYS_sched_setparam
2875#ifdef __NR_sched_setparam
2876 {"sched_setparam", __NR_sched_setparam},
2877#endif
2878#endif
2879#ifdef SYS_sched_setscheduler
2880#ifdef __NR_sched_setscheduler
2881 {"sched_setscheduler", __NR_sched_setscheduler},
2882#endif
2883#endif
2884#ifdef SYS_sched_yield
2885#ifdef __NR_sched_yield
2886 {"sched_yield", __NR_sched_yield},
2887#endif
2888#endif
2889#ifdef SYS_security
2890#ifdef __NR_security
2891 {"security", __NR_security},
2892#endif
2893#endif
2894#ifdef SYS_select
2895#ifdef __NR_select
2896 {"select", __NR_select},
2897#endif
2898#endif
2899#ifdef SYS_semctl
2900#ifdef __NR_semctl
2901 {"semctl", __NR_semctl},
2902#endif
2903#endif
2904#ifdef SYS_semget
2905#ifdef __NR_semget
2906 {"semget", __NR_semget},
2907#endif
2908#endif
2909#ifdef SYS_semop
2910#ifdef __NR_semop
2911 {"semop", __NR_semop},
2912#endif
2913#endif
2914#ifdef SYS_semtimedop
2915#ifdef __NR_semtimedop
2916 {"semtimedop", __NR_semtimedop},
2917#endif
2918#endif
2919#ifdef SYS_sendfile
2920#ifdef __NR_sendfile
2921 {"sendfile", __NR_sendfile},
2922#endif
2923#endif
2924#ifdef SYS_sendmmsg
2925#ifdef __NR_sendmmsg
2926 {"sendmmsg", __NR_sendmmsg},
2927#endif
2928#endif
2929#ifdef SYS_sendmsg
2930#ifdef __NR_sendmsg
2931 {"sendmsg", __NR_sendmsg},
2932#endif
2933#endif
2934#ifdef SYS_sendto
2935#ifdef __NR_sendto
2936 {"sendto", __NR_sendto},
2937#endif
2938#endif
2939#ifdef SYS_set_mempolicy
2940#ifdef __NR_set_mempolicy
2941 {"set_mempolicy", __NR_set_mempolicy},
2942#endif
2943#endif
2944#ifdef SYS_set_robust_list
2945#ifdef __NR_set_robust_list
2946 {"set_robust_list", __NR_set_robust_list},
2947#endif
2948#endif
2949#ifdef SYS_set_thread_area
2950#ifdef __NR_set_thread_area
2951 {"set_thread_area", __NR_set_thread_area},
2952#endif
2953#endif
2954#ifdef SYS_set_tid_address
2955#ifdef __NR_set_tid_address
2956 {"set_tid_address", __NR_set_tid_address},
2957#endif
2958#endif
2959#ifdef SYS_setdomainname
2960#ifdef __NR_setdomainname
2961 {"setdomainname", __NR_setdomainname},
2962#endif
2963#endif
2964#ifdef SYS_setfsgid
2965#ifdef __NR_setfsgid
2966 {"setfsgid", __NR_setfsgid},
2967#endif
2968#endif
2969#ifdef SYS_setfsuid
2970#ifdef __NR_setfsuid
2971 {"setfsuid", __NR_setfsuid},
2972#endif
2973#endif
2974#ifdef SYS_setgid
2975#ifdef __NR_setgid
2976 {"setgid", __NR_setgid},
2977#endif
2978#endif
2979#ifdef SYS_setgroups
2980#ifdef __NR_setgroups
2981 {"setgroups", __NR_setgroups},
2982#endif
2983#endif
2984#ifdef SYS_sethostname
2985#ifdef __NR_sethostname
2986 {"sethostname", __NR_sethostname},
2987#endif
2988#endif
2989#ifdef SYS_setitimer
2990#ifdef __NR_setitimer
2991 {"setitimer", __NR_setitimer},
2992#endif
2993#endif
2994#ifdef SYS_setns
2995#ifdef __NR_setns
2996 {"setns", __NR_setns},
2997#endif
2998#endif
2999#ifdef SYS_setpgid
3000#ifdef __NR_setpgid
3001 {"setpgid", __NR_setpgid},
3002#endif
3003#endif
3004#ifdef SYS_setpriority
3005#ifdef __NR_setpriority
3006 {"setpriority", __NR_setpriority},
3007#endif
3008#endif
3009#ifdef SYS_setregid
3010#ifdef __NR_setregid
3011 {"setregid", __NR_setregid},
3012#endif
3013#endif
3014#ifdef SYS_setresgid
3015#ifdef __NR_setresgid
3016 {"setresgid", __NR_setresgid},
3017#endif
3018#endif
3019#ifdef SYS_setresuid
3020#ifdef __NR_setresuid
3021 {"setresuid", __NR_setresuid},
3022#endif
3023#endif
3024#ifdef SYS_setreuid
3025#ifdef __NR_setreuid
3026 {"setreuid", __NR_setreuid},
3027#endif
3028#endif
3029#ifdef SYS_setrlimit
3030#ifdef __NR_setrlimit
3031 {"setrlimit", __NR_setrlimit},
3032#endif
3033#endif
3034#ifdef SYS_setsid
3035#ifdef __NR_setsid
3036 {"setsid", __NR_setsid},
3037#endif
3038#endif
3039#ifdef SYS_setsockopt
3040#ifdef __NR_setsockopt
3041 {"setsockopt", __NR_setsockopt},
3042#endif
3043#endif
3044#ifdef SYS_settimeofday
3045#ifdef __NR_settimeofday
3046 {"settimeofday", __NR_settimeofday},
3047#endif
3048#endif
3049#ifdef SYS_setuid
3050#ifdef __NR_setuid
3051 {"setuid", __NR_setuid},
3052#endif
3053#endif
3054#ifdef SYS_setxattr
3055#ifdef __NR_setxattr
3056 {"setxattr", __NR_setxattr},
3057#endif
3058#endif
3059#ifdef SYS_shmat
3060#ifdef __NR_shmat
3061 {"shmat", __NR_shmat},
3062#endif
3063#endif
3064#ifdef SYS_shmctl
3065#ifdef __NR_shmctl
3066 {"shmctl", __NR_shmctl},
3067#endif
3068#endif
3069#ifdef SYS_shmdt
3070#ifdef __NR_shmdt
3071 {"shmdt", __NR_shmdt},
3072#endif
3073#endif
3074#ifdef SYS_shmget
3075#ifdef __NR_shmget
3076 {"shmget", __NR_shmget},
3077#endif
3078#endif
3079#ifdef SYS_shutdown
3080#ifdef __NR_shutdown
3081 {"shutdown", __NR_shutdown},
3082#endif
3083#endif
3084#ifdef SYS_sigaltstack
3085#ifdef __NR_sigaltstack
3086 {"sigaltstack", __NR_sigaltstack},
3087#endif
3088#endif
3089#ifdef SYS_signalfd
3090#ifdef __NR_signalfd
3091 {"signalfd", __NR_signalfd},
3092#endif
3093#endif
3094#ifdef SYS_signalfd4
3095#ifdef __NR_signalfd4
3096 {"signalfd4", __NR_signalfd4},
3097#endif
3098#endif
3099#ifdef SYS_socket
3100#ifdef __NR_socket
3101 {"socket", __NR_socket},
3102#endif
3103#endif
3104#ifdef SYS_socketpair
3105#ifdef __NR_socketpair
3106 {"socketpair", __NR_socketpair},
3107#endif
3108#endif
3109#ifdef SYS_splice
3110#ifdef __NR_splice
3111 {"splice", __NR_splice},
3112#endif
3113#endif
3114#ifdef SYS_stat
3115#ifdef __NR_stat
3116 {"stat", __NR_stat},
3117#endif
3118#endif
3119#ifdef SYS_statfs
3120#ifdef __NR_statfs
3121 {"statfs", __NR_statfs},
3122#endif
3123#endif
3124#ifdef SYS_swapoff
3125#ifdef __NR_swapoff
3126 {"swapoff", __NR_swapoff},
3127#endif
3128#endif
3129#ifdef SYS_swapon
3130#ifdef __NR_swapon
3131 {"swapon", __NR_swapon},
3132#endif
3133#endif
3134#ifdef SYS_symlink
3135#ifdef __NR_symlink
3136 {"symlink", __NR_symlink},
3137#endif
3138#endif
3139#ifdef SYS_symlinkat
3140#ifdef __NR_symlinkat
3141 {"symlinkat", __NR_symlinkat},
3142#endif
3143#endif
3144#ifdef SYS_sync
3145#ifdef __NR_sync
3146 {"sync", __NR_sync},
3147#endif
3148#endif
3149#ifdef SYS_sync_file_range
3150#ifdef __NR_sync_file_range
3151 {"sync_file_range", __NR_sync_file_range},
3152#endif
3153#endif
3154#ifdef SYS_syncfs
3155#ifdef __NR_syncfs
3156 {"syncfs", __NR_syncfs},
3157#endif
3158#endif
3159#ifdef SYS_sysfs
3160#ifdef __NR_sysfs
3161 {"sysfs", __NR_sysfs},
3162#endif
3163#endif
3164#ifdef SYS_sysinfo
3165#ifdef __NR_sysinfo
3166 {"sysinfo", __NR_sysinfo},
3167#endif
3168#endif
3169#ifdef SYS_syslog
3170#ifdef __NR_syslog
3171 {"syslog", __NR_syslog},
3172#endif
3173#endif
3174#ifdef SYS_tee
3175#ifdef __NR_tee
3176 {"tee", __NR_tee},
3177#endif
3178#endif
3179#ifdef SYS_tgkill
3180#ifdef __NR_tgkill
3181 {"tgkill", __NR_tgkill},
3182#endif
3183#endif
3184#ifdef SYS_time
3185#ifdef __NR_time
3186 {"time", __NR_time},
3187#endif
3188#endif
3189#ifdef SYS_timer_create
3190#ifdef __NR_timer_create
3191 {"timer_create", __NR_timer_create},
3192#endif
3193#endif
3194#ifdef SYS_timer_delete
3195#ifdef __NR_timer_delete
3196 {"timer_delete", __NR_timer_delete},
3197#endif
3198#endif
3199#ifdef SYS_timer_getoverrun
3200#ifdef __NR_timer_getoverrun
3201 {"timer_getoverrun", __NR_timer_getoverrun},
3202#endif
3203#endif
3204#ifdef SYS_timer_gettime
3205#ifdef __NR_timer_gettime
3206 {"timer_gettime", __NR_timer_gettime},
3207#endif
3208#endif
3209#ifdef SYS_timer_settime
3210#ifdef __NR_timer_settime
3211 {"timer_settime", __NR_timer_settime},
3212#endif
3213#endif
3214#ifdef SYS_timerfd_create
3215#ifdef __NR_timerfd_create
3216 {"timerfd_create", __NR_timerfd_create},
3217#endif
3218#endif
3219#ifdef SYS_timerfd_gettime
3220#ifdef __NR_timerfd_gettime
3221 {"timerfd_gettime", __NR_timerfd_gettime},
3222#endif
3223#endif
3224#ifdef SYS_timerfd_settime
3225#ifdef __NR_timerfd_settime
3226 {"timerfd_settime", __NR_timerfd_settime},
3227#endif
3228#endif
3229#ifdef SYS_times
3230#ifdef __NR_times
3231 {"times", __NR_times},
3232#endif
3233#endif
3234#ifdef SYS_tkill
3235#ifdef __NR_tkill
3236 {"tkill", __NR_tkill},
3237#endif
3238#endif
3239#ifdef SYS_truncate
3240#ifdef __NR_truncate
3241 {"truncate", __NR_truncate},
3242#endif
3243#endif
3244#ifdef SYS_tuxcall
3245#ifdef __NR_tuxcall
3246 {"tuxcall", __NR_tuxcall},
3247#endif
3248#endif
3249#ifdef SYS_umask
3250#ifdef __NR_umask
3251 {"umask", __NR_umask},
3252#endif
3253#endif
3254#ifdef SYS_umount2
3255#ifdef __NR_umount2
3256 {"umount2", __NR_umount2},
3257#endif
3258#endif
3259#ifdef SYS_uname
3260#ifdef __NR_uname
3261 {"uname", __NR_uname},
3262#endif
3263#endif
3264#ifdef SYS_unlink
3265#ifdef __NR_unlink
3266 {"unlink", __NR_unlink},
3267#endif
3268#endif
3269#ifdef SYS_unlinkat
3270#ifdef __NR_unlinkat
3271 {"unlinkat", __NR_unlinkat},
3272#endif
3273#endif
3274#ifdef SYS_unshare
3275#ifdef __NR_unshare
3276 {"unshare", __NR_unshare},
3277#endif
3278#endif
3279#ifdef SYS_uselib
3280#ifdef __NR_uselib
3281 {"uselib", __NR_uselib},
3282#endif
3283#endif
3284#ifdef SYS_ustat
3285#ifdef __NR_ustat
3286 {"ustat", __NR_ustat},
3287#endif
3288#endif
3289#ifdef SYS_utime
3290#ifdef __NR_utime
3291 {"utime", __NR_utime},
3292#endif
3293#endif
3294#ifdef SYS_utimensat
3295#ifdef __NR_utimensat
3296 {"utimensat", __NR_utimensat},
3297#endif
3298#endif
3299#ifdef SYS_utimes
3300#ifdef __NR_utimes
3301 {"utimes", __NR_utimes},
3302#endif
3303#endif
3304#ifdef SYS_vfork
3305#ifdef __NR_vfork
3306 {"vfork", __NR_vfork},
3307#endif
3308#endif
3309#ifdef SYS_vhangup
3310#ifdef __NR_vhangup
3311 {"vhangup", __NR_vhangup},
3312#endif
3313#endif
3314#ifdef SYS_vmsplice
3315#ifdef __NR_vmsplice
3316 {"vmsplice", __NR_vmsplice},
3317#endif
3318#endif
3319#ifdef SYS_vserver
3320#ifdef __NR_vserver
3321 {"vserver", __NR_vserver},
3322#endif
3323#endif
3324#ifdef SYS_wait4
3325#ifdef __NR_wait4
3326 {"wait4", __NR_wait4},
3327#endif
3328#endif
3329#ifdef SYS_waitid
3330#ifdef __NR_waitid
3331 {"waitid", __NR_waitid},
3332#endif
3333#endif
3334#ifdef SYS_write
3335#ifdef __NR_write
3336 {"write", __NR_write},
3337#endif
3338#endif
3339#ifdef SYS_writev
3340#ifdef __NR_writev
3341 {"writev", __NR_writev},
3342#endif
3343#endif
3344#endif
3345#if defined __x86_64__ && defined __ILP32__
3346#ifdef SYS_accept
3347#ifdef __NR_accept
3348 {"accept", __NR_accept},
3349#endif
3350#endif
3351#ifdef SYS_accept4
3352#ifdef __NR_accept4
3353 {"accept4", __NR_accept4},
3354#endif
3355#endif
3356#ifdef SYS_access
3357#ifdef __NR_access
3358 {"access", __NR_access},
3359#endif
3360#endif
3361#ifdef SYS_acct
3362#ifdef __NR_acct
3363 {"acct", __NR_acct},
3364#endif
3365#endif
3366#ifdef SYS_add_key
3367#ifdef __NR_add_key
3368 {"add_key", __NR_add_key},
3369#endif
3370#endif
3371#ifdef SYS_adjtimex
3372#ifdef __NR_adjtimex
3373 {"adjtimex", __NR_adjtimex},
3374#endif
3375#endif
3376#ifdef SYS_afs_syscall
3377#ifdef __NR_afs_syscall
3378 {"afs_syscall", __NR_afs_syscall},
3379#endif
3380#endif
3381#ifdef SYS_alarm
3382#ifdef __NR_alarm
3383 {"alarm", __NR_alarm},
3384#endif
3385#endif
3386#ifdef SYS_arch_prctl
3387#ifdef __NR_arch_prctl
3388 {"arch_prctl", __NR_arch_prctl},
3389#endif
3390#endif
3391#ifdef SYS_bind
3392#ifdef __NR_bind
3393 {"bind", __NR_bind},
3394#endif
3395#endif
3396#ifdef SYS_brk
3397#ifdef __NR_brk
3398 {"brk", __NR_brk},
3399#endif
3400#endif
3401#ifdef SYS_capget
3402#ifdef __NR_capget
3403 {"capget", __NR_capget},
3404#endif
3405#endif
3406#ifdef SYS_capset
3407#ifdef __NR_capset
3408 {"capset", __NR_capset},
3409#endif
3410#endif
3411#ifdef SYS_chdir
3412#ifdef __NR_chdir
3413 {"chdir", __NR_chdir},
3414#endif
3415#endif
3416#ifdef SYS_chmod
3417#ifdef __NR_chmod
3418 {"chmod", __NR_chmod},
3419#endif
3420#endif
3421#ifdef SYS_chown
3422#ifdef __NR_chown
3423 {"chown", __NR_chown},
3424#endif
3425#endif
3426#ifdef SYS_chroot
3427#ifdef __NR_chroot
3428 {"chroot", __NR_chroot},
3429#endif
3430#endif
3431#ifdef SYS_clock_adjtime
3432#ifdef __NR_clock_adjtime
3433 {"clock_adjtime", __NR_clock_adjtime},
3434#endif
3435#endif
3436#ifdef SYS_clock_getres
3437#ifdef __NR_clock_getres
3438 {"clock_getres", __NR_clock_getres},
3439#endif
3440#endif
3441#ifdef SYS_clock_gettime
3442#ifdef __NR_clock_gettime
3443 {"clock_gettime", __NR_clock_gettime},
3444#endif
3445#endif
3446#ifdef SYS_clock_nanosleep
3447#ifdef __NR_clock_nanosleep
3448 {"clock_nanosleep", __NR_clock_nanosleep},
3449#endif
3450#endif
3451#ifdef SYS_clock_settime
3452#ifdef __NR_clock_settime
3453 {"clock_settime", __NR_clock_settime},
3454#endif
3455#endif
3456#ifdef SYS_clone
3457#ifdef __NR_clone
3458 {"clone", __NR_clone},
3459#endif
3460#endif
3461#ifdef SYS_close
3462#ifdef __NR_close
3463 {"close", __NR_close},
3464#endif
3465#endif
3466#ifdef SYS_connect
3467#ifdef __NR_connect
3468 {"connect", __NR_connect},
3469#endif
3470#endif
3471#ifdef SYS_creat
3472#ifdef __NR_creat
3473 {"creat", __NR_creat},
3474#endif
3475#endif
3476#ifdef SYS_delete_module
3477#ifdef __NR_delete_module
3478 {"delete_module", __NR_delete_module},
3479#endif
3480#endif
3481#ifdef SYS_dup
3482#ifdef __NR_dup
3483 {"dup", __NR_dup},
3484#endif
3485#endif
3486#ifdef SYS_dup2
3487#ifdef __NR_dup2
3488 {"dup2", __NR_dup2},
3489#endif
3490#endif
3491#ifdef SYS_dup3
3492#ifdef __NR_dup3
3493 {"dup3", __NR_dup3},
3494#endif
3495#endif
3496#ifdef SYS_epoll_create
3497#ifdef __NR_epoll_create
3498 {"epoll_create", __NR_epoll_create},
3499#endif
3500#endif
3501#ifdef SYS_epoll_create1
3502#ifdef __NR_epoll_create1
3503 {"epoll_create1", __NR_epoll_create1},
3504#endif
3505#endif
3506#ifdef SYS_epoll_ctl
3507#ifdef __NR_epoll_ctl
3508 {"epoll_ctl", __NR_epoll_ctl},
3509#endif
3510#endif
3511#ifdef SYS_epoll_pwait
3512#ifdef __NR_epoll_pwait
3513 {"epoll_pwait", __NR_epoll_pwait},
3514#endif
3515#endif
3516#ifdef SYS_epoll_wait
3517#ifdef __NR_epoll_wait
3518 {"epoll_wait", __NR_epoll_wait},
3519#endif
3520#endif
3521#ifdef SYS_eventfd
3522#ifdef __NR_eventfd
3523 {"eventfd", __NR_eventfd},
3524#endif
3525#endif
3526#ifdef SYS_eventfd2
3527#ifdef __NR_eventfd2
3528 {"eventfd2", __NR_eventfd2},
3529#endif
3530#endif
3531#ifdef SYS_execve
3532#ifdef __NR_execve
3533 {"execve", __NR_execve},
3534#endif
3535#endif
3536#ifdef SYS_exit
3537#ifdef __NR_exit
3538 {"exit", __NR_exit},
3539#endif
3540#endif
3541#ifdef SYS_exit_group
3542#ifdef __NR_exit_group
3543 {"exit_group", __NR_exit_group},
3544#endif
3545#endif
3546#ifdef SYS_faccessat
3547#ifdef __NR_faccessat
3548 {"faccessat", __NR_faccessat},
3549#endif
3550#endif
3551#ifdef SYS_fadvise64
3552#ifdef __NR_fadvise64
3553 {"fadvise64", __NR_fadvise64},
3554#endif
3555#endif
3556#ifdef SYS_fallocate
3557#ifdef __NR_fallocate
3558 {"fallocate", __NR_fallocate},
3559#endif
3560#endif
3561#ifdef SYS_fanotify_init
3562#ifdef __NR_fanotify_init
3563 {"fanotify_init", __NR_fanotify_init},
3564#endif
3565#endif
3566#ifdef SYS_fanotify_mark
3567#ifdef __NR_fanotify_mark
3568 {"fanotify_mark", __NR_fanotify_mark},
3569#endif
3570#endif
3571#ifdef SYS_fchdir
3572#ifdef __NR_fchdir
3573 {"fchdir", __NR_fchdir},
3574#endif
3575#endif
3576#ifdef SYS_fchmod
3577#ifdef __NR_fchmod
3578 {"fchmod", __NR_fchmod},
3579#endif
3580#endif
3581#ifdef SYS_fchmodat
3582#ifdef __NR_fchmodat
3583 {"fchmodat", __NR_fchmodat},
3584#endif
3585#endif
3586#ifdef SYS_fchown
3587#ifdef __NR_fchown
3588 {"fchown", __NR_fchown},
3589#endif
3590#endif
3591#ifdef SYS_fchownat
3592#ifdef __NR_fchownat
3593 {"fchownat", __NR_fchownat},
3594#endif
3595#endif
3596#ifdef SYS_fcntl
3597#ifdef __NR_fcntl
3598 {"fcntl", __NR_fcntl},
3599#endif
3600#endif
3601#ifdef SYS_fdatasync
3602#ifdef __NR_fdatasync
3603 {"fdatasync", __NR_fdatasync},
3604#endif
3605#endif
3606#ifdef SYS_fgetxattr
3607#ifdef __NR_fgetxattr
3608 {"fgetxattr", __NR_fgetxattr},
3609#endif
3610#endif
3611#ifdef SYS_finit_module
3612#ifdef __NR_finit_module
3613 {"finit_module", __NR_finit_module},
3614#endif
3615#endif
3616#ifdef SYS_flistxattr
3617#ifdef __NR_flistxattr
3618 {"flistxattr", __NR_flistxattr},
3619#endif
3620#endif
3621#ifdef SYS_flock
3622#ifdef __NR_flock
3623 {"flock", __NR_flock},
3624#endif
3625#endif
3626#ifdef SYS_fork
3627#ifdef __NR_fork
3628 {"fork", __NR_fork},
3629#endif
3630#endif
3631#ifdef SYS_fremovexattr
3632#ifdef __NR_fremovexattr
3633 {"fremovexattr", __NR_fremovexattr},
3634#endif
3635#endif
3636#ifdef SYS_fsetxattr
3637#ifdef __NR_fsetxattr
3638 {"fsetxattr", __NR_fsetxattr},
3639#endif
3640#endif
3641#ifdef SYS_fstat
3642#ifdef __NR_fstat
3643 {"fstat", __NR_fstat},
3644#endif
3645#endif
3646#ifdef SYS_fstatfs
3647#ifdef __NR_fstatfs
3648 {"fstatfs", __NR_fstatfs},
3649#endif
3650#endif
3651#ifdef SYS_fsync
3652#ifdef __NR_fsync
3653 {"fsync", __NR_fsync},
3654#endif
3655#endif
3656#ifdef SYS_ftruncate
3657#ifdef __NR_ftruncate
3658 {"ftruncate", __NR_ftruncate},
3659#endif
3660#endif
3661#ifdef SYS_futex
3662#ifdef __NR_futex
3663 {"futex", __NR_futex},
3664#endif
3665#endif
3666#ifdef SYS_futimesat
3667#ifdef __NR_futimesat
3668 {"futimesat", __NR_futimesat},
3669#endif
3670#endif
3671#ifdef SYS_get_mempolicy
3672#ifdef __NR_get_mempolicy
3673 {"get_mempolicy", __NR_get_mempolicy},
3674#endif
3675#endif
3676#ifdef SYS_get_robust_list
3677#ifdef __NR_get_robust_list
3678 {"get_robust_list", __NR_get_robust_list},
3679#endif
3680#endif
3681#ifdef SYS_getcpu
3682#ifdef __NR_getcpu
3683 {"getcpu", __NR_getcpu},
3684#endif
3685#endif
3686#ifdef SYS_getcwd
3687#ifdef __NR_getcwd
3688 {"getcwd", __NR_getcwd},
3689#endif
3690#endif
3691#ifdef SYS_getdents
3692#ifdef __NR_getdents
3693 {"getdents", __NR_getdents},
3694#endif
3695#endif
3696#ifdef SYS_getdents64
3697#ifdef __NR_getdents64
3698 {"getdents64", __NR_getdents64},
3699#endif
3700#endif
3701#ifdef SYS_getegid
3702#ifdef __NR_getegid
3703 {"getegid", __NR_getegid},
3704#endif
3705#endif
3706#ifdef SYS_geteuid
3707#ifdef __NR_geteuid
3708 {"geteuid", __NR_geteuid},
3709#endif
3710#endif
3711#ifdef SYS_getgid
3712#ifdef __NR_getgid
3713 {"getgid", __NR_getgid},
3714#endif
3715#endif
3716#ifdef SYS_getgroups
3717#ifdef __NR_getgroups
3718 {"getgroups", __NR_getgroups},
3719#endif
3720#endif
3721#ifdef SYS_getitimer
3722#ifdef __NR_getitimer
3723 {"getitimer", __NR_getitimer},
3724#endif
3725#endif
3726#ifdef SYS_getpeername
3727#ifdef __NR_getpeername
3728 {"getpeername", __NR_getpeername},
3729#endif
3730#endif
3731#ifdef SYS_getpgid
3732#ifdef __NR_getpgid
3733 {"getpgid", __NR_getpgid},
3734#endif
3735#endif
3736#ifdef SYS_getpgrp
3737#ifdef __NR_getpgrp
3738 {"getpgrp", __NR_getpgrp},
3739#endif
3740#endif
3741#ifdef SYS_getpid
3742#ifdef __NR_getpid
3743 {"getpid", __NR_getpid},
3744#endif
3745#endif
3746#ifdef SYS_getpmsg
3747#ifdef __NR_getpmsg
3748 {"getpmsg", __NR_getpmsg},
3749#endif
3750#endif
3751#ifdef SYS_getppid
3752#ifdef __NR_getppid
3753 {"getppid", __NR_getppid},
3754#endif
3755#endif
3756#ifdef SYS_getpriority
3757#ifdef __NR_getpriority
3758 {"getpriority", __NR_getpriority},
3759#endif
3760#endif
3761#ifdef SYS_getresgid
3762#ifdef __NR_getresgid
3763 {"getresgid", __NR_getresgid},
3764#endif
3765#endif
3766#ifdef SYS_getresuid
3767#ifdef __NR_getresuid
3768 {"getresuid", __NR_getresuid},
3769#endif
3770#endif
3771#ifdef SYS_getrlimit
3772#ifdef __NR_getrlimit
3773 {"getrlimit", __NR_getrlimit},
3774#endif
3775#endif
3776#ifdef SYS_getrusage
3777#ifdef __NR_getrusage
3778 {"getrusage", __NR_getrusage},
3779#endif
3780#endif
3781#ifdef SYS_getsid
3782#ifdef __NR_getsid
3783 {"getsid", __NR_getsid},
3784#endif
3785#endif
3786#ifdef SYS_getsockname
3787#ifdef __NR_getsockname
3788 {"getsockname", __NR_getsockname},
3789#endif
3790#endif
3791#ifdef SYS_getsockopt
3792#ifdef __NR_getsockopt
3793 {"getsockopt", __NR_getsockopt},
3794#endif
3795#endif
3796#ifdef SYS_gettid
3797#ifdef __NR_gettid
3798 {"gettid", __NR_gettid},
3799#endif
3800#endif
3801#ifdef SYS_gettimeofday
3802#ifdef __NR_gettimeofday
3803 {"gettimeofday", __NR_gettimeofday},
3804#endif
3805#endif
3806#ifdef SYS_getuid
3807#ifdef __NR_getuid
3808 {"getuid", __NR_getuid},
3809#endif
3810#endif
3811#ifdef SYS_getxattr
3812#ifdef __NR_getxattr
3813 {"getxattr", __NR_getxattr},
3814#endif
3815#endif
3816#ifdef SYS_init_module
3817#ifdef __NR_init_module
3818 {"init_module", __NR_init_module},
3819#endif
3820#endif
3821#ifdef SYS_inotify_add_watch
3822#ifdef __NR_inotify_add_watch
3823 {"inotify_add_watch", __NR_inotify_add_watch},
3824#endif
3825#endif
3826#ifdef SYS_inotify_init
3827#ifdef __NR_inotify_init
3828 {"inotify_init", __NR_inotify_init},
3829#endif
3830#endif
3831#ifdef SYS_inotify_init1
3832#ifdef __NR_inotify_init1
3833 {"inotify_init1", __NR_inotify_init1},
3834#endif
3835#endif
3836#ifdef SYS_inotify_rm_watch
3837#ifdef __NR_inotify_rm_watch
3838 {"inotify_rm_watch", __NR_inotify_rm_watch},
3839#endif
3840#endif
3841#ifdef SYS_io_cancel
3842#ifdef __NR_io_cancel
3843 {"io_cancel", __NR_io_cancel},
3844#endif
3845#endif
3846#ifdef SYS_io_destroy
3847#ifdef __NR_io_destroy
3848 {"io_destroy", __NR_io_destroy},
3849#endif
3850#endif
3851#ifdef SYS_io_getevents
3852#ifdef __NR_io_getevents
3853 {"io_getevents", __NR_io_getevents},
3854#endif
3855#endif
3856#ifdef SYS_io_setup
3857#ifdef __NR_io_setup
3858 {"io_setup", __NR_io_setup},
3859#endif
3860#endif
3861#ifdef SYS_io_submit
3862#ifdef __NR_io_submit
3863 {"io_submit", __NR_io_submit},
3864#endif
3865#endif
3866#ifdef SYS_ioctl
3867#ifdef __NR_ioctl
3868 {"ioctl", __NR_ioctl},
3869#endif
3870#endif
3871#ifdef SYS_ioperm
3872#ifdef __NR_ioperm
3873 {"ioperm", __NR_ioperm},
3874#endif
3875#endif
3876#ifdef SYS_iopl
3877#ifdef __NR_iopl
3878 {"iopl", __NR_iopl},
3879#endif
3880#endif
3881#ifdef SYS_ioprio_get
3882#ifdef __NR_ioprio_get
3883 {"ioprio_get", __NR_ioprio_get},
3884#endif
3885#endif
3886#ifdef SYS_ioprio_set
3887#ifdef __NR_ioprio_set
3888 {"ioprio_set", __NR_ioprio_set},
3889#endif
3890#endif
3891#ifdef SYS_kcmp
3892#ifdef __NR_kcmp
3893 {"kcmp", __NR_kcmp},
3894#endif
3895#endif
3896#ifdef SYS_kexec_load
3897#ifdef __NR_kexec_load
3898 {"kexec_load", __NR_kexec_load},
3899#endif
3900#endif
3901#ifdef SYS_keyctl
3902#ifdef __NR_keyctl
3903 {"keyctl", __NR_keyctl},
3904#endif
3905#endif
3906#ifdef SYS_kill
3907#ifdef __NR_kill
3908 {"kill", __NR_kill},
3909#endif
3910#endif
3911#ifdef SYS_lchown
3912#ifdef __NR_lchown
3913 {"lchown", __NR_lchown},
3914#endif
3915#endif
3916#ifdef SYS_lgetxattr
3917#ifdef __NR_lgetxattr
3918 {"lgetxattr", __NR_lgetxattr},
3919#endif
3920#endif
3921#ifdef SYS_link
3922#ifdef __NR_link
3923 {"link", __NR_link},
3924#endif
3925#endif
3926#ifdef SYS_linkat
3927#ifdef __NR_linkat
3928 {"linkat", __NR_linkat},
3929#endif
3930#endif
3931#ifdef SYS_listen
3932#ifdef __NR_listen
3933 {"listen", __NR_listen},
3934#endif
3935#endif
3936#ifdef SYS_listxattr
3937#ifdef __NR_listxattr
3938 {"listxattr", __NR_listxattr},
3939#endif
3940#endif
3941#ifdef SYS_llistxattr
3942#ifdef __NR_llistxattr
3943 {"llistxattr", __NR_llistxattr},
3944#endif
3945#endif
3946#ifdef SYS_lookup_dcookie
3947#ifdef __NR_lookup_dcookie
3948 {"lookup_dcookie", __NR_lookup_dcookie},
3949#endif
3950#endif
3951#ifdef SYS_lremovexattr
3952#ifdef __NR_lremovexattr
3953 {"lremovexattr", __NR_lremovexattr},
3954#endif
3955#endif
3956#ifdef SYS_lseek
3957#ifdef __NR_lseek
3958 {"lseek", __NR_lseek},
3959#endif
3960#endif
3961#ifdef SYS_lsetxattr
3962#ifdef __NR_lsetxattr
3963 {"lsetxattr", __NR_lsetxattr},
3964#endif
3965#endif
3966#ifdef SYS_lstat
3967#ifdef __NR_lstat
3968 {"lstat", __NR_lstat},
3969#endif
3970#endif
3971#ifdef SYS_madvise
3972#ifdef __NR_madvise
3973 {"madvise", __NR_madvise},
3974#endif
3975#endif
3976#ifdef SYS_mbind
3977#ifdef __NR_mbind
3978 {"mbind", __NR_mbind},
3979#endif
3980#endif
3981#ifdef SYS_migrate_pages
3982#ifdef __NR_migrate_pages
3983 {"migrate_pages", __NR_migrate_pages},
3984#endif
3985#endif
3986#ifdef SYS_mincore
3987#ifdef __NR_mincore
3988 {"mincore", __NR_mincore},
3989#endif
3990#endif
3991#ifdef SYS_mkdir
3992#ifdef __NR_mkdir
3993 {"mkdir", __NR_mkdir},
3994#endif
3995#endif
3996#ifdef SYS_mkdirat
3997#ifdef __NR_mkdirat
3998 {"mkdirat", __NR_mkdirat},
3999#endif
4000#endif
4001#ifdef SYS_mknod
4002#ifdef __NR_mknod
4003 {"mknod", __NR_mknod},
4004#endif
4005#endif
4006#ifdef SYS_mknodat
4007#ifdef __NR_mknodat
4008 {"mknodat", __NR_mknodat},
4009#endif
4010#endif
4011#ifdef SYS_mlock
4012#ifdef __NR_mlock
4013 {"mlock", __NR_mlock},
4014#endif
4015#endif
4016#ifdef SYS_mlockall
4017#ifdef __NR_mlockall
4018 {"mlockall", __NR_mlockall},
4019#endif
4020#endif
4021#ifdef SYS_mmap
4022#ifdef __NR_mmap
4023 {"mmap", __NR_mmap},
4024#endif
4025#endif
4026#ifdef SYS_modify_ldt
4027#ifdef __NR_modify_ldt
4028 {"modify_ldt", __NR_modify_ldt},
4029#endif
4030#endif
4031#ifdef SYS_mount
4032#ifdef __NR_mount
4033 {"mount", __NR_mount},
4034#endif
4035#endif
4036#ifdef SYS_move_pages
4037#ifdef __NR_move_pages
4038 {"move_pages", __NR_move_pages},
4039#endif
4040#endif
4041#ifdef SYS_mprotect
4042#ifdef __NR_mprotect
4043 {"mprotect", __NR_mprotect},
4044#endif
4045#endif
4046#ifdef SYS_mq_getsetattr
4047#ifdef __NR_mq_getsetattr
4048 {"mq_getsetattr", __NR_mq_getsetattr},
4049#endif
4050#endif
4051#ifdef SYS_mq_notify
4052#ifdef __NR_mq_notify
4053 {"mq_notify", __NR_mq_notify},
4054#endif
4055#endif
4056#ifdef SYS_mq_open
4057#ifdef __NR_mq_open
4058 {"mq_open", __NR_mq_open},
4059#endif
4060#endif
4061#ifdef SYS_mq_timedreceive
4062#ifdef __NR_mq_timedreceive
4063 {"mq_timedreceive", __NR_mq_timedreceive},
4064#endif
4065#endif
4066#ifdef SYS_mq_timedsend
4067#ifdef __NR_mq_timedsend
4068 {"mq_timedsend", __NR_mq_timedsend},
4069#endif
4070#endif
4071#ifdef SYS_mq_unlink
4072#ifdef __NR_mq_unlink
4073 {"mq_unlink", __NR_mq_unlink},
4074#endif
4075#endif
4076#ifdef SYS_mremap
4077#ifdef __NR_mremap
4078 {"mremap", __NR_mremap},
4079#endif
4080#endif
4081#ifdef SYS_msgctl
4082#ifdef __NR_msgctl
4083 {"msgctl", __NR_msgctl},
4084#endif
4085#endif
4086#ifdef SYS_msgget
4087#ifdef __NR_msgget
4088 {"msgget", __NR_msgget},
4089#endif
4090#endif
4091#ifdef SYS_msgrcv
4092#ifdef __NR_msgrcv
4093 {"msgrcv", __NR_msgrcv},
4094#endif
4095#endif
4096#ifdef SYS_msgsnd
4097#ifdef __NR_msgsnd
4098 {"msgsnd", __NR_msgsnd},
4099#endif
4100#endif
4101#ifdef SYS_msync
4102#ifdef __NR_msync
4103 {"msync", __NR_msync},
4104#endif
4105#endif
4106#ifdef SYS_munlock
4107#ifdef __NR_munlock
4108 {"munlock", __NR_munlock},
4109#endif
4110#endif
4111#ifdef SYS_munlockall
4112#ifdef __NR_munlockall
4113 {"munlockall", __NR_munlockall},
4114#endif
4115#endif
4116#ifdef SYS_munmap
4117#ifdef __NR_munmap
4118 {"munmap", __NR_munmap},
4119#endif
4120#endif
4121#ifdef SYS_name_to_handle_at
4122#ifdef __NR_name_to_handle_at
4123 {"name_to_handle_at", __NR_name_to_handle_at},
4124#endif
4125#endif
4126#ifdef SYS_nanosleep
4127#ifdef __NR_nanosleep
4128 {"nanosleep", __NR_nanosleep},
4129#endif
4130#endif
4131#ifdef SYS_newfstatat
4132#ifdef __NR_newfstatat
4133 {"newfstatat", __NR_newfstatat},
4134#endif
4135#endif
4136#ifdef SYS_open
4137#ifdef __NR_open
4138 {"open", __NR_open},
4139#endif
4140#endif
4141#ifdef SYS_open_by_handle_at
4142#ifdef __NR_open_by_handle_at
4143 {"open_by_handle_at", __NR_open_by_handle_at},
4144#endif
4145#endif
4146#ifdef SYS_openat
4147#ifdef __NR_openat
4148 {"openat", __NR_openat},
4149#endif
4150#endif
4151#ifdef SYS_pause
4152#ifdef __NR_pause
4153 {"pause", __NR_pause},
4154#endif
4155#endif
4156#ifdef SYS_perf_event_open
4157#ifdef __NR_perf_event_open
4158 {"perf_event_open", __NR_perf_event_open},
4159#endif
4160#endif
4161#ifdef SYS_personality
4162#ifdef __NR_personality
4163 {"personality", __NR_personality},
4164#endif
4165#endif
4166#ifdef SYS_pipe
4167#ifdef __NR_pipe
4168 {"pipe", __NR_pipe},
4169#endif
4170#endif
4171#ifdef SYS_pipe2
4172#ifdef __NR_pipe2
4173 {"pipe2", __NR_pipe2},
4174#endif
4175#endif
4176#ifdef SYS_pivot_root
4177#ifdef __NR_pivot_root
4178 {"pivot_root", __NR_pivot_root},
4179#endif
4180#endif
4181#ifdef SYS_poll
4182#ifdef __NR_poll
4183 {"poll", __NR_poll},
4184#endif
4185#endif
4186#ifdef SYS_ppoll
4187#ifdef __NR_ppoll
4188 {"ppoll", __NR_ppoll},
4189#endif
4190#endif
4191#ifdef SYS_prctl
4192#ifdef __NR_prctl
4193 {"prctl", __NR_prctl},
4194#endif
4195#endif
4196#ifdef SYS_pread64
4197#ifdef __NR_pread64
4198 {"pread64", __NR_pread64},
4199#endif
4200#endif
4201#ifdef SYS_preadv
4202#ifdef __NR_preadv
4203 {"preadv", __NR_preadv},
4204#endif
4205#endif
4206#ifdef SYS_prlimit64
4207#ifdef __NR_prlimit64
4208 {"prlimit64", __NR_prlimit64},
4209#endif
4210#endif
4211#ifdef SYS_process_vm_readv
4212#ifdef __NR_process_vm_readv
4213 {"process_vm_readv", __NR_process_vm_readv},
4214#endif
4215#endif
4216#ifdef SYS_process_vm_writev
4217#ifdef __NR_process_vm_writev
4218 {"process_vm_writev", __NR_process_vm_writev},
4219#endif
4220#endif
4221#ifdef SYS_pselect6
4222#ifdef __NR_pselect6
4223 {"pselect6", __NR_pselect6},
4224#endif
4225#endif
4226#ifdef SYS_ptrace
4227#ifdef __NR_ptrace
4228 {"ptrace", __NR_ptrace},
4229#endif
4230#endif
4231#ifdef SYS_putpmsg
4232#ifdef __NR_putpmsg
4233 {"putpmsg", __NR_putpmsg},
4234#endif
4235#endif
4236#ifdef SYS_pwrite64
4237#ifdef __NR_pwrite64
4238 {"pwrite64", __NR_pwrite64},
4239#endif
4240#endif
4241#ifdef SYS_pwritev
4242#ifdef __NR_pwritev
4243 {"pwritev", __NR_pwritev},
4244#endif
4245#endif
4246#ifdef SYS_quotactl
4247#ifdef __NR_quotactl
4248 {"quotactl", __NR_quotactl},
4249#endif
4250#endif
4251#ifdef SYS_read
4252#ifdef __NR_read
4253 {"read", __NR_read},
4254#endif
4255#endif
4256#ifdef SYS_readahead
4257#ifdef __NR_readahead
4258 {"readahead", __NR_readahead},
4259#endif
4260#endif
4261#ifdef SYS_readlink
4262#ifdef __NR_readlink
4263 {"readlink", __NR_readlink},
4264#endif
4265#endif
4266#ifdef SYS_readlinkat
4267#ifdef __NR_readlinkat
4268 {"readlinkat", __NR_readlinkat},
4269#endif
4270#endif
4271#ifdef SYS_readv
4272#ifdef __NR_readv
4273 {"readv", __NR_readv},
4274#endif
4275#endif
4276#ifdef SYS_reboot
4277#ifdef __NR_reboot
4278 {"reboot", __NR_reboot},
4279#endif
4280#endif
4281#ifdef SYS_recvfrom
4282#ifdef __NR_recvfrom
4283 {"recvfrom", __NR_recvfrom},
4284#endif
4285#endif
4286#ifdef SYS_recvmmsg
4287#ifdef __NR_recvmmsg
4288 {"recvmmsg", __NR_recvmmsg},
4289#endif
4290#endif
4291#ifdef SYS_recvmsg
4292#ifdef __NR_recvmsg
4293 {"recvmsg", __NR_recvmsg},
4294#endif
4295#endif
4296#ifdef SYS_remap_file_pages
4297#ifdef __NR_remap_file_pages
4298 {"remap_file_pages", __NR_remap_file_pages},
4299#endif
4300#endif
4301#ifdef SYS_removexattr
4302#ifdef __NR_removexattr
4303 {"removexattr", __NR_removexattr},
4304#endif
4305#endif
4306#ifdef SYS_rename
4307#ifdef __NR_rename
4308 {"rename", __NR_rename},
4309#endif
4310#endif
4311#ifdef SYS_renameat
4312#ifdef __NR_renameat
4313 {"renameat", __NR_renameat},
4314#endif
4315#endif
4316#ifdef SYS_request_key
4317#ifdef __NR_request_key
4318 {"request_key", __NR_request_key},
4319#endif
4320#endif
4321#ifdef SYS_restart_syscall
4322#ifdef __NR_restart_syscall
4323 {"restart_syscall", __NR_restart_syscall},
4324#endif
4325#endif
4326#ifdef SYS_rmdir
4327#ifdef __NR_rmdir
4328 {"rmdir", __NR_rmdir},
4329#endif
4330#endif
4331#ifdef SYS_rt_sigaction
4332#ifdef __NR_rt_sigaction
4333 {"rt_sigaction", __NR_rt_sigaction},
4334#endif
4335#endif
4336#ifdef SYS_rt_sigpending
4337#ifdef __NR_rt_sigpending
4338 {"rt_sigpending", __NR_rt_sigpending},
4339#endif
4340#endif
4341#ifdef SYS_rt_sigprocmask
4342#ifdef __NR_rt_sigprocmask
4343 {"rt_sigprocmask", __NR_rt_sigprocmask},
4344#endif
4345#endif
4346#ifdef SYS_rt_sigqueueinfo
4347#ifdef __NR_rt_sigqueueinfo
4348 {"rt_sigqueueinfo", __NR_rt_sigqueueinfo},
4349#endif
4350#endif
4351#ifdef SYS_rt_sigreturn
4352#ifdef __NR_rt_sigreturn
4353 {"rt_sigreturn", __NR_rt_sigreturn},
4354#endif
4355#endif
4356#ifdef SYS_rt_sigsuspend
4357#ifdef __NR_rt_sigsuspend
4358 {"rt_sigsuspend", __NR_rt_sigsuspend},
4359#endif
4360#endif
4361#ifdef SYS_rt_sigtimedwait
4362#ifdef __NR_rt_sigtimedwait
4363 {"rt_sigtimedwait", __NR_rt_sigtimedwait},
4364#endif
4365#endif
4366#ifdef SYS_rt_tgsigqueueinfo
4367#ifdef __NR_rt_tgsigqueueinfo
4368 {"rt_tgsigqueueinfo", __NR_rt_tgsigqueueinfo},
4369#endif
4370#endif
4371#ifdef SYS_sched_get_priority_max
4372#ifdef __NR_sched_get_priority_max
4373 {"sched_get_priority_max", __NR_sched_get_priority_max},
4374#endif
4375#endif
4376#ifdef SYS_sched_get_priority_min
4377#ifdef __NR_sched_get_priority_min
4378 {"sched_get_priority_min", __NR_sched_get_priority_min},
4379#endif
4380#endif
4381#ifdef SYS_sched_getaffinity
4382#ifdef __NR_sched_getaffinity
4383 {"sched_getaffinity", __NR_sched_getaffinity},
4384#endif
4385#endif
4386#ifdef SYS_sched_getparam
4387#ifdef __NR_sched_getparam
4388 {"sched_getparam", __NR_sched_getparam},
4389#endif
4390#endif
4391#ifdef SYS_sched_getscheduler
4392#ifdef __NR_sched_getscheduler
4393 {"sched_getscheduler", __NR_sched_getscheduler},
4394#endif
4395#endif
4396#ifdef SYS_sched_rr_get_interval
4397#ifdef __NR_sched_rr_get_interval
4398 {"sched_rr_get_interval", __NR_sched_rr_get_interval},
4399#endif
4400#endif
4401#ifdef SYS_sched_setaffinity
4402#ifdef __NR_sched_setaffinity
4403 {"sched_setaffinity", __NR_sched_setaffinity},
4404#endif
4405#endif
4406#ifdef SYS_sched_setparam
4407#ifdef __NR_sched_setparam
4408 {"sched_setparam", __NR_sched_setparam},
4409#endif
4410#endif
4411#ifdef SYS_sched_setscheduler
4412#ifdef __NR_sched_setscheduler
4413 {"sched_setscheduler", __NR_sched_setscheduler},
4414#endif
4415#endif
4416#ifdef SYS_sched_yield
4417#ifdef __NR_sched_yield
4418 {"sched_yield", __NR_sched_yield},
4419#endif
4420#endif
4421#ifdef SYS_security
4422#ifdef __NR_security
4423 {"security", __NR_security},
4424#endif
4425#endif
4426#ifdef SYS_select
4427#ifdef __NR_select
4428 {"select", __NR_select},
4429#endif
4430#endif
4431#ifdef SYS_semctl
4432#ifdef __NR_semctl
4433 {"semctl", __NR_semctl},
4434#endif
4435#endif
4436#ifdef SYS_semget
4437#ifdef __NR_semget
4438 {"semget", __NR_semget},
4439#endif
4440#endif
4441#ifdef SYS_semop
4442#ifdef __NR_semop
4443 {"semop", __NR_semop},
4444#endif
4445#endif
4446#ifdef SYS_semtimedop
4447#ifdef __NR_semtimedop
4448 {"semtimedop", __NR_semtimedop},
4449#endif
4450#endif
4451#ifdef SYS_sendfile
4452#ifdef __NR_sendfile
4453 {"sendfile", __NR_sendfile},
4454#endif
4455#endif
4456#ifdef SYS_sendmmsg
4457#ifdef __NR_sendmmsg
4458 {"sendmmsg", __NR_sendmmsg},
4459#endif
4460#endif
4461#ifdef SYS_sendmsg
4462#ifdef __NR_sendmsg
4463 {"sendmsg", __NR_sendmsg},
4464#endif
4465#endif
4466#ifdef SYS_sendto
4467#ifdef __NR_sendto
4468 {"sendto", __NR_sendto},
4469#endif
4470#endif
4471#ifdef SYS_set_mempolicy
4472#ifdef __NR_set_mempolicy
4473 {"set_mempolicy", __NR_set_mempolicy},
4474#endif
4475#endif
4476#ifdef SYS_set_robust_list
4477#ifdef __NR_set_robust_list
4478 {"set_robust_list", __NR_set_robust_list},
4479#endif
4480#endif
4481#ifdef SYS_set_tid_address
4482#ifdef __NR_set_tid_address
4483 {"set_tid_address", __NR_set_tid_address},
4484#endif
4485#endif
4486#ifdef SYS_setdomainname
4487#ifdef __NR_setdomainname
4488 {"setdomainname", __NR_setdomainname},
4489#endif
4490#endif
4491#ifdef SYS_setfsgid
4492#ifdef __NR_setfsgid
4493 {"setfsgid", __NR_setfsgid},
4494#endif
4495#endif
4496#ifdef SYS_setfsuid
4497#ifdef __NR_setfsuid
4498 {"setfsuid", __NR_setfsuid},
4499#endif
4500#endif
4501#ifdef SYS_setgid
4502#ifdef __NR_setgid
4503 {"setgid", __NR_setgid},
4504#endif
4505#endif
4506#ifdef SYS_setgroups
4507#ifdef __NR_setgroups
4508 {"setgroups", __NR_setgroups},
4509#endif
4510#endif
4511#ifdef SYS_sethostname
4512#ifdef __NR_sethostname
4513 {"sethostname", __NR_sethostname},
4514#endif
4515#endif
4516#ifdef SYS_setitimer
4517#ifdef __NR_setitimer
4518 {"setitimer", __NR_setitimer},
4519#endif
4520#endif
4521#ifdef SYS_setns
4522#ifdef __NR_setns
4523 {"setns", __NR_setns},
4524#endif
4525#endif
4526#ifdef SYS_setpgid
4527#ifdef __NR_setpgid
4528 {"setpgid", __NR_setpgid},
4529#endif
4530#endif
4531#ifdef SYS_setpriority
4532#ifdef __NR_setpriority
4533 {"setpriority", __NR_setpriority},
4534#endif
4535#endif
4536#ifdef SYS_setregid
4537#ifdef __NR_setregid
4538 {"setregid", __NR_setregid},
4539#endif
4540#endif
4541#ifdef SYS_setresgid
4542#ifdef __NR_setresgid
4543 {"setresgid", __NR_setresgid},
4544#endif
4545#endif
4546#ifdef SYS_setresuid
4547#ifdef __NR_setresuid
4548 {"setresuid", __NR_setresuid},
4549#endif
4550#endif
4551#ifdef SYS_setreuid
4552#ifdef __NR_setreuid
4553 {"setreuid", __NR_setreuid},
4554#endif
4555#endif
4556#ifdef SYS_setrlimit
4557#ifdef __NR_setrlimit
4558 {"setrlimit", __NR_setrlimit},
4559#endif
4560#endif
4561#ifdef SYS_setsid
4562#ifdef __NR_setsid
4563 {"setsid", __NR_setsid},
4564#endif
4565#endif
4566#ifdef SYS_setsockopt
4567#ifdef __NR_setsockopt
4568 {"setsockopt", __NR_setsockopt},
4569#endif
4570#endif
4571#ifdef SYS_settimeofday
4572#ifdef __NR_settimeofday
4573 {"settimeofday", __NR_settimeofday},
4574#endif
4575#endif
4576#ifdef SYS_setuid
4577#ifdef __NR_setuid
4578 {"setuid", __NR_setuid},
4579#endif
4580#endif
4581#ifdef SYS_setxattr
4582#ifdef __NR_setxattr
4583 {"setxattr", __NR_setxattr},
4584#endif
4585#endif
4586#ifdef SYS_shmat
4587#ifdef __NR_shmat
4588 {"shmat", __NR_shmat},
4589#endif
4590#endif
4591#ifdef SYS_shmctl
4592#ifdef __NR_shmctl
4593 {"shmctl", __NR_shmctl},
4594#endif
4595#endif
4596#ifdef SYS_shmdt
4597#ifdef __NR_shmdt
4598 {"shmdt", __NR_shmdt},
4599#endif
4600#endif
4601#ifdef SYS_shmget
4602#ifdef __NR_shmget
4603 {"shmget", __NR_shmget},
4604#endif
4605#endif
4606#ifdef SYS_shutdown
4607#ifdef __NR_shutdown
4608 {"shutdown", __NR_shutdown},
4609#endif
4610#endif
4611#ifdef SYS_sigaltstack
4612#ifdef __NR_sigaltstack
4613 {"sigaltstack", __NR_sigaltstack},
4614#endif
4615#endif
4616#ifdef SYS_signalfd
4617#ifdef __NR_signalfd
4618 {"signalfd", __NR_signalfd},
4619#endif
4620#endif
4621#ifdef SYS_signalfd4
4622#ifdef __NR_signalfd4
4623 {"signalfd4", __NR_signalfd4},
4624#endif
4625#endif
4626#ifdef SYS_socket
4627#ifdef __NR_socket
4628 {"socket", __NR_socket},
4629#endif
4630#endif
4631#ifdef SYS_socketpair
4632#ifdef __NR_socketpair
4633 {"socketpair", __NR_socketpair},
4634#endif
4635#endif
4636#ifdef SYS_splice
4637#ifdef __NR_splice
4638 {"splice", __NR_splice},
4639#endif
4640#endif
4641#ifdef SYS_stat
4642#ifdef __NR_stat
4643 {"stat", __NR_stat},
4644#endif
4645#endif
4646#ifdef SYS_statfs
4647#ifdef __NR_statfs
4648 {"statfs", __NR_statfs},
4649#endif
4650#endif
4651#ifdef SYS_swapoff
4652#ifdef __NR_swapoff
4653 {"swapoff", __NR_swapoff},
4654#endif
4655#endif
4656#ifdef SYS_swapon
4657#ifdef __NR_swapon
4658 {"swapon", __NR_swapon},
4659#endif
4660#endif
4661#ifdef SYS_symlink
4662#ifdef __NR_symlink
4663 {"symlink", __NR_symlink},
4664#endif
4665#endif
4666#ifdef SYS_symlinkat
4667#ifdef __NR_symlinkat
4668 {"symlinkat", __NR_symlinkat},
4669#endif
4670#endif
4671#ifdef SYS_sync
4672#ifdef __NR_sync
4673 {"sync", __NR_sync},
4674#endif
4675#endif
4676#ifdef SYS_sync_file_range
4677#ifdef __NR_sync_file_range
4678 {"sync_file_range", __NR_sync_file_range},
4679#endif
4680#endif
4681#ifdef SYS_syncfs
4682#ifdef __NR_syncfs
4683 {"syncfs", __NR_syncfs},
4684#endif
4685#endif
4686#ifdef SYS_sysfs
4687#ifdef __NR_sysfs
4688 {"sysfs", __NR_sysfs},
4689#endif
4690#endif
4691#ifdef SYS_sysinfo
4692#ifdef __NR_sysinfo
4693 {"sysinfo", __NR_sysinfo},
4694#endif
4695#endif
4696#ifdef SYS_syslog
4697#ifdef __NR_syslog
4698 {"syslog", __NR_syslog},
4699#endif
4700#endif
4701#ifdef SYS_tee
4702#ifdef __NR_tee
4703 {"tee", __NR_tee},
4704#endif
4705#endif
4706#ifdef SYS_tgkill
4707#ifdef __NR_tgkill
4708 {"tgkill", __NR_tgkill},
4709#endif
4710#endif
4711#ifdef SYS_time
4712#ifdef __NR_time
4713 {"time", __NR_time},
4714#endif
4715#endif
4716#ifdef SYS_timer_create
4717#ifdef __NR_timer_create
4718 {"timer_create", __NR_timer_create},
4719#endif
4720#endif
4721#ifdef SYS_timer_delete
4722#ifdef __NR_timer_delete
4723 {"timer_delete", __NR_timer_delete},
4724#endif
4725#endif
4726#ifdef SYS_timer_getoverrun
4727#ifdef __NR_timer_getoverrun
4728 {"timer_getoverrun", __NR_timer_getoverrun},
4729#endif
4730#endif
4731#ifdef SYS_timer_gettime
4732#ifdef __NR_timer_gettime
4733 {"timer_gettime", __NR_timer_gettime},
4734#endif
4735#endif
4736#ifdef SYS_timer_settime
4737#ifdef __NR_timer_settime
4738 {"timer_settime", __NR_timer_settime},
4739#endif
4740#endif
4741#ifdef SYS_timerfd_create
4742#ifdef __NR_timerfd_create
4743 {"timerfd_create", __NR_timerfd_create},
4744#endif
4745#endif
4746#ifdef SYS_timerfd_gettime
4747#ifdef __NR_timerfd_gettime
4748 {"timerfd_gettime", __NR_timerfd_gettime},
4749#endif
4750#endif
4751#ifdef SYS_timerfd_settime
4752#ifdef __NR_timerfd_settime
4753 {"timerfd_settime", __NR_timerfd_settime},
4754#endif
4755#endif
4756#ifdef SYS_times
4757#ifdef __NR_times
4758 {"times", __NR_times},
4759#endif
4760#endif
4761#ifdef SYS_tkill
4762#ifdef __NR_tkill
4763 {"tkill", __NR_tkill},
4764#endif
4765#endif
4766#ifdef SYS_truncate
4767#ifdef __NR_truncate
4768 {"truncate", __NR_truncate},
4769#endif
4770#endif
4771#ifdef SYS_tuxcall
4772#ifdef __NR_tuxcall
4773 {"tuxcall", __NR_tuxcall},
4774#endif
4775#endif
4776#ifdef SYS_umask
4777#ifdef __NR_umask
4778 {"umask", __NR_umask},
4779#endif
4780#endif
4781#ifdef SYS_umount2
4782#ifdef __NR_umount2
4783 {"umount2", __NR_umount2},
4784#endif
4785#endif
4786#ifdef SYS_uname
4787#ifdef __NR_uname
4788 {"uname", __NR_uname},
4789#endif
4790#endif
4791#ifdef SYS_unlink
4792#ifdef __NR_unlink
4793 {"unlink", __NR_unlink},
4794#endif
4795#endif
4796#ifdef SYS_unlinkat
4797#ifdef __NR_unlinkat
4798 {"unlinkat", __NR_unlinkat},
4799#endif
4800#endif
4801#ifdef SYS_unshare
4802#ifdef __NR_unshare
4803 {"unshare", __NR_unshare},
4804#endif
4805#endif
4806#ifdef SYS_ustat
4807#ifdef __NR_ustat
4808 {"ustat", __NR_ustat},
4809#endif
4810#endif
4811#ifdef SYS_utime
4812#ifdef __NR_utime
4813 {"utime", __NR_utime},
4814#endif
4815#endif
4816#ifdef SYS_utimensat
4817#ifdef __NR_utimensat
4818 {"utimensat", __NR_utimensat},
4819#endif
4820#endif
4821#ifdef SYS_utimes
4822#ifdef __NR_utimes
4823 {"utimes", __NR_utimes},
4824#endif
4825#endif
4826#ifdef SYS_vfork
4827#ifdef __NR_vfork
4828 {"vfork", __NR_vfork},
4829#endif
4830#endif
4831#ifdef SYS_vhangup
4832#ifdef __NR_vhangup
4833 {"vhangup", __NR_vhangup},
4834#endif
4835#endif
4836#ifdef SYS_vmsplice
4837#ifdef __NR_vmsplice
4838 {"vmsplice", __NR_vmsplice},
4839#endif
4840#endif
4841#ifdef SYS_wait4
4842#ifdef __NR_wait4
4843 {"wait4", __NR_wait4},
4844#endif
4845#endif
4846#ifdef SYS_waitid
4847#ifdef __NR_waitid
4848 {"waitid", __NR_waitid},
4849#endif
4850#endif
4851#ifdef SYS_write
4852#ifdef __NR_write
4853 {"write", __NR_write},
4854#endif
4855#endif
4856#ifdef SYS_writev
4857#ifdef __NR_writev
4858 {"writev", __NR_writev},
4859#endif
4860#endif
4861#endif
4862
4863//
4864// end of generated code
4865//
4866}; // end of syslist
4867
4868const char *syscall_find_nr(int nr) {
4869 int i;
4870 int elems = sizeof(syslist) / sizeof(syslist[0]);
4871 for (i = 0; i < elems; i++) {
4872 if (nr == syslist[i].nr)
4873 return syslist[i].name;
4874 }
4875
4876 return "unknown";
4877}
4878
4879// return -1 if error, or syscall number
4880static int syscall_find_name(const char *name) {
4881 int i;
4882 int elems = sizeof(syslist) / sizeof(syslist[0]);
4883 for (i = 0; i < elems; i++) {
4884 if (strcmp(name, syslist[i].name) == 0)
4885 return syslist[i].nr;
4886 }
4887
4888 return -1;
4889}
4890
4891// return 1 if error, 0 if OK
4892int syscall_check_list(const char *slist, void (*callback)(int)) {
4893 // don't allow empty lists
4894 if (slist == NULL || *slist == '\0') {
4895 fprintf(stderr, "Error: empty syscall lists are not allowed\n");
4896 return -1;
4897 }
4898
4899 // work on a copy of the string
4900 char *str = strdup(slist);
4901 if (!str)
4902 errExit("strdup");
4903
4904 char *ptr = str;
4905 char *start = str;
4906 while (*ptr != '\0') {
4907 if (islower(*ptr) || isdigit(*ptr) || *ptr == '_')
4908 ;
4909 else if (*ptr == ',') {
4910 *ptr = '\0';
4911 int nr = syscall_find_name(start);
4912 if (nr == -1)
4913 fprintf(stderr, "Warning: syscall %s not found\n", start);
4914 else if (callback != NULL)
4915 callback(nr);
4916
4917 start = ptr + 1;
4918 }
4919 ptr++;
4920 }
4921 if (*start != '\0') {
4922 int nr = syscall_find_name(start);
4923 if (nr == -1)
4924 fprintf(stderr, "Warning: syscall %s not found\n", start);
4925 else if (callback != NULL)
4926 callback(nr);
4927 }
4928
4929 free(str);
4930 return 0;
4931}
4932
4933void syscall_print(void) {
4934 int i;
4935 int elems = sizeof(syslist) / sizeof(syslist[0]);
4936 for (i = 0; i < elems; i++) {
4937 printf("%d\t- %s\n", syslist[i].nr, syslist[i].name);
4938 }
4939 printf("\n");
4940}
4941
4942#endif // HAVE_SECCOMP
diff --git a/src/firejail/usage.c b/src/firejail/usage.c
new file mode 100644
index 000000000..71ae203ff
--- /dev/null
+++ b/src/firejail/usage.c
@@ -0,0 +1,312 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
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#include "firejail.h"
21
22void usage(void) {
23 printf("firejail - version %s\n\n", VERSION);
24 printf("Firejail is a SUID sandbox program that reduces the risk of security breaches by\n");
25 printf("restricting the running environment of untrusted applications using Linux\n");
26 printf("namespaces. It includes a sandbox profile for Mozilla Firefox.\n\n");
27 printf("\n");
28 printf("Usage: firejail [options] [program and arguments]\n\n");
29 printf("\n");
30 printf("Without any options, the sandbox consists of a filesystem chroot build from the\n");
31 printf("current system directories mounted read-only, and new PID and IPC\n");
32 printf("namespaces. If no program is specified as an argument, /bin/bash is started by\n");
33 printf("default in the sandbox.\n\n");
34 printf("\n");
35 printf("Options:\n\n");
36 printf("\t-- - signal the end of options and disables further option processing.\n\n");
37 printf("\t--bandwidth=name - set bandwidth limits for the sandbox identified\n");
38 printf("\t\tby name, see Traffic Shaping section for more details.\n\n");
39 printf("\t--bandwidth=pid - set bandwidth limits for the sandbox identified\n");
40 printf("\t\tby PID, see Traffic Shaping section for more details.\n\n");
41#ifdef HAVE_BIND
42 printf("\t--bind=dirname1,dirname2 - mount-bind dirname1 on top of dirname2.\n\n");
43 printf("\t--bind=filename1,dirname2 - mount-bind filename1 on top of filename2.\n\n");
44#endif
45 printf("\t--blacklist=dirname_or_filename - blacklist directory or file.\n\n");
46 printf("\t-c - execute command and exit.\n\n");
47 printf("\t--caps - enable default Linux capabilities filter. The filter disables\n");
48 printf("\t\tCAP_SYS_MODULE, CAP_SYS_RAWIO, CAP_SYS_BOOT, CAP_SYS_NICE,\n");
49 printf("\t\tCAP_SYS_TTY_CONFIG, CAP_SYSLOG, CAP_MKNOD, CAP_SYS_ADMIN.\n\n");
50 printf("\t--caps.drop=all - drop all capabilities.\n\n");
51 printf("\t--caps.drop=capability,capability,capability - blacklist Linux\n");
52 printf("\t\tcapabilities filter.\n\n");
53 printf("\t--caps.keep=capability,capability,capability - whitelist Linux\n");
54 printf("\t\tcapabilities filter.\n\n");
55 printf("\t--caps.print=name - print the caps filter for the sandbox identified\n");
56 printf("\t\tby name.\n\n");
57 printf("\t--caps.print=pid - print the caps filter for the sandbox identified\n");
58 printf("\t\tby PID.\n\n");
59 printf("\t--cgroup=tasks-file - place the sandbox in the specified control group.\n");
60 printf("\t\ttasks-file is the full path of cgroup tasks file.\n");
61 printf("\t\tExample: --cgroup=/sys/fs/cgroup/g1/tasks\n\n");
62#ifdef HAVE_CHROOT
63 printf("\t--chroot=dirname - chroot into dirname directory.\n\n");
64#endif
65 printf("\t--cpu=cpu-number,cpu-number - set cpu affinity.\n");
66 printf("\t\tExample: cpu=0,1,2\n\n");
67 printf("\t--csh - use /bin/csh as default shell.\n\n");
68 printf("\t--debug - print sandbox debug messages.\n\n");
69 printf("\t--debug-syscalls - print all recognized system calls in the current\n");
70 printf("\t\tFirejail software build and exit.\n\n");
71 printf("\t--debug-caps - print all recognized capabilities in the current\n");
72 printf("\t\tFirejail software build and exit.\n\n");
73 printf("\t--defaultgw=address - use this address as default gateway in the new\n");
74 printf("\t\tnetwork namespace.\n\n");
75 printf("\t--dns=address - set a DNS server for the sandbox. Up to three DNS\n");
76 printf("\t\tservers can be defined.\n\n");
77 printf("\t--dns.print=name - print DNS configuration for the sandbox identified\n");
78 printf("\t\tby name.\n\n");
79 printf("\t--dns.print=pid - print DNS configuration of the sandbox identified.\n");
80 printf("\t\tby PID.\n\n");
81 printf("\t--help, -? - this help screen.\n\n");
82 printf("\t--ip=address - set interface IP address.\n\n");
83 printf("\t--ip=none - no IP address and no default gateway address are configured\n");
84 printf("\t\tin the new network namespace. Use this option in case you intend\n");
85 printf("\t\tto start an external DHCP client in the sandbox.\n\n");
86 printf("\t--iprange=address,address - configure an IP address in this range\n\n");
87 printf("\t--ipc-namespace - enable a new IPC namespace if the sandbox was started\n");
88 printf("\t\tas a regular user. IPC namespace is enabled by default only if\n");
89 printf("\t\tthe sandbox is started as root.\n\n");
90 printf("\t--join=name - join the sandbox identified by name.\n\n");
91 printf("\t--join=pid - join the sandbox identified by PID.\n\n");
92 printf("\t--list - list all sandboxes.\n\n");
93 printf("\t--mac=xx:xx:xx:xx:xx:xx - set interface MAC address.\n\n");
94 printf("\t--name=name - set sandbox hostname.\n\n");
95 printf("\t--net=bridgename - enable network namespaces and connect to this bridge\n");
96 printf("\t\tdevice. Unless specified with option --ip and --defaultgw, an\n");
97 printf("\t\tIP address and a default gateway will be assigned automatically\n");
98 printf("\t\tto the sandbox. The IP address is checked using ARP before\n");
99 printf("\t\tassignment. The IP address assigned as default gateway is the\n");
100 printf("\t\tbridge device IP address. Up to four --net devices can\n");
101 printf("\t\tbe defined. Mixing bridge and macvlan devices is allowed.\n\n");
102 printf("\t--net=ethernet_interface - enable network namespaces and connect\n");
103 printf("\t\tto this ethernet_interface using the standard Linux macvlan\n");
104 printf("\t\tdriver. Unless specified with option --ip and --defaultgw, an\n");
105 printf("\t\tIP address and a default gateway will be assigned automatically\n");
106 printf("\t\tto the sandbox. The IP address is checked using ARP before\n");
107 printf("\t\tassignment. The IP address assigned as default gateway is the\n");
108 printf("\t\tdefault gateway of the host. Up to four --net devices can\n");
109 printf("\t\tbe defined. Mixing bridge and macvlan devices is allowed.\n\n");
110 printf("\t--net=none - enable a new, unconnected network namespace.\n\n");
111
112 printf("\t--netfilter - enable the default client network filter in the new\n");
113 printf("\t\tnetwork namespace:\n\n");
114 printf("\t\t*filter\n");
115 printf("\t\t:INPUT DROP [0:0]\n");
116 printf("\t\t:FORWARD DROP [0:0]\n");
117 printf("\t\t:OUTPUT ACCEPT [0:0]\n");
118 printf("\t\t-A INPUT -i lo -j ACCEPT\n");
119 printf("\t\t-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n");
120 printf("\t\t-A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT\n");
121 printf("\t\t-A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT\n");
122 printf("\t\t-A INPUT -p icmp --icmp-type echo-request -j ACCEPT \n");
123 printf("\t\tCOMMIT\n\n");
124 printf("\t--netfilter=filename - enable the network filter specified by\n");
125 printf("\t\tfilename in the new network namespace. The filter file format\n");
126 printf("\t\tis the format of iptables-save and iptable-restore commands.\n\n");
127
128 printf("\t--netstats - monitor network statistics for sandboxes creating a new\n");
129 printf("\t\tnetwork namespace.\n\n");
130 printf("\t--nogroups - disable supplementary groups. Without this option,\n");
131 printf("\t\tsupplementary groups are enabled for the user starting the\n");
132 printf("\t\tsandbox. For root user supplementary groups are always\n");
133 printf("\t\tdisabled.\n\n");
134
135 printf("\t--noroot - install a user namespace with a single user - the current\n");
136 printf("\t\tuser. root user does not exist in the new namespace. This option\n");
137 printf("\t\tis not supported for --chroot and --overlay configurations.\n\n");
138
139 printf("\t--output=logfile - stdout logging and log rotation. Copy stdout to\n");
140 printf("\t\tlogfile, and keep the size of the file under 500KB using log\n");
141 printf("\t\trotation. Five files with prefixes .1 to .5 are used in\n");
142 printf("\t\trotation.\n\n");
143 printf("\t--overlay - mount a filesystem overlay on top of the current filesystem.\n");
144 printf("\t\t(OverlayFS support is required in Linux kernel for this option\n");
145 printf("\t\tto work)\n\n");
146
147 printf("\t--private - mount new /root and /home/user directories in temporary\n");
148 printf("\t\tfilesystems. All modifications are discarded when the sandbox is\n");
149 printf("\t\tclosed.\n\n");
150 printf("\t--private=directory - use directory as user home.\n\n");
151 printf("\t--private.keep=file,directory - build a new user home in a temporary\n");
152 printf("\t\tfilesystem, and copy the files and directories in the list in\n");
153 printf("\t\tthe new home. All modifications are discarded when the sandbox\n");
154 printf("\t\tis closed.\n\n");
155 printf("\t--private-dev - create a new /dev directory. Only null, full, zero, tty,\n");
156 printf("\t\tpst, ptms, random, urandom and shm devices are available.\n\n");
157
158 printf("\t--profile=filename - use a custom profile.\n\n");
159 printf("\t--read-only=dirname_or_filename - set directory or file read-only.\n\n");
160 printf("\t--rlimit-fsize=number - set the maximum file size that can be created\n");
161 printf("\t\tby a process.\n\n");
162 printf("\t--rlimit-nofile=number - set the maximum number of files that can be\n");
163 printf("\t\topened by a process.\n\n");
164 printf("\t--rlimit-nproc=number - set the maximum number of processes that can be\n");
165 printf("\t\tcreated for the real user ID of the calling process.\n\n");
166 printf("\t--rlimit-sigpending=number - set the maximum number of pending signals\n");
167 printf("\t\tfor a process.\n\n");
168
169 printf("\t--scan - ARP-scan all the networks from inside a network namespace.\n");
170 printf("\t\tThis makes it possible to detect macvlan kernel device drivers\n");
171 printf("\t\trunning on the current host.\n\n");
172
173#ifdef HAVE_SECCOMP
174 printf("\t--seccomp - enable seccomp filter and blacklist the syscalls in the\n");
175 printf("\t\tlist. The default list is as follows: mount, umount2,\n");
176 printf("\t\tptrace, kexec_load, open_by_handle_at, init_module,\n");
177 printf("\t\tfinit_module, delete_module, iopl, ioperm, swapon, swapoff,\n");
178 printf("\t\tmknode, syslog, process_vm_readv and process_vm_writev\n");
179 printf("\t\tsysfs,_sysctl, adjtimex, clock_adjtime, lookup_dcookie,\n");
180 printf("\t\tperf_event_open, fanotify_init and kcmp.\n\n");
181
182 printf("\t--seccomp=syscall,syscall,syscall - enable seccomp filter, blacklist the\n");
183 printf("\t\tdefault syscall list and the syscalls specified by the command.\n\n");
184
185 printf("\t--seccomp.drop=syscall,syscall,syscall - enable seccomp filter, and\n");
186 printf("\t\tblacklist the syscalls specified by the command.\n\n");
187
188 printf("\t--seccomp.keep=syscall,syscall,syscall - enable seccomp filter, and\n");
189 printf("\t\twhitelist the syscalls specified by the command.\n\n");
190
191 printf("\t--seccomp.print=name - print the seccomp filter for the sandbox\n");
192 printf("\t\tidentified by name.\n\n");
193 printf("\t--seccomp.print=pid - print the seccomp filter for the sandbox\n");
194 printf("\t\tidentified by PID.\n\n");
195#endif
196
197 printf("\t--shell=none - run the program directly without a user shell.\n\n");
198 printf("\t--shell=program - set default user shell.\n\n");
199 printf("\t--shutdown=name - shutdown the sandbox identified by name.\n\n");
200 printf("\t--shutdown=pid - shutdown the sandbox identified by PID.\n\n");
201 printf("\t--tmpfs=dirname - mount a tmpfs filesystem on directory dirname.\n\n");
202 printf("\t--top - monitor the most CPU-intensive sandboxes.\n\n");
203 printf("\t--trace - trace open, access and connect system calls.\n\n");
204 printf("\t--tree - print a tree of all sandboxed processes.\n\n");
205 printf("\t--version - print program version and exit.\n\n");
206 printf("\t--zsh - use /usr/bin/zsh as default shell.\n\n");
207 printf("\n");
208 printf("\n");
209
210
211 printf("Traffic Shaping\n\n");
212
213 printf("Network bandwidth is an expensive resource shared among all sandboxes\n");
214 printf("running on a system. Traffic shaping allows the user to increase network\n");
215 printf("performance by controlling the amount of data that flows into and out of the\n");
216 printf("sandboxes. Firejail implements a simple rate-limiting shaper based on Linux\n");
217 printf("command tc. The shaper works at sandbox level, and can be used only for\n");
218 printf("sandboxes configured with new network namespaces.\n\n");
219
220 printf("Set rate-limits:\n");
221 printf("\tfirejail --bandwidth={name|pid} set network-name down-speed up-speed\n\n");
222 printf("Clear rate-limits:\n");
223 printf("\tfirejail --bandwidth={name|pid} clear network-name\n\n");
224 printf("Status:\n");
225 printf("\tfirejail --bandwidth={name|pid} status\n\n");
226 printf("where:\n");
227 printf("\tname - sandbox name\n");
228 printf("\tpid - sandbox pid\n");
229 printf("\tnetwork-name - network name as used by --net option\n");
230 printf("\tdown-speed - download speed in KB/s (decimal kilobyte per second)\n");
231 printf("\tup-speed - upload speed in KB/s (decimal kilobyte per second)\n");
232 printf("\n");
233 printf("Example:\n");
234 printf("\t$ firejail --name=mybrowser --net=eth0 firefox &\n");
235 printf("\t$ firejail --bandwidth=mybrowser set eth0 80 20\n");
236 printf("\t$ firejail --bandwidth=mybrowser status\n");
237 printf("\t$ firejail --bandwidth=mybrowser clear eth0\n");
238 printf("\n");
239 printf("\n");
240
241
242
243 printf("Monitoring\n\n");
244
245 printf("Option --list prints a list of all sandboxes. The format for each entry is as\n");
246 printf("follows:\n\n");
247 printf("\tPID:USER:Command\n\n");
248
249 printf("Option --tree prints the tree of processes running in the sandbox. The format\n");
250 printf("for each process entry is as follows:\n\n");
251 printf("\tPID:USER:Command\n\n");
252
253 printf("Option --top is similar to the UNIX top command, however it applies only to\n");
254 printf("sandboxes. Listed below are the available fields (columns) in alphabetical\n");
255 printf("order:\n\n");
256 printf("\tCommand - command used to start the sandbox.\n");
257 printf("\tCPU%% - CPU usage, the sandbox share of the elapsed CPU time since the\n");
258 printf("\t last screen update\n");
259 printf("\tPID - Unique process ID for the task controlling the sandbox.\n");
260 printf("\tPrcs - number of processes running in sandbox, including the controlling\n");
261 printf("\t process.\n");
262 printf("\tRES - Resident Memory Size (KiB), sandbox non-swapped physical memory.\n");
263 printf("\t It is a sum of the RES values for all processes running in the\n");
264 printf("\t sandbox.\n");
265 printf("\tSHR - Shared Memory Size (KiB), it reflects memory shared with other\n");
266 printf("\t processes. It is a sum of the SHR values for all processes running\n");
267 printf("\t in the sandbox, including the controlling process.\n");
268 printf("\tUptime - sandbox running time in hours:minutes:seconds format.\n");
269 printf("\tUser - The owner of the sandbox.\n");
270 printf("\n");
271 printf("\n");
272 printf("Profile files\n\n");
273 printf("Several command line configuration options can be passed to the program using\n");
274 printf("profile files. Default Firejail profile files are stored in /etc/firejail\n");
275 printf("directory, user profile files are stored in ~/.config/firejail directory. See\n");
276 printf("man 5 firejail-profile for more information.\n\n");
277 printf("\n");
278 printf("Restricted shell\n\n");
279 printf("To configure a restricted shell, replace /bin/bash with /usr/bin/firejail i\n");
280 printf("/etc/password file for each user that needs to be restricted.\n");
281 printf("Alternatively, you can specify /usr/bin/firejail in adduser command:\n\n");
282 printf(" adduser --shell /usr/bin/firejail username\n\n");
283 printf("Arguments to be passed to firejail executable upon login are declared in\n");
284 printf("/etc/firejail/login.users file.\n\n");
285 printf("\n");
286 printf("Examples:\n\n");
287 printf(" $ firejail\n");
288 printf(" start a regular /bin/bash session in sandbox\n");
289 printf(" $ firejail firefox\n");
290 printf(" start Mozilla Firefox\n");
291 printf(" $ firejail --seccomp firefox\n");
292 printf(" start Mozilla Firefox in a seccomp sandbox\n");
293 printf(" $ firejail --caps firefox\n");
294 printf(" start Mozilla Firefox in a Linux capabilities sandbox\n");
295 printf(" $ firejail --debug firefox\n");
296 printf(" debug Firefox sandbox\n");
297 printf(" $ firejail --private\n");
298 printf(" start a /bin/bash session with a new tmpfs home directory\n");
299 printf(" $ firejail --net=br0 ip=10.10.20.10\n");
300 printf(" start a /bin/bash session in a new network namespace; the session is\n");
301 printf(" connected to the main network using br0 bridge device, an IP address\n");
302 printf(" of 10.10.20.10 is assigned to the sandbox\n");
303 printf(" $ firejail --net=br0 --net=br1 --net=br2\n");
304 printf(" start a /bin/bash session in a new network namespace and connect it\n");
305 printf(" to br0, br1, and br2 host bridge devices\n");
306 printf(" $ firejail --list\n");
307 printf(" list all running sandboxes\n");
308 printf("\n");
309 printf("License GPL version 2 or later\n");
310 printf("Homepage: http://firejail.sourceforge.net\n");
311 printf("\n");
312}
diff --git a/src/firejail/util.c b/src/firejail/util.c
new file mode 100644
index 000000000..2c50caf17
--- /dev/null
+++ b/src/firejail/util.c
@@ -0,0 +1,480 @@
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#include "firejail.h"
21#include <sys/stat.h>
22#include <fcntl.h>
23#include <syslog.h>
24#include <errno.h>
25#include <dirent.h>
26#include <grp.h>
27
28#define MAX_GROUPS 1024
29// drop privileges
30// - for root group or if nogroups is set, supplementary groups are not configured
31void drop_privs(int nogroups) {
32 gid_t gid = getgid();
33
34 // configure supplementary groups
35 if (gid == 0 || nogroups) {
36 if (setgroups(0, NULL) < 0)
37 errExit("setgroups");
38 if (arg_debug)
39 printf("Username %s, no supplementary groups\n", cfg.username);
40 }
41 else {
42 assert(cfg.username);
43 gid_t groups[MAX_GROUPS];
44 int ngroups = MAX_GROUPS;
45 int rv = getgrouplist(cfg.username, gid, groups, &ngroups);
46
47 if (arg_debug && rv) {
48 printf("Username %s, groups ", cfg.username);
49 int i;
50 for (i = 0; i < ngroups; i++)
51 printf("%u, ", groups[i]);
52 printf("\n");
53 }
54
55 if (rv == -1) {
56 fprintf(stderr, "Warning: cannot extract supplementary group list, dropping them\n");
57 if (setgroups(0, NULL) < 0)
58 errExit("setgroups");
59 }
60 else {
61 rv = setgroups(ngroups, groups);
62 if (rv) {
63 fprintf(stderr, "Warning: cannot set supplementary group list, dropping them\n");
64 if (setgroups(0, NULL) < 0)
65 errExit("setgroups");
66 }
67 }
68 }
69
70 // set uid/gid
71 if (setgid(getgid()) < 0)
72 errExit("setgid/getgid");
73 if (setuid(getuid()) < 0)
74 errExit("setuid/getuid");
75}
76
77
78void logsignal(int s) {
79 if (!arg_debug)
80 return;
81
82 openlog("firejail", LOG_NDELAY | LOG_PID, LOG_USER);
83 syslog(LOG_INFO, "Signal %d caught", s);
84 closelog();
85}
86
87
88void logmsg(const char *msg) {
89 if (!arg_debug)
90 return;
91
92 openlog("firejail", LOG_NDELAY | LOG_PID, LOG_USER);
93 syslog(LOG_INFO, "%s\n", msg);
94 closelog();
95}
96
97
98void logargs(int argc, char **argv) {
99 if (!arg_debug)
100 return;
101
102 int i;
103 int len = 0;
104
105 // calculate message length
106 for (i = 0; i < argc; i++)
107 len += strlen(argv[i]) + 1; // + ' '
108
109 // build message
110 char msg[len + 1];
111 char *ptr = msg;
112 for (i = 0; i < argc; i++) {
113 sprintf(ptr, "%s ", argv[i]);
114 ptr += strlen(ptr);
115 }
116
117 // log message
118 logmsg(msg);
119}
120
121
122void logerr(const char *msg) {
123 if (!arg_debug)
124 return;
125
126 openlog("firejail", LOG_NDELAY | LOG_PID, LOG_USER);
127 syslog(LOG_ERR, "%s\n", msg);
128 closelog();
129}
130
131
132// return -1 if error, 0 if no error
133int copy_file(const char *srcname, const char *destname) {
134 assert(srcname);
135 assert(destname);
136
137 // open source
138 int src = open(srcname, O_RDONLY);
139 if (src < 0) {
140 fprintf(stderr, "Warning: cannot open %s, file not copied\n", srcname);
141 return -1;
142 }
143
144 // open destination
145 int dst = open(destname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
146 if (dst < 0) {
147 fprintf(stderr, "Warning: cannot open %s, file not copied\n", destname);
148 close(src);
149 return -1;
150 }
151
152 // copy
153 ssize_t len;
154 static const int BUFLEN = 1024;
155 unsigned char buf[BUFLEN];
156 while ((len = read(src, buf, BUFLEN)) > 0) {
157 int done = 0;
158 while (done != len) {
159 int rv = write(dst, buf + done, len - done);
160 if (rv == -1) {
161 close(src);
162 close(dst);
163 return -1;
164 }
165
166 done += rv;
167 }
168 }
169
170 close(src);
171 close(dst);
172 return 0;
173}
174
175
176char *get_link(const char *fname) {
177 assert(fname);
178 struct stat sb;
179 char *linkname;
180 ssize_t r;
181
182 if (lstat(fname, &sb) == -1)
183 return NULL;
184
185 linkname = malloc(sb.st_size + 1);
186 if (linkname == NULL)
187 return NULL;
188 memset(linkname, 0, sb.st_size + 1);
189
190 r = readlink(fname, linkname, sb.st_size + 1);
191 if (r < 0) {
192 free(linkname);
193 return NULL;
194 }
195 return linkname;
196}
197
198
199// return 1 if the file is a directory
200int is_dir(const char *fname) {
201 assert(fname);
202 if (*fname == '\0')
203 return 0;
204
205 // if fname doesn't end in '/', add one
206 int rv;
207 struct stat s;
208 if (fname[strlen(fname) - 1] == '/')
209 rv = stat(fname, &s);
210 else {
211 char *tmp;
212 if (asprintf(&tmp, "%s/", fname) == -1) {
213 fprintf(stderr, "Error: cannot allocate memory, %s:%d\n", __FILE__, __LINE__);
214 errExit("asprintf");
215 }
216 rv = stat(tmp, &s);
217 free(tmp);
218 }
219
220 if (rv == -1)
221 return 0;
222
223 if (S_ISDIR(s.st_mode))
224 return 1;
225
226 return 0;
227}
228
229// return 1 if the file is a link
230int is_link(const char *fname) {
231 assert(fname);
232 if (*fname == '\0')
233 return 0;
234
235 struct stat s;
236 if (lstat(fname, &s) == 0) {
237 if (S_ISLNK(s.st_mode))
238 return 1;
239 }
240
241 return 0;
242}
243
244
245// remove multiple spaces and return allocated memory
246char *line_remove_spaces(const char *buf) {
247 assert(buf);
248 if (strlen(buf) == 0)
249 return NULL;
250
251 // allocate memory for the new string
252 char *rv = malloc(strlen(buf) + 1);
253 if (rv == NULL)
254 errExit("malloc");
255
256 // remove space at start of line
257 const char *ptr1 = buf;
258 while (*ptr1 == ' ' || *ptr1 == '\t')
259 ptr1++;
260
261 // copy data and remove additional spaces
262 char *ptr2 = rv;
263 int state = 0;
264 while (*ptr1 != '\0') {
265 if (*ptr1 == '\n' || *ptr1 == '\r')
266 break;
267
268 if (state == 0) {
269 if (*ptr1 != ' ' && *ptr1 != '\t')
270 *ptr2++ = *ptr1++;
271 else {
272 *ptr2++ = ' ';
273 ptr1++;
274 state = 1;
275 }
276 }
277 else { // state == 1
278 while (*ptr1 == ' ' || *ptr1 == '\t')
279 ptr1++;
280 state = 0;
281 }
282 }
283
284 // strip last blank character if any
285 if (*(ptr2 - 1) == ' ')
286 --ptr2;
287 *ptr2 = '\0';
288 // if (arg_debug)
289 // printf("Processing line #%s#\n", rv);
290
291 return rv;
292}
293
294
295char *split_comma(char *str) {
296 if (str == NULL || *str == '\0')
297 return NULL;
298 char *ptr = strchr(str, ',');
299 if (!ptr)
300 return NULL;
301 *ptr = '\0';
302 ptr++;
303 if (*ptr == '\0')
304 return NULL;
305 return ptr;
306}
307
308
309int not_unsigned(const char *str) {
310 int rv = 0;
311 const char *ptr = str;
312 while (*ptr != ' ' && *ptr != '\t' && *ptr != '\0') {
313 if (!isdigit(*ptr)) {
314 rv = 1;
315 break;
316 }
317 ptr++;
318 }
319
320 return rv;
321}
322
323
324#define BUFLEN 4096
325// find the first child for this parent; return 1 if error
326int find_child(pid_t parent, pid_t *child) {
327 *child = 0; // use it to flag a found child
328
329 DIR *dir;
330 if (!(dir = opendir("/proc"))) {
331 // sleep 2 seconds and try again
332 sleep(2);
333 if (!(dir = opendir("/proc"))) {
334 fprintf(stderr, "Error: cannot open /proc directory\n");
335 exit(1);
336 }
337 }
338
339 struct dirent *entry;
340 char *end;
341 while (*child == 0 && (entry = readdir(dir))) {
342 pid_t pid = strtol(entry->d_name, &end, 10);
343 if (end == entry->d_name || *end)
344 continue;
345 if (pid == parent)
346 continue;
347
348 // open stat file
349 char *file;
350 if (asprintf(&file, "/proc/%u/status", pid) == -1) {
351 perror("asprintf");
352 exit(1);
353 }
354 FILE *fp = fopen(file, "r");
355 if (!fp) {
356 free(file);
357 continue;
358 }
359
360 // look for firejail executable name
361 char buf[BUFLEN];
362 while (fgets(buf, BUFLEN - 1, fp)) {
363 if (strncmp(buf, "PPid:", 5) == 0) {
364 char *ptr = buf + 5;
365 while (*ptr != '\0' && (*ptr == ' ' || *ptr == '\t')) {
366 ptr++;
367 }
368 if (*ptr == '\0') {
369 fprintf(stderr, "Error: cannot read /proc file\n");
370 exit(1);
371 }
372 if (parent == atoi(ptr))
373 *child = pid;
374 break; // stop reading the file
375 }
376 }
377 fclose(fp);
378 free(file);
379 }
380 closedir(dir);
381
382 return (*child)? 0:1; // 0 = found, 1 = not found
383}
384
385
386
387void extract_command_name(const char *str) {
388 assert(str);
389 cfg.command_name = strdup(str);
390 if (!cfg.command_name)
391 errExit("strdup");
392
393 // restrict the command name to the first word
394 char *ptr = cfg.command_name;
395 while (*ptr != ' ' && *ptr != '\t' && *ptr != '\0')
396 ptr++;
397 *ptr = '\0';
398
399 // remove the path: /usr/bin/firefox becomes firefox
400 ptr = strrchr(cfg.command_name, '/');
401 if (ptr) {
402 ptr++;
403 if (*ptr == '\0') {
404 fprintf(stderr, "Error: invalid command name\n");
405 exit(1);
406 }
407
408 char *tmp = strdup(ptr);
409 if (!tmp)
410 errExit("strdup");
411 free(cfg.command_name);
412 cfg.command_name = tmp;
413 }
414}
415
416
417void update_map(char *mapping, char *map_file) {
418 int fd, j;
419 size_t map_len; /* Length of 'mapping' */
420
421 /* Replace commas in mapping string with newlines */
422
423 map_len = strlen(mapping);
424 for (j = 0; j < map_len; j++)
425 if (mapping[j] == ',')
426 mapping[j] = '\n';
427
428 fd = open(map_file, O_RDWR);
429 if (fd == -1) {
430 fprintf(stderr, "Error: cannot open %s: %s\n", map_file, strerror(errno));
431 exit(EXIT_FAILURE);
432 }
433
434 if (write(fd, mapping, map_len) != map_len) {
435 fprintf(stderr, "Error: cannot write to %s: %s\n", map_file, strerror(errno));
436 exit(EXIT_FAILURE);
437 }
438
439 close(fd);
440}
441
442
443void wait_for_other(int fd) {
444 //****************************
445 // wait for the parent to be initialized
446 //****************************
447 char childstr[BUFLEN + 1];
448 int newfd = dup(fd);
449 if (newfd == -1)
450 errExit("dup");
451 FILE* stream;
452 stream = fdopen(newfd, "r");
453 *childstr = '\0';
454 if (fgets(childstr, BUFLEN, stream)) {
455 // remove \n)
456 char *ptr = childstr;
457 while(*ptr !='\0' && *ptr != '\n')
458 ptr++;
459 if (*ptr == '\0')
460 errExit("fgets");
461 *ptr = '\0';
462 }
463 else {
464 fprintf(stderr, "Error: cannot establish communication with the parent, exiting...\n");
465 exit(1);
466 }
467 fclose(stream);
468}
469
470
471void notify_other(int fd) {
472 FILE* stream;
473 int newfd = dup(fd);
474 if (newfd == -1)
475 errExit("dup");
476 stream = fdopen(newfd, "w");
477 fprintf(stream, "%u\n", getpid());
478 fflush(stream);
479 fclose(stream);
480}
diff --git a/src/firejail/veth.c b/src/firejail/veth.c
new file mode 100644
index 000000000..ecc31f18d
--- /dev/null
+++ b/src/firejail/veth.c
@@ -0,0 +1,191 @@
1/* code based on iproute2 ip/iplink.c, modified to be included in firejail project
2 *
3 * Original source code:
4 *
5 * Information:
6 * http://www.linuxfoundation.org/collaborate/workgroups/networking/iproute2
7 *
8 * Download:
9 * http://www.kernel.org/pub/linux/utils/net/iproute2/
10 *
11 * Repository:
12 * git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git
13 *
14 * License: GPL v2
15 *
16 * Original copyright header
17 *
18 * iplink.c "ip link".
19 *
20 * This program is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU General Public License
22 * as published by the Free Software Foundation; either version
23 * 2 of the License, or (at your option) any later version.
24 *
25 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
26 *
27 */
28 /*
29 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
30 *
31 * This file is part of firejail project
32 *
33 * This program is free software; you can redistribute it and/or modify
34 * it under the terms of the GNU General Public License as published by
35 * the Free Software Foundation; either version 2 of the License, or
36 * (at your option) any later version.
37 *
38 * This program is distributed in the hope that it will be useful,
39 * but WITHOUT ANY WARRANTY; without even the implied warranty of
40 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41 * GNU General Public License for more details.
42 *
43 * You should have received a copy of the GNU General Public License along
44 * with this program; if not, write to the Free Software Foundation, Inc.,
45 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
46*/
47
48#include "firejail.h"
49#include "../include/libnetlink.h"
50#include <linux/veth.h>
51
52struct iplink_req
53{
54 struct nlmsghdr n;
55 struct ifinfomsg i;
56 char buf[1024];
57};
58
59static struct rtnl_handle rth = { .fd = -1 };
60
61int net_create_veth(const char *dev, const char *nsdev, unsigned pid) {
62 int len;
63 struct iplink_req req;
64
65 if (arg_debug)
66 printf("create veth %s/%s/%u\n", dev, nsdev, pid);
67 assert(dev);
68 assert(nsdev);
69 assert(pid);
70
71 if (rtnl_open(&rth, 0) < 0) {
72 fprintf(stderr, "cannot open netlink\n");
73 exit(1);
74 }
75
76 memset(&req, 0, sizeof(req));
77
78 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
79 req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL;
80 req.n.nlmsg_type = RTM_NEWLINK;
81 req.i.ifi_family = 0;
82
83 if (dev) {
84 len = strlen(dev) + 1;
85 addattr_l(&req.n, sizeof(req), IFLA_IFNAME, dev, len);
86 }
87
88 struct rtattr *linkinfo = NLMSG_TAIL(&req.n);
89 addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
90 addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, "veth", strlen("veth"));
91
92 struct rtattr * data = NLMSG_TAIL(&req.n);
93 addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0);
94
95 struct rtattr * peerdata = NLMSG_TAIL(&req.n);
96 addattr_l (&req.n, sizeof(req), VETH_INFO_PEER, NULL, 0);
97 req.n.nlmsg_len += sizeof(struct ifinfomsg);
98
99 // place the link in the child namespace
100 addattr_l (&req.n, sizeof(req), IFLA_NET_NS_PID, &pid, 4);
101
102 if (nsdev) {
103 int len = strlen(nsdev) + 1;
104 addattr_l(&req.n, sizeof(req), IFLA_IFNAME, nsdev, len);
105 }
106 peerdata->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)peerdata;
107
108 data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data;
109 linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo;
110
111 // send message
112 if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
113 exit(2);
114
115 return 0;
116}
117
118
119int net_create_macvlan(const char *dev, const char *parent, unsigned pid) {
120 int len;
121 struct iplink_req req;
122 if (arg_debug)
123 printf("create macvlan %s, parent %s\n", dev, parent);
124 assert(dev);
125 assert(parent);
126
127 if (rtnl_open(&rth, 0) < 0) {
128 fprintf(stderr, "cannot open netlink\n");
129 exit(1);
130 }
131
132 memset(&req, 0, sizeof(req));
133
134 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
135 req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL;
136 req.n.nlmsg_type = RTM_NEWLINK;
137 req.i.ifi_family = 0;
138
139 // we start with the parent
140 int parent_ifindex = 2;
141 addattr_l(&req.n, sizeof(req), IFLA_LINK, &parent_ifindex, 4);
142
143 // add new interface name
144 len = strlen(dev) + 1;
145 addattr_l(&req.n, sizeof(req), IFLA_IFNAME, dev, len);
146
147 // place the interface in child namespace
148 addattr_l (&req.n, sizeof(req), IFLA_NET_NS_PID, &pid, 4);
149
150
151 // add link info for the new interface
152 struct rtattr *linkinfo = NLMSG_TAIL(&req.n);
153 addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
154 addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, "macvlan", strlen("macvlan"));
155
156 // set macvlan bridge mode
157 struct rtattr * data = NLMSG_TAIL(&req.n);
158 addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0);
159 int macvlan_type = MACVLAN_MODE_BRIDGE;
160 addattr_l (&req.n, sizeof(req), IFLA_INFO_KIND, &macvlan_type, 4);
161
162 data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data;
163// req.n.nlmsg_len += sizeof(struct ifinfomsg);
164
165
166 data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data;
167 linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo;
168
169 // send message
170 if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
171 exit(2);
172
173 return 0;
174}
175
176/*
177int main(int argc, char **argv) {
178 printf("Hello\n");
179
180
181 char *dev = argv[3];
182 char *nsdev = argv[8];
183 unsigned pid;
184 sscanf(argv[10], "%u", &pid);
185
186
187 net_create_veth(dev, nsdev, pid);
188
189 return 0;
190}
191*/ \ No newline at end of file