Skip to content

Commit

Permalink
Postpone installation of seccomp filters just before execve
Browse files Browse the repository at this point in the history
  • Loading branch information
topimiettinen committed Aug 19, 2017
1 parent 085027f commit 85bb547
Show file tree
Hide file tree
Showing 9 changed files with 93 additions and 26 deletions.
3 changes: 3 additions & 0 deletions src/firejail/bandwidth.c
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,9 @@ void bandwidth_pid(pid_t pid, const char *command, const char *dev, int down, in
arg[2] = cmd;
arg[3] = NULL;
clearenv();
#ifdef HAVE_SECCOMP
seccomp_install_filters();
#endif
execvp(arg[0], arg);

// it will never get here
Expand Down
1 change: 1 addition & 0 deletions src/firejail/firejail.h
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,7 @@ void fs_private_home_list(void);

// seccomp.c
char *seccomp_check_list(const char *str);
int seccomp_install_filters(void);
int seccomp_load(const char *fname);
void seccomp_filter_32(void);
void seccomp_filter_64(void);
Expand Down
3 changes: 3 additions & 0 deletions src/firejail/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ void check_output(int argc, char **argv) {
a[2] = cmd;
a[3] = NULL;

#ifdef HAVE_SECCOMP
seccomp_install_filters();
#endif
execvp(a[0], a);

perror("execvp");
Expand Down
20 changes: 16 additions & 4 deletions src/firejail/sandbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,9 @@ void start_audit(void) {
if (asprintf(&audit_prog, "%s/firejail/faudit", LIBDIR) == -1)
errExit("asprintf");
assert(getenv("LD_PRELOAD") == NULL);
#ifdef HAVE_SECCOMP
seccomp_install_filters();
#endif
execl(audit_prog, audit_prog, NULL);
perror("execl");
exit(1);
Expand Down Expand Up @@ -367,7 +370,10 @@ void start_application(void) {
if (arg_audit) {
assert(arg_audit_prog);
#ifdef HAVE_GCOV
__gcov_dump();
__gcov_dump();
#endif
#ifdef HAVE_SECCOMP
seccomp_install_filters();
#endif
execl(arg_audit_prog, arg_audit_prog, NULL);
}
Expand All @@ -394,7 +400,10 @@ void start_application(void) {

int rv = ok_to_run(cfg.original_argv[cfg.original_program_index]);
#ifdef HAVE_GCOV
__gcov_dump();
__gcov_dump();
#endif
#ifdef HAVE_SECCOMP
seccomp_install_filters();
#endif
if (rv)
execvp(cfg.original_argv[cfg.original_program_index], &cfg.original_argv[cfg.original_program_index]);
Expand Down Expand Up @@ -447,7 +456,10 @@ void start_application(void) {
if (!arg_command && !arg_quiet)
print_time();
#ifdef HAVE_GCOV
__gcov_dump();
__gcov_dump();
#endif
#ifdef HAVE_SECCOMP
seccomp_install_filters();
#endif
execvp(arg[0], arg);
}
Expand Down Expand Up @@ -988,7 +1000,7 @@ int sandbox(void* sandbox_arg) {
if (cfg.cgroup)
save_cgroup();

// set seccomp //todo: push it down after drop_privs and/or configuring noroot
// set seccomp
#ifdef HAVE_SECCOMP
// install protocol filter
#ifdef SYS_socket
Expand Down
5 changes: 4 additions & 1 deletion src/firejail/sbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,11 +205,14 @@ int sbox_run(unsigned filter, int num, ...) {
if (arg_quiet)
setenv("FIREJAIL_QUIET", "yes", 1);

#ifdef HAVE_SECCOMP
seccomp_install_filters();
#endif
if (arg[0]) // get rid of scan-build warning
execvp(arg[0], arg);
else
assert(0);
perror("execl");
perror("execvp");
_exit(1);
}

Expand Down
49 changes: 34 additions & 15 deletions src/firejail/seccomp.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@
#include "../include/seccomp.h"
#include <sys/mman.h>

typedef struct filter_list {
struct filter_list *next;
struct sock_fprog prog;
} FilterList;

static FilterList *filter_list_head = NULL;

static int err_printed = 0;

char *seccomp_check_list(const char *str) {
Expand Down Expand Up @@ -52,6 +59,24 @@ char *seccomp_check_list(const char *str) {
return rv;
}

// install seccomp filters
int seccomp_install_filters(void) {
int r = 0;
FilterList *fl = filter_list_head;
if (fl) {
prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);

for (; fl; fl = fl->next) {
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &fl->prog)) {
if (!err_printed)
fwarning("seccomp disabled, it requires a Linux kernel version 3.5 or newer.\n");
err_printed = 1;
r = 1;
}
}
}
return r;
}

int seccomp_load(const char *fname) {
assert(fname);
Expand All @@ -77,22 +102,16 @@ int seccomp_load(const char *fname) {
// close file
close(fd);

// install filter
struct sock_fprog prog = {
.len = entries,
.filter = filter,
};
int r = 0;
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) || prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
if (!err_printed)
fwarning("seccomp disabled, it requires a Linux kernel version 3.5 or newer.\n");
err_printed = 1;
r = 1;
FilterList *fl = malloc(sizeof(FilterList));
if (!fl) {
fprintf(stderr, "Error: cannot allocate memory\n");
exit(1);
}

munmap(filter, size);
return r;

fl->next = filter_list_head;
fl->prog.len = entries;
fl->prog.filter = filter;
filter_list_head = fl;
return 0;
errexit:
fprintf(stderr, "Error: cannot read %s\n", fname);
exit(1);
Expand Down
30 changes: 30 additions & 0 deletions src/firejail/x11.c
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,9 @@ void x11_start_xvfb(int argc, char **argv) {

// running without privileges - see drop_privs call above
assert(getenv("LD_PRELOAD") == NULL);
#ifdef HAVE_SECCOMP
seccomp_install_filters();
#endif
execvp(server_argv[0], server_argv);
perror("execvp");
_exit(1);
Expand Down Expand Up @@ -365,6 +368,9 @@ void x11_start_xvfb(int argc, char **argv) {

// running without privileges - see drop_privs call above
assert(getenv("LD_PRELOAD") == NULL);
#ifdef HAVE_SECCOMP
seccomp_install_filters();
#endif
execvp(jail_argv[0], jail_argv);
perror("execvp");
_exit(1);
Expand Down Expand Up @@ -557,6 +563,9 @@ void x11_start_xephyr(int argc, char **argv) {

// running without privileges - see drop_privs call above
assert(getenv("LD_PRELOAD") == NULL);
#ifdef HAVE_SECCOMP
seccomp_install_filters();
#endif
execvp(server_argv[0], server_argv);
perror("execvp");
_exit(1);
Expand Down Expand Up @@ -601,6 +610,9 @@ void x11_start_xephyr(int argc, char **argv) {

// running without privileges - see drop_privs call above
assert(getenv("LD_PRELOAD") == NULL);
#ifdef HAVE_SECCOMP
seccomp_install_filters();
#endif
execvp(jail_argv[0], jail_argv);
perror("execvp");
_exit(1);
Expand Down Expand Up @@ -730,6 +742,9 @@ void x11_start_xpra_old(int argc, char **argv, int display, char *display_str) {

// running without privileges - see drop_privs call above
assert(getenv("LD_PRELOAD") == NULL);
#ifdef HAVE_SECCOMP
seccomp_install_filters();
#endif
execvp(server_argv[0], server_argv);
perror("execvp");
_exit(1);
Expand Down Expand Up @@ -781,6 +796,9 @@ void x11_start_xpra_old(int argc, char **argv, int display, char *display_str) {

// running without privileges - see drop_privs call above
assert(getenv("LD_PRELOAD") == NULL);
#ifdef HAVE_SECCOMP
seccomp_install_filters();
#endif
execvp(attach_argv[0], attach_argv);
perror("execvp");
_exit(1);
Expand Down Expand Up @@ -810,6 +828,9 @@ void x11_start_xpra_old(int argc, char **argv, int display, char *display_str) {
if (jail == 0) {
// running without privileges - see drop_privs call above
assert(getenv("LD_PRELOAD") == NULL);
#ifdef HAVE_SECCOMP
seccomp_install_filters();
#endif
if (firejail_argv[0]) // shut up llvm scan-build
execvp(firejail_argv[0], firejail_argv);
perror("execvp");
Expand Down Expand Up @@ -838,6 +859,9 @@ void x11_start_xpra_old(int argc, char **argv, int display, char *display_str) {
}
// running without privileges - see drop_privs call above
assert(getenv("LD_PRELOAD") == NULL);
#ifdef HAVE_SECCOMP
seccomp_install_filters();
#endif
execvp(stop_argv[0], stop_argv);
perror("execvp");
_exit(1);
Expand Down Expand Up @@ -1004,6 +1028,9 @@ void x11_start_xpra_new(int argc, char **argv, char *display_str) {

// running without privileges - see drop_privs call above
assert(getenv("LD_PRELOAD") == NULL);
#ifdef HAVE_SECCOMP
seccomp_install_filters();
#endif
execvp(server_argv[0], server_argv);
perror("execvp");
_exit(1);
Expand Down Expand Up @@ -1140,6 +1167,9 @@ void x11_xorg(void) {
clearenv();
#ifdef HAVE_GCOV
__gcov_flush();
#endif
#ifdef HAVE_SECCOMP
seccomp_install_filters();
#endif
execlp("/usr/bin/xauth", "/usr/bin/xauth", "-v", "-f", tmpfname,
"generate", display, "MIT-MAGIC-COOKIE-1", "untrusted", NULL);
Expand Down
6 changes: 1 addition & 5 deletions src/fseccomp/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,12 +182,8 @@ static const SyscallGroupList sysgroups[] = {
#endif
},
{ .name = "@default-keep", .list =
"dup,"
"execve,"
"prctl,"
"setgid,"
"setgroups,"
"setuid"
"prctl"
},
{ .name = "@module", .list =
#ifdef SYS_delete_module
Expand Down
2 changes: 1 addition & 1 deletion src/man/firejail.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1687,7 +1687,7 @@ rm: cannot remove `testfile': Operation not permitted
\fB\-\-seccomp.keep=syscall,syscall,syscall
Enable seccomp filter, and whitelist the syscalls specified by the
command. The system calls needed by Firejail (group @default-keep:
dup, prctl, setgid, setgroups, setuid) are always whitelisted.
prctl, execve) are handled with the preload library.
.br

.br
Expand Down

0 comments on commit 85bb547

Please sign in to comment.