aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.in4
-rwxr-xr-xconfigure3
-rw-r--r--configure.ac2
-rw-r--r--src/firejail/Makefile.in4
-rw-r--r--src/firejail/appimage_size.c20
-rw-r--r--src/firejail/firejail.h6
-rw-r--r--src/firejail/network.c46
-rw-r--r--src/firejail/network_main.c87
-rw-r--r--src/fnet/Makefile.in43
-rw-r--r--src/fnet/fnet.h40
-rw-r--r--src/fnet/interface.c183
-rw-r--r--src/fnet/main.c63
-rw-r--r--src/fnet/veth.c (renamed from src/firejail/veth.c)8
13 files changed, 429 insertions, 80 deletions
diff --git a/Makefile.in b/Makefile.in
index dbf53e2cb..0ae8fc903 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,6 +1,6 @@
1all: apps man 1all: apps man
2MYLIBS = src/lib 2MYLIBS = src/lib
3APPS = src/firejail src/firemon src/firecfg src/libtrace src/libtracelog src/ftee src/faudit src/libconnect 3APPS = src/firejail src/firemon src/firecfg src/libtrace src/libtracelog src/ftee src/faudit src/libconnect src/fnet
4MANPAGES = firejail.1 firemon.1 firecfg.1 firejail-profile.5 firejail-login.5 4MANPAGES = firejail.1 firemon.1 firecfg.1 firejail-profile.5 firejail-login.5
5 5
6prefix=@prefix@ 6prefix=@prefix@
@@ -76,6 +76,7 @@ realinstall:
76 install -c -m 0755 src/fshaper/fshaper.sh $(DESTDIR)/$(libdir)/firejail/. 76 install -c -m 0755 src/fshaper/fshaper.sh $(DESTDIR)/$(libdir)/firejail/.
77 install -c -m 0644 src/firecfg/firecfg.config $(DESTDIR)/$(libdir)/firejail/. 77 install -c -m 0644 src/firecfg/firecfg.config $(DESTDIR)/$(libdir)/firejail/.
78 install -c -m 0755 src/faudit/faudit $(DESTDIR)/$(libdir)/firejail/. 78 install -c -m 0755 src/faudit/faudit $(DESTDIR)/$(libdir)/firejail/.
79 install -c -m 0755 src/fnet/fnet $(DESTDIR)/$(libdir)/firejail/.
79 # documents 80 # documents
80 install -m 0755 -d $(DESTDIR)/$(DOCDIR) 81 install -m 0755 -d $(DESTDIR)/$(DOCDIR)
81 install -c -m 0644 COPYING $(DESTDIR)/$(DOCDIR)/. 82 install -c -m 0644 COPYING $(DESTDIR)/$(DOCDIR)/.
@@ -124,6 +125,7 @@ install-strip: all
124 strip src/libconnect/libconnect.so 125 strip src/libconnect/libconnect.so
125 strip src/ftee/ftee 126 strip src/ftee/ftee
126 strip src/faudit/faudit 127 strip src/faudit/faudit
128 strip src/fnet/fnet
127 $(MAKE) realinstall 129 $(MAKE) realinstall
128 130
129uninstall: 131uninstall:
diff --git a/configure b/configure
index a470dffba..58d236815 100755
--- a/configure
+++ b/configure
@@ -3759,7 +3759,7 @@ if test "$prefix" = /usr; then
3759 sysconfdir="/etc" 3759 sysconfdir="/etc"
3760fi 3760fi
3761 3761
3762ac_config_files="$ac_config_files Makefile src/lib/Makefile src/firejail/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/ftee/Makefile src/faudit/Makefile src/libconnect/Makefile" 3762ac_config_files="$ac_config_files Makefile src/lib/Makefile src/fnet/Makefile src/firejail/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/ftee/Makefile src/faudit/Makefile src/libconnect/Makefile"
3763 3763
3764cat >confcache <<\_ACEOF 3764cat >confcache <<\_ACEOF
3765# This file is a shell script that caches the results of configure 3765# This file is a shell script that caches the results of configure
@@ -4470,6 +4470,7 @@ do
4470 case $ac_config_target in 4470 case $ac_config_target in
4471 "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; 4471 "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
4472 "src/lib/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib/Makefile" ;; 4472 "src/lib/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib/Makefile" ;;
4473 "src/fnet/Makefile") CONFIG_FILES="$CONFIG_FILES src/fnet/Makefile" ;;
4473 "src/firejail/Makefile") CONFIG_FILES="$CONFIG_FILES src/firejail/Makefile" ;; 4474 "src/firejail/Makefile") CONFIG_FILES="$CONFIG_FILES src/firejail/Makefile" ;;
4474 "src/firemon/Makefile") CONFIG_FILES="$CONFIG_FILES src/firemon/Makefile" ;; 4475 "src/firemon/Makefile") CONFIG_FILES="$CONFIG_FILES src/firemon/Makefile" ;;
4475 "src/libtrace/Makefile") CONFIG_FILES="$CONFIG_FILES src/libtrace/Makefile" ;; 4476 "src/libtrace/Makefile") CONFIG_FILES="$CONFIG_FILES src/libtrace/Makefile" ;;
diff --git a/configure.ac b/configure.ac
index 95947a8e3..c7125e9c5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -148,7 +148,7 @@ if test "$prefix" = /usr; then
148 sysconfdir="/etc" 148 sysconfdir="/etc"
149fi 149fi
150 150
151AC_OUTPUT(Makefile src/lib/Makefile src/firejail/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/ftee/Makefile src/faudit/Makefile src/libconnect/Makefile) 151AC_OUTPUT(Makefile src/lib/Makefile src/fnet/Makefile src/firejail/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/ftee/Makefile src/faudit/Makefile src/libconnect/Makefile)
152 152
153echo 153echo
154echo "Configuration options:" 154echo "Configuration options:"
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)
30CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' $(HAVE_X11) $(HAVE_PRIVATE_HOME) $(HAVE_APPARMOR) $(HAVE_OVERLAYFS) $(HAVE_SECCOMP) $(HAVE_GLOBALCFG) $(HAVE_SECCOMP_H) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_BIND) $(HAVE_FILE_TRANSFER) $(HAVE_WHITELIST) -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security 30CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' $(HAVE_X11) $(HAVE_PRIVATE_HOME) $(HAVE_APPARMOR) $(HAVE_OVERLAYFS) $(HAVE_SECCOMP) $(HAVE_GLOBALCFG) $(HAVE_SECCOMP_H) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_BIND) $(HAVE_FILE_TRANSFER) $(HAVE_WHITELIST) -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security
31LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread 31LDFLAGS += -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
36firejail: $(OBJS) ../lib/libnetlink.o ../lib/common.o 36firejail: $(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
39clean:; rm -f *.o firejail firejail.1 firejail.1.gz 39clean:; 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/*
2Compile with: 21Compile with:
3gcc elfsize.c -o elfsize 22gcc elfsize.c -o elfsize
4Example: 23Example:
@@ -9,7 +28,6 @@ Size of section headers e_shentsize 64
9Number of section headers e_shnum 29 28Number of section headers e_shnum 29
10e_shoff + ( e_shentsize * e_shnum ) = 126584 29e_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);
362int net_get_if_addr(const char *bridge, uint32_t *ip, uint32_t *mask, uint8_t mac[6], int *mtu); 362int net_get_if_addr(const char *bridge, uint32_t *ip, uint32_t *mask, uint8_t mac[6], int *mtu);
363int net_add_route(uint32_t dest, uint32_t mask, uint32_t gw); 363int net_add_route(uint32_t dest, uint32_t mask, uint32_t gw);
364void net_ifprint(void); 364void net_ifprint(void);
365void net_bridge_add_interface(const char *bridge, const char *dev);
366uint32_t network_get_defaultgw(void); 365uint32_t network_get_defaultgw(void);
367int net_config_mac(const char *ifname, const unsigned char mac[6]); 366int net_config_mac(const char *ifname, const unsigned char mac[6]);
368int net_get_mac(const char *ifname, unsigned char mac[6]); 367int 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)
433void arp_scan(const char *dev, uint32_t srcaddr, uint32_t srcmask); 432void arp_scan(const char *dev, uint32_t srcaddr, uint32_t srcmask);
434 433
435// veth.c
436int net_create_veth(const char *dev, const char *nsdev, unsigned pid);
437int net_create_macvlan(const char *dev, const char *parent, unsigned pid);
438int net_move_interface(const char *dev, unsigned pid);
439
440// util.c 434// util.c
441void drop_privs(int nogroups); 435void drop_privs(int nogroups);
442int mkpath_as_root(const char* path); 436int 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
435void 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
482uint32_t network_get_defaultgw(void) { 436uint32_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
28static 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
292void network_main(pid_t child) { 335void 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 @@
1all: fnet
2
3prefix=@prefix@
4exec_prefix=@exec_prefix@
5libdir=@libdir@
6sysconfdir=@sysconfdir@
7
8VERSION=@PACKAGE_VERSION@
9NAME=@PACKAGE_NAME@
10HAVE_SECCOMP_H=@HAVE_SECCOMP_H@
11HAVE_SECCOMP=@HAVE_SECCOMP@
12HAVE_CHROOT=@HAVE_CHROOT@
13HAVE_BIND=@HAVE_BIND@
14HAVE_FATAL_WARNINGS=@HAVE_FATAL_WARNINGS@
15HAVE_NETWORK=@HAVE_NETWORK@
16HAVE_USERNS=@HAVE_USERNS@
17HAVE_X11=@HAVE_X11@
18HAVE_FILE_TRANSFER=@HAVE_FILE_TRANSFER@
19HAVE_WHITELIST=@HAVE_WHITELIST@
20HAVE_GLOBALCFG=@HAVE_GLOBALCFG@
21HAVE_APPARMOR=@HAVE_APPARMOR@
22HAVE_OVERLAYFS=@HAVE_OVERLAYFS@
23HAVE_PRIVATE_HOME=@HAVE_PRIVATE_HOME@
24EXTRA_LDFLAGS +=@EXTRA_LDFLAGS@
25
26H_FILE_LIST = $(sort $(wildcard *.[h]))
27C_FILE_LIST = $(sort $(wildcard *.c))
28OBJS = $(C_FILE_LIST:.c=.o)
29BINOBJS = $(foreach file, $(OBJS), $file)
30CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' $(HAVE_X11) $(HAVE_PRIVATE_HOME) $(HAVE_APPARMOR) $(HAVE_OVERLAYFS) $(HAVE_SECCOMP) $(HAVE_GLOBALCFG) $(HAVE_SECCOMP_H) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_BIND) $(HAVE_FILE_TRANSFER) $(HAVE_WHITELIST) -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security
31LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread
32
33%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/euid_common.h ../include/libnetlink.h ../include/pid.h
34 $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
35
36fnet: $(OBJS) ../lib/libnetlink.o ../lib/common.o
37 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/libnetlink.o ../lib/common.o $(LIBS) $(EXTRA_LDFLAGS)
38
39clean:; rm -f *.o fnet
40
41distclean: 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
30int net_create_veth(const char *dev, const char *nsdev, unsigned pid);
31int net_create_macvlan(const char *dev, const char *parent, unsigned pid);
32int net_move_interface(const char *dev, unsigned pid);
33
34// interface.c
35void net_bridge_add_interface(const char *bridge, const char *dev);
36void net_if_up(const char *ifname);
37int net_get_mtu(const char *ifname);
38void 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
33void 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
79void 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
138int 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
162void 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
26static 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
33int 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) {
120int net_create_macvlan(const char *dev, const char *parent, unsigned pid) { 118int 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
185int net_move_interface(const char *dev, unsigned pid) { 181int 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) {