diff options
Diffstat (limited to 'src/firejail/netfilter.c')
-rw-r--r-- | src/firejail/netfilter.c | 111 |
1 files changed, 62 insertions, 49 deletions
diff --git a/src/firejail/netfilter.c b/src/firejail/netfilter.c index 1df4b7a0f..0136ab1f8 100644 --- a/src/firejail/netfilter.c +++ b/src/firejail/netfilter.c | |||
@@ -69,31 +69,33 @@ void netfilter(const char *fname) { | |||
69 | if (netfilter_default) | 69 | if (netfilter_default) |
70 | fname = netfilter_default; | 70 | fname = netfilter_default; |
71 | if (fname) { | 71 | if (fname) { |
72 | // buffer the filter | 72 | assert(fname); |
73 | struct stat s; | 73 | |
74 | if (stat(fname, &s) == -1) { | 74 | // open filter file |
75 | fprintf(stderr, "Error: cannot find network filter file %s\n", fname); | 75 | int fd = open(fname, O_RDONLY); |
76 | exit(1); | 76 | if (fd == -1) |
77 | } | 77 | goto errexit; |
78 | 78 | int size = lseek(fd, 0, SEEK_END); | |
79 | filter = malloc(s.st_size + 1); // + '\0' | 79 | if (size == -1) |
80 | if (!filter) | 80 | goto errexit; |
81 | errExit("malloc"); | 81 | if (lseek(fd, 0 , SEEK_SET) == -1) |
82 | memset(filter, 0, s.st_size + 1); | 82 | goto errexit; |
83 | 83 | ||
84 | /* coverity[toctou] */ | 84 | // read filter |
85 | FILE *fp = fopen(fname, "r"); | 85 | filter = malloc(size + 1); // + '\0' |
86 | if (!fp) { | 86 | if (filter == NULL) |
87 | fprintf(stderr, "Error: cannot open network filter file %s\n", fname); | 87 | goto errexit; |
88 | exit(1); | 88 | memset(&filter[0], 0, sizeof(filter)); |
89 | } | 89 | int rd = 0; |
90 | 90 | while (rd < size) { | |
91 | size_t sz = fread(filter, 1, s.st_size, fp); | 91 | int rv = read(fd, (unsigned char *) filter + rd, size - rd); |
92 | if ((off_t)sz != s.st_size) { | 92 | if (rv == -1) |
93 | fprintf(stderr, "Error: cannot read network filter file %s\n", fname); | 93 | goto errexit; |
94 | exit(1); | 94 | rd += rv; |
95 | } | 95 | } |
96 | fclose(fp); | 96 | |
97 | // close file | ||
98 | close(fd); | ||
97 | allocated = 1; | 99 | allocated = 1; |
98 | } | 100 | } |
99 | 101 | ||
@@ -178,6 +180,11 @@ doexit: | |||
178 | 180 | ||
179 | if (allocated) | 181 | if (allocated) |
180 | free(filter); | 182 | free(filter); |
183 | return; | ||
184 | |||
185 | errexit: | ||
186 | fprintf(stderr, "Error: cannot read network filter %s\n", fname); | ||
187 | exit(1); | ||
181 | } | 188 | } |
182 | 189 | ||
183 | void netfilter6(const char *fname) { | 190 | void netfilter6(const char *fname) { |
@@ -186,38 +193,38 @@ void netfilter6(const char *fname) { | |||
186 | 193 | ||
187 | char *filter; | 194 | char *filter; |
188 | 195 | ||
189 | // buffer the filter | 196 | // open filter file |
190 | struct stat s; | 197 | int fd = open(fname, O_RDONLY); |
191 | if (stat(fname, &s) == -1) { | 198 | if (fd == -1) |
192 | fprintf(stderr, "Error: cannot find network filter file %s\n", fname); | 199 | goto errexit; |
193 | exit(1); | 200 | int size = lseek(fd, 0, SEEK_END); |
194 | } | 201 | if (size == -1) |
195 | 202 | goto errexit; | |
196 | filter = malloc(s.st_size + 1); // + '\0' | 203 | if (lseek(fd, 0 , SEEK_SET) == -1) |
197 | if (!filter) | 204 | goto errexit; |
198 | errExit("malloc"); | 205 | |
199 | memset(filter, 0, s.st_size + 1); | 206 | // read filter |
200 | 207 | filter = malloc(size + 1); // + '\0' | |
201 | /* coverity[toctou] */ | 208 | if (filter == NULL) |
202 | FILE *fp = fopen(fname, "r"); | 209 | goto errexit; |
203 | if (!fp) { | 210 | memset(&filter[0], 0, sizeof(filter)); |
204 | fprintf(stderr, "Error: cannot open network filter file %s\n", fname); | 211 | int rd = 0; |
205 | exit(1); | 212 | while (rd < size) { |
206 | } | 213 | int rv = read(fd, (unsigned char *) filter + rd, size - rd); |
207 | 214 | if (rv == -1) | |
208 | size_t sz = fread(filter, 1, s.st_size, fp); | 215 | goto errexit; |
209 | if ((off_t)sz != s.st_size) { | 216 | rd += rv; |
210 | fprintf(stderr, "Error: cannot read network filter file %s\n", fname); | ||
211 | exit(1); | ||
212 | } | 217 | } |
213 | fclose(fp); | 218 | |
219 | // close file | ||
220 | close(fd); | ||
214 | 221 | ||
215 | // temporarily mount a tempfs on top of /tmp directory | 222 | // temporarily mount a tempfs on top of /tmp directory |
216 | if (mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) | 223 | if (mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) |
217 | errExit("mounting /tmp"); | 224 | errExit("mounting /tmp"); |
218 | 225 | ||
219 | // create the filter file | 226 | // create the filter file |
220 | fp = fopen("/tmp/netfilter6", "w"); | 227 | FILE *fp = fopen("/tmp/netfilter6", "w"); |
221 | if (!fp) { | 228 | if (!fp) { |
222 | fprintf(stderr, "Error: cannot open /tmp/netfilter6 file\n"); | 229 | fprintf(stderr, "Error: cannot open /tmp/netfilter6 file\n"); |
223 | exit(1); | 230 | exit(1); |
@@ -228,6 +235,7 @@ void netfilter6(const char *fname) { | |||
228 | // find iptables command | 235 | // find iptables command |
229 | char *ip6tables = NULL; | 236 | char *ip6tables = NULL; |
230 | char *ip6tables_restore = NULL; | 237 | char *ip6tables_restore = NULL; |
238 | struct stat s; | ||
231 | if (stat("/sbin/ip6tables", &s) == 0) { | 239 | if (stat("/sbin/ip6tables", &s) == 0) { |
232 | ip6tables = "/sbin/ip6tables"; | 240 | ip6tables = "/sbin/ip6tables"; |
233 | ip6tables_restore = "/sbin/ip6tables-restore"; | 241 | ip6tables_restore = "/sbin/ip6tables-restore"; |
@@ -284,4 +292,9 @@ doexit: | |||
284 | // unmount /tmp | 292 | // unmount /tmp |
285 | umount("/tmp"); | 293 | umount("/tmp"); |
286 | free(filter); | 294 | free(filter); |
295 | return; | ||
296 | |||
297 | errexit: | ||
298 | fprintf(stderr, "Error: cannot read network filter %s\n", fname); | ||
299 | exit(1); | ||
287 | } | 300 | } |