aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--README.md14
-rw-r--r--RELNOTES2
-rw-r--r--src/firejail/firejail.h4
-rw-r--r--src/firejail/main.c12
-rw-r--r--src/firejail/netfilter.c91
-rw-r--r--src/firejail/usage.c6
-rw-r--r--src/firejail/util.c43
-rw-r--r--src/man/firejail.txt52
-rwxr-xr-xtest/network/ip6.exp16
-rwxr-xr-xtest/network/net_netfilter.exp6
11 files changed, 167 insertions, 80 deletions
diff --git a/.gitignore b/.gitignore
index 0882eeecf..52a2718ee 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,6 +22,7 @@ src/ftee/ftee
22src/tags 22src/tags
23src/faudit/faudit 23src/faudit/faudit
24src/fnet/fnet 24src/fnet/fnet
25src/fnetfilter/fnetfilter
25src/fseccomp/fseccomp 26src/fseccomp/fseccomp
26src/fcopy/fcopy 27src/fcopy/fcopy
27src/fldd/fldd 28src/fldd/fldd
diff --git a/README.md b/README.md
index 839afef67..924b2ddb3 100644
--- a/README.md
+++ b/README.md
@@ -210,6 +210,20 @@ $
210 --debug-private-lib 210 --debug-private-lib
211 Debug messages for --private-lib option. 211 Debug messages for --private-lib option.
212 212
213 --netfilter.print=name|pid
214 Print the firewall installed in the sandbox specified by name
215 or PID. Example:
216
217 $ firejail --net=browser --net=eth0 --netfilter firefox &
218 $ firejail --netfilter.print=browser
219
220 --netfilter6.print=name|pid
221 Print the IPv6 firewall installed in the sandbox specified by
222 name or PID. Example:
223
224 $ firejail --net=browser --net=eth0 --netfilter firefox &
225 $ firejail --netfilter6.print=browser
226
213````` 227`````
214 228
215## New profiles: 229## New profiles:
diff --git a/RELNOTES b/RELNOTES
index 785cfadc3..db156546c 100644
--- a/RELNOTES
+++ b/RELNOTES
@@ -25,6 +25,8 @@ firejail (0.9.51) baseline; urgency=low
25 * feature: --rlimit-cpu 25 * feature: --rlimit-cpu
26 * feature: --timeout 26 * feature: --timeout
27 * feature: profile build tool (--build) 27 * feature: profile build tool (--build)
28 * feature: --netfilter.print
29 * feature: --netfilter6.print
28 * new profiles: upstreamed many profiles from the following sources: 30 * new profiles: upstreamed many profiles from the following sources:
29 https://github.com/chiraag-nataraj/firejail-profiles, 31 https://github.com/chiraag-nataraj/firejail-profiles,
30 https://github.com/nyancat18/fe, 32 https://github.com/nyancat18/fe,
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index ab3c13598..f7bebe1b6 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -516,7 +516,6 @@ void create_empty_dir_as_root(const char *dir, mode_t mode);
516void create_empty_file_as_root(const char *dir, mode_t mode); 516void create_empty_file_as_root(const char *dir, mode_t mode);
517int set_perms(const char *fname, uid_t uid, gid_t gid, mode_t mode); 517int set_perms(const char *fname, uid_t uid, gid_t gid, mode_t mode);
518void mkdir_attr(const char *fname, mode_t mode, uid_t uid, gid_t gid); 518void mkdir_attr(const char *fname, mode_t mode, uid_t uid, gid_t gid);
519char *read_text_file_or_exit(const char *fname);
520unsigned extract_timeout(const char *str); 519unsigned extract_timeout(const char *str);
521 520
522// fs_var.c 521// fs_var.c
@@ -607,6 +606,7 @@ void check_output(int argc, char **argv);
607void check_netfilter_file(const char *fname); 606void check_netfilter_file(const char *fname);
608void netfilter(const char *fname); 607void netfilter(const char *fname);
609void netfilter6(const char *fname); 608void netfilter6(const char *fname);
609void netfilter_print(pid_t pid, int ipv6);
610 610
611// netns.c 611// netns.c
612void check_netns(const char *nsname); 612void check_netns(const char *nsname);
@@ -766,7 +766,7 @@ void build_appimage_cmdline(char **command_line, char **window_title, int argc,
766// sbox.c 766// sbox.c
767// programs 767// programs
768#define PATH_FNET (LIBDIR "/firejail/fnet") 768#define PATH_FNET (LIBDIR "/firejail/fnet")
769#define PATH_FNETFILTER (LIBDIR "/firejail/fnetfilter#define PATH_FNET (LIBDIR "/firejail/fnet") 769#define PATH_FNETFILTER (LIBDIR "/firejail/fnetfilter")
770#define PATH_FIREMON (PREFIX "/bin/firemon") 770#define PATH_FIREMON (PREFIX "/bin/firemon")
771#define PATH_FIREJAIL (PREFIX "/bin/firejail") 771#define PATH_FIREJAIL (PREFIX "/bin/firejail")
772#define PATH_FSECCOMP (LIBDIR "/firejail/fseccomp") 772#define PATH_FSECCOMP (LIBDIR "/firejail/fseccomp")
diff --git a/src/firejail/main.c b/src/firejail/main.c
index c8b347b5f..d6b0a230e 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -429,6 +429,18 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
429 exit_err_feature("networking"); 429 exit_err_feature("networking");
430 exit(0); 430 exit(0);
431 } 431 }
432 else if (strncmp(argv[i], "--netfilter.print=", 18) == 0) {
433 // extract pid or sandbox name
434 pid_t pid = read_pid(argv[i] + 18);
435 netfilter_print(pid, 0);
436 exit(0);
437 }
438 else if (strncmp(argv[i], "--netfilter6.print=", 19) == 0) {
439 // extract pid or sandbox name
440 pid_t pid = read_pid(argv[i] + 19);
441 netfilter_print(pid, 1);
442 exit(0);
443 }
432#endif 444#endif
433 //************************************* 445 //*************************************
434 // independent commands - the program will exit! 446 // independent commands - the program will exit!
diff --git a/src/firejail/netfilter.c b/src/firejail/netfilter.c
index 517d0462f..e1d0edd01 100644
--- a/src/firejail/netfilter.c
+++ b/src/firejail/netfilter.c
@@ -63,6 +63,9 @@ void netfilter(const char *fname) {
63 return; 63 return;
64 } 64 }
65 65
66 if (arg_debug)
67 printf("Installing firewall\n");
68
66 // create an empty user-owned SBOX_STDIN_FILE 69 // create an empty user-owned SBOX_STDIN_FILE
67 create_empty_file_as_root(SBOX_STDIN_FILE, 0644); 70 create_empty_file_as_root(SBOX_STDIN_FILE, 0644);
68 if (set_perms(SBOX_STDIN_FILE, getuid(), getgid(), 0644)) 71 if (set_perms(SBOX_STDIN_FILE, getuid(), getgid(), 0644))
@@ -106,19 +109,15 @@ void netfilter6(const char *fname) {
106 return; 109 return;
107 } 110 }
108 111
109 // create the filter file
110 char *filter = read_text_file_or_exit(fname);
111 FILE *fp = fopen(SBOX_STDIN_FILE, "w");
112 if (!fp) {
113 fprintf(stderr, "Error: cannot open %s\n", SBOX_STDIN_FILE);
114 exit(1);
115 }
116 fprintf(fp, "%s\n", filter);
117 fclose(fp);
118
119 // push filter
120 if (arg_debug) 112 if (arg_debug)
121 printf("Installing network filter:\n%s\n", filter); 113 printf("Installing IPv6 firewall\n");
114
115 // create an empty user-owned SBOX_STDIN_FILE
116 create_empty_file_as_root(SBOX_STDIN_FILE, 0644);
117 if (set_perms(SBOX_STDIN_FILE, getuid(), getgid(), 0644))
118 errExit("set_perms");
119
120 sbox_run(SBOX_USER| SBOX_CAPS_NONE | SBOX_SECCOMP, 3, PATH_FNETFILTER, fname, SBOX_STDIN_FILE);
122 121
123 // first run of iptables on this platform installs a number of kernel modules such as ip_tables, x_tables, iptable_filter 122 // first run of iptables on this platform installs a number of kernel modules such as ip_tables, x_tables, iptable_filter
124 // we run this command with caps and seccomp disabled in order to allow the loading of these modules 123 // we run this command with caps and seccomp disabled in order to allow the loading of these modules
@@ -129,6 +128,72 @@ void netfilter6(const char *fname) {
129 if (arg_debug) 128 if (arg_debug)
130 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 2, ip6tables, "-vL"); 129 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 2, ip6tables, "-vL");
131 130
132 free(filter);
133 return; 131 return;
134} 132}
133
134void netfilter_print(pid_t pid, int ipv6) {
135 EUID_ASSERT();
136
137 // verify sandbox
138 EUID_ROOT();
139 char *comm = pid_proc_comm(pid);
140 EUID_USER();
141 if (!comm) {
142 fprintf(stderr, "Error: cannot find sandbox\n");
143 exit(1);
144 }
145
146 // check for firejail sandbox
147 if (strcmp(comm, "firejail") != 0) {
148 fprintf(stderr, "Error: cannot find sandbox\n");
149 exit(1);
150 }
151 free(comm);
152
153 // check network namespace
154 char *name;
155 if (asprintf(&name, "/run/firejail/network/%d-netmap", pid) == -1)
156 errExit("asprintf");
157 struct stat s;
158 if (stat(name, &s) == -1) {
159 fprintf(stderr, "Error: the sandbox doesn't use a new network namespace\n");
160 exit(1);
161 }
162
163 // join the network namespace
164 pid_t child;
165 if (find_child(pid, &child) == -1) {
166 fprintf(stderr, "Error: cannot join the network namespace\n");
167 exit(1);
168 }
169
170 EUID_ROOT();
171 if (join_namespace(child, "net")) {
172 fprintf(stderr, "Error: cannot join the network namespace\n");
173 exit(1);
174 }
175
176 // find iptables executable
177 char *iptables = NULL;
178 char *iptables_restore = NULL;
179 if (ipv6) {
180 if (stat("/sbin/ip6tables", &s) == 0)
181 iptables = "/sbin/ip6tables";
182 else if (stat("/usr/sbin/ip6tables", &s) == 0)
183 iptables = "/usr/sbin/ip6tables";
184 }
185 else {
186 if (stat("/sbin/iptables", &s) == 0)
187 iptables = "/sbin/iptables";
188 else if (stat("/usr/sbin/iptables", &s) == 0)
189 iptables = "/usr/sbin/iptables";
190 }
191
192 if (iptables == NULL) {
193 fprintf(stderr, "Error: iptables command not found\n");
194 exit(1);
195 }
196
197 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 2, iptables, "-vL");
198}
199
diff --git a/src/firejail/usage.c b/src/firejail/usage.c
index 38de99471..f1581e847 100644
--- a/src/firejail/usage.c
+++ b/src/firejail/usage.c
@@ -122,8 +122,10 @@ void usage(void) {
122 printf(" --net=ethernet_interface - enable network namespaces and connect to this\n"); 122 printf(" --net=ethernet_interface - enable network namespaces and connect to this\n");
123 printf("\tEthernet interface.\n"); 123 printf("\tEthernet interface.\n");
124 printf(" --net=none - enable a new, unconnected network namespace.\n"); 124 printf(" --net=none - enable a new, unconnected network namespace.\n");
125 printf(" --netfilter[=filename] - enable the default client network filter.\n"); 125 printf(" --netfilter[=filename] - enable firewall.\n");
126 printf(" --netfilter6=filename - enable the IPv6 network filter.\n"); 126 printf(" --netfilter.print=name|pid - print the firewall.\n");
127 printf(" --netfilter6=filename - enable IPv6 firewall.\n");
128 printf(" --netfilter6.print=name|pid - print the IPv6 firewall.\n");
127 printf(" --netns=name - Run the program in a named, persistent network namespace.\n"); 129 printf(" --netns=name - Run the program in a named, persistent network namespace.\n");
128 printf(" --netstats - monitor network statistics.\n"); 130 printf(" --netstats - monitor network statistics.\n");
129#endif 131#endif
diff --git a/src/firejail/util.c b/src/firejail/util.c
index cea2b76e3..fde180e49 100644
--- a/src/firejail/util.c
+++ b/src/firejail/util.c
@@ -908,49 +908,6 @@ void mkdir_attr(const char *fname, mode_t mode, uid_t uid, gid_t gid) {
908 ASSERT_PERMS(fname, uid, gid, mode); 908 ASSERT_PERMS(fname, uid, gid, mode);
909} 909}
910 910
911char *read_text_file_or_exit(const char *fname) {
912 assert(fname);
913
914 // open file
915 int fd = open(fname, O_RDONLY);
916 if (fd == -1) {
917 fprintf(stderr, "Error: cannot read %s\n", fname);
918 exit(1);
919 }
920
921 int size = lseek(fd, 0, SEEK_END);
922 if (size == -1)
923 goto errexit;
924 if (lseek(fd, 0 , SEEK_SET) == -1)
925 goto errexit;
926
927 // allocate memory
928 char *data = malloc(size + 1); // + '\0'
929 if (data == NULL)
930 goto errexit;
931 memset(data, 0, size + 1);
932
933 // read file
934 int rd = 0;
935 while (rd < size) {
936 int rv = read(fd, (unsigned char *) data + rd, size - rd);
937 if (rv == -1) {
938 goto errexit;
939 }
940 rd += rv;
941 }
942
943 // close file
944 close(fd);
945 return data;
946
947errexit:
948 close(fd);
949 fprintf(stderr, "Error: cannot read %s\n", fname);
950 exit(1);
951}
952
953
954unsigned extract_timeout(const char *str) { 911unsigned extract_timeout(const char *str) {
955 unsigned s; 912 unsigned s;
956 unsigned m; 913 unsigned m;
diff --git a/src/man/firejail.txt b/src/man/firejail.txt
index e0eb723bc..bf27c07ad 100644
--- a/src/man/firejail.txt
+++ b/src/man/firejail.txt
@@ -858,10 +858,13 @@ be created and configured using "ip netns".
858 858
859.TP 859.TP
860\fB\-\-netfilter 860\fB\-\-netfilter
861Enable a default client network filter in the new network namespace. 861Enable a default firewall if a new network namespace is created inside the sandbox.
862New network namespaces are created using \-\-net option. If a new network namespaces is not created, 862This option has no effect for sandboxes using the system network namespace.
863\-\-netfilter option does nothing. 863.br
864The default filter is as follows: 864
865.br
866The default firewall is optimized for regular desktop applications. No incoming
867connections are accepted:
865.br 868.br
866 869
867.br 870.br
@@ -904,19 +907,18 @@ Example:
904$ firejail \-\-net=eth0 \-\-netfilter firefox 907$ firejail \-\-net=eth0 \-\-netfilter firefox
905.TP 908.TP
906\fB\-\-netfilter=filename 909\fB\-\-netfilter=filename
907Enable the network filter specified by filename in the new network namespace. The filter file format 910Enable the firewall specified by filename if a new network namespace is created inside the sandbox.
908is the format of iptables-save and iptable-restore commands. 911This option has no effect for sandboxes using the system network namespace.
909New network namespaces are created using \-\-net option. If a new network namespaces is not created,
910\-\-netfilter option does nothing.
911.br 912.br
912 913
913.br 914.br
914The following filters are available in /etc/firejail directory: 915Please use the regular iptables-save/iptables-restore format for the filter file. The following
916examples are available in /etc/firejail directory:
915.br 917.br
916 918
917.br 919.br
918.B webserver.net 920.B webserver.net
919is a webserver filter that allows access only to TCP ports 80 and 443. 921is a webserver firewall that allows access only to TCP ports 80 and 443.
920Example: 922Example:
921.br 923.br
922 924
@@ -928,7 +930,7 @@ $ firejail --netfilter=/etc/firejail/webserver.net --net=eth0 \\
928 930
929.br 931.br
930.B nolocal.net 932.B nolocal.net
931is a client filter that disable access to local network. Example: 933is a desktop client firewall that disable access to local network. Example:
932.br 934.br
933 935
934.br 936.br
@@ -936,11 +938,31 @@ $ firejail --netfilter=/etc/firejail/nolocal.net \\
936.br 938.br
937--net=eth0 firefox 939--net=eth0 firefox
938.TP 940.TP
941\fB\-\-netfilter.print=name|pid
942Print the firewall installed in the sandbox specified by name or PID. Example:
943.br
944
945.br
946$ firejail --net=browser --net=eth0 --netfilter firefox &
947.br
948$ firejail --netfilter.print=browser
949
950.TP
939\fB\-\-netfilter6=filename 951\fB\-\-netfilter6=filename
940Enable the IPv6 network filter specified by filename in the new network namespace. The filter file format 952Enable the IPv6 firewall specified by filename if a new network namespace is created inside the sandbox.
941is the format of ip6tables-save and ip6table-restore commands. 953This option has no effect for sandboxes using the system network namespace.
942New network namespaces are created using \-\-net option. If a new network namespaces is not created, 954Please use the regular iptables-save/iptables-restore format for the filter file.
943\-\-netfilter6 option does nothing. 955
956.TP
957\fB\-\-netfilter6.print=name|pid
958Print the IPv6 firewall installed in the sandbox specified by name or PID. Example:
959.br
960
961.br
962$ firejail --net=browser --net=eth0 --netfilter firefox &
963.br
964$ firejail --netfilter6.print=browser
965
944.TP 966.TP
945\fB\-\-netstats 967\fB\-\-netstats
946Monitor network namespace statistics, see \fBMONITORING\fR section for more details. 968Monitor network namespace statistics, see \fBMONITORING\fR section for more details.
diff --git a/test/network/ip6.exp b/test/network/ip6.exp
index 26780e167..c55f690db 100755
--- a/test/network/ip6.exp
+++ b/test/network/ip6.exp
@@ -10,7 +10,7 @@ match_max 100000
10send -- "firejail --debug --noprofile --net=br0 --ip6=2001:0db8:0:f101::1/64 --netfilter6=ipv6.net\r" 10send -- "firejail --debug --noprofile --net=br0 --ip6=2001:0db8:0:f101::1/64 --netfilter6=ipv6.net\r"
11expect { 11expect {
12 timeout {puts "TESTING ERROR 0\n";exit} 12 timeout {puts "TESTING ERROR 0\n";exit}
13 "Installing network filter" 13 "Installing IPv6 firewall"
14} 14}
15expect { 15expect {
16 timeout {puts "TESTING ERROR 1\n";exit} 16 timeout {puts "TESTING ERROR 1\n";exit}
@@ -46,10 +46,12 @@ send -- "exit\r"
46sleep 2 46sleep 2
47 47
48 48
49
50
49send -- "firejail --debug --profile=ip6.profile\r" 51send -- "firejail --debug --profile=ip6.profile\r"
50expect { 52expect {
51 timeout {puts "TESTING ERROR 10\n";exit} 53 timeout {puts "TESTING ERROR 10\n";exit}
52 "Installing network filter" 54 "Installing IPv6 firewall"
53} 55}
54expect { 56expect {
55 timeout {puts "TESTING ERROR 11\n";exit} 57 timeout {puts "TESTING ERROR 11\n";exit}
@@ -82,7 +84,17 @@ expect {
82} 84}
83 85
84send -- "exit\r" 86send -- "exit\r"
87sleep 2
85 88
89send -- "firejail --debug --netfilter6=ipv6.net\r"
90expect {
91 timeout {puts "TESTING ERROR 11\n";exit}
92 "Installing IPv6 firewall" {puts "TESTING ERROR 12\n";exit}
93 "Child process initialized"
94}
86after 100 95after 100
96send -- "exit\r"
87 97
98
99after 100
88puts "\nall done\n" 100puts "\nall done\n"
diff --git a/test/network/net_netfilter.exp b/test/network/net_netfilter.exp
index 52fd3bf11..8f371bafc 100755
--- a/test/network/net_netfilter.exp
+++ b/test/network/net_netfilter.exp
@@ -11,7 +11,7 @@ match_max 100000
11send -- "firejail --debug --noprofile --net=br0 --ip=10.10.20.5 --netfilter\r" 11send -- "firejail --debug --noprofile --net=br0 --ip=10.10.20.5 --netfilter\r"
12expect { 12expect {
13 timeout {puts "TESTING ERROR 0\n";exit} 13 timeout {puts "TESTING ERROR 0\n";exit}
14 "Installing network filter" 14 "Installing firewall"
15} 15}
16expect { 16expect {
17 timeout {puts "TESTING ERROR 1\n";exit} 17 timeout {puts "TESTING ERROR 1\n";exit}
@@ -51,7 +51,7 @@ sleep 1
51send -- "firejail --debug --noprofile --net=br0 --ip=10.10.20.5 --netfilter=netfilter.filter\r" 51send -- "firejail --debug --noprofile --net=br0 --ip=10.10.20.5 --netfilter=netfilter.filter\r"
52expect { 52expect {
53 timeout {puts "TESTING ERROR 6\n";exit} 53 timeout {puts "TESTING ERROR 6\n";exit}
54 "Installing network filter" 54 "Installing firewall"
55} 55}
56expect { 56expect {
57 timeout {puts "TESTING ERROR 6.1\n";exit} 57 timeout {puts "TESTING ERROR 6.1\n";exit}
@@ -71,7 +71,7 @@ sleep 1
71send -- "firejail --debug --net=br0 --ip=10.10.20.5 --profile=netfilter.profile\r" 71send -- "firejail --debug --net=br0 --ip=10.10.20.5 --profile=netfilter.profile\r"
72expect { 72expect {
73 timeout {puts "TESTING ERROR 7\n";exit} 73 timeout {puts "TESTING ERROR 7\n";exit}
74 "Installing network filter" 74 "Installing firewall"
75} 75}
76expect { 76expect {
77 timeout {puts "TESTING ERROR 7.1\n";exit} 77 timeout {puts "TESTING ERROR 7.1\n";exit}