diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/firejail/Makefile.in | 4 | ||||
-rw-r--r-- | src/firejail/appimage_size.c | 20 | ||||
-rw-r--r-- | src/firejail/firejail.h | 6 | ||||
-rw-r--r-- | src/firejail/network.c | 46 | ||||
-rw-r--r-- | src/firejail/network_main.c | 87 | ||||
-rw-r--r-- | src/fnet/Makefile.in | 43 | ||||
-rw-r--r-- | src/fnet/fnet.h | 40 | ||||
-rw-r--r-- | src/fnet/interface.c | 183 | ||||
-rw-r--r-- | src/fnet/main.c | 63 | ||||
-rw-r--r-- | src/fnet/veth.c (renamed from src/firejail/veth.c) | 8 |
10 files changed, 423 insertions, 77 deletions
diff --git a/src/firejail/Makefile.in b/src/firejail/Makefile.in index fce460906..7d4bcb19b 100644 --- a/src/firejail/Makefile.in +++ b/src/firejail/Makefile.in | |||
@@ -30,11 +30,11 @@ BINOBJS = $(foreach file, $(OBJS), $file) | |||
30 | CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' $(HAVE_X11) $(HAVE_PRIVATE_HOME) $(HAVE_APPARMOR) $(HAVE_OVERLAYFS) $(HAVE_SECCOMP) $(HAVE_GLOBALCFG) $(HAVE_SECCOMP_H) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_BIND) $(HAVE_FILE_TRANSFER) $(HAVE_WHITELIST) -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security | 30 | CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' $(HAVE_X11) $(HAVE_PRIVATE_HOME) $(HAVE_APPARMOR) $(HAVE_OVERLAYFS) $(HAVE_SECCOMP) $(HAVE_GLOBALCFG) $(HAVE_SECCOMP_H) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_BIND) $(HAVE_FILE_TRANSFER) $(HAVE_WHITELIST) -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security |
31 | LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread | 31 | LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread |
32 | 32 | ||
33 | %.o : %.c $(H_FILE_LIST) ../include/common.h ../include/euid_common.h ../include/libnetlink.h ../include/pid.h | 33 | %.o : %.c $(H_FILE_LIST) ../include/common.h ../include/euid_common.h ../include/pid.h |
34 | $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ | 34 | $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ |
35 | 35 | ||
36 | firejail: $(OBJS) ../lib/libnetlink.o ../lib/common.o | 36 | firejail: $(OBJS) ../lib/libnetlink.o ../lib/common.o |
37 | $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/libnetlink.o ../lib/common.o $(LIBS) $(EXTRA_LDFLAGS) | 37 | $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o $(LIBS) $(EXTRA_LDFLAGS) |
38 | 38 | ||
39 | clean:; rm -f *.o firejail firejail.1 firejail.1.gz | 39 | clean:; rm -f *.o firejail firejail.1 firejail.1.gz |
40 | 40 | ||
diff --git a/src/firejail/appimage_size.c b/src/firejail/appimage_size.c index c8b3d28c5..64fff6901 100644 --- a/src/firejail/appimage_size.c +++ b/src/firejail/appimage_size.c | |||
@@ -1,4 +1,23 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2014-2016 Firejail Authors | ||
3 | * | ||
4 | * This file is part of firejail project | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | /* | ||
2 | Compile with: | 21 | Compile with: |
3 | gcc elfsize.c -o elfsize | 22 | gcc elfsize.c -o elfsize |
4 | Example: | 23 | Example: |
@@ -9,7 +28,6 @@ Size of section headers e_shentsize 64 | |||
9 | Number of section headers e_shnum 29 | 28 | Number of section headers e_shnum 29 |
10 | e_shoff + ( e_shentsize * e_shnum ) = 126584 | 29 | e_shoff + ( e_shentsize * e_shnum ) = 126584 |
11 | */ | 30 | */ |
12 | |||
13 | #include <elf.h> | 31 | #include <elf.h> |
14 | #include <byteswap.h> | 32 | #include <byteswap.h> |
15 | #include <stdio.h> | 33 | #include <stdio.h> |
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 9a9bb1ae7..6c0441472 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -362,7 +362,6 @@ void net_if_ip6(const char *ifname, const char *addr6); | |||
362 | int net_get_if_addr(const char *bridge, uint32_t *ip, uint32_t *mask, uint8_t mac[6], int *mtu); | 362 | int net_get_if_addr(const char *bridge, uint32_t *ip, uint32_t *mask, uint8_t mac[6], int *mtu); |
363 | int net_add_route(uint32_t dest, uint32_t mask, uint32_t gw); | 363 | int net_add_route(uint32_t dest, uint32_t mask, uint32_t gw); |
364 | void net_ifprint(void); | 364 | void net_ifprint(void); |
365 | void net_bridge_add_interface(const char *bridge, const char *dev); | ||
366 | uint32_t network_get_defaultgw(void); | 365 | uint32_t network_get_defaultgw(void); |
367 | int net_config_mac(const char *ifname, const unsigned char mac[6]); | 366 | int net_config_mac(const char *ifname, const unsigned char mac[6]); |
368 | int net_get_mac(const char *ifname, unsigned char mac[6]); | 367 | int net_get_mac(const char *ifname, unsigned char mac[6]); |
@@ -432,11 +431,6 @@ uint32_t arp_assign(const char *dev, Bridge *br); | |||
432 | // scan interface (--scan option) | 431 | // scan interface (--scan option) |
433 | void arp_scan(const char *dev, uint32_t srcaddr, uint32_t srcmask); | 432 | void arp_scan(const char *dev, uint32_t srcaddr, uint32_t srcmask); |
434 | 433 | ||
435 | // veth.c | ||
436 | int net_create_veth(const char *dev, const char *nsdev, unsigned pid); | ||
437 | int net_create_macvlan(const char *dev, const char *parent, unsigned pid); | ||
438 | int net_move_interface(const char *dev, unsigned pid); | ||
439 | |||
440 | // util.c | 434 | // util.c |
441 | void drop_privs(int nogroups); | 435 | void drop_privs(int nogroups); |
442 | int mkpath_as_root(const char* path); | 436 | int mkpath_as_root(const char* path); |
diff --git a/src/firejail/network.c b/src/firejail/network.c index 4473ef099..ac0d86559 100644 --- a/src/firejail/network.c +++ b/src/firejail/network.c | |||
@@ -431,52 +431,6 @@ int net_add_route(uint32_t ip, uint32_t mask, uint32_t gw) { | |||
431 | } | 431 | } |
432 | 432 | ||
433 | 433 | ||
434 | // add a veth device to a bridge | ||
435 | void net_bridge_add_interface(const char *bridge, const char *dev) { | ||
436 | if (strlen(bridge) > IFNAMSIZ) { | ||
437 | fprintf(stderr, "Error: invalid network device name %s\n", bridge); | ||
438 | exit(1); | ||
439 | } | ||
440 | |||
441 | // somehow adding the interface to the bridge resets MTU on bridge device!!! | ||
442 | // workaround: restore MTU on the bridge device | ||
443 | // todo: put a real fix in | ||
444 | int mtu1 = net_get_mtu(bridge); | ||
445 | |||
446 | struct ifreq ifr; | ||
447 | int err; | ||
448 | int ifindex = if_nametoindex(dev); | ||
449 | |||
450 | if (ifindex <= 0) | ||
451 | errExit("if_nametoindex"); | ||
452 | |||
453 | int sock; | ||
454 | if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) | ||
455 | errExit("socket"); | ||
456 | |||
457 | memset(&ifr, 0, sizeof(ifr)); | ||
458 | strncpy(ifr.ifr_name, bridge, IFNAMSIZ); | ||
459 | #ifdef SIOCBRADDIF | ||
460 | ifr.ifr_ifindex = ifindex; | ||
461 | err = ioctl(sock, SIOCBRADDIF, &ifr); | ||
462 | if (err < 0) | ||
463 | #endif | ||
464 | { | ||
465 | unsigned long args[4] = { BRCTL_ADD_IF, ifindex, 0, 0 }; | ||
466 | |||
467 | ifr.ifr_data = (char *) args; | ||
468 | err = ioctl(sock, SIOCDEVPRIVATE, &ifr); | ||
469 | } | ||
470 | (void) err; | ||
471 | close(sock); | ||
472 | |||
473 | int mtu2 = net_get_mtu(bridge); | ||
474 | if (mtu1 != mtu2) { | ||
475 | if (arg_debug) | ||
476 | printf("Restoring MTU for %s\n", bridge); | ||
477 | net_set_mtu(bridge, mtu1); | ||
478 | } | ||
479 | } | ||
480 | 434 | ||
481 | #define BUFSIZE 1024 | 435 | #define BUFSIZE 1024 |
482 | uint32_t network_get_defaultgw(void) { | 436 | uint32_t network_get_defaultgw(void) { |
diff --git a/src/firejail/network_main.c b/src/firejail/network_main.c index 907b84642..d2aa84bb6 100644 --- a/src/firejail/network_main.c +++ b/src/firejail/network_main.c | |||
@@ -23,6 +23,50 @@ | |||
23 | #include <sys/stat.h> | 23 | #include <sys/stat.h> |
24 | #include <unistd.h> | 24 | #include <unistd.h> |
25 | #include <net/if.h> | 25 | #include <net/if.h> |
26 | #include <stdarg.h> | ||
27 | |||
28 | static void fnet_run(int num, ...) { | ||
29 | int i; | ||
30 | va_list valist; | ||
31 | va_start(valist, num); | ||
32 | |||
33 | char *fnet; | ||
34 | if (asprintf(&fnet, "%s/firejail/fnet", LIBDIR) == -1) | ||
35 | errExit("asprintf"); | ||
36 | |||
37 | char *arg[num + 2]; | ||
38 | arg[0] = fnet; | ||
39 | for (i = 0; i < num; i++) | ||
40 | arg[i + 1] = va_arg(valist, char*); | ||
41 | arg[i + 1] = NULL; | ||
42 | |||
43 | pid_t child = fork(); | ||
44 | if (child < 0) | ||
45 | errExit("fork"); | ||
46 | if (child == 0) { | ||
47 | // elevate privileges in order to get grsecurity working | ||
48 | if (setreuid(0, 0)) | ||
49 | errExit("setreuid"); | ||
50 | if (setregid(0, 0)) | ||
51 | errExit("setregid"); | ||
52 | |||
53 | execvp(arg[0], arg); | ||
54 | perror("execl"); | ||
55 | _exit(1); | ||
56 | } | ||
57 | |||
58 | int status; | ||
59 | if (waitpid(child, &status, 0) == -1 ) { | ||
60 | errExit("waitpid"); | ||
61 | } | ||
62 | if (WIFEXITED(status) && status != 0) { | ||
63 | fprintf(stderr, "Error: cannot run fnet\n"); | ||
64 | exit(1); | ||
65 | } | ||
66 | |||
67 | va_end(valist); | ||
68 | free(fnet); | ||
69 | } | ||
26 | 70 | ||
27 | // configure bridge structure | 71 | // configure bridge structure |
28 | // - extract ip address and mask from the bridge interface | 72 | // - extract ip address and mask from the bridge interface |
@@ -127,13 +171,12 @@ void net_configure_veth_pair(Bridge *br, const char *ifname, pid_t child) { | |||
127 | else | 171 | else |
128 | dev = br->veth_name; | 172 | dev = br->veth_name; |
129 | 173 | ||
130 | net_create_veth(dev, ifname, child); | 174 | // net_create_veth(dev, ifname, child); |
131 | 175 | char *cstr; | |
132 | // add interface to the bridge | 176 | if (asprintf(&cstr, "%d", child) == -1) |
133 | net_bridge_add_interface(br->dev, dev); | 177 | errExit("asprintf"); |
134 | 178 | fnet_run(6, "create", "veth", dev, ifname, br->dev, cstr); | |
135 | // bring up the interface | 179 | free(cstr); |
136 | net_if_up(dev); | ||
137 | 180 | ||
138 | char *msg; | 181 | char *msg; |
139 | if (asprintf(&msg, "%d.%d.%d.%d address assigned to sandbox", PRINT_IP(br->ipsandbox)) == -1) | 182 | if (asprintf(&msg, "%d.%d.%d.%d address assigned to sandbox", PRINT_IP(br->ipsandbox)) == -1) |
@@ -290,47 +333,61 @@ void net_dns_print(pid_t pid) { | |||
290 | } | 333 | } |
291 | 334 | ||
292 | void network_main(pid_t child) { | 335 | void network_main(pid_t child) { |
336 | char *cstr; | ||
337 | if (asprintf(&cstr, "%d", child) == -1) | ||
338 | errExit("asprintf"); | ||
339 | |||
293 | // create veth pair or macvlan device | 340 | // create veth pair or macvlan device |
294 | if (cfg.bridge0.configured) { | 341 | if (cfg.bridge0.configured) { |
295 | if (cfg.bridge0.macvlan == 0) { | 342 | if (cfg.bridge0.macvlan == 0) { |
296 | net_configure_veth_pair(&cfg.bridge0, "eth0", child); | 343 | net_configure_veth_pair(&cfg.bridge0, "eth0", child); |
297 | } | 344 | } |
298 | else | 345 | else |
299 | net_create_macvlan(cfg.bridge0.devsandbox, cfg.bridge0.dev, child); | 346 | // net_create_macvlan(cfg.bridge0.devsandbox, cfg.bridge0.dev, child); |
347 | fnet_run(5, "create", "macvlan", cfg.bridge0.devsandbox, cfg.bridge0.dev, cstr); | ||
300 | } | 348 | } |
301 | 349 | ||
302 | if (cfg.bridge1.configured) { | 350 | if (cfg.bridge1.configured) { |
303 | if (cfg.bridge1.macvlan == 0) | 351 | if (cfg.bridge1.macvlan == 0) |
304 | net_configure_veth_pair(&cfg.bridge1, "eth1", child); | 352 | net_configure_veth_pair(&cfg.bridge1, "eth1", child); |
305 | else | 353 | else |
306 | net_create_macvlan(cfg.bridge1.devsandbox, cfg.bridge1.dev, child); | 354 | // net_create_macvlan(cfg.bridge1.devsandbox, cfg.bridge1.dev, child); |
355 | fnet_run(5, "create", "macvlan", cfg.bridge1.devsandbox, cfg.bridge1.dev, cstr); | ||
307 | } | 356 | } |
308 | 357 | ||
309 | if (cfg.bridge2.configured) { | 358 | if (cfg.bridge2.configured) { |
310 | if (cfg.bridge2.macvlan == 0) | 359 | if (cfg.bridge2.macvlan == 0) |
311 | net_configure_veth_pair(&cfg.bridge2, "eth2", child); | 360 | net_configure_veth_pair(&cfg.bridge2, "eth2", child); |
312 | else | 361 | else |
313 | net_create_macvlan(cfg.bridge2.devsandbox, cfg.bridge2.dev, child); | 362 | // net_create_macvlan(cfg.bridge2.devsandbox, cfg.bridge2.dev, child); |
363 | fnet_run(5, "create", "macvlan", cfg.bridge2.devsandbox, cfg.bridge2.dev, cstr); | ||
314 | } | 364 | } |
315 | 365 | ||
316 | if (cfg.bridge3.configured) { | 366 | if (cfg.bridge3.configured) { |
317 | if (cfg.bridge3.macvlan == 0) | 367 | if (cfg.bridge3.macvlan == 0) |
318 | net_configure_veth_pair(&cfg.bridge3, "eth3", child); | 368 | net_configure_veth_pair(&cfg.bridge3, "eth3", child); |
319 | else | 369 | else |
320 | net_create_macvlan(cfg.bridge3.devsandbox, cfg.bridge3.dev, child); | 370 | // net_create_macvlan(cfg.bridge3.devsandbox, cfg.bridge3.dev, child); |
371 | fnet_run(5, "create", "macvlan", cfg.bridge3.devsandbox, cfg.bridge3.dev, cstr); | ||
321 | } | 372 | } |
322 | 373 | ||
323 | // move interfaces in sandbox | 374 | // move interfaces in sandbox |
324 | if (cfg.interface0.configured) { | 375 | if (cfg.interface0.configured) { |
325 | net_move_interface(cfg.interface0.dev, child); | 376 | // net_move_interface(cfg.interface0.dev, child); |
377 | fnet_run(3, "moveif", cfg.interface0.dev, cstr); | ||
326 | } | 378 | } |
327 | if (cfg.interface1.configured) { | 379 | if (cfg.interface1.configured) { |
328 | net_move_interface(cfg.interface1.dev, child); | 380 | // net_move_interface(cfg.interface1.dev, child); |
381 | fnet_run(3, "moveif", cfg.interface1.dev, cstr); | ||
329 | } | 382 | } |
330 | if (cfg.interface2.configured) { | 383 | if (cfg.interface2.configured) { |
331 | net_move_interface(cfg.interface2.dev, child); | 384 | // net_move_interface(cfg.interface2.dev, child); |
385 | fnet_run(3, "moveif", cfg.interface3.dev, cstr); | ||
332 | } | 386 | } |
333 | if (cfg.interface3.configured) { | 387 | if (cfg.interface3.configured) { |
334 | net_move_interface(cfg.interface3.dev, child); | 388 | // net_move_interface(cfg.interface3.dev, child); |
389 | fnet_run(3, "moveif", cfg.interface3.dev, cstr); | ||
335 | } | 390 | } |
391 | |||
392 | free(cstr); | ||
336 | } | 393 | } |
diff --git a/src/fnet/Makefile.in b/src/fnet/Makefile.in new file mode 100644 index 000000000..1bfb4c68d --- /dev/null +++ b/src/fnet/Makefile.in | |||
@@ -0,0 +1,43 @@ | |||
1 | all: fnet | ||
2 | |||
3 | prefix=@prefix@ | ||
4 | exec_prefix=@exec_prefix@ | ||
5 | libdir=@libdir@ | ||
6 | sysconfdir=@sysconfdir@ | ||
7 | |||
8 | VERSION=@PACKAGE_VERSION@ | ||
9 | NAME=@PACKAGE_NAME@ | ||
10 | HAVE_SECCOMP_H=@HAVE_SECCOMP_H@ | ||
11 | HAVE_SECCOMP=@HAVE_SECCOMP@ | ||
12 | HAVE_CHROOT=@HAVE_CHROOT@ | ||
13 | HAVE_BIND=@HAVE_BIND@ | ||
14 | HAVE_FATAL_WARNINGS=@HAVE_FATAL_WARNINGS@ | ||
15 | HAVE_NETWORK=@HAVE_NETWORK@ | ||
16 | HAVE_USERNS=@HAVE_USERNS@ | ||
17 | HAVE_X11=@HAVE_X11@ | ||
18 | HAVE_FILE_TRANSFER=@HAVE_FILE_TRANSFER@ | ||
19 | HAVE_WHITELIST=@HAVE_WHITELIST@ | ||
20 | HAVE_GLOBALCFG=@HAVE_GLOBALCFG@ | ||
21 | HAVE_APPARMOR=@HAVE_APPARMOR@ | ||
22 | HAVE_OVERLAYFS=@HAVE_OVERLAYFS@ | ||
23 | HAVE_PRIVATE_HOME=@HAVE_PRIVATE_HOME@ | ||
24 | EXTRA_LDFLAGS +=@EXTRA_LDFLAGS@ | ||
25 | |||
26 | H_FILE_LIST = $(sort $(wildcard *.[h])) | ||
27 | C_FILE_LIST = $(sort $(wildcard *.c)) | ||
28 | OBJS = $(C_FILE_LIST:.c=.o) | ||
29 | BINOBJS = $(foreach file, $(OBJS), $file) | ||
30 | CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' $(HAVE_X11) $(HAVE_PRIVATE_HOME) $(HAVE_APPARMOR) $(HAVE_OVERLAYFS) $(HAVE_SECCOMP) $(HAVE_GLOBALCFG) $(HAVE_SECCOMP_H) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_BIND) $(HAVE_FILE_TRANSFER) $(HAVE_WHITELIST) -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security | ||
31 | LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread | ||
32 | |||
33 | %.o : %.c $(H_FILE_LIST) ../include/common.h ../include/euid_common.h ../include/libnetlink.h ../include/pid.h | ||
34 | $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ | ||
35 | |||
36 | fnet: $(OBJS) ../lib/libnetlink.o ../lib/common.o | ||
37 | $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/libnetlink.o ../lib/common.o $(LIBS) $(EXTRA_LDFLAGS) | ||
38 | |||
39 | clean:; rm -f *.o fnet | ||
40 | |||
41 | distclean: clean | ||
42 | rm -fr Makefile | ||
43 | |||
diff --git a/src/fnet/fnet.h b/src/fnet/fnet.h new file mode 100644 index 000000000..58efbbed5 --- /dev/null +++ b/src/fnet/fnet.h | |||
@@ -0,0 +1,40 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2016 Firejail Authors | ||
3 | * | ||
4 | * This file is part of firejail project | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | #ifndef FNET_H | ||
21 | #define FNET_H | ||
22 | |||
23 | #include <stdio.h> | ||
24 | #include <stdlib.h> | ||
25 | #include <string.h> | ||
26 | #include <assert.h> | ||
27 | #include "../include/common.h" | ||
28 | |||
29 | // veth.c | ||
30 | int net_create_veth(const char *dev, const char *nsdev, unsigned pid); | ||
31 | int net_create_macvlan(const char *dev, const char *parent, unsigned pid); | ||
32 | int net_move_interface(const char *dev, unsigned pid); | ||
33 | |||
34 | // interface.c | ||
35 | void net_bridge_add_interface(const char *bridge, const char *dev); | ||
36 | void net_if_up(const char *ifname); | ||
37 | int net_get_mtu(const char *ifname); | ||
38 | void net_set_mtu(const char *ifname, int mtu); | ||
39 | |||
40 | #endif | ||
diff --git a/src/fnet/interface.c b/src/fnet/interface.c new file mode 100644 index 000000000..b1903dd46 --- /dev/null +++ b/src/fnet/interface.c | |||
@@ -0,0 +1,183 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2016 Firejail Authors | ||
3 | * | ||
4 | * This file is part of firejail project | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | |||
21 | #include "fnet.h" | ||
22 | #include <arpa/inet.h> | ||
23 | #include <sys/socket.h> | ||
24 | #include <sys/ioctl.h> | ||
25 | #include <netdb.h> | ||
26 | #include <ifaddrs.h> | ||
27 | #include <net/if.h> | ||
28 | #include <net/if_arp.h> | ||
29 | #include <net/route.h> | ||
30 | #include <linux/if_bridge.h> | ||
31 | |||
32 | // add a veth device to a bridge | ||
33 | void net_bridge_add_interface(const char *bridge, const char *dev) { | ||
34 | if (strlen(bridge) > IFNAMSIZ) { | ||
35 | fprintf(stderr, "Error fnet: invalid network device name %s\n", bridge); | ||
36 | exit(1); | ||
37 | } | ||
38 | |||
39 | // somehow adding the interface to the bridge resets MTU on bridge device!!! | ||
40 | // workaround: restore MTU on the bridge device | ||
41 | // todo: put a real fix in | ||
42 | int mtu1 = net_get_mtu(bridge); | ||
43 | |||
44 | struct ifreq ifr; | ||
45 | int err; | ||
46 | int ifindex = if_nametoindex(dev); | ||
47 | |||
48 | if (ifindex <= 0) | ||
49 | errExit("if_nametoindex"); | ||
50 | |||
51 | int sock; | ||
52 | if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) | ||
53 | errExit("socket"); | ||
54 | |||
55 | memset(&ifr, 0, sizeof(ifr)); | ||
56 | strncpy(ifr.ifr_name, bridge, IFNAMSIZ); | ||
57 | #ifdef SIOCBRADDIF | ||
58 | ifr.ifr_ifindex = ifindex; | ||
59 | err = ioctl(sock, SIOCBRADDIF, &ifr); | ||
60 | if (err < 0) | ||
61 | #endif | ||
62 | { | ||
63 | unsigned long args[4] = { BRCTL_ADD_IF, ifindex, 0, 0 }; | ||
64 | |||
65 | ifr.ifr_data = (char *) args; | ||
66 | err = ioctl(sock, SIOCDEVPRIVATE, &ifr); | ||
67 | } | ||
68 | (void) err; | ||
69 | close(sock); | ||
70 | |||
71 | int mtu2 = net_get_mtu(bridge); | ||
72 | if (mtu1 != mtu2) { | ||
73 | net_set_mtu(bridge, mtu1); | ||
74 | } | ||
75 | } | ||
76 | |||
77 | |||
78 | // bring interface up | ||
79 | void net_if_up(const char *ifname) { | ||
80 | if (strlen(ifname) > IFNAMSIZ) { | ||
81 | fprintf(stderr, "Error fnet: invalid network device name %s\n", ifname); | ||
82 | exit(1); | ||
83 | } | ||
84 | |||
85 | int sock = socket(AF_INET,SOCK_DGRAM,0); | ||
86 | if (sock < 0) | ||
87 | errExit("socket"); | ||
88 | |||
89 | // get the existing interface flags | ||
90 | struct ifreq ifr; | ||
91 | memset(&ifr, 0, sizeof(ifr)); | ||
92 | strncpy(ifr.ifr_name, ifname, IFNAMSIZ); | ||
93 | ifr.ifr_addr.sa_family = AF_INET; | ||
94 | |||
95 | // read the existing flags | ||
96 | if (ioctl(sock, SIOCGIFFLAGS, &ifr ) < 0) { | ||
97 | close(sock); | ||
98 | printf("Error fnet: cannot bring up interface %s\n", ifname); | ||
99 | errExit("ioctl"); | ||
100 | } | ||
101 | |||
102 | ifr.ifr_flags |= IFF_UP; | ||
103 | |||
104 | // set the new flags | ||
105 | if (ioctl( sock, SIOCSIFFLAGS, &ifr ) < 0) { | ||
106 | close(sock); | ||
107 | printf("Error fnet: cannot bring up interface %s\n", ifname); | ||
108 | errExit("ioctl"); | ||
109 | } | ||
110 | |||
111 | // checking | ||
112 | // read the existing flags | ||
113 | if (ioctl(sock, SIOCGIFFLAGS, &ifr ) < 0) { | ||
114 | close(sock); | ||
115 | printf("Error fnet: cannot bring up interface %s\n", ifname); | ||
116 | errExit("ioctl"); | ||
117 | } | ||
118 | |||
119 | // wait not more than 500ms for the interface to come up | ||
120 | int cnt = 0; | ||
121 | while (cnt < 50) { | ||
122 | usleep(10000); // sleep 10ms | ||
123 | |||
124 | // read the existing flags | ||
125 | if (ioctl(sock, SIOCGIFFLAGS, &ifr ) < 0) { | ||
126 | close(sock); | ||
127 | printf("Error fnet: cannot bring up interface %s\n", ifname); | ||
128 | errExit("ioctl"); | ||
129 | } | ||
130 | if (ifr.ifr_flags & IFF_RUNNING) | ||
131 | break; | ||
132 | cnt++; | ||
133 | } | ||
134 | |||
135 | close(sock); | ||
136 | } | ||
137 | |||
138 | int net_get_mtu(const char *ifname) { | ||
139 | int mtu = 0; | ||
140 | if (strlen(ifname) > IFNAMSIZ) { | ||
141 | fprintf(stderr, "Error fnet: invalid network device name %s\n", ifname); | ||
142 | exit(1); | ||
143 | } | ||
144 | |||
145 | int s; | ||
146 | struct ifreq ifr; | ||
147 | |||
148 | if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) | ||
149 | errExit("socket"); | ||
150 | |||
151 | memset(&ifr, 0, sizeof(ifr)); | ||
152 | ifr.ifr_addr.sa_family = AF_INET; | ||
153 | strncpy(ifr.ifr_name, ifname, IFNAMSIZ); | ||
154 | if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) == 0) | ||
155 | mtu = ifr.ifr_mtu; | ||
156 | close(s); | ||
157 | |||
158 | |||
159 | return mtu; | ||
160 | } | ||
161 | |||
162 | void net_set_mtu(const char *ifname, int mtu) { | ||
163 | if (strlen(ifname) > IFNAMSIZ) { | ||
164 | fprintf(stderr, "Error fnet: invalid network device name %s\n", ifname); | ||
165 | exit(1); | ||
166 | } | ||
167 | |||
168 | int s; | ||
169 | struct ifreq ifr; | ||
170 | |||
171 | if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) | ||
172 | errExit("socket"); | ||
173 | |||
174 | memset(&ifr, 0, sizeof(ifr)); | ||
175 | ifr.ifr_addr.sa_family = AF_INET; | ||
176 | strncpy(ifr.ifr_name, ifname, IFNAMSIZ); | ||
177 | ifr.ifr_mtu = mtu; | ||
178 | if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) != 0) | ||
179 | fprintf(stderr, "Warning fnet: cannot set mtu for interface %s\n", ifname); | ||
180 | close(s); | ||
181 | } | ||
182 | |||
183 | |||
diff --git a/src/fnet/main.c b/src/fnet/main.c new file mode 100644 index 000000000..ae780c2ea --- /dev/null +++ b/src/fnet/main.c | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2016 Firejail Authors | ||
3 | * | ||
4 | * This file is part of firejail project | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | #include <stdio.h> | ||
21 | #include <stdlib.h> | ||
22 | #include <errno.h> | ||
23 | #include <sys/prctl.h> | ||
24 | #include <linux/capability.h> | ||
25 | |||
26 | static void usage(void) { | ||
27 | printf("Usage:\n"); | ||
28 | printf("\tfnet create veth dev1 dev2 bridge child\n"); | ||
29 | printf("\tfnet create macvlan dev parent child\n"); | ||
30 | printf("\tfnet moveif dev proc\n"); | ||
31 | } | ||
32 | |||
33 | int main(int argc, char **argv) { | ||
34 | if (argc < 2) | ||
35 | return 1; | ||
36 | |||
37 | if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") ==0) { | ||
38 | usage(); | ||
39 | return 0; | ||
40 | } | ||
41 | else if (argc == 7 && strcmp(argv[1], "create") == 0 && strcmp(argv[2], "veth") == 0) { | ||
42 | // create veth pair and move one end in the the namespace | ||
43 | net_create_veth(argv[3], argv[4], atoi(argv[6])); | ||
44 | |||
45 | // connect the ohter veth end to the bridge ... | ||
46 | net_bridge_add_interface(argv[5], argv[3]); | ||
47 | |||
48 | // ... and bring it up | ||
49 | net_if_up(argv[3]); | ||
50 | } | ||
51 | else if (argc == 6 && strcmp(argv[1], "create") == 0 && strcmp(argv[2], "macvlan") == 0) { | ||
52 | net_create_macvlan(argv[3], argv[4], atoi(argv[5])); | ||
53 | } | ||
54 | else if (argc == 4 && strcmp(argv[1], "moveif") == 0) { | ||
55 | net_move_interface(argv[2], atoi(argv[3])); | ||
56 | } | ||
57 | else { | ||
58 | fprintf(stderr, "Error fnet: invalid arguments\n"); | ||
59 | return 1; | ||
60 | } | ||
61 | |||
62 | return 0; | ||
63 | } | ||
diff --git a/src/firejail/veth.c b/src/fnet/veth.c index df3c1d1f9..d06bc9256 100644 --- a/src/firejail/veth.c +++ b/src/fnet/veth.c | |||
@@ -45,7 +45,7 @@ | |||
45 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | 45 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
46 | */ | 46 | */ |
47 | 47 | ||
48 | #include "firejail.h" | 48 | #include "fnet.h" |
49 | #include "../include/libnetlink.h" | 49 | #include "../include/libnetlink.h" |
50 | #include <linux/veth.h> | 50 | #include <linux/veth.h> |
51 | #include <net/if.h> | 51 | #include <net/if.h> |
@@ -63,8 +63,6 @@ int net_create_veth(const char *dev, const char *nsdev, unsigned pid) { | |||
63 | int len; | 63 | int len; |
64 | struct iplink_req req; | 64 | struct iplink_req req; |
65 | 65 | ||
66 | if (arg_debug) | ||
67 | printf("create veth %s/%s/%u\n", dev, nsdev, pid); | ||
68 | assert(dev); | 66 | assert(dev); |
69 | assert(nsdev); | 67 | assert(nsdev); |
70 | assert(pid); | 68 | assert(pid); |
@@ -120,8 +118,6 @@ int net_create_veth(const char *dev, const char *nsdev, unsigned pid) { | |||
120 | int net_create_macvlan(const char *dev, const char *parent, unsigned pid) { | 118 | int net_create_macvlan(const char *dev, const char *parent, unsigned pid) { |
121 | int len; | 119 | int len; |
122 | struct iplink_req req; | 120 | struct iplink_req req; |
123 | if (arg_debug) | ||
124 | printf("create macvlan %s, parent %s\n", dev, parent); | ||
125 | assert(dev); | 121 | assert(dev); |
126 | assert(parent); | 122 | assert(parent); |
127 | 123 | ||
@@ -184,8 +180,6 @@ int net_create_macvlan(const char *dev, const char *parent, unsigned pid) { | |||
184 | // when the interface is moved, netlink does not preserve interface configuration | 180 | // when the interface is moved, netlink does not preserve interface configuration |
185 | int net_move_interface(const char *dev, unsigned pid) { | 181 | int net_move_interface(const char *dev, unsigned pid) { |
186 | struct iplink_req req; | 182 | struct iplink_req req; |
187 | if (arg_debug) | ||
188 | printf("move device %s inside the namespace\n", dev); | ||
189 | assert(dev); | 183 | assert(dev); |
190 | 184 | ||
191 | if (rtnl_open(&rth, 0) < 0) { | 185 | if (rtnl_open(&rth, 0) < 0) { |