Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Whitelist2 #4229

Merged
merged 5 commits into from
May 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions etc/firejail.config
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@
# Enable or disable whitelisting support, default enabled.
# whitelist yes

# Disable whitelist top level directories, in addition to those
# that are disabled out of the box. None by default; this is an example.
# whitelist-disable-topdir /etc,/usr/etc

# Enable or disable X11 sandboxing support, default enabled.
# x11 yes

Expand Down
26 changes: 26 additions & 0 deletions src/firejail/checkcfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ char *xvfb_extra_params = "";
char *netfilter_default = NULL;
unsigned long join_timeout = 5000000; // microseconds
char *config_seccomp_error_action_str = "EPERM";
char **whitelist_reject_topdirs = NULL;

int checkcfg(int val) {
assert(val < CFG_MAX);
Expand Down Expand Up @@ -238,6 +239,31 @@ int checkcfg(int val) {
errExit("strdup");
}

else if (strncmp(ptr, "whitelist-disable-topdir ", 25) == 0) {
char *str = strdup(ptr + 25);
if (!str)
errExit("strdup");

size_t cnt = 0;
size_t sz = 4;
whitelist_reject_topdirs = malloc(sz * sizeof(char *));
if (!whitelist_reject_topdirs)
errExit("malloc");

char *tok = strtok(str, ",");
while (tok) {
whitelist_reject_topdirs[cnt++] = tok;
if (cnt >= sz) {
sz *= 2;
whitelist_reject_topdirs = realloc(whitelist_reject_topdirs, sz * sizeof(char *));
if (!whitelist_reject_topdirs)
errExit("realloc");
}
tok = strtok(NULL, ",");
}
whitelist_reject_topdirs[cnt] = NULL;
}

else
goto errout;

Expand Down
8 changes: 4 additions & 4 deletions src/firejail/chroot.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,9 @@ void fs_chroot(const char *rootdir) {
assert(rootdir);

// fails if there is any symlink or if rootdir is not a directory
int parentfd = safe_fd(rootdir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
int parentfd = safer_openat(-1, rootdir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
if (parentfd == -1)
errExit("safe_fd");
errExit("safer_openat");
// rootdir has to be owned by root and is not allowed to be generally writable,
// this also excludes /tmp and friends
struct stat s;
Expand Down Expand Up @@ -215,12 +215,12 @@ void fs_chroot(const char *rootdir) {

if (arg_debug)
printf("Mounting %s on chroot %s\n", orig_pulse, orig_pulse);
int src = safe_fd(orig_pulse, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
int src = safer_openat(-1, orig_pulse, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
if (src == -1) {
fprintf(stderr, "Error: cannot open %s\n", orig_pulse);
exit(1);
}
int dst = safe_fd(pulse, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
int dst = safer_openat(-1, pulse, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
if (dst == -1) {
fprintf(stderr, "Error: cannot open %s\n", pulse);
exit(1);
Expand Down
2 changes: 1 addition & 1 deletion src/firejail/dbus.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ void dbus_proxy_stop(void) {
}

static void socket_overlay(char *socket_path, char *proxy_path) {
int fd = safe_fd(proxy_path, O_PATH | O_NOFOLLOW | O_CLOEXEC);
int fd = safer_openat(-1, proxy_path, O_PATH | O_NOFOLLOW | O_CLOEXEC);
if (fd == -1)
errExit("opening DBus proxy socket");
struct stat s;
Expand Down
29 changes: 13 additions & 16 deletions src/firejail/firejail.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,26 +122,22 @@ typedef struct interface_t {
uint8_t configured;
} Interface;

typedef struct topdir_t {
char *path;
int fd;
} TopDir;

typedef struct profile_entry_t {
struct profile_entry_t *next;
char *data; // command

// whitelist command parameters
char *link; // link name - set if the file is a link
enum {
WLDIR_HOME = 1, // whitelist in home directory
WLDIR_TMP, // whitelist in /tmp directory
WLDIR_MEDIA, // whitelist in /media directory
WLDIR_MNT, // whitelist in /mnt directory
WLDIR_VAR, // whitelist in /var directory
WLDIR_DEV, // whitelist in /dev directory
WLDIR_OPT, // whitelist in /opt directory
WLDIR_SRV, // whitelist in /srv directory
WLDIR_ETC, // whitelist in /etc directory
WLDIR_SHARE, // whitelist in /usr/share directory
WLDIR_MODULE, // whitelist in /sys/module directory
WLDIR_RUN // whitelist in /run/user/$uid directory
} wldir;
struct wparam_t {
char *file; // resolved file path
char *link; // link path
TopDir *top; // top level directory
} *wparam;

} ProfileEntry;

typedef struct config_t {
Expand Down Expand Up @@ -528,7 +524,7 @@ void mkdir_attr(const char *fname, mode_t mode, uid_t uid, gid_t gid);
unsigned extract_timeout(const char *str);
void disable_file_or_dir(const char *fname);
void disable_file_path(const char *path, const char *file);
int safe_fd(const char *path, int flags);
int safer_openat(int dirfd, const char *path, int flags);
int has_handler(pid_t pid, int signal);
void enter_network_namespace(pid_t pid);
int read_pid(const char *name, pid_t *pid);
Expand Down Expand Up @@ -792,6 +788,7 @@ extern char *xvfb_extra_params;
extern char *netfilter_default;
extern unsigned long join_timeout;
extern char *config_seccomp_error_action_str;
extern char **whitelist_reject_topdirs;

int checkcfg(int val);
void print_compiletime_support(void);
Expand Down
10 changes: 5 additions & 5 deletions src/firejail/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ void fs_tmpfs(const char *dir, unsigned check_owner) {
if (arg_debug)
printf("Mounting tmpfs on %s, check owner: %s\n", dir, (check_owner)? "yes": "no");
// get a file descriptor for dir, fails if there is any symlink
int fd = safe_fd(dir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
int fd = safer_openat(-1, dir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
if (fd == -1)
errExit("while opening directory");
struct stat s;
Expand Down Expand Up @@ -493,7 +493,7 @@ static void fs_remount_simple(const char *path, OPERATION op) {
assert(path);

// open path without following symbolic links
int fd1 = safe_fd(path, O_PATH|O_NOFOLLOW|O_CLOEXEC);
int fd1 = safer_openat(-1, path, O_PATH|O_NOFOLLOW|O_CLOEXEC);
if (fd1 == -1)
goto out;
struct stat s1;
Expand Down Expand Up @@ -559,7 +559,7 @@ static void fs_remount_simple(const char *path, OPERATION op) {

// mount --bind -o remount,ro path
// need to open path again without following symbolic links
int fd2 = safe_fd(path, O_PATH|O_NOFOLLOW|O_CLOEXEC);
int fd2 = safer_openat(-1, path, O_PATH|O_NOFOLLOW|O_CLOEXEC);
if (fd2 == -1)
errExit("open");
struct stat s2;
Expand Down Expand Up @@ -992,9 +992,9 @@ void fs_overlayfs(void) {
char *firejail;
if (asprintf(&firejail, "%s/.firejail", cfg.homedir) == -1)
errExit("asprintf");
int fd = safe_fd(firejail, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
int fd = safer_openat(-1, firejail, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
if (fd == -1)
errExit("safe_fd");
errExit("safer_openat");
free(firejail);
// create basedir if it doesn't exist
// the new directory will be owned by root
Expand Down
6 changes: 3 additions & 3 deletions src/firejail/fs_home.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,10 +262,10 @@ void fs_private_homedir(void) {
if (arg_debug)
printf("Mount-bind %s on top of %s\n", private_homedir, homedir);
// get file descriptors for homedir and private_homedir, fails if there is any symlink
int src = safe_fd(private_homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
int src = safer_openat(-1, private_homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
if (src == -1)
errExit("opening private directory");
int dst = safe_fd(homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
int dst = safer_openat(-1, homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
if (dst == -1)
errExit("opening home directory");
// both mount source and target should be owned by the user
Expand Down Expand Up @@ -576,7 +576,7 @@ void fs_private_home_list(void) {
if (arg_debug)
printf("Mount-bind %s on top of %s\n", RUN_HOME_DIR, homedir);

int fd = safe_fd(homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
int fd = safer_openat(-1, homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
if (fd == -1)
errExit("opening home directory");
// home directory should be owned by the user
Expand Down
Loading