From 1e01430bdfcb63c9f8027ddbb204a224cb179576 Mon Sep 17 00:00:00 2001 From: smitsohu Date: Wed, 22 Aug 2018 11:03:17 +0200 Subject: drop privs when permissions are changed in /run/user/$UID --- src/firejail/fs.c | 44 ++++++++++++++++++++++++++++++++++++++++---- src/firejail/util.c | 6 +++--- 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/firejail/fs.c b/src/firejail/fs.c index 24ff553d7..8db14d502 100644 --- a/src/firejail/fs.c +++ b/src/firejail/fs.c @@ -641,8 +641,26 @@ void fs_proc_sys_dev_boot(void) { char *fnamegpg; if (asprintf(&fnamegpg, "/run/user/%d/gnupg", getuid()) == -1) errExit("asprintf"); - if (stat(fnamegpg, &s) == -1) - mkdir_attr(fnamegpg, 0700, getuid(), getgid()); + if (stat(fnamegpg, &s) == -1) { + pid_t child = fork(); + if (child < 0) + errExit("fork"); + if (child == 0) { + // drop privileges + drop_privs(0); + if (mkdir(fnamegpg, 0700) == -1) + {;} // do nothing + if (set_perms(fnamegpg, -1, -1, 0700)) + {;} +#ifdef HAVE_GCOV + __gcov_flush(); +#endif + _exit(0); + } + // wait for the child to finish + waitpid(child, NULL, 0); + fs_logger2("create", fnamegpg); + } if (stat(fnamegpg, &s) == 0) disable_file(BLACKLIST_FILE, fnamegpg); free(fnamegpg); @@ -651,8 +669,26 @@ void fs_proc_sys_dev_boot(void) { char *fnamesysd; if (asprintf(&fnamesysd, "/run/user/%d/systemd", getuid()) == -1) errExit("asprintf"); - if (stat(fnamesysd, &s) == -1) - mkdir_attr(fnamesysd, 0755, getuid(), getgid()); + if (stat(fnamesysd, &s) == -1) { + pid_t child = fork(); + if (child < 0) + errExit("fork"); + if (child == 0) { + // drop privileges + drop_privs(0); + if (mkdir(fnamesysd, 0755) == -1) + {;} // do nothing + if (set_perms(fnamesysd, -1, -1, 0755)) + {;} +#ifdef HAVE_GCOV + __gcov_flush(); +#endif + _exit(0); + } + // wait for the child to finish + waitpid(child, NULL, 0); + fs_logger2("create", fnamesysd); + } if (stat(fnamesysd, &s) == 0) disable_file(BLACKLIST_FILE, fnamesysd); free(fnamesysd); diff --git a/src/firejail/util.c b/src/firejail/util.c index c15e3b691..86faaf8b8 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c @@ -1053,7 +1053,7 @@ int safe_fd(const char *path, int flags) { errExit("open"); // traverse the path and return -1 if a symlink is encountered - int entered = 0; + int weird_pathname = 1; int fd = -1; char *tok = strtok(dup, "/"); while (tok) { @@ -1062,7 +1062,7 @@ int safe_fd(const char *path, int flags) { tok = strtok(NULL, "/"); continue; } - entered = 1; + weird_pathname = 0; // open the directory fd = openat(parentfd, tok, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); @@ -1077,7 +1077,7 @@ int safe_fd(const char *path, int flags) { } if (p != dup) { // consistent flags for top level directories (////foo, /.///foo) - if (!entered) + if (weird_pathname) flags = O_PATH|O_DIRECTORY|O_CLOEXEC; // open last path segment fd = openat(parentfd, p + 1, flags|O_NOFOLLOW); -- cgit v1.2.3-54-g00ecf