aboutsummaryrefslogtreecommitdiffstats
path: root/src/firejail/netfilter.c
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@yahoo.com>2016-11-28 10:36:04 -0500
committerLibravatar netblue30 <netblue30@yahoo.com>2016-11-28 10:36:04 -0500
commitd0c1fcfa273d323a26aa8477130e176dc2435bf5 (patch)
tree5c0823ed12cabf602ace114a12b53fb3b2872b99 /src/firejail/netfilter.c
parentcleanup (diff)
downloadfirejail-d0c1fcfa273d323a26aa8477130e176dc2435bf5.tar.gz
firejail-d0c1fcfa273d323a26aa8477130e176dc2435bf5.tar.zst
firejail-d0c1fcfa273d323a26aa8477130e176dc2435bf5.zip
netfilter rework
Diffstat (limited to 'src/firejail/netfilter.c')
-rw-r--r--src/firejail/netfilter.c233
1 files changed, 45 insertions, 188 deletions
diff --git a/src/firejail/netfilter.c b/src/firejail/netfilter.c
index 43f08e45b..ef4915f15 100644
--- a/src/firejail/netfilter.c
+++ b/src/firejail/netfilter.c
@@ -61,59 +61,6 @@ void check_netfilter_file(const char *fname) {
61 61
62 62
63void netfilter(const char *fname) { 63void netfilter(const char *fname) {
64 // default filter
65 char *filter = client_filter;
66
67 // custom filter
68 int allocated = 0;
69 if (netfilter_default)
70 fname = netfilter_default;
71 if (fname) {
72 assert(fname);
73
74 // open filter file
75 int fd = open(fname, O_RDONLY);
76 if (fd == -1)
77 goto errexit;
78 int size = lseek(fd, 0, SEEK_END);
79 if (size == -1)
80 goto errexit;
81 if (lseek(fd, 0 , SEEK_SET) == -1)
82 goto errexit;
83
84 // read filter
85 filter = malloc(size + 1); // + '\0'
86 if (filter == NULL)
87 goto errexit;
88 memset(filter, 0, size + 1);
89 int rd = 0;
90 while (rd < size) {
91 int rv = read(fd, (unsigned char *) filter + rd, size - rd);
92 if (rv == -1) {
93 close(fd);
94 goto errexit;
95 }
96 rd += rv;
97 }
98
99 // close file
100 close(fd);
101 allocated = 1;
102 }
103
104 // temporarily mount a tempfs on top of /tmp directory
105 if (mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
106 errExit("mounting /tmp");
107
108 // create the filter file
109 FILE *fp = fopen("/tmp/netfilter", "w");
110 if (!fp) {
111 fprintf(stderr, "Error: cannot open /tmp/netfilter file\n");
112 exit(1);
113 }
114 fprintf(fp, "%s\n", filter);
115 fclose(fp);
116
117 // find iptables command 64 // find iptables command
118 struct stat s; 65 struct stat s;
119 char *iptables = NULL; 66 char *iptables = NULL;
@@ -127,113 +74,49 @@ void netfilter(const char *fname) {
127 iptables_restore = "/usr/sbin/iptables-restore"; 74 iptables_restore = "/usr/sbin/iptables-restore";
128 } 75 }
129 if (iptables == NULL || iptables_restore == NULL) { 76 if (iptables == NULL || iptables_restore == NULL) {
130 fprintf(stderr, "Error: iptables command not found\n"); 77 fprintf(stderr, "Error: iptables command not found, netfilter not configured\n");
131 goto doexit; 78 return;
132 } 79 }
133 80
134 // push filter 81 // read filter
135 pid_t child = fork(); 82 char *filter = client_filter;
136 if (child < 0) 83 int allocated = 0;
137 errExit("fork"); 84 if (netfilter_default)
138 if (child == 0) { 85 fname = netfilter_default;
139 if (arg_debug) 86 if (fname) {
140 printf("Installing network filter:\n%s\n", filter); 87 filter = read_text_file_or_exit(fname);
141 88 allocated = 1;
142 int fd;
143 if((fd = open("/tmp/netfilter", O_RDONLY)) == -1) {
144 fprintf(stderr,"Error: cannot open /tmp/netfilter\n");
145 exit(1);
146 }
147 dup2(fd,STDIN_FILENO);
148
149 // wipe out environment variables
150 clearenv();
151 execl(iptables_restore, iptables_restore, NULL);
152 perror("execl");
153 _exit(1);
154 } 89 }
155 // wait for the child to finish
156 waitpid(child, NULL, 0);
157 90
158 // debug 91 // create the filter file
159 if (arg_debug) { 92 FILE *fp = fopen(SBOX_STDIN_FILE, "w");
160 child = fork(); 93 if (!fp) {
161 if (child < 0) 94 fprintf(stderr, "Error: cannot open %s\n", SBOX_STDIN_FILE);
162 errExit("fork"); 95 exit(1);
163 if (child == 0) {
164 // elevate privileges in order to get grsecurity working
165 if (setreuid(0, 0))
166 errExit("setreuid");
167 if (setregid(0, 0))
168 errExit("setregid");
169 environ = NULL;
170 assert(getenv("LD_PRELOAD") == NULL);
171 execl(iptables, iptables, "-vL", NULL);
172 perror("execl");
173 _exit(1);
174 }
175 // wait for the child to finish
176 waitpid(child, NULL, 0);
177 } 96 }
97 fprintf(fp, "%s\n", filter);
98 fclose(fp);
99
178 100
179doexit: 101 // push filter
180 // unmount /tmp 102 if (arg_debug)
181 umount("/tmp"); 103 printf("Installing network filter:\n%s\n", filter);
104 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP | SBOX_STDIN_FROM_FILE, 1, iptables_restore);
105 unlink(SBOX_STDIN_FILE);
106
107 // debug
108 if (arg_debug)
109 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 2, iptables, "-vL");
182 110
183 if (allocated) 111 if (allocated)
184 free(filter); 112 free(filter);
185 return; 113 return;
186
187errexit:
188 fprintf(stderr, "Error: cannot read network filter %s\n", fname);
189 exit(1);
190} 114}
191 115
192void netfilter6(const char *fname) { 116void netfilter6(const char *fname) {
193 if (fname == NULL) 117 if (fname == NULL)
194 return; 118 return;
195 119
196 char *filter;
197
198 // open filter file
199 int fd = open(fname, O_RDONLY);
200 if (fd == -1)
201 goto errexit;
202 int size = lseek(fd, 0, SEEK_END);
203 if (size == -1)
204 goto errexit;
205 if (lseek(fd, 0 , SEEK_SET) == -1)
206 goto errexit;
207
208 // read filter
209 filter = malloc(size + 1); // + '\0'
210 if (filter == NULL)
211 goto errexit;
212 memset(filter, 0, size + 1);
213 int rd = 0;
214 while (rd < size) {
215 int rv = read(fd, (unsigned char *) filter + rd, size - rd);
216 if (rv == -1)
217 goto errexit;
218 rd += rv;
219 }
220
221 // close file
222 close(fd);
223
224 // temporarily mount a tempfs on top of /tmp directory
225 if (mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
226 errExit("mounting /tmp");
227
228 // create the filter file
229 FILE *fp = fopen("/tmp/netfilter6", "w");
230 if (!fp) {
231 fprintf(stderr, "Error: cannot open /tmp/netfilter6 file\n");
232 exit(1);
233 }
234 fprintf(fp, "%s\n", filter);
235 fclose(fp);
236
237 // find iptables command 120 // find iptables command
238 char *ip6tables = NULL; 121 char *ip6tables = NULL;
239 char *ip6tables_restore = NULL; 122 char *ip6tables_restore = NULL;
@@ -247,56 +130,30 @@ void netfilter6(const char *fname) {
247 ip6tables_restore = "/usr/sbin/ip6tables-restore"; 130 ip6tables_restore = "/usr/sbin/ip6tables-restore";
248 } 131 }
249 if (ip6tables == NULL || ip6tables_restore == NULL) { 132 if (ip6tables == NULL || ip6tables_restore == NULL) {
250 fprintf(stderr, "Error: ip6tables command not found\n"); 133 fprintf(stderr, "Error: ip6tables command not found, netfilter6 not configured\n");
251 goto doexit; 134 return;
252 } 135 }
253 136
254 // push filter 137 // create the filter file
255 pid_t child = fork(); 138 char *filter = read_text_file_or_exit(fname);
256 if (child < 0) 139 FILE *fp = fopen(SBOX_STDIN_FILE, "w");
257 errExit("fork"); 140 if (!fp) {
258 if (child == 0) { 141 fprintf(stderr, "Error: cannot open /tmp/netfilter6 file\n");
259 if (arg_debug) 142 exit(1);
260 printf("Installing network filter:\n%s\n", filter);
261
262 int fd;
263 if((fd = open("/tmp/netfilter6", O_RDONLY)) == -1) {
264 fprintf(stderr,"Error: cannot open /tmp/netfilter6\n");
265 exit(1);
266 }
267 dup2(fd,STDIN_FILENO);
268
269 // wipe out environment variables
270 clearenv();
271 execl(ip6tables_restore, ip6tables_restore, NULL);
272 perror("execl");
273 _exit(1);
274 } 143 }
275 // wait for the child to finish 144 fprintf(fp, "%s\n", filter);
276 waitpid(child, NULL, 0); 145 fclose(fp);
277 146
147 // push filter
148 if (arg_debug)
149 printf("Installing network filter:\n%s\n", filter);
150 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP | SBOX_STDIN_FROM_FILE, 1, ip6tables_restore);
151 unlink(SBOX_STDIN_FILE);
152
278 // debug 153 // debug
279 if (arg_debug) { 154 if (arg_debug)
280 child = fork(); 155 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 2, ip6tables, "-vL");
281 if (child < 0)
282 errExit("fork");
283 if (child == 0) {
284 clearenv();
285 execl(ip6tables, ip6tables, "-vL", NULL);
286 perror("execl");
287 _exit(1);
288 }
289 // wait for the child to finish
290 waitpid(child, NULL, 0);
291 }
292 156
293doexit:
294 // unmount /tmp
295 umount("/tmp");
296 free(filter); 157 free(filter);
297 return; 158 return;
298
299errexit:
300 fprintf(stderr, "Error: cannot read network filter %s\n", fname);
301 exit(1);
302} 159}