diff options
-rw-r--r-- | src/firejail/fs_whitelist.c | 62 |
1 files changed, 41 insertions, 21 deletions
diff --git a/src/firejail/fs_whitelist.c b/src/firejail/fs_whitelist.c index af1993457..d67087616 100644 --- a/src/firejail/fs_whitelist.c +++ b/src/firejail/fs_whitelist.c | |||
@@ -196,7 +196,6 @@ static void whitelist_path(ProfileEntry *entry) { | |||
196 | const char *fname; | 196 | const char *fname; |
197 | char *wfile = NULL; | 197 | char *wfile = NULL; |
198 | 198 | ||
199 | EUID_USER(); | ||
200 | if (entry->home_dir) { | 199 | if (entry->home_dir) { |
201 | if (strncmp(path, cfg.homedir, strlen(cfg.homedir)) == 0) { | 200 | if (strncmp(path, cfg.homedir, strlen(cfg.homedir)) == 0) { |
202 | fname = path + strlen(cfg.homedir); | 201 | fname = path + strlen(cfg.homedir); |
@@ -204,7 +203,8 @@ static void whitelist_path(ProfileEntry *entry) { | |||
204 | goto errexit; | 203 | goto errexit; |
205 | } | 204 | } |
206 | else | 205 | else |
207 | fname = path; | 206 | // symlink pointing outside /home, skip the mount |
207 | return; | ||
208 | 208 | ||
209 | if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_HOME_USER_DIR, fname) == -1) | 209 | if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_HOME_USER_DIR, fname) == -1) |
210 | errExit("asprintf"); | 210 | errExit("asprintf"); |
@@ -236,17 +236,27 @@ static void whitelist_path(ProfileEntry *entry) { | |||
236 | errExit("asprintf"); | 236 | errExit("asprintf"); |
237 | } | 237 | } |
238 | else if (entry->var_dir) { | 238 | else if (entry->var_dir) { |
239 | fname = path + 5; // strlen("/var/") | 239 | if (strncmp(path, "/var/", 5) == 0) { |
240 | if (*fname == '\0') | 240 | fname = path + 5; // strlen("/var/") |
241 | goto errexit; | 241 | if (*fname == '\0') |
242 | goto errexit; | ||
243 | } | ||
244 | else | ||
245 | // symlink pointing outside /var, skip the mount | ||
246 | return; | ||
242 | 247 | ||
243 | if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_VAR_DIR, fname) == -1) | 248 | if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_VAR_DIR, fname) == -1) |
244 | errExit("asprintf"); | 249 | errExit("asprintf"); |
245 | } | 250 | } |
246 | else if (entry->dev_dir) { | 251 | else if (entry->dev_dir) { |
247 | fname = path + 5; // strlen("/dev/") | 252 | if (strncmp(path, "/dev/", 5) == 0) { |
248 | if (*fname == '\0') | 253 | fname = path + 5; // strlen("/dev/") |
249 | goto errexit; | 254 | if (*fname == '\0') |
255 | goto errexit; | ||
256 | } | ||
257 | else | ||
258 | // symlink pointing outside /dev, skip the mount | ||
259 | return; | ||
250 | 260 | ||
251 | if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_DEV_DIR, fname) == -1) | 261 | if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_DEV_DIR, fname) == -1) |
252 | errExit("asprintf"); | 262 | errExit("asprintf"); |
@@ -268,9 +278,14 @@ static void whitelist_path(ProfileEntry *entry) { | |||
268 | errExit("asprintf"); | 278 | errExit("asprintf"); |
269 | } | 279 | } |
270 | else if (entry->etc_dir) { | 280 | else if (entry->etc_dir) { |
271 | fname = path + 5; // strlen("/etc/") | 281 | if (strncmp(path, "/etc/", 5) == 0) { |
272 | if (*fname == '\0') | 282 | fname = path + 5; // strlen("/etc/") |
273 | goto errexit; | 283 | if (*fname == '\0') |
284 | goto errexit; | ||
285 | } | ||
286 | else | ||
287 | // symlink pointing outside /etc, skip the mount | ||
288 | return; | ||
274 | 289 | ||
275 | if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_ETC_DIR, fname) == -1) | 290 | if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_ETC_DIR, fname) == -1) |
276 | errExit("asprintf"); | 291 | errExit("asprintf"); |
@@ -293,6 +308,7 @@ static void whitelist_path(ProfileEntry *entry) { | |||
293 | } | 308 | } |
294 | 309 | ||
295 | // check if the file exists | 310 | // check if the file exists |
311 | EUID_USER(); | ||
296 | assert(wfile); | 312 | assert(wfile); |
297 | struct stat s; | 313 | struct stat s; |
298 | if (stat(wfile, &s) == 0) { | 314 | if (stat(wfile, &s) == 0) { |
@@ -300,11 +316,12 @@ static void whitelist_path(ProfileEntry *entry) { | |||
300 | printf("Whitelisting %s\n", path); | 316 | printf("Whitelisting %s\n", path); |
301 | } | 317 | } |
302 | else { | 318 | else { |
319 | free(wfile); | ||
303 | EUID_ROOT(); | 320 | EUID_ROOT(); |
304 | return; | 321 | return; |
305 | } | 322 | } |
306 | |||
307 | EUID_ROOT(); | 323 | EUID_ROOT(); |
324 | |||
308 | // create the path if necessary | 325 | // create the path if necessary |
309 | mkpath(path, s.st_mode); | 326 | mkpath(path, s.st_mode); |
310 | fs_logger2("whitelist", path); | 327 | fs_logger2("whitelist", path); |
@@ -329,8 +346,10 @@ static void whitelist_path(ProfileEntry *entry) { | |||
329 | SET_PERMS_STREAM(fp, s.st_uid, s.st_gid, s.st_mode); | 346 | SET_PERMS_STREAM(fp, s.st_uid, s.st_gid, s.st_mode); |
330 | fclose(fp); | 347 | fclose(fp); |
331 | } | 348 | } |
332 | else | 349 | else { |
350 | free(wfile); | ||
333 | return; // the file is already present | 351 | return; // the file is already present |
352 | } | ||
334 | } | 353 | } |
335 | 354 | ||
336 | // mount | 355 | // mount |
@@ -565,19 +584,20 @@ void fs_whitelist(void) { | |||
565 | entry->var_dir = 1; | 584 | entry->var_dir = 1; |
566 | var_dir = 1; | 585 | var_dir = 1; |
567 | // both path and absolute path are under /var | 586 | // both path and absolute path are under /var |
568 | // exceptions: /var/run and /var/lock | 587 | // exceptions: /var/tmp, /var/run and /var/lock |
569 | if (strcmp(new_name, "/var/run")== 0) | 588 | if (strcmp(new_name, "/var/run")== 0 && strcmp(fname, "/run") == 0); |
570 | ; | 589 | else if (strcmp(new_name, "/var/lock")== 0 && strcmp(fname, "/run/lock") == 0); |
571 | else if (strcmp(new_name, "/var/lock")== 0) | 590 | else if (strcmp(new_name, "/var/tmp")== 0 && strcmp(fname, "/tmp") == 0); |
572 | ; | 591 | else { |
573 | else if (strncmp(fname, "/var/", 5) != 0) { | 592 | // both path and absolute path are under /var |
574 | goto errexit; | 593 | if (strncmp(fname, "/var/", 5) != 0) { |
594 | goto errexit; | ||
595 | } | ||
575 | } | 596 | } |
576 | } | 597 | } |
577 | else if (strncmp(new_name, "/dev/", 5) == 0) { | 598 | else if (strncmp(new_name, "/dev/", 5) == 0) { |
578 | entry->dev_dir = 1; | 599 | entry->dev_dir = 1; |
579 | dev_dir = 1; | 600 | dev_dir = 1; |
580 | |||
581 | // special handling for /dev/shm | 601 | // special handling for /dev/shm |
582 | // on some platforms (Debian wheezy, Ubuntu 14.04), it is a symlink to /run/shm | 602 | // on some platforms (Debian wheezy, Ubuntu 14.04), it is a symlink to /run/shm |
583 | if (strcmp(new_name, "/dev/shm") == 0 && strcmp(fname, "/run/shm") == 0); | 603 | if (strcmp(new_name, "/dev/shm") == 0 && strcmp(fname, "/run/shm") == 0); |