Skip to content

Commit

Permalink
seccomp: allow defining separate filters for 32-bit arch
Browse files Browse the repository at this point in the history
System calls (names and numbers) are not exactly the same for 32 bit
and 64 bit architectures. Let's allow defining separate filters for
32-bit arch using seccomp.32, seccomp.32.drop, seccomp.32.keep. This
is useful for mixed 64/32 bit application environments like Steam and
Wine.

Implement protocol and mdwx filtering also for 32 bit arch. It's still
better to block secondary archs completely if not needed.

Lists of supported system calls are also updated.

Warn if preload libraries would be needed due to trace, tracelog or
postexecseccomp (seccomp.drop=execve etc), because a 32-bit dynamic
linker does not understand the 64 bit preload libraries.

Closes #3267.

Signed-off-by: Topi Miettinen <[email protected]>
  • Loading branch information
topimiettinen committed Mar 28, 2020
1 parent ec0a097 commit 88eadbf
Show file tree
Hide file tree
Showing 29 changed files with 1,330 additions and 5,388 deletions.
4 changes: 3 additions & 1 deletion Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ MYLIBS = src/lib
APPS = src/firejail src/firemon src/fsec-print src/fsec-optimize src/firecfg src/fnetfilter src/libtrace src/libtracelog src/ftee \
src/faudit src/fnet src/fseccomp src/fbuilder src/fcopy src/fldd src/libpostexecseccomp src/profstats
MANPAGES = firejail.1 firemon.1 firecfg.1 firejail-profile.5 firejail-login.5 firejail-users.5
SECCOMP_FILTERS = seccomp seccomp.debug seccomp.32 seccomp.block_secondary seccomp.mdwx
SECCOMP_FILTERS = seccomp seccomp.debug seccomp.32 seccomp.block_secondary seccomp.mdwx seccomp.mdwx.32

prefix=@prefix@
exec_prefix=@exec_prefix@
Expand Down Expand Up @@ -48,6 +48,7 @@ ifeq ($(HAVE_SECCOMP),-DHAVE_SECCOMP)
src/fsec-optimize/fsec-optimize seccomp.32
src/fseccomp/fseccomp secondary block seccomp.block_secondary
src/fseccomp/fseccomp memory-deny-write-execute seccomp.mdwx
src/fseccomp/fseccomp memory-deny-write-execute.32 seccomp.mdwx.32
endif

clean:
Expand Down Expand Up @@ -109,6 +110,7 @@ ifeq ($(HAVE_SECCOMP),-DHAVE_SECCOMP)
install -c -m 0644 seccomp.32 $(DESTDIR)/$(libdir)/firejail/.
install -c -m 0644 seccomp.block_secondary $(DESTDIR)/$(libdir)/firejail/.
install -c -m 0644 seccomp.mdwx $(DESTDIR)/$(libdir)/firejail/.
install -c -m 0644 seccomp.mdwx.32 $(DESTDIR)/$(libdir)/firejail/.
endif
ifeq ($(HAVE_CONTRIB_INSTALL),yes)
install -c -m 0755 contrib/fix_private-bin.py $(DESTDIR)/$(libdir)/firejail/.
Expand Down
2 changes: 1 addition & 1 deletion src/bash_completion/firejail.bash_completion
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ _firejail()
_init_completion -s || return

case $prev in
--help|--version|-debug-caps|--debug-syscalls|--list|--tree|--top|--join|--shutdown)
--help|--version|-debug-caps|--debug-syscalls|--debug-syscalls32|--list|--tree|--top|--join|--shutdown)
return 0
;;
--profile)
Expand Down
6 changes: 3 additions & 3 deletions src/firejail/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ all: firejail

include ../common.mk

%.o : %.c $(H_FILE_LIST) ../include/rundefs.h ../include/common.h ../include/ldd_utils.h ../include/euid_common.h ../include/pid.h ../include/seccomp.h ../include/syscall.h ../include/firejail_user.h
%.o : %.c $(H_FILE_LIST) ../include/rundefs.h ../include/common.h ../include/ldd_utils.h ../include/euid_common.h ../include/pid.h ../include/seccomp.h ../include/syscall_i386.h ../include/syscall_x86_64.h ../include/firejail_user.h
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDE) -c $< -o $@

firejail: $(OBJS) ../lib/libnetlink.o ../lib/common.o ../lib/ldd_utils.o ../lib/firejail_user.o
$(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/ldd_utils.o ../lib/firejail_user.o $(LIBS) $(EXTRA_LDFLAGS)
firejail: $(OBJS) ../lib/libnetlink.o ../lib/common.o ../lib/ldd_utils.o ../lib/firejail_user.o ../lib/errno.o ../lib/syscall.o
$(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/ldd_utils.o ../lib/firejail_user.o ../lib/errno.o ../lib/syscall.o $(LIBS) $(EXTRA_LDFLAGS)

clean:; rm -fr *.o firejail *.gcov *.gcda *.gcno *.plist

Expand Down
11 changes: 6 additions & 5 deletions src/firejail/firejail.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,9 @@ typedef struct config_t {
char *dns4;

// seccomp
char *seccomp_list;// optional seccomp list on top of default filter
char *seccomp_list_drop; // seccomp drop list
char *seccomp_list_keep; // seccomp keep list
char *seccomp_list, *seccomp_list32; // optional seccomp list on top of default filter
char *seccomp_list_drop, *seccomp_list_drop32; // seccomp drop list
char *seccomp_list_keep, *seccomp_list_keep32; // seccomp keep list
char *protocol; // protocol list

// rlimits
Expand Down Expand Up @@ -270,6 +270,7 @@ extern int arg_overlay_keep; // place overlay diff in a known directory
extern int arg_overlay_reuse; // allow the reuse of overlays

extern int arg_seccomp; // enable default seccomp filter
extern int arg_seccomp32; // enable default seccomp filter for 32 bit arch
extern int arg_seccomp_postexec; // need postexec ld.preload library?
extern int arg_seccomp_block_secondary; // block any secondary architectures

Expand Down Expand Up @@ -568,8 +569,8 @@ void fs_private_home_list(void);
char *seccomp_check_list(const char *str);
int seccomp_install_filters(void);
int seccomp_load(const char *fname);
int seccomp_filter_drop(void);
int seccomp_filter_keep(void);
int seccomp_filter_drop(bool native);
int seccomp_filter_keep(bool native);
void seccomp_print_filter(pid_t pid);

// caps.c
Expand Down
70 changes: 70 additions & 0 deletions src/firejail/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "firejail.h"
#include "../include/pid.h"
#include "../include/firejail_user.h"
#include "../include/syscall.h"
#define _GNU_SOURCE
#include <sys/utsname.h>
#include <sched.h>
Expand Down Expand Up @@ -72,6 +73,7 @@ int arg_overlay_keep = 0; // place overlay diff in a known directory
int arg_overlay_reuse = 0; // allow the reuse of overlays

int arg_seccomp = 0; // enable default seccomp filter
int arg_seccomp32 = 0; // enable default seccomp filter for 32 bit arch
int arg_seccomp_postexec = 0; // need postexec ld.preload library?
int arg_seccomp_block_secondary = 0; // block any secondary architectures

Expand Down Expand Up @@ -548,6 +550,14 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
else
exit_err_feature("seccomp");
}
else if (strcmp(argv[i], "--debug-syscalls32") == 0) {
if (checkcfg(CFG_SECCOMP)) {
int rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 2, PATH_FSECCOMP_MAIN, "debug-syscalls32");
exit(rv);
}
else
exit_err_feature("seccomp");
}
else if (strcmp(argv[i], "--debug-errnos") == 0) {
if (checkcfg(CFG_SECCOMP)) {
int rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 2, PATH_FSECCOMP_MAIN, "debug-errnos");
Expand Down Expand Up @@ -956,6 +966,18 @@ static void run_builder(int argc, char **argv) {
exit(1);
}

void filter_add_errno(int fd, int syscall, int arg, void *ptrarg, bool native) {}

static int check_postexec(const char *list) {
char *prelist, *postlist;

if (list) {
syscalls_in_list(list, "@default-keep", -1, &prelist, &postlist, true);
if (postlist)
return 1;
}
return 0;
}

//*******************************************
// Main program
Expand Down Expand Up @@ -1263,6 +1285,18 @@ int main(int argc, char **argv) {
else
exit_err_feature("seccomp");
}
else if (strncmp(argv[i], "--seccomp.32=", 13) == 0) {
if (checkcfg(CFG_SECCOMP)) {
if (arg_seccomp32) {
fprintf(stderr, "Error: seccomp.32 already enabled\n");
exit(1);
}
arg_seccomp32 = 1;
cfg.seccomp_list32 = seccomp_check_list(argv[i] + 13);
}
else
exit_err_feature("seccomp");
}
else if (strncmp(argv[i], "--seccomp.drop=", 15) == 0) {
if (checkcfg(CFG_SECCOMP)) {
if (arg_seccomp) {
Expand All @@ -1275,6 +1309,18 @@ int main(int argc, char **argv) {
else
exit_err_feature("seccomp");
}
else if (strncmp(argv[i], "--seccomp.32.drop=", 18) == 0) {
if (checkcfg(CFG_SECCOMP)) {
if (arg_seccomp32) {
fprintf(stderr, "Error: seccomp.32 already enabled\n");
exit(1);
}
arg_seccomp32 = 1;
cfg.seccomp_list_drop32 = seccomp_check_list(argv[i] + 18);
}
else
exit_err_feature("seccomp");
}
else if (strncmp(argv[i], "--seccomp.keep=", 15) == 0) {
if (checkcfg(CFG_SECCOMP)) {
if (arg_seccomp) {
Expand All @@ -1287,8 +1333,24 @@ int main(int argc, char **argv) {
else
exit_err_feature("seccomp");
}
else if (strncmp(argv[i], "--seccomp.32.keep=", 18) == 0) {
if (checkcfg(CFG_SECCOMP)) {
if (arg_seccomp32) {
fprintf(stderr, "Error: seccomp.32 already enabled\n");
exit(1);
}
arg_seccomp32 = 1;
cfg.seccomp_list_keep32 = seccomp_check_list(argv[i] + 18);
}
else
exit_err_feature("seccomp");
}
else if (strcmp(argv[i], "--seccomp.block-secondary") == 0) {
if (checkcfg(CFG_SECCOMP)) {
if (arg_seccomp32) {
fprintf(stderr, "Error: seccomp.32 conflicts with block-secondary\n");
exit(1);
}
arg_seccomp_block_secondary = 1;
}
else
Expand Down Expand Up @@ -2542,6 +2604,14 @@ int main(int argc, char **argv) {
// check network configuration options - it will exit if anything went wrong
net_check_cfg();

#ifdef HAVE_SECCOMP
if (arg_seccomp)
arg_seccomp_postexec = check_postexec(cfg.seccomp_list) || check_postexec(cfg.seccomp_list_drop);
#endif
bool need_preload = arg_trace || arg_tracelog || arg_seccomp_postexec;
if (need_preload && (cfg.seccomp_list32 || cfg.seccomp_list_drop32 || cfg.seccomp_list_keep32))
fwarning("preload libraries (trace, tracelog, postexecseccomp due to seccomp.drop=execve etc.) are incompatible with 32 bit filters\n");

// check and assign an IP address - for macvlan it will be done again in the sandbox!
if (any_bridge_configured()) {
EUID_ROOT();
Expand Down
12 changes: 9 additions & 3 deletions src/firejail/preproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,20 +98,26 @@ void preproc_mount_mnt_dir(void) {
//copy default seccomp files
copy_file(PATH_SECCOMP_32, RUN_SECCOMP_32, getuid(), getgid(), 0644); // root needed
}
if (arg_allow_debuggers)
if (arg_allow_debuggers) {
copy_file(PATH_SECCOMP_DEFAULT_DEBUG, RUN_SECCOMP_CFG, getuid(), getgid(), 0644); // root needed
else
copy_file(PATH_SECCOMP_DEBUG_32, RUN_SECCOMP_32, getuid(), getgid(), 0644); // root needed
} else
copy_file(PATH_SECCOMP_DEFAULT, RUN_SECCOMP_CFG, getuid(), getgid(), 0644); // root needed

if (arg_memory_deny_write_execute)
if (arg_memory_deny_write_execute) {
copy_file(PATH_SECCOMP_MDWX, RUN_SECCOMP_MDWX, getuid(), getgid(), 0644); // root needed
copy_file(PATH_SECCOMP_MDWX_32, RUN_SECCOMP_MDWX_32, getuid(), getgid(), 0644); // root needed
}
// as root, create empty RUN_SECCOMP_PROTOCOL and RUN_SECCOMP_POSTEXEC files
create_empty_file_as_root(RUN_SECCOMP_PROTOCOL, 0644);
if (set_perms(RUN_SECCOMP_PROTOCOL, getuid(), getgid(), 0644))
errExit("set_perms");
create_empty_file_as_root(RUN_SECCOMP_POSTEXEC, 0644);
if (set_perms(RUN_SECCOMP_POSTEXEC, getuid(), getgid(), 0644))
errExit("set_perms");
create_empty_file_as_root(RUN_SECCOMP_POSTEXEC_32, 0644);
if (set_perms(RUN_SECCOMP_POSTEXEC_32, getuid(), getgid(), 0644))
errExit("set_perms");
#endif
}
}
Expand Down
34 changes: 34 additions & 0 deletions src/firejail/profile.c
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,18 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {

return 0;
}
if (strncmp(ptr, "seccomp.32 ", 11) == 0) {
#ifdef HAVE_SECCOMP
if (checkcfg(CFG_SECCOMP)) {
arg_seccomp32 = 1;
cfg.seccomp_list32 = seccomp_check_list(ptr + 11);
}
else if (!arg_quiet)
warning_feature_disabled("seccomp");
#endif

return 0;
}

if (strcmp(ptr, "seccomp.block-secondary") == 0) {
#ifdef HAVE_SECCOMP
Expand All @@ -811,6 +823,17 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
#endif
return 0;
}
if (strncmp(ptr, "seccomp.32.drop ", 13) == 0) {
#ifdef HAVE_SECCOMP
if (checkcfg(CFG_SECCOMP)) {
arg_seccomp32 = 1;
cfg.seccomp_list_drop32 = seccomp_check_list(ptr + 13);
}
else
warning_feature_disabled("seccomp");
#endif
return 0;
}

// seccomp keep list
if (strncmp(ptr, "seccomp.keep ", 13) == 0) {
Expand All @@ -824,6 +847,17 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
#endif
return 0;
}
if (strncmp(ptr, "seccomp.32.keep ", 13) == 0) {
#ifdef HAVE_SECCOMP
if (checkcfg(CFG_SECCOMP)) {
arg_seccomp32 = 1;
cfg.seccomp_list_keep32 = seccomp_check_list(ptr + 13);
}
else
warning_feature_disabled("seccomp");
#endif
return 0;
}

// memory deny write&execute
if (strcmp(ptr, "memory-deny-write-execute") == 0) {
Expand Down
14 changes: 10 additions & 4 deletions src/firejail/sandbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -793,8 +793,6 @@ int sandbox(void* sandbox_arg) {
if (rv)
exit(rv);
}
if (arg_seccomp && (cfg.seccomp_list || cfg.seccomp_list_drop || cfg.seccomp_list_keep))
arg_seccomp_postexec = 1;
#endif

// need ld.so.preload if tracing or seccomp with any non-default lists
Expand Down Expand Up @@ -1113,9 +1111,15 @@ int sandbox(void* sandbox_arg) {
// if a keep list is available, disregard the drop list
if (arg_seccomp == 1) {
if (cfg.seccomp_list_keep)
seccomp_filter_keep();
seccomp_filter_keep(true);
else
seccomp_filter_drop();
seccomp_filter_drop(true);
}
if (arg_seccomp32 == 1) {
if (cfg.seccomp_list_keep32)
seccomp_filter_keep(false);
else
seccomp_filter_drop(false);

}
else { // clean seccomp files under /run/firejail/mnt
Expand All @@ -1128,9 +1132,11 @@ int sandbox(void* sandbox_arg) {
if (arg_debug)
printf("Install memory write&execute filter\n");
seccomp_load(RUN_SECCOMP_MDWX); // install filter
seccomp_load(RUN_SECCOMP_MDWX_32);
}
else {
int rv = unlink(RUN_SECCOMP_MDWX);
rv |= unlink(RUN_SECCOMP_MDWX_32);
(void) rv;
}
// make seccomp filters read-only
Expand Down
Loading

0 comments on commit 88eadbf

Please sign in to comment.