diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/firejail/firejail.h | 1 | ||||
-rw-r--r-- | src/firejail/main.c | 35 | ||||
-rw-r--r-- | src/firejail/network_main.c | 99 | ||||
-rw-r--r-- | src/firejail/profile.c | 7 |
4 files changed, 70 insertions, 72 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 0654439d6..0faf10340 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -408,7 +408,6 @@ int sandbox(void* sandbox_arg); | |||
408 | void start_application(int no_sandbox); | 408 | void start_application(int no_sandbox); |
409 | 409 | ||
410 | // network_main.c | 410 | // network_main.c |
411 | void net_configure_bridge(Bridge *br, char *dev_name); | ||
412 | void net_configure_sandbox_ip(Bridge *br); | 411 | void net_configure_sandbox_ip(Bridge *br); |
413 | void net_configure_veth_pair(Bridge *br, const char *ifname, pid_t child); | 412 | void net_configure_veth_pair(Bridge *br, const char *ifname, pid_t child); |
414 | void net_check_cfg(void); | 413 | void net_check_cfg(void); |
diff --git a/src/firejail/main.c b/src/firejail/main.c index 42ed504f9..8e4fc6f38 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -265,7 +265,7 @@ static void check_network(Bridge *br) { | |||
265 | assert(br); | 265 | assert(br); |
266 | if (br->macvlan == 0) // for bridge devices check network range or arp-scan and assign address | 266 | if (br->macvlan == 0) // for bridge devices check network range or arp-scan and assign address |
267 | net_configure_sandbox_ip(br); | 267 | net_configure_sandbox_ip(br); |
268 | else if (br->ipsandbox && br->ip && br->mask) { // for macvlan check network range | 268 | else if (br->ipsandbox) { // for macvlan check network range |
269 | char *rv = in_netrange(br->ipsandbox, br->ip, br->mask); | 269 | char *rv = in_netrange(br->ipsandbox, br->ip, br->mask); |
270 | if (rv) { | 270 | if (rv) { |
271 | fprintf(stderr, "%s", rv); | 271 | fprintf(stderr, "%s", rv); |
@@ -1848,7 +1848,8 @@ int main(int argc, char **argv) { | |||
1848 | fprintf(stderr, "Error: maximum 4 network devices are allowed\n"); | 1848 | fprintf(stderr, "Error: maximum 4 network devices are allowed\n"); |
1849 | return 1; | 1849 | return 1; |
1850 | } | 1850 | } |
1851 | net_configure_bridge(br, argv[i] + 6); | 1851 | br->dev = argv[i] + 6; |
1852 | br->configured = 1; | ||
1852 | } | 1853 | } |
1853 | else | 1854 | else |
1854 | exit_err_feature("networking"); | 1855 | exit_err_feature("networking"); |
@@ -1913,10 +1914,6 @@ int main(int argc, char **argv) { | |||
1913 | fprintf(stderr, "Error: invalid IP range\n"); | 1914 | fprintf(stderr, "Error: invalid IP range\n"); |
1914 | return 1; | 1915 | return 1; |
1915 | } | 1916 | } |
1916 | if (in_netrange(br->iprange_start, br->ip, br->mask) || in_netrange(br->iprange_end, br->ip, br->mask)) { | ||
1917 | fprintf(stderr, "Error: IP range addresses not in network range\n"); | ||
1918 | return 1; | ||
1919 | } | ||
1920 | } | 1917 | } |
1921 | else | 1918 | else |
1922 | exit_err_feature("networking"); | 1919 | exit_err_feature("networking"); |
@@ -1994,26 +1991,16 @@ int main(int argc, char **argv) { | |||
1994 | fprintf(stderr, "Error: no network device configured\n"); | 1991 | fprintf(stderr, "Error: no network device configured\n"); |
1995 | exit(1); | 1992 | exit(1); |
1996 | } | 1993 | } |
1997 | if (br->arg_ip_none || br->masksandbox) { | 1994 | if (br->arg_ip_none || br->mask) { |
1998 | fprintf(stderr, "Error: cannot configure the network mask twice for the same interface\n"); | 1995 | fprintf(stderr, "Error: cannot configure the network mask twice for the same interface\n"); |
1999 | exit(1); | 1996 | exit(1); |
2000 | } | 1997 | } |
2001 | 1998 | ||
2002 | // configure this network mask for the last bridge defined | 1999 | // configure this network mask for the last bridge defined |
2003 | if (atoip(argv[i] + 10, &br->masksandbox)) { | 2000 | if (atoip(argv[i] + 10, &br->mask)) { |
2004 | fprintf(stderr, "Error: invalid network mask\n"); | 2001 | fprintf(stderr, "Error: invalid network mask\n"); |
2005 | exit(1); | 2002 | exit(1); |
2006 | } | 2003 | } |
2007 | |||
2008 | // if the bridge is not configured, use this mask as the bridge mask | ||
2009 | if (br->mask == 0) | ||
2010 | br->mask = br->masksandbox; | ||
2011 | else { | ||
2012 | fprintf(stderr, "Error: interface %s already has a network mask defined; " | ||
2013 | "please remove --netmask\n", | ||
2014 | br->dev); | ||
2015 | exit(1); | ||
2016 | } | ||
2017 | } | 2004 | } |
2018 | else | 2005 | else |
2019 | exit_err_feature("networking"); | 2006 | exit_err_feature("networking"); |
@@ -2431,10 +2418,14 @@ int main(int argc, char **argv) { | |||
2431 | flock(lockfd_network, LOCK_EX); | 2418 | flock(lockfd_network, LOCK_EX); |
2432 | } | 2419 | } |
2433 | 2420 | ||
2434 | check_network(&cfg.bridge0); | 2421 | if (cfg.bridge0.configured && cfg.bridge0.arg_ip_none == 0) |
2435 | check_network(&cfg.bridge1); | 2422 | check_network(&cfg.bridge0); |
2436 | check_network(&cfg.bridge2); | 2423 | if (cfg.bridge1.configured && cfg.bridge1.arg_ip_none == 0) |
2437 | check_network(&cfg.bridge3); | 2424 | check_network(&cfg.bridge1); |
2425 | if (cfg.bridge2.configured && cfg.bridge2.arg_ip_none == 0) | ||
2426 | check_network(&cfg.bridge2); | ||
2427 | if (cfg.bridge3.configured && cfg.bridge3.arg_ip_none == 0) | ||
2428 | check_network(&cfg.bridge3); | ||
2438 | 2429 | ||
2439 | // save network mapping in shared memory | 2430 | // save network mapping in shared memory |
2440 | network_set_run_file(sandbox_pid); | 2431 | network_set_run_file(sandbox_pid); |
diff --git a/src/firejail/network_main.c b/src/firejail/network_main.c index 488615bda..e30d07229 100644 --- a/src/firejail/network_main.c +++ b/src/firejail/network_main.c | |||
@@ -28,11 +28,9 @@ | |||
28 | 28 | ||
29 | // configure bridge structure | 29 | // configure bridge structure |
30 | // - extract ip address and mask from the bridge interface | 30 | // - extract ip address and mask from the bridge interface |
31 | void net_configure_bridge(Bridge *br, char *dev_name) { | 31 | static void net_configure_bridge(Bridge *br) { |
32 | assert(br); | 32 | assert(br); |
33 | assert(dev_name); | 33 | assert(br->dev); |
34 | |||
35 | br->dev = dev_name; | ||
36 | 34 | ||
37 | // check the bridge device exists | 35 | // check the bridge device exists |
38 | char sysbridge[30 + strlen(br->dev)]; | 36 | char sysbridge[30 + strlen(br->dev)]; |
@@ -58,22 +56,23 @@ void net_configure_bridge(Bridge *br, char *dev_name) { | |||
58 | } | 56 | } |
59 | } | 57 | } |
60 | 58 | ||
61 | // allow unconfigured interfaces | 59 | int mtu = br->mtu; // preserve mtu value in case the user changed it with --mtu |
62 | if (net_get_if_addr(br->dev, &br->ip, &br->mask, br->mac, &br->mtu)) { | 60 | if (net_get_if_addr(br->dev, &br->ip, &br->mask, br->mac, &br->mtu)) |
61 | // allow unconfigured interfaces | ||
63 | fwarning("the network interface %s is not configured\n", br->dev); | 62 | fwarning("the network interface %s is not configured\n", br->dev); |
64 | // don't configure an ip address on unconfigured interfaces | 63 | if (mtu) |
65 | // br->arg_ip_none = 1; | 64 | br->mtu = mtu; |
65 | |||
66 | if (arg_debug) { | ||
67 | if (br->macvlan == 0) | ||
68 | printf("Bridge device %s at %d.%d.%d.%d/%d\n", | ||
69 | br->dev, PRINT_IP(br->ip), mask2bits(br->mask)); | ||
70 | else | ||
71 | printf("macvlan parent device %s at %d.%d.%d.%d/%d\n", | ||
72 | br->dev, PRINT_IP(br->ip), mask2bits(br->mask)); | ||
66 | } | 73 | } |
67 | else { | ||
68 | if (arg_debug) { | ||
69 | if (br->macvlan == 0) | ||
70 | printf("Bridge device %s at %d.%d.%d.%d/%d\n", | ||
71 | br->dev, PRINT_IP(br->ip), mask2bits(br->mask)); | ||
72 | else | ||
73 | printf("macvlan parent device %s at %d.%d.%d.%d/%d\n", | ||
74 | br->dev, PRINT_IP(br->ip), mask2bits(br->mask)); | ||
75 | } | ||
76 | 74 | ||
75 | if (br->mask) { | ||
77 | uint32_t range = ~br->mask + 1; // the number of potential addresses | 76 | uint32_t range = ~br->mask + 1; // the number of potential addresses |
78 | // this software is not supported for /31 networks | 77 | // this software is not supported for /31 networks |
79 | if (range < 4) { | 78 | if (range < 4) { |
@@ -82,7 +81,31 @@ void net_configure_bridge(Bridge *br, char *dev_name) { | |||
82 | } | 81 | } |
83 | } | 82 | } |
84 | 83 | ||
85 | br->configured = 1; | 84 | |
85 | // no interface network mask - no ip address will be configured | ||
86 | if (br->mask == 0) | ||
87 | goto err_no_ip; | ||
88 | // no interface ip - extract the network address from the address configured by the user | ||
89 | else if (br->ip == 0 && br->ipsandbox) | ||
90 | br->ip = br->ipsandbox & br->mask; | ||
91 | // no interface ip - extract the network address from the default gateway configured by the user | ||
92 | else if (br->ip == 0 && cfg.defaultgw) | ||
93 | br->ip = cfg.defaultgw & br->mask; | ||
94 | // no ip address will be configured | ||
95 | else if (br->ip == 0) | ||
96 | goto err_no_ip; | ||
97 | |||
98 | if ((br->iprange_start && in_netrange(br->iprange_start, br->ip, br->mask)) || | ||
99 | (br->iprange_end && in_netrange(br->iprange_end, br->ip, br->mask))) { | ||
100 | fprintf(stderr, "Error: IP range addresses not in network range\n"); | ||
101 | exit(1); | ||
102 | } | ||
103 | |||
104 | return; | ||
105 | |||
106 | err_no_ip: | ||
107 | br->arg_ip_none = 1; | ||
108 | fwarning("Not enough information to configure an IP address for\n interface --net=%s\n", br->dev); | ||
86 | } | 109 | } |
87 | 110 | ||
88 | 111 | ||
@@ -93,7 +116,7 @@ void net_configure_sandbox_ip(Bridge *br) { | |||
93 | 116 | ||
94 | if (br->arg_ip_none) | 117 | if (br->arg_ip_none) |
95 | br->ipsandbox = 0; | 118 | br->ipsandbox = 0; |
96 | else if (br->ipsandbox && br->ip && br->mask) { | 119 | else if (br->ipsandbox) { |
97 | // check network range | 120 | // check network range |
98 | char *rv = in_netrange(br->ipsandbox, br->ip, br->mask); | 121 | char *rv = in_netrange(br->ipsandbox, br->ip, br->mask); |
99 | if (rv) { | 122 | if (rv) { |
@@ -106,20 +129,9 @@ void net_configure_sandbox_ip(Bridge *br) { | |||
106 | exit(1); | 129 | exit(1); |
107 | } | 130 | } |
108 | } | 131 | } |
109 | else if (br->ipsandbox && br->masksandbox) { | 132 | else |
110 | // send an ARP request and check if there is anybody on this IP address | ||
111 | if (arp_check(br->dev, br->ipsandbox)) { | ||
112 | fprintf(stderr, "Error: IP address %d.%d.%d.%d is already in use\n", PRINT_IP(br->ipsandbox)); | ||
113 | exit(1); | ||
114 | } | ||
115 | } | ||
116 | else if (br->ip && br->mask) | ||
117 | // ip address assigned by arp-scan for a bridge device | 133 | // ip address assigned by arp-scan for a bridge device |
118 | br->ipsandbox = arp_assign(br->dev, br); //br->ip, br->mask); | 134 | br->ipsandbox = arp_assign(br->dev, br); //br->ip, br->mask); |
119 | else { | ||
120 | br->ipsandbox = 0; | ||
121 | br->arg_ip_none = 1; | ||
122 | } | ||
123 | } | 135 | } |
124 | 136 | ||
125 | 137 | ||
@@ -159,31 +171,22 @@ void net_configure_veth_pair(Bridge *br, const char *ifname, pid_t child) { | |||
159 | // the default address should be in the range of at least on of the bridge devices | 171 | // the default address should be in the range of at least on of the bridge devices |
160 | void check_default_gw(uint32_t defaultgw) { | 172 | void check_default_gw(uint32_t defaultgw) { |
161 | assert(defaultgw); | 173 | assert(defaultgw); |
162 | |||
163 | if (cfg.bridge0.configured) { | 174 | if (cfg.bridge0.configured) { |
164 | if (cfg.bridge0.ip == 0 && cfg.bridge0.ipsandbox) | ||
165 | return; | ||
166 | char *rv = in_netrange(defaultgw, cfg.bridge0.ip, cfg.bridge0.mask); | 175 | char *rv = in_netrange(defaultgw, cfg.bridge0.ip, cfg.bridge0.mask); |
167 | if (rv == 0) | 176 | if (rv == 0) |
168 | return; | 177 | return; |
169 | } | 178 | } |
170 | if (cfg.bridge1.configured) { | 179 | if (cfg.bridge1.configured) { |
171 | if (cfg.bridge1.ip == 0 && cfg.bridge1.ipsandbox) | ||
172 | return; | ||
173 | char *rv = in_netrange(defaultgw, cfg.bridge1.ip, cfg.bridge1.mask); | 180 | char *rv = in_netrange(defaultgw, cfg.bridge1.ip, cfg.bridge1.mask); |
174 | if (rv == 0) | 181 | if (rv == 0) |
175 | return; | 182 | return; |
176 | } | 183 | } |
177 | if (cfg.bridge2.configured) { | 184 | if (cfg.bridge2.configured) { |
178 | if (cfg.bridge2.ip == 0 && cfg.bridge2.ipsandbox) | ||
179 | return; | ||
180 | char *rv = in_netrange(defaultgw, cfg.bridge2.ip, cfg.bridge2.mask); | 185 | char *rv = in_netrange(defaultgw, cfg.bridge2.ip, cfg.bridge2.mask); |
181 | if (rv == 0) | 186 | if (rv == 0) |
182 | return; | 187 | return; |
183 | } | 188 | } |
184 | if (cfg.bridge3.configured) { | 189 | if (cfg.bridge3.configured) { |
185 | if (cfg.bridge3.ip == 0 && cfg.bridge3.ipsandbox) | ||
186 | return; | ||
187 | char *rv = in_netrange(defaultgw, cfg.bridge3.ip, cfg.bridge3.mask); | 190 | char *rv = in_netrange(defaultgw, cfg.bridge3.ip, cfg.bridge3.mask); |
188 | if (rv == 0) | 191 | if (rv == 0) |
189 | return; | 192 | return; |
@@ -196,14 +199,22 @@ void check_default_gw(uint32_t defaultgw) { | |||
196 | void net_check_cfg(void) { | 199 | void net_check_cfg(void) { |
197 | EUID_ASSERT(); | 200 | EUID_ASSERT(); |
198 | int net_configured = 0; | 201 | int net_configured = 0; |
199 | if (cfg.bridge0.configured) | 202 | if (cfg.bridge0.configured) { |
203 | net_configure_bridge(&cfg.bridge0); | ||
200 | net_configured++; | 204 | net_configured++; |
201 | if (cfg.bridge1.configured) | 205 | } |
206 | if (cfg.bridge1.configured) { | ||
207 | net_configure_bridge(&cfg.bridge1); | ||
202 | net_configured++; | 208 | net_configured++; |
203 | if (cfg.bridge2.configured) | 209 | } |
210 | if (cfg.bridge2.configured) { | ||
211 | net_configure_bridge(&cfg.bridge2); | ||
204 | net_configured++; | 212 | net_configured++; |
205 | if (cfg.bridge3.configured) | 213 | } |
214 | if (cfg.bridge3.configured) { | ||
215 | net_configure_bridge(&cfg.bridge3); | ||
206 | net_configured++; | 216 | net_configured++; |
217 | } | ||
207 | 218 | ||
208 | int if_configured = 0; | 219 | int if_configured = 0; |
209 | if (cfg.interface0.configured) | 220 | if (cfg.interface0.configured) |
diff --git a/src/firejail/profile.c b/src/firejail/profile.c index fc575d4b5..425f8f5c9 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c | |||
@@ -358,7 +358,8 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
358 | fprintf(stderr, "Error: maximum 4 network devices are allowed\n"); | 358 | fprintf(stderr, "Error: maximum 4 network devices are allowed\n"); |
359 | exit(1); | 359 | exit(1); |
360 | } | 360 | } |
361 | net_configure_bridge(br, ptr + 4); | 361 | br->dev = ptr + 4; |
362 | br->configured = 1; | ||
362 | } | 363 | } |
363 | else | 364 | else |
364 | warning_feature_disabled("networking"); | 365 | warning_feature_disabled("networking"); |
@@ -423,10 +424,6 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
423 | fprintf(stderr, "Error: invalid IP range\n"); | 424 | fprintf(stderr, "Error: invalid IP range\n"); |
424 | exit(1); | 425 | exit(1); |
425 | } | 426 | } |
426 | if (in_netrange(br->iprange_start, br->ip, br->mask) || in_netrange(br->iprange_end, br->ip, br->mask)) { | ||
427 | fprintf(stderr, "Error: IP range addresses not in network range\n"); | ||
428 | exit(1); | ||
429 | } | ||
430 | } | 427 | } |
431 | else | 428 | else |
432 | warning_feature_disabled("networking"); | 429 | warning_feature_disabled("networking"); |