diff options
Diffstat (limited to 'src/firejail/fs_whitelist.c')
-rw-r--r-- | src/firejail/fs_whitelist.c | 121 |
1 files changed, 119 insertions, 2 deletions
diff --git a/src/firejail/fs_whitelist.c b/src/firejail/fs_whitelist.c index 2751a8c71..3514c073d 100644 --- a/src/firejail/fs_whitelist.c +++ b/src/firejail/fs_whitelist.c | |||
@@ -83,6 +83,36 @@ static void whitelist_path(ProfileEntry *entry) { | |||
83 | if (asprintf(&wfile, "%s/%s", WHITELIST_TMP_DIR, fname) == -1) | 83 | if (asprintf(&wfile, "%s/%s", WHITELIST_TMP_DIR, fname) == -1) |
84 | errExit("asprintf"); | 84 | errExit("asprintf"); |
85 | } | 85 | } |
86 | else if (entry->media_dir) { | ||
87 | fname = path + 6; // strlen("/media") | ||
88 | if (*fname == '\0') { | ||
89 | fprintf(stderr, "Error: file %s is not in /media directory, exiting...\n", path); | ||
90 | exit(1); | ||
91 | } | ||
92 | |||
93 | if (asprintf(&wfile, "%s/%s", WHITELIST_MEDIA_DIR, fname) == -1) | ||
94 | errExit("asprintf"); | ||
95 | } | ||
96 | else if (entry->var_dir) { | ||
97 | fname = path + 4; // strlen("/var") | ||
98 | if (*fname == '\0') { | ||
99 | fprintf(stderr, "Error: file %s is not in /var directory, exiting...\n", path); | ||
100 | exit(1); | ||
101 | } | ||
102 | |||
103 | if (asprintf(&wfile, "%s/%s", WHITELIST_VAR_DIR, fname) == -1) | ||
104 | errExit("asprintf"); | ||
105 | } | ||
106 | else if (entry->dev_dir) { | ||
107 | fname = path + 4; // strlen("/dev") | ||
108 | if (*fname == '\0') { | ||
109 | fprintf(stderr, "Error: file %s is not in /dev directory, exiting...\n", path); | ||
110 | exit(1); | ||
111 | } | ||
112 | |||
113 | if (asprintf(&wfile, "%s/%s", WHITELIST_DEV_DIR, fname) == -1) | ||
114 | errExit("asprintf"); | ||
115 | } | ||
86 | 116 | ||
87 | // check if the file exists | 117 | // check if the file exists |
88 | struct stat s; | 118 | struct stat s; |
@@ -145,6 +175,9 @@ void fs_whitelist(void) { | |||
145 | char *new_name = NULL; | 175 | char *new_name = NULL; |
146 | int home_dir = 0; // /home/user directory flag | 176 | int home_dir = 0; // /home/user directory flag |
147 | int tmp_dir = 0; // /tmp directory flag | 177 | int tmp_dir = 0; // /tmp directory flag |
178 | int media_dir = 0; // /media directory flag | ||
179 | int var_dir = 0; // /var directory flag | ||
180 | int dev_dir = 0; // /dev directory flag | ||
148 | 181 | ||
149 | // verify whitelist files, extract symbolic links, etc. | 182 | // verify whitelist files, extract symbolic links, etc. |
150 | while (entry) { | 183 | while (entry) { |
@@ -173,7 +206,7 @@ void fs_whitelist(void) { | |||
173 | if (*new_name != '/') | 206 | if (*new_name != '/') |
174 | goto errexit; | 207 | goto errexit; |
175 | 208 | ||
176 | // check for home directory or tmp directory | 209 | // check for supported directories |
177 | if (strncmp(new_name, cfg.homedir, strlen(cfg.homedir)) == 0) { | 210 | if (strncmp(new_name, cfg.homedir, strlen(cfg.homedir)) == 0) { |
178 | entry->home_dir = 1; | 211 | entry->home_dir = 1; |
179 | home_dir = 1; | 212 | home_dir = 1; |
@@ -188,6 +221,27 @@ void fs_whitelist(void) { | |||
188 | if (strncmp(fname, "/tmp/", 5) != 0) | 221 | if (strncmp(fname, "/tmp/", 5) != 0) |
189 | goto errexit; | 222 | goto errexit; |
190 | } | 223 | } |
224 | else if (strncmp(new_name, "/media/", 7) == 0) { | ||
225 | entry->media_dir = 1; | ||
226 | media_dir = 1; | ||
227 | // both path and absolute path are under /media | ||
228 | if (strncmp(fname, "/media/", 7) != 0) | ||
229 | goto errexit; | ||
230 | } | ||
231 | else if (strncmp(new_name, "/var/", 5) == 0) { | ||
232 | entry->var_dir = 1; | ||
233 | var_dir = 1; | ||
234 | // both path and absolute path are under /var | ||
235 | if (strncmp(fname, "/var/", 5) != 0) | ||
236 | goto errexit; | ||
237 | } | ||
238 | else if (strncmp(new_name, "/dev/", 5) == 0) { | ||
239 | entry->dev_dir = 1; | ||
240 | dev_dir = 1; | ||
241 | // both path and absolute path are under /dev | ||
242 | if (strncmp(fname, "/dev/", 5) != 0) | ||
243 | goto errexit; | ||
244 | } | ||
191 | else | 245 | else |
192 | goto errexit; | 246 | goto errexit; |
193 | 247 | ||
@@ -249,7 +303,70 @@ void fs_whitelist(void) { | |||
249 | if (arg_debug) | 303 | if (arg_debug) |
250 | printf("Mounting tmpfs on /tmp directory\n"); | 304 | printf("Mounting tmpfs on /tmp directory\n"); |
251 | if (mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=777,gid=0") < 0) | 305 | if (mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=777,gid=0") < 0) |
252 | errExit("mounting tmpfs on /tmpt"); | 306 | errExit("mounting tmpfs on /tmp"); |
307 | } | ||
308 | |||
309 | // /media mountpoint | ||
310 | if (media_dir) { | ||
311 | // keep a copy of real /media directory in WHITELIST_MEDIA_DIR | ||
312 | int rv = mkdir(WHITELIST_MEDIA_DIR, S_IRWXU | S_IRWXG | S_IRWXO); | ||
313 | if (rv == -1) | ||
314 | errExit("mkdir"); | ||
315 | if (chown(WHITELIST_MEDIA_DIR, 0, 0) < 0) | ||
316 | errExit("chown"); | ||
317 | if (chmod(WHITELIST_MEDIA_DIR, 0755) < 0) | ||
318 | errExit("chmod"); | ||
319 | |||
320 | if (mount("/media", WHITELIST_MEDIA_DIR, NULL, MS_BIND|MS_REC, NULL) < 0) | ||
321 | errExit("mount bind"); | ||
322 | |||
323 | // mount tmpfs on /media | ||
324 | if (arg_debug) | ||
325 | printf("Mounting tmpfs on /media directory\n"); | ||
326 | if (mount("tmpfs", "/media", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) | ||
327 | errExit("mounting tmpfs on /media"); | ||
328 | } | ||
329 | |||
330 | // /media mountpoint | ||
331 | if (var_dir) { | ||
332 | // keep a copy of real /var directory in WHITELIST_VAR_DIR | ||
333 | int rv = mkdir(WHITELIST_VAR_DIR, S_IRWXU | S_IRWXG | S_IRWXO); | ||
334 | if (rv == -1) | ||
335 | errExit("mkdir"); | ||
336 | if (chown(WHITELIST_VAR_DIR, 0, 0) < 0) | ||
337 | errExit("chown"); | ||
338 | if (chmod(WHITELIST_VAR_DIR, 0755) < 0) | ||
339 | errExit("chmod"); | ||
340 | |||
341 | if (mount("/var", WHITELIST_VAR_DIR, NULL, MS_BIND|MS_REC, NULL) < 0) | ||
342 | errExit("mount bind"); | ||
343 | |||
344 | // mount tmpfs on /var | ||
345 | if (arg_debug) | ||
346 | printf("Mounting tmpfs on /var directory\n"); | ||
347 | if (mount("tmpfs", "/var", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) | ||
348 | errExit("mounting tmpfs on /var"); | ||
349 | } | ||
350 | |||
351 | // /dev mountpoint | ||
352 | if (dev_dir) { | ||
353 | // keep a copy of real /dev directory in WHITELIST_DEV_DIR | ||
354 | int rv = mkdir(WHITELIST_DEV_DIR, S_IRWXU | S_IRWXG | S_IRWXO); | ||
355 | if (rv == -1) | ||
356 | errExit("mkdir"); | ||
357 | if (chown(WHITELIST_DEV_DIR, 0, 0) < 0) | ||
358 | errExit("chown"); | ||
359 | if (chmod(WHITELIST_DEV_DIR, 0755) < 0) | ||
360 | errExit("chmod"); | ||
361 | |||
362 | if (mount("/dev", WHITELIST_DEV_DIR, NULL, MS_BIND|MS_REC, NULL) < 0) | ||
363 | errExit("mount bind"); | ||
364 | |||
365 | // mount tmpfs on /var | ||
366 | if (arg_debug) | ||
367 | printf("Mounting tmpfs on /dev directory\n"); | ||
368 | if (mount("tmpfs", "/dev", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) | ||
369 | errExit("mounting tmpfs on /dev"); | ||
253 | } | 370 | } |
254 | 371 | ||
255 | // go through profile rules again, and interpret whitelist commands | 372 | // go through profile rules again, and interpret whitelist commands |