diff options
Diffstat (limited to 'src/firejail/util.c')
-rw-r--r-- | src/firejail/util.c | 89 |
1 files changed, 83 insertions, 6 deletions
diff --git a/src/firejail/util.c b/src/firejail/util.c index 44f1cbd02..b8643ff60 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c | |||
@@ -417,6 +417,13 @@ int is_dir(const char *fname) { | |||
417 | if (*fname == '\0') | 417 | if (*fname == '\0') |
418 | return 0; | 418 | return 0; |
419 | 419 | ||
420 | int called_as_root = 0; | ||
421 | if (geteuid() == 0) | ||
422 | called_as_root = 1; | ||
423 | |||
424 | if (called_as_root) | ||
425 | EUID_USER(); | ||
426 | |||
420 | // if fname doesn't end in '/', add one | 427 | // if fname doesn't end in '/', add one |
421 | int rv; | 428 | int rv; |
422 | struct stat s; | 429 | struct stat s; |
@@ -432,6 +439,9 @@ int is_dir(const char *fname) { | |||
432 | free(tmp); | 439 | free(tmp); |
433 | } | 440 | } |
434 | 441 | ||
442 | if (called_as_root) | ||
443 | EUID_ROOT(); | ||
444 | |||
435 | if (rv == -1) | 445 | if (rv == -1) |
436 | return 0; | 446 | return 0; |
437 | 447 | ||
@@ -447,6 +457,14 @@ int is_link(const char *fname) { | |||
447 | if (*fname == '\0') | 457 | if (*fname == '\0') |
448 | return 0; | 458 | return 0; |
449 | 459 | ||
460 | int called_as_root = 0; | ||
461 | if (geteuid() == 0) | ||
462 | called_as_root = 1; | ||
463 | |||
464 | if (called_as_root) | ||
465 | EUID_USER(); | ||
466 | |||
467 | // remove trailing '/' if any | ||
450 | char *tmp = strdup(fname); | 468 | char *tmp = strdup(fname); |
451 | if (!tmp) | 469 | if (!tmp) |
452 | errExit("strdup"); | 470 | errExit("strdup"); |
@@ -456,9 +474,66 @@ int is_link(const char *fname) { | |||
456 | ssize_t rv = readlink(tmp, &c, 1); | 474 | ssize_t rv = readlink(tmp, &c, 1); |
457 | free(tmp); | 475 | free(tmp); |
458 | 476 | ||
477 | if (called_as_root) | ||
478 | EUID_ROOT(); | ||
479 | |||
459 | return (rv != -1); | 480 | return (rv != -1); |
460 | } | 481 | } |
461 | 482 | ||
483 | char *realpath_as_user(const char *fname) { | ||
484 | assert(fname); | ||
485 | |||
486 | int called_as_root = 0; | ||
487 | if (geteuid() == 0) | ||
488 | called_as_root = 1; | ||
489 | |||
490 | if (called_as_root) | ||
491 | EUID_USER(); | ||
492 | |||
493 | char *rv = realpath(fname, NULL); | ||
494 | |||
495 | if (called_as_root) | ||
496 | EUID_ROOT(); | ||
497 | |||
498 | return rv; | ||
499 | } | ||
500 | |||
501 | int stat_as_user(const char *fname, struct stat *s) { | ||
502 | assert(fname); | ||
503 | |||
504 | int called_as_root = 0; | ||
505 | if (geteuid() == 0) | ||
506 | called_as_root = 1; | ||
507 | |||
508 | if (called_as_root) | ||
509 | EUID_USER(); | ||
510 | |||
511 | int rv = stat(fname, s); | ||
512 | |||
513 | if (called_as_root) | ||
514 | EUID_ROOT(); | ||
515 | |||
516 | return rv; | ||
517 | } | ||
518 | |||
519 | int lstat_as_user(const char *fname, struct stat *s) { | ||
520 | assert(fname); | ||
521 | |||
522 | int called_as_root = 0; | ||
523 | if (geteuid() == 0) | ||
524 | called_as_root = 1; | ||
525 | |||
526 | if (called_as_root) | ||
527 | EUID_USER(); | ||
528 | |||
529 | int rv = lstat(fname, s); | ||
530 | |||
531 | if (called_as_root) | ||
532 | EUID_ROOT(); | ||
533 | |||
534 | return rv; | ||
535 | } | ||
536 | |||
462 | // remove all slashes and single dots from the end of a path | 537 | // remove all slashes and single dots from the end of a path |
463 | // for example /foo/bar///././. -> /foo/bar | 538 | // for example /foo/bar///././. -> /foo/bar |
464 | void trim_trailing_slash_or_dot(char *path) { | 539 | void trim_trailing_slash_or_dot(char *path) { |
@@ -891,14 +966,13 @@ static int remove_callback(const char *fpath, const struct stat *sb, int typefla | |||
891 | 966 | ||
892 | int remove_overlay_directory(void) { | 967 | int remove_overlay_directory(void) { |
893 | EUID_ASSERT(); | 968 | EUID_ASSERT(); |
894 | struct stat s; | ||
895 | sleep(1); | 969 | sleep(1); |
896 | 970 | ||
897 | char *path; | 971 | char *path; |
898 | if (asprintf(&path, "%s/.firejail", cfg.homedir) == -1) | 972 | if (asprintf(&path, "%s/.firejail", cfg.homedir) == -1) |
899 | errExit("asprintf"); | 973 | errExit("asprintf"); |
900 | 974 | ||
901 | if (lstat(path, &s) == 0) { | 975 | if (access(path, F_OK) == 0) { |
902 | pid_t child = fork(); | 976 | pid_t child = fork(); |
903 | if (child < 0) | 977 | if (child < 0) |
904 | errExit("fork"); | 978 | errExit("fork"); |
@@ -909,6 +983,7 @@ int remove_overlay_directory(void) { | |||
909 | fprintf(stderr, "Error: cannot open %s\n", path); | 983 | fprintf(stderr, "Error: cannot open %s\n", path); |
910 | _exit(1); | 984 | _exit(1); |
911 | } | 985 | } |
986 | struct stat s; | ||
912 | if (fstat(fd, &s) == -1) | 987 | if (fstat(fd, &s) == -1) |
913 | errExit("fstat"); | 988 | errExit("fstat"); |
914 | if (!S_ISDIR(s.st_mode)) { | 989 | if (!S_ISDIR(s.st_mode)) { |
@@ -944,7 +1019,7 @@ int remove_overlay_directory(void) { | |||
944 | // wait for the child to finish | 1019 | // wait for the child to finish |
945 | waitpid(child, NULL, 0); | 1020 | waitpid(child, NULL, 0); |
946 | // check if ~/.firejail was deleted | 1021 | // check if ~/.firejail was deleted |
947 | if (stat(path, &s) == 0) | 1022 | if (access(path, F_OK) == 0) |
948 | return 1; | 1023 | return 1; |
949 | } | 1024 | } |
950 | return 0; | 1025 | return 0; |
@@ -977,9 +1052,8 @@ void flush_stdin(void) { | |||
977 | int create_empty_dir_as_user(const char *dir, mode_t mode) { | 1052 | int create_empty_dir_as_user(const char *dir, mode_t mode) { |
978 | assert(dir); | 1053 | assert(dir); |
979 | mode &= 07777; | 1054 | mode &= 07777; |
980 | struct stat s; | ||
981 | 1055 | ||
982 | if (stat(dir, &s)) { | 1056 | if (access(dir, F_OK) != 0) { |
983 | if (arg_debug) | 1057 | if (arg_debug) |
984 | printf("Creating empty %s directory\n", dir); | 1058 | printf("Creating empty %s directory\n", dir); |
985 | pid_t child = fork(); | 1059 | pid_t child = fork(); |
@@ -1001,7 +1075,7 @@ int create_empty_dir_as_user(const char *dir, mode_t mode) { | |||
1001 | _exit(0); | 1075 | _exit(0); |
1002 | } | 1076 | } |
1003 | waitpid(child, NULL, 0); | 1077 | waitpid(child, NULL, 0); |
1004 | if (stat(dir, &s) == 0) | 1078 | if (access(dir, F_OK) == 0) |
1005 | return 1; | 1079 | return 1; |
1006 | } | 1080 | } |
1007 | return 0; | 1081 | return 0; |
@@ -1113,8 +1187,11 @@ unsigned extract_timeout(const char *str) { | |||
1113 | 1187 | ||
1114 | void disable_file_or_dir(const char *fname) { | 1188 | void disable_file_or_dir(const char *fname) { |
1115 | assert(fname); | 1189 | assert(fname); |
1190 | assert(geteuid() == 0); | ||
1116 | 1191 | ||
1192 | EUID_USER(); | ||
1117 | int fd = open(fname, O_PATH|O_CLOEXEC); | 1193 | int fd = open(fname, O_PATH|O_CLOEXEC); |
1194 | EUID_ROOT(); | ||
1118 | if (fd < 0) | 1195 | if (fd < 0) |
1119 | return; | 1196 | return; |
1120 | 1197 | ||