Skip to content

Commit

Permalink
Merge pull request #4585 from smitsohu/euid
Browse files Browse the repository at this point in the history
add more EUID improvements
  • Loading branch information
smitsohu committed Oct 2, 2021
2 parents f391291 + 9e18bf8 commit d2389ec
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 59 deletions.
3 changes: 2 additions & 1 deletion src/fcopy/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ static void selinux_relabel_path(const char *path, const char *inside_path) {
if (arg_debug)
printf("Relabeling %s as %s (%s)\n", path, inside_path, fcon);

setfilecon_raw(procfs_path, fcon);
if (setfilecon_raw(procfs_path, fcon) != 0 && arg_debug)
printf("Cannot relabel %s: %s\n", path, strerror(errno));
}
freecon(fcon);
close:
Expand Down
12 changes: 5 additions & 7 deletions src/firejail/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,6 @@ static void disable_file(OPERATION op, const char *filename) {
}

fs_tmpfs(fname, uid);
EUID_USER(); // fs_tmpfs returns with EUID 0

selinux_relabel_path(fname, fname);
}
else
Expand Down Expand Up @@ -282,6 +280,8 @@ static void globbing(OPERATION op, const char *pattern, const char *noblacklist[

// blacklist files or directories by mounting empty files on top of them
void fs_blacklist(void) {
EUID_ASSERT();

ProfileEntry *entry = cfg.profile;
if (!entry)
return;
Expand All @@ -293,7 +293,6 @@ void fs_blacklist(void) {
if (noblacklist == NULL)
errExit("failed allocating memory for noblacklist entries");

EUID_USER();
while (entry) {
OPERATION op = OPERATION_MAX;
char *ptr;
Expand Down Expand Up @@ -469,8 +468,6 @@ void fs_blacklist(void) {
for (i = 0; i < noblacklist_c; i++)
free(noblacklist[i]);
free(noblacklist);

EUID_ROOT();
}

//***********************************************
Expand All @@ -479,7 +476,7 @@ void fs_blacklist(void) {

// mount a writable tmpfs on directory; requires a resolved path
void fs_tmpfs(const char *dir, unsigned check_owner) {
EUID_USER();
EUID_ASSERT();
assert(dir);
if (arg_debug)
printf("Mounting tmpfs on %s, check owner: %s\n", dir, (check_owner)? "yes": "no");
Expand All @@ -504,12 +501,13 @@ void fs_tmpfs(const char *dir, unsigned check_owner) {
errExit("fstatvfs");
unsigned long flags = buf.f_flag & ~(MS_RDONLY|MS_BIND|MS_REMOUNT);
// mount via the symbolic link in /proc/self/fd
EUID_ROOT();
char *proc;
if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1)
errExit("asprintf");
EUID_ROOT();
if (mount("tmpfs", proc, "tmpfs", flags|MS_NOSUID|MS_NODEV, options) < 0)
errExit("mounting tmpfs");
EUID_USER();
// check the last mount operation
MountData *mdata = get_last_mount();
if (strcmp(mdata->fstype, "tmpfs") != 0 || strcmp(mdata->dir, dir) != 0)
Expand Down
2 changes: 2 additions & 0 deletions src/firejail/fs_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -330,8 +330,10 @@ void fs_dev_disable_sound(void) {
}

// disable all jack sockets in /dev/shm
EUID_USER();
glob_t globbuf;
int globerr = glob("/dev/shm/jack*", GLOB_NOSORT, NULL, &globbuf);
EUID_ROOT();
if (globerr)
return;

Expand Down
11 changes: 7 additions & 4 deletions src/firejail/fs_home.c
Original file line number Diff line number Diff line change
Expand Up @@ -395,14 +395,16 @@ void fs_private(void) {
}
if (chown(homedir, u, g) < 0)
errExit("chown");

fs_logger2("mkdir", homedir);
fs_logger2("tmpfs", homedir);
}
else
else {
// mask user home directory
// the directory should be owned by the current user
EUID_USER();
fs_tmpfs(homedir, 1);
EUID_ROOT();
}

selinux_relabel_path(homedir, homedir);
}
Expand Down Expand Up @@ -564,12 +566,13 @@ void fs_private_home_list(void) {
int xflag = store_xauthority();
int aflag = store_asoundrc();

// create /run/firejail/mnt/home directory
EUID_ROOT();
// create /run/firejail/mnt/home directory
mkdir_attr(RUN_HOME_DIR, 0755, uid, gid);
selinux_relabel_path(RUN_HOME_DIR, homedir);

fs_logger_print(); // save the current log
// save the current log
fs_logger_print();
EUID_USER();

// copy the list of files in the new home directory
Expand Down
59 changes: 25 additions & 34 deletions src/firejail/fs_whitelist.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ static int whitelist_mkpath(const char* path, mode_t mode) {
}

static void whitelist_file(int dirfd, const char *relpath, const char *path) {
EUID_ASSERT();
assert(relpath && path);

// open mount source, using a file descriptor that refers to the
Expand All @@ -130,12 +131,9 @@ static void whitelist_file(int dirfd, const char *relpath, const char *path) {
}

// create mount target as root, except if inside home or run/user/$UID directory
int userprivs = 0;
if ((strncmp(path, cfg.homedir, homedir_len) == 0 && path[homedir_len] == '/') ||
(strncmp(path, runuser, runuser_len) == 0 && path[runuser_len] == '/')) {
EUID_USER();
userprivs = 1;
}
if ((strncmp(path, cfg.homedir, homedir_len) != 0 || path[homedir_len] != '/') &&
(strncmp(path, runuser, runuser_len) != 0 || path[runuser_len] != '/'))
EUID_ROOT();

// create path of the mount target
int fd2 = whitelist_mkpath(path, 0755);
Expand All @@ -146,8 +144,7 @@ static void whitelist_file(int dirfd, const char *relpath, const char *path) {
if (arg_debug || arg_debug_whitelists)
printf("Debug %d: skip whitelist %s\n", __LINE__, path);
close(fd);
if (userprivs)
EUID_ROOT();
EUID_USER();
return;
}

Expand All @@ -166,8 +163,7 @@ static void whitelist_file(int dirfd, const char *relpath, const char *path) {
}
close(fd);
close(fd2);
if (userprivs)
EUID_ROOT();
EUID_USER();
return;
}
fd3 = openat(fd2, file, O_PATH|O_DIRECTORY|O_|O_CLOEXEC);
Expand All @@ -184,19 +180,17 @@ static void whitelist_file(int dirfd, const char *relpath, const char *path) {
}
close(fd);
close(fd2);
if (userprivs)
EUID_ROOT();
EUID_USER();
return;
}

close(fd2);
if (userprivs)
EUID_ROOT();

if (arg_debug || arg_debug_whitelists)
printf("Whitelisting %s\n", path);
EUID_ROOT();
if (bind_mount_by_fd(fd, fd3))
errExit("mount bind");
EUID_USER();
// check the last mount operation
MountData *mptr = get_last_mount(); // will do exit(1) if the mount cannot be found
#ifdef TEST_MOUNTINFO
Expand All @@ -219,22 +213,19 @@ static void whitelist_file(int dirfd, const char *relpath, const char *path) {
}

static void whitelist_symlink(const char *link, const char *target) {
EUID_ASSERT();
assert(link && target);

// create files as root, except if inside home or run/user/$UID directory
int userprivs = 0;
if ((strncmp(link, cfg.homedir, homedir_len) == 0 && link[homedir_len] == '/') ||
(strncmp(link, runuser, runuser_len) == 0 && link[runuser_len] == '/')) {
EUID_USER();
userprivs = 1;
}
if ((strncmp(link, cfg.homedir, homedir_len) != 0 || link[homedir_len] != '/') &&
(strncmp(link, runuser, runuser_len) != 0 || link[runuser_len] != '/'))
EUID_ROOT();

int fd = whitelist_mkpath(link, 0755);
if (fd == -1) {
if (arg_debug || arg_debug_whitelists)
printf("Debug %d: cannot create symbolic link %s\n", __LINE__, link);
if (userprivs)
EUID_ROOT();
EUID_USER();
return;
}

Expand All @@ -252,8 +243,7 @@ static void whitelist_symlink(const char *link, const char *target) {
printf("Created symbolic link %s -> %s\n", link, target);

close(fd);
if (userprivs)
EUID_ROOT();
EUID_USER();
}

static void globbing(const char *pattern) {
Expand Down Expand Up @@ -330,10 +320,11 @@ static void tmpfs_topdirs(const TopDir *topdirs) {
// init tmpfs
if (strcmp(topdirs[i].path, "/run") == 0) {
// restore /run/firejail directory
if (mkdir(RUN_FIREJAIL_DIR, 0755) == -1)
errExit("mkdir");
EUID_ROOT();
mkdir_attr(RUN_FIREJAIL_DIR, 0755, 0, 0);
if (bind_mount_fd_to_path(fd, RUN_FIREJAIL_DIR))
errExit("mount bind");
EUID_USER();
close(fd);
fs_logger2("whitelist", RUN_FIREJAIL_DIR);

Expand All @@ -351,12 +342,14 @@ static void tmpfs_topdirs(const TopDir *topdirs) {
errExit("asprintf");
if (strcmp(env, pamtmpdir) == 0) {
// create empty user-owned /tmp/user/$UID directory
EUID_ROOT();
mkdir_attr("/tmp/user", 0711, 0, 0);
selinux_relabel_path("/tmp/user", "/tmp/user");
fs_logger("mkdir /tmp/user");
mkdir_attr(pamtmpdir, 0700, getuid(), 0);
selinux_relabel_path(pamtmpdir, pamtmpdir);
fs_logger2("mkdir", pamtmpdir);
EUID_USER();
}
free(pamtmpdir);
}
Expand All @@ -374,11 +367,8 @@ static void tmpfs_topdirs(const TopDir *topdirs) {
}

// user home directory
if (tmpfs_home) {
EUID_USER();
if (tmpfs_home)
fs_private(); // checks owner if outside /home
EUID_ROOT();
}

// /run/user/$UID directory
if (tmpfs_runuser) {
Expand All @@ -402,6 +392,7 @@ static int reject_topdir(const char *dir) {
// keep track of whitelist top level directories by adding them to an array
// open each directory
static TopDir *add_topdir(const char *dir, TopDir *topdirs, const char *path) {
EUID_ASSERT();
assert(dir && path);

// /proc and /sys are not allowed
Expand Down Expand Up @@ -516,6 +507,8 @@ static char *extract_topdir(const char *path) {
}

void fs_whitelist(void) {
EUID_ASSERT();

ProfileEntry *entry = cfg.profile;
if (!entry)
return;
Expand All @@ -536,7 +529,6 @@ void fs_whitelist(void) {
errExit("calloc");

// verify whitelist files, extract symbolic links, etc.
EUID_USER();
while (entry) {
int nowhitelist_flag = 0;

Expand Down Expand Up @@ -630,7 +622,7 @@ void fs_whitelist(void) {
if (!fname) {
if (arg_debug || arg_debug_whitelists) {
printf("Removed path: %s\n", entry->data);
printf("\texpanded: %s\n", new_name);
printf("\tnew_name: %s\n", new_name);
printf("\trealpath: (null)\n");
printf("\t%s\n", strerror(errno));
}
Expand Down Expand Up @@ -712,7 +704,6 @@ void fs_whitelist(void) {
free(nowhitelist);

// mount tmpfs on all top level directories
EUID_ROOT();
tmpfs_topdirs(topdirs);

// go through profile rules again, and interpret whitelist commands
Expand Down
2 changes: 2 additions & 0 deletions src/firejail/sandbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -1004,10 +1004,12 @@ int sandbox(void* sandbox_arg) {
// apply the profile file
//****************************
// apply all whitelist commands ...
EUID_USER();
fs_whitelist();

// ... followed by blacklist commands
fs_blacklist(); // mkdir and mkfile are processed all over again
EUID_ROOT();

//****************************
// nosound/no3d/notv/novideo and fix for pulseaudio 7.0
Expand Down
21 changes: 20 additions & 1 deletion src/firejail/selinux.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "firejail.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>

#include <fcntl.h>
#ifndef O_PATH
Expand Down Expand Up @@ -57,7 +58,17 @@ void selinux_relabel_path(const char *path, const char *inside_path)

/* Open the file as O_PATH, to pin it while we determine and adjust the label
* Defeat symlink races by not allowing symbolic links */
int called_as_root = 0;
if (geteuid() == 0)
called_as_root = 1;
if (called_as_root)
EUID_USER();

fd = safer_openat(-1, path, O_|O_CLOEXEC|O_PATH);

if (called_as_root)
EUID_ROOT();

if (fd < 0)
return;
if (fstat(fd, &st) < 0)
Expand All @@ -68,8 +79,16 @@ void selinux_relabel_path(const char *path, const char *inside_path)
if (arg_debug)
printf("Relabeling %s as %s (%s)\n", path, inside_path, fcon);

setfilecon_raw(procfs_path, fcon);
if (!called_as_root)
EUID_ROOT();

if (setfilecon_raw(procfs_path, fcon) != 0 && arg_debug)
printf("Cannot relabel %s: %s\n", path, strerror(errno));

if (!called_as_root)
EUID_USER();
}

freecon(fcon);
close:
close(fd);
Expand Down
14 changes: 2 additions & 12 deletions src/firejail/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -459,31 +459,21 @@ int is_dir(const char *fname) {
if (*fname == '\0')
return 0;

int called_as_root = 0;
if (geteuid() == 0)
called_as_root = 1;

if (called_as_root)
EUID_USER();

// if fname doesn't end in '/', add one
int rv;
struct stat s;
if (fname[strlen(fname) - 1] == '/')
rv = stat(fname, &s);
rv = stat_as_user(fname, &s);
else {
char *tmp;
if (asprintf(&tmp, "%s/", fname) == -1) {
fprintf(stderr, "Error: cannot allocate memory, %s:%d\n", __FILE__, __LINE__);
errExit("asprintf");
}
rv = stat(tmp, &s);
rv = stat_as_user(tmp, &s);
free(tmp);
}

if (called_as_root)
EUID_ROOT();

if (rv == -1)
return 0;

Expand Down

0 comments on commit d2389ec

Please sign in to comment.