aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/firejail/firejail.h2
-rw-r--r--src/firejail/main.c7
-rw-r--r--src/firejail/netfilter.c111
-rw-r--r--src/firejail/profile.c8
-rw-r--r--src/firejail/sandbox.c3
-rw-r--r--src/firejail/usage.c3
-rw-r--r--src/man/firejail.txt6
7 files changed, 137 insertions, 3 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index 15110607d..6b497559d 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -215,7 +215,9 @@ extern int arg_rlimit_sigpending;// rlimit sigpending
215extern int arg_nogroups; // disable supplementary groups 215extern int arg_nogroups; // disable supplementary groups
216extern int arg_noroot; // create a new user namespace and disable root user 216extern int arg_noroot; // create a new user namespace and disable root user
217extern int arg_netfilter; // enable netfilter 217extern int arg_netfilter; // enable netfilter
218extern int arg_netfilter6; // enable netfilter6
218extern char *arg_netfilter_file; // netfilter file 219extern char *arg_netfilter_file; // netfilter file
220extern char *arg_netfilter6_file; // netfilter file
219extern int arg_doubledash; // double dash 221extern int arg_doubledash; // double dash
220extern int arg_shell_none; // run the program directly without a shell 222extern int arg_shell_none; // run the program directly without a shell
221extern int arg_private_dev; // private dev directory 223extern int arg_private_dev; // private dev directory
diff --git a/src/firejail/main.c b/src/firejail/main.c
index 7b493a351..246ee4bba 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -77,7 +77,9 @@ int arg_rlimit_sigpending = 0; // rlimit fsize
77int arg_nogroups = 0; // disable supplementary groups 77int arg_nogroups = 0; // disable supplementary groups
78int arg_noroot = 0; // create a new user namespace and disable root user 78int arg_noroot = 0; // create a new user namespace and disable root user
79int arg_netfilter; // enable netfilter 79int arg_netfilter; // enable netfilter
80int arg_netfilter6; // enable netfilter6
80char *arg_netfilter_file = NULL; // netfilter file 81char *arg_netfilter_file = NULL; // netfilter file
82char *arg_netfilter6_file = NULL; // netfilter6 file
81int arg_doubledash = 0; // double dash 83int arg_doubledash = 0; // double dash
82int arg_shell_none = 0; // run the program directly without a shell 84int arg_shell_none = 0; // run the program directly without a shell
83int arg_private_dev = 0; // private dev directory 85int arg_private_dev = 0; // private dev directory
@@ -1147,6 +1149,11 @@ int main(int argc, char **argv) {
1147 arg_netfilter_file = argv[i] + 12; 1149 arg_netfilter_file = argv[i] + 12;
1148 check_netfilter_file(arg_netfilter_file); 1150 check_netfilter_file(arg_netfilter_file);
1149 } 1151 }
1152 else if (strncmp(argv[i], "--netfilter6=", 13) == 0) {
1153 arg_netfilter6 = 1;
1154 arg_netfilter6_file = argv[i] + 13;
1155 check_netfilter_file(arg_netfilter6_file);
1156 }
1150 1157
1151 //************************************* 1158 //*************************************
1152 // command 1159 // command
diff --git a/src/firejail/netfilter.c b/src/firejail/netfilter.c
index 3f667c871..70fd8801f 100644
--- a/src/firejail/netfilter.c
+++ b/src/firejail/netfilter.c
@@ -64,7 +64,7 @@ void netfilter(const char *fname) {
64 // buffer the filter 64 // buffer the filter
65 struct stat s; 65 struct stat s;
66 if (stat(fname, &s) == -1) { 66 if (stat(fname, &s) == -1) {
67 fprintf(stderr, "Error: cannot find network filter file\n"); 67 fprintf(stderr, "Error: cannot find network filter file %s\n", fname);
68 exit(1); 68 exit(1);
69 } 69 }
70 70
@@ -76,13 +76,13 @@ void netfilter(const char *fname) {
76 /* coverity[toctou] */ 76 /* coverity[toctou] */
77 FILE *fp = fopen(fname, "r"); 77 FILE *fp = fopen(fname, "r");
78 if (!fp) { 78 if (!fp) {
79 fprintf(stderr, "Error: cannot open network filter file\n"); 79 fprintf(stderr, "Error: cannot open network filter file %s\n", fname);
80 exit(1); 80 exit(1);
81 } 81 }
82 82
83 size_t sz = fread(filter, 1, s.st_size, fp); 83 size_t sz = fread(filter, 1, s.st_size, fp);
84 if ((off_t)sz != s.st_size) { 84 if ((off_t)sz != s.st_size) {
85 fprintf(stderr, "Error: cannot read network filter file\n"); 85 fprintf(stderr, "Error: cannot read network filter file %s\n", fname);
86 exit(1); 86 exit(1);
87 } 87 }
88 fclose(fp); 88 fclose(fp);
@@ -164,3 +164,108 @@ doexit:
164 if (allocated) 164 if (allocated)
165 free(filter); 165 free(filter);
166} 166}
167
168void netfilter6(const char *fname) {
169 if (fname == NULL)
170 return;
171
172 char *filter;
173
174 // buffer the filter
175 struct stat s;
176 if (stat(fname, &s) == -1) {
177 fprintf(stderr, "Error: cannot find network filter file %s\n", fname);
178 exit(1);
179 }
180
181 filter = malloc(s.st_size + 1); // + '\0'
182 if (!filter)
183 errExit("malloc");
184 memset(filter, 0, s.st_size + 1);
185
186 /* coverity[toctou] */
187 FILE *fp = fopen(fname, "r");
188 if (!fp) {
189 fprintf(stderr, "Error: cannot open network filter file %s\n", fname);
190 exit(1);
191 }
192
193 size_t sz = fread(filter, 1, s.st_size, fp);
194 if ((off_t)sz != s.st_size) {
195 fprintf(stderr, "Error: cannot read network filter file %s\n", fname);
196 exit(1);
197 }
198 fclose(fp);
199
200 // temporarily mount a tempfs on top of /tmp directory
201 if (mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
202 errExit("mounting /tmp");
203
204 // create the filter file
205 fp = fopen("/tmp/netfilter6", "w");
206 if (!fp) {
207 fprintf(stderr, "Error: cannot open /tmp/netfilter6 file\n");
208 exit(1);
209 }
210 fprintf(fp, "%s\n", filter);
211 fclose(fp);
212
213 // find iptables command
214 char *ip6tables = NULL;
215 char *ip6tables_restore = NULL;
216 if (stat("/sbin/ip6tables", &s) == 0) {
217 ip6tables = "/sbin/ip6tables";
218 ip6tables_restore = "/sbin/ip6tables-restore";
219 }
220 else if (stat("/usr/sbin/ip6tables", &s) == 0) {
221 ip6tables = "/usr/sbin/ip6tables";
222 ip6tables_restore = "/usr/sbin/ip6tables-restore";
223 }
224 if (ip6tables == NULL || ip6tables_restore == NULL) {
225 fprintf(stderr, "Error: ip6tables command not found\n");
226 goto doexit;
227 }
228
229 // push filter
230 pid_t child = fork();
231 if (child < 0)
232 errExit("fork");
233 if (child == 0) {
234 if (arg_debug)
235 printf("Installing network filter:\n%s\n", filter);
236
237 int fd;
238 if((fd = open("/tmp/netfilter6", O_RDONLY)) == -1) {
239 fprintf(stderr,"Error: cannot open /tmp/netfilter6\n");
240 exit(1);
241 }
242 dup2(fd,STDIN_FILENO);
243 close(fd);
244
245 // wipe out environment variables
246 environ = NULL;
247 execl(ip6tables_restore, ip6tables_restore, NULL);
248 // it will never get here!!!
249 }
250 // wait for the child to finish
251 waitpid(child, NULL, 0);
252
253 // debug
254 if (arg_debug) {
255 child = fork();
256 if (child < 0)
257 errExit("fork");
258 if (child == 0) {
259 environ = NULL;
260 execl(ip6tables, ip6tables, "-vL", NULL);
261 // it will never get here!!!
262 }
263 // wait for the child to finish
264 waitpid(child, NULL, 0);
265 }
266
267doexit:
268 // unmount /tmp
269 umount("/tmp");
270 free(filter);
271}
diff --git a/src/firejail/profile.c b/src/firejail/profile.c
index 0f6d49868..6286bfe0f 100644
--- a/src/firejail/profile.c
+++ b/src/firejail/profile.c
@@ -157,6 +157,14 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
157 check_netfilter_file(arg_netfilter_file); 157 check_netfilter_file(arg_netfilter_file);
158 return 0; 158 return 0;
159 } 159 }
160 else if (strncmp(ptr, "netfilter6 ", 11) == 0) {
161 arg_netfilter6 = 1;
162 arg_netfilter6_file = strdup(ptr + 11);
163 if (!arg_netfilter6_file)
164 errExit("strdup");
165 check_netfilter_file(arg_netfilter6_file);
166 return 0;
167 }
160 else if (strcmp(ptr, "net none") == 0) { 168 else if (strcmp(ptr, "net none") == 0) {
161 arg_nonetwork = 1; 169 arg_nonetwork = 1;
162 cfg.bridge0.configured = 0; 170 cfg.bridge0.configured = 0;
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c
index ac0f62dab..e317579e9 100644
--- a/src/firejail/sandbox.c
+++ b/src/firejail/sandbox.c
@@ -322,6 +322,9 @@ int sandbox(void* sandbox_arg) {
322 if (arg_netfilter && any_bridge_configured()) { // assuming by default the client filter 322 if (arg_netfilter && any_bridge_configured()) { // assuming by default the client filter
323 netfilter(arg_netfilter_file); 323 netfilter(arg_netfilter_file);
324 } 324 }
325 if (arg_netfilter6 && any_bridge_configured()) { // assuming by default the client filter
326 netfilter6(arg_netfilter6_file);
327 }
325 328
326 // load IBUS env variables 329 // load IBUS env variables
327 if (arg_nonetwork || any_bridge_configured() || any_interface_configured()) { 330 if (arg_nonetwork || any_bridge_configured() || any_interface_configured()) {
diff --git a/src/firejail/usage.c b/src/firejail/usage.c
index 5eab05076..07ab04021 100644
--- a/src/firejail/usage.c
+++ b/src/firejail/usage.c
@@ -149,6 +149,9 @@ void usage(void) {
149 printf("\t--netfilter=filename - enable the network filter specified by\n"); 149 printf("\t--netfilter=filename - enable the network filter specified by\n");
150 printf("\t\tfilename in the new network namespace. The filter file format\n"); 150 printf("\t\tfilename in the new network namespace. The filter file format\n");
151 printf("\t\tis the format of iptables-save and iptable-restore commands.\n\n"); 151 printf("\t\tis the format of iptables-save and iptable-restore commands.\n\n");
152 printf("\t--netfilter6=filename - enable the IPv6 network filter specified by\n");
153 printf("\t\tfilename in the new network namespace. The filter file format\n");
154 printf("\t\tis the format of ip6tables-save and ip6table-restore commands.\n\n");
152 155
153 printf("\t--netstats - monitor network statistics for sandboxes creating a new\n"); 156 printf("\t--netstats - monitor network statistics for sandboxes creating a new\n");
154 printf("\t\tnetwork namespace.\n\n"); 157 printf("\t\tnetwork namespace.\n\n");
diff --git a/src/man/firejail.txt b/src/man/firejail.txt
index c8dd7d786..75e962b56 100644
--- a/src/man/firejail.txt
+++ b/src/man/firejail.txt
@@ -691,6 +691,12 @@ $ firejail --netfilter=/etc/firejail/nolocal.net \\
691.br 691.br
692--net=eth0 firefox 692--net=eth0 firefox
693.TP 693.TP
694\fB\-\-netfilter6=filename
695Enable the IPv6 network filter specified by filename in the new network namespace. The filter file format
696is the format of ip6tables-save and ip6table-restore commands.
697New network namespaces are created using \-\-net option. If a new network namespaces is not created,
698\-\-netfilter6 option does nothing.
699.TP
694\fB\-\-netstats 700\fB\-\-netstats
695Monitor network namespace statistics, see \fBMONITORING\fR section for more details. 701Monitor network namespace statistics, see \fBMONITORING\fR section for more details.
696.br 702.br