Skip to content

Commit

Permalink
add /run whitelist support
Browse files Browse the repository at this point in the history
note: firejail needs to run without /run/firejail
for a short time now, but fs_tmpfs() and the functions
called therein don't need it currently.
  • Loading branch information
smitsohu committed May 4, 2021
1 parent 5445d87 commit 44f3981
Showing 1 changed file with 50 additions and 15 deletions.
65 changes: 50 additions & 15 deletions src/firejail/fs_whitelist.c
Original file line number Diff line number Diff line change
Expand Up @@ -307,25 +307,56 @@ static void globbing(const char *pattern) {
}

// mount tmpfs on all top level directories
static void tmpfs_topdirs(TopDir *topdirs) {
// process user home directory first
static void tmpfs_topdirs(const TopDir *topdirs) {
// process "nested" top level directories first
int i;
for (i = 0; i < TOP_MAX && topdirs[i].path; i++) {
if (strcmp(topdirs[i].path, cfg.homedir) == 0) {
// user home directory
if (strcmp(topdirs[i].path, cfg.homedir) == 0)
fs_private();
break;
// /run/user/$UID
else if (strcmp(topdirs[i].path, runuser) == 0) {
fs_tmpfs(topdirs[i].path, 0);
selinux_relabel_path(topdirs[i].path, topdirs[i].path);
}
}

// process all other top level directories
for (i = 0; i < TOP_MAX && topdirs[i].path; i++) {
if (strcmp(topdirs[i].path, cfg.homedir) != 0) {
// mount the tmpfs
if (strcmp(topdirs[i].path, cfg.homedir) != 0 &&
strcmp(topdirs[i].path, runuser) != 0) {
// open /run/firejail, so it can be restored right after mounting the tmpfs
int fd = -1;
if (strcmp(topdirs[i].path, "/run") == 0) {
fd = open("/run/firejail", O_PATH|O_CLOEXEC);
if (fd == -1)
errExit("open");
}

// mount tmpfs
fs_tmpfs(topdirs[i].path, 0);
selinux_relabel_path(topdirs[i].path, topdirs[i].path);

// init tmpfs
// fix pam-tmpdir (#2685)
if (strcmp(topdirs[i].path, "/tmp") == 0) {
if (strcmp(topdirs[i].path, "/run") == 0) {
// bring back /run/firejail directory
if (mkdir("/run/firejail", 0755) == -1)
errExit("mkdir");
char *proc;
if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1)
errExit("asprintf");
if (mount(proc, "/run/firejail", NULL, MS_BIND | MS_REC, NULL) < 0)
errExit("mount bind");
free(proc);
close(fd);
fs_logger("whitelist /run/firejail");

// bring back /run/user/$UID directory
// get path relative to /run
const char *rel = runuser + 5;
whitelist_file(topdirs[i].fd, topdirs[i].path, rel, runuser);
}
else if (strcmp(topdirs[i].path, "/tmp") == 0) {
// fix pam-tmpdir (#2685)
const char *env = env_get("TMP");
if (env) {
char *pamtmpdir;
Expand All @@ -351,6 +382,8 @@ static void tmpfs_topdirs(TopDir *topdirs) {
const char *rel = cfg.homedir + topdir_len + 1;
whitelist_file(topdirs[i].fd, topdirs[i].path, rel, cfg.homedir);
}

selinux_relabel_path(topdirs[i].path, topdirs[i].path);
}
}
}
Expand All @@ -372,10 +405,9 @@ static int reject_topdir(const char *dir) {
static TopDir *add_topdir(const char *dir, TopDir *topdirs, const char *path) {
assert(dir && path);

// /proc, /run and /sys are not allowed
// /proc and /sys are not allowed
if (strcmp(dir, "/") == 0 ||
strcmp(dir, "/proc") == 0 ||
strcmp(dir, "/run") == 0 ||
strcmp(dir, "/sys") == 0)
whitelist_error(path);

Expand Down Expand Up @@ -448,14 +480,17 @@ static char *extract_topdir(const char *path) {
if (!dup)
errExit("strdup");

// user home is treated as top level directory
// user home directory can be anywhere; disconnect user home
// whitelisting from top level directory whitelisting
// by treating user home as separate whitelist top level directory
if (strncmp(dup, cfg.homedir, homedir_len) == 0 && dup[homedir_len] == '/')
dup[homedir_len] = '\0';
// whitelisting in /run and /sys is not allowed,
// but /run/user/$UID and /sys/module are exceptions
// and are treated as top level directories here
// /run/user/$UID is treated as top level directory
// (whitelisting in /run/user/$UID predated whitelisting in /run)
else if (strncmp(dup, runuser, runuser_len) == 0 && dup[runuser_len] == '/')
dup[runuser_len] = '\0';
// whitelisting in /sys is not allowed, but /sys/module is an exception
// and is treated as top level directory here
else if (strncmp(dup, "/sys/module", 11) == 0 && dup[11] == '/')
dup[11] = '\0';
// treat /usr subdirectories as top level directories
Expand Down

0 comments on commit 44f3981

Please sign in to comment.