From 196a857a11848d0bff33ea1485884fb22bf42da6 Mon Sep 17 00:00:00 2001 From: netblue30 Date: Thu, 27 Oct 2016 21:37:18 -0400 Subject: sbox --- .gitignore | 1 + src/firejail/Makefile.in | 2 +- src/firejail/firejail.h | 12 +++ src/firejail/list.c | 101 ------------------------- src/firejail/main.c | 27 ++++--- src/firejail/network_main.c | 61 +++------------ src/firejail/protocol.c | 2 +- src/firejail/sbox.c | 177 ++++++++++++++++++++++++++++++++++++++++++++ src/firejail/seccomp.c | 2 +- src/firejail/seccomp.h | 149 ------------------------------------- src/fnet/main.c | 11 +++ src/include/seccomp.h | 149 +++++++++++++++++++++++++++++++++++++ 12 files changed, 378 insertions(+), 316 deletions(-) delete mode 100644 src/firejail/list.c create mode 100644 src/firejail/sbox.c delete mode 100644 src/firejail/seccomp.h create mode 100644 src/include/seccomp.h diff --git a/.gitignore b/.gitignore index 0d5979c8b..6acb6775c 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,5 @@ src/firecfg/firecfg src/ftee/ftee src/tags src/faudit/faudit +src/fnet/fnet uids.h diff --git a/src/firejail/Makefile.in b/src/firejail/Makefile.in index 7d4bcb19b..c4c168236 100644 --- a/src/firejail/Makefile.in +++ b/src/firejail/Makefile.in @@ -30,7 +30,7 @@ BINOBJS = $(foreach file, $(OBJS), $file) CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' $(HAVE_X11) $(HAVE_PRIVATE_HOME) $(HAVE_APPARMOR) $(HAVE_OVERLAYFS) $(HAVE_SECCOMP) $(HAVE_GLOBALCFG) $(HAVE_SECCOMP_H) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_BIND) $(HAVE_FILE_TRANSFER) $(HAVE_WHITELIST) -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread -%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/euid_common.h ../include/pid.h +%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/euid_common.h ../include/pid.h ../include/seccomp.h $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ firejail: $(OBJS) ../lib/libnetlink.o ../lib/common.o diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 6c0441472..367f599ec 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -25,6 +25,7 @@ // debug restricted shell //#define DEBUG_RESTRICTED_SHELL + // filesystem #define RUN_FIREJAIL_BASEDIR "/run" #define RUN_FIREJAIL_DIR "/run/firejail" @@ -681,6 +682,17 @@ long unsigned int appimage2_size(const char *fname); // cmdline.c void build_cmdline(char **command_line, char **window_title, int argc, char **argv, int index); +// sbox.c +// programs +#define PATH_FNET (LIBDIR "/firejail/fnet") +#define PATH_FIREMON (PREFIX "/bin/firemon") +// bitmapped filters for sbox_run +#define SBOX_ROOT 1 +#define SBOX_USER 2 +#define SBOX_CAPS 4 +#define SBOX_SECCOMP 8 +int sbox_run(unsigned filter, int num, ...); + #endif diff --git a/src/firejail/list.c b/src/firejail/list.c deleted file mode 100644 index d093a1f85..000000000 --- a/src/firejail/list.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2014-2016 Firejail Authors - * - * This file is part of firejail project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ -#include "firejail.h" -#include -#include - -static void set_privileges(void) { - struct stat s; - if (stat("/proc/sys/kernel/grsecurity", &s) == 0) { - EUID_ROOT(); - - // elevate privileges - if (setreuid(0, 0)) - errExit("setreuid"); - if (setregid(0, 0)) - errExit("setregid"); - } - else - drop_privs(1); -} - -static char *get_firemon_path(const char *cmd) { - assert(cmd); - - // start the argv[0] program in a new sandbox - char *firemon; - if (asprintf(&firemon, "%s/bin/firemon %s", PREFIX, cmd) == -1) - errExit("asprintf"); - - return firemon; -} - -void top(void) { - EUID_ASSERT(); - drop_privs(1); - char *cmd = get_firemon_path("--top"); - - char *arg[4]; - arg[0] = "bash"; - arg[1] = "-c"; - arg[2] = cmd; - arg[3] = NULL; - execvp("/bin/bash", arg); -} - -void netstats(void) { - EUID_ASSERT(); - set_privileges(); - char *cmd = get_firemon_path("--netstats"); - - char *arg[4]; - arg[0] = "bash"; - arg[1] = "-c"; - arg[2] = cmd; - arg[3] = NULL; - execvp("/bin/bash", arg); -} - -void list(void) { - EUID_ASSERT(); - drop_privs(1); - char *cmd = get_firemon_path("--list"); - - char *arg[4]; - arg[0] = "bash"; - arg[1] = "-c"; - arg[2] = cmd; - arg[3] = NULL; - execvp("/bin/bash", arg); -} - -void tree(void) { - EUID_ASSERT(); - drop_privs(1); - char *cmd = get_firemon_path("--tree"); - - char *arg[4]; - arg[0] = "bash"; - arg[1] = "-c"; - arg[2] = cmd; - arg[3] = NULL; - execvp("/bin/bash", arg); -} - diff --git a/src/firejail/main.c b/src/firejail/main.c index f41d5fcd3..15d42a4e0 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c @@ -54,9 +54,9 @@ Config cfg; // configuration int arg_private = 0; // mount private /home and /tmp directoryu int arg_private_template = 0; // mount private /home using a template int arg_debug = 0; // print debug messages -int arg_debug_check_filename; // print debug messages for filename checking -int arg_debug_blacklists; // print debug messages for blacklists -int arg_debug_whitelists; // print debug messages for whitelists +int arg_debug_check_filename = 0; // print debug messages for filename checking +int arg_debug_blacklists = 0; // print debug messages for blacklists +int arg_debug_whitelists = 0; // print debug messages for whitelists int arg_nonetwork = 0; // --net=none int arg_command = 0; // -c int arg_overlay = 0; // overlay option @@ -498,27 +498,32 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { exit(0); } else if (strcmp(argv[i], "--list") == 0) { - list(); - exit(0); + int rv = sbox_run(SBOX_USER | SBOX_CAPS | SBOX_SECCOMP, 2, PATH_FIREMON, "--list"); + exit(rv); } else if (strcmp(argv[i], "--tree") == 0) { - tree(); - exit(0); + int rv = sbox_run(SBOX_USER | SBOX_CAPS | SBOX_SECCOMP, 2, PATH_FIREMON, "--tree"); + exit(rv); } else if (strcmp(argv[i], "--top") == 0) { - top(); - exit(0); + int rv = sbox_run(SBOX_USER | SBOX_CAPS | SBOX_SECCOMP, 2, PATH_FIREMON, "--top"); + exit(rv); } #ifdef HAVE_NETWORK else if (strcmp(argv[i], "--netstats") == 0) { if (checkcfg(CFG_NETWORK)) { - netstats(); + struct stat s; + int rv; + if (stat("/proc/sys/kernel/grsecurity", &s) == 0) + rv = sbox_run(SBOX_ROOT | SBOX_CAPS | SBOX_SECCOMP, 2, PATH_FIREMON, "--netstats"); + else + rv = sbox_run(SBOX_USER | SBOX_CAPS | SBOX_SECCOMP, 2, PATH_FIREMON, "--netstats"); + exit(rv); } else { fprintf(stderr, "Error: networking features are disabled in Firejail configuration file\n"); exit(1); } - exit(0); } #endif #ifdef HAVE_FILE_TRANSFER diff --git a/src/firejail/network_main.c b/src/firejail/network_main.c index d2aa84bb6..35d6dd214 100644 --- a/src/firejail/network_main.c +++ b/src/firejail/network_main.c @@ -25,49 +25,6 @@ #include #include -static void fnet_run(int num, ...) { - int i; - va_list valist; - va_start(valist, num); - - char *fnet; - if (asprintf(&fnet, "%s/firejail/fnet", LIBDIR) == -1) - errExit("asprintf"); - - char *arg[num + 2]; - arg[0] = fnet; - for (i = 0; i < num; i++) - arg[i + 1] = va_arg(valist, char*); - arg[i + 1] = NULL; - - pid_t child = fork(); - if (child < 0) - errExit("fork"); - if (child == 0) { - // elevate privileges in order to get grsecurity working - if (setreuid(0, 0)) - errExit("setreuid"); - if (setregid(0, 0)) - errExit("setregid"); - - execvp(arg[0], arg); - perror("execl"); - _exit(1); - } - - int status; - if (waitpid(child, &status, 0) == -1 ) { - errExit("waitpid"); - } - if (WIFEXITED(status) && status != 0) { - fprintf(stderr, "Error: cannot run fnet\n"); - exit(1); - } - - va_end(valist); - free(fnet); -} - // configure bridge structure // - extract ip address and mask from the bridge interface void net_configure_bridge(Bridge *br, char *dev_name) { @@ -175,7 +132,7 @@ void net_configure_veth_pair(Bridge *br, const char *ifname, pid_t child) { char *cstr; if (asprintf(&cstr, "%d", child) == -1) errExit("asprintf"); - fnet_run(6, "create", "veth", dev, ifname, br->dev, cstr); + sbox_run(SBOX_ROOT | SBOX_SECCOMP, 7, PATH_FNET, "create", "veth", dev, ifname, br->dev, cstr); free(cstr); char *msg; @@ -344,7 +301,7 @@ void network_main(pid_t child) { } else // net_create_macvlan(cfg.bridge0.devsandbox, cfg.bridge0.dev, child); - fnet_run(5, "create", "macvlan", cfg.bridge0.devsandbox, cfg.bridge0.dev, cstr); + sbox_run(SBOX_ROOT | SBOX_SECCOMP, 6, PATH_FNET, "create", "macvlan", cfg.bridge0.devsandbox, cfg.bridge0.dev, cstr); } if (cfg.bridge1.configured) { @@ -352,7 +309,7 @@ void network_main(pid_t child) { net_configure_veth_pair(&cfg.bridge1, "eth1", child); else // net_create_macvlan(cfg.bridge1.devsandbox, cfg.bridge1.dev, child); - fnet_run(5, "create", "macvlan", cfg.bridge1.devsandbox, cfg.bridge1.dev, cstr); + sbox_run(SBOX_ROOT | SBOX_SECCOMP, 6, PATH_FNET, "create", "macvlan", cfg.bridge1.devsandbox, cfg.bridge1.dev, cstr); } if (cfg.bridge2.configured) { @@ -360,7 +317,7 @@ void network_main(pid_t child) { net_configure_veth_pair(&cfg.bridge2, "eth2", child); else // net_create_macvlan(cfg.bridge2.devsandbox, cfg.bridge2.dev, child); - fnet_run(5, "create", "macvlan", cfg.bridge2.devsandbox, cfg.bridge2.dev, cstr); + sbox_run(SBOX_ROOT | SBOX_SECCOMP, 6, PATH_FNET, "create", "macvlan", cfg.bridge2.devsandbox, cfg.bridge2.dev, cstr); } if (cfg.bridge3.configured) { @@ -368,25 +325,25 @@ void network_main(pid_t child) { net_configure_veth_pair(&cfg.bridge3, "eth3", child); else // net_create_macvlan(cfg.bridge3.devsandbox, cfg.bridge3.dev, child); - fnet_run(5, "create", "macvlan", cfg.bridge3.devsandbox, cfg.bridge3.dev, cstr); + sbox_run(SBOX_ROOT | SBOX_SECCOMP, 6, PATH_FNET, "create", "macvlan", cfg.bridge3.devsandbox, cfg.bridge3.dev, cstr); } // move interfaces in sandbox if (cfg.interface0.configured) { // net_move_interface(cfg.interface0.dev, child); - fnet_run(3, "moveif", cfg.interface0.dev, cstr); + sbox_run(SBOX_ROOT | SBOX_SECCOMP, 4, PATH_FNET, "moveif", cfg.interface0.dev, cstr); } if (cfg.interface1.configured) { // net_move_interface(cfg.interface1.dev, child); - fnet_run(3, "moveif", cfg.interface1.dev, cstr); + sbox_run(SBOX_ROOT | SBOX_SECCOMP, 4, PATH_FNET, "moveif", cfg.interface1.dev, cstr); } if (cfg.interface2.configured) { // net_move_interface(cfg.interface2.dev, child); - fnet_run(3, "moveif", cfg.interface3.dev, cstr); + sbox_run(SBOX_ROOT | SBOX_SECCOMP, 4, PATH_FNET, "moveif", cfg.interface3.dev, cstr); } if (cfg.interface3.configured) { // net_move_interface(cfg.interface3.dev, child); - fnet_run(3, "moveif", cfg.interface3.dev, cstr); + sbox_run(SBOX_ROOT | SBOX_SECCOMP, 4, PATH_FNET, "moveif", cfg.interface3.dev, cstr); } free(cstr); diff --git a/src/firejail/protocol.c b/src/firejail/protocol.c index 1ef5bf13d..6321c703a 100644 --- a/src/firejail/protocol.c +++ b/src/firejail/protocol.c @@ -47,7 +47,7 @@ #ifdef HAVE_SECCOMP #include "firejail.h" -#include "seccomp.h" +#include "../include/seccomp.h" #include #include diff --git a/src/firejail/sbox.c b/src/firejail/sbox.c new file mode 100644 index 000000000..8c6ace27e --- /dev/null +++ b/src/firejail/sbox.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2014-2016 Firejail Authors + * + * This file is part of firejail project + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include "firejail.h" +#include +#include +#include +#include +#include +#include "../include/seccomp.h" + +static struct sock_filter filter[] = { + VALIDATE_ARCHITECTURE, + EXAMINE_SYSCALL, + +#if defined(__x86_64__) +#define X32_SYSCALL_BIT 0x40000000 + // handle X32 ABI + BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, X32_SYSCALL_BIT, 1, 0), + BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, 0, 1, 0), + RETURN_ERRNO(EPERM), +#endif + + // syscall list +#ifdef SYS_mount + BLACKLIST(SYS_mount), // mount/unmount filesystems +#endif +#ifdef SYS_umount2 + BLACKLIST(SYS_umount2), +#endif +#ifdef SYS_ptrace + BLACKLIST(SYS_ptrace), // trace processes +#endif +#ifdef SYS_kexec_file_load + BLACKLIST(SYS_kexec_file_load), +#endif +#ifdef SYS_kexec_load + BLACKLIST(SYS_kexec_load), // loading a different kernel +#endif +#ifdef SYS_name_to_handle_at + BLACKLIST(SYS_name_to_handle_at), +#endif +#ifdef SYS_open_by_handle_at + BLACKLIST(SYS_open_by_handle_at), // open by handle +#endif +#ifdef SYS_init_module + BLACKLIST(SYS_init_module), // kernel module handling +#endif +#ifdef SYS_finit_module // introduced in 2013 + BLACKLIST(SYS_finit_module), +#endif +#ifdef SYS_create_module + BLACKLIST(SYS_create_module), +#endif +#ifdef SYS_delete_module + BLACKLIST(SYS_delete_module), +#endif +#ifdef SYS_iopl + BLACKLIST(SYS_iopl), // io permissions +#endif +#ifdef SYS_ioperm + BLACKLIST(SYS_ioperm), +#endif +#ifdef SYS_iopl + BLACKLIST(SYS_iopl), // io permissions +#endif +#ifdef SYS_ioprio_set + BLACKLIST(SYS_ioprio_set), +#endif +#ifdef SYS_ni_syscall // new io permissions call on arm devices + BLACKLIST(SYS_ni_syscall), +#endif +#ifdef SYS_swapon + BLACKLIST(SYS_swapon), // swap on/off +#endif +#ifdef SYS_swapoff + BLACKLIST(SYS_swapoff), +#endif +#ifdef SYS_syslog + BLACKLIST(SYS_syslog), // kernel printk control +#endif + RETURN_ALLOW +}; + +static struct sock_fprog prog = { + .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])), + .filter = filter, +}; + +typedef struct sbox_config { + char *name; + char *path; + unsigned filters; +} SboxConfig; + + +int sbox_run(unsigned filter, int num, ...) { + EUID_ROOT(); + char *path = NULL; + int i; + va_list valist; + va_start(valist, num); + + // build argument list + char *arg[num + 1]; + for (i = 0; i < num; i++) + arg[i] = va_arg(valist, char*); + arg[i] = NULL; + va_end(valist); + +#if 0 +{ +int i; +for (i = 0; i <= num; i++) + printf("#%s# ", arg[i]); +printf("\n"); +} +#endif + pid_t child = fork(); + if (child < 0) + errExit("fork"); + if (child == 0) { + // apply filters + if (filter & SBOX_CAPS) + caps_drop_all(); + + if (filter & SBOX_SECCOMP) { + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { + perror("prctl(NO_NEW_PRIVS)"); + } + if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) { + perror("prctl(PR_SET_SECCOMP)"); + } + } + + if (filter & SBOX_ROOT) { + // elevate privileges in order to get grsecurity working + if (setreuid(0, 0)) + errExit("setreuid"); + if (setregid(0, 0)) + errExit("setregid"); + } + else if (filter & SBOX_USER) + drop_privs(1); + + execvp(arg[0], arg); + perror("execl"); + _exit(1); + } + + int status; + if (waitpid(child, &status, 0) == -1 ) { + errExit("waitpid"); + } + if (WIFEXITED(status) && status != 0) { + fprintf(stderr, "Error: cannot run fnet\n"); + exit(1); + } + + return status; +} diff --git a/src/firejail/seccomp.c b/src/firejail/seccomp.c index 549359d94..09862ec20 100644 --- a/src/firejail/seccomp.c +++ b/src/firejail/seccomp.c @@ -20,7 +20,7 @@ #ifdef HAVE_SECCOMP #include "firejail.h" -#include "seccomp.h" +#include "../include/seccomp.h" #define SECSIZE 128 // initial filter size static struct sock_filter *sfilter = NULL; diff --git a/src/firejail/seccomp.h b/src/firejail/seccomp.h deleted file mode 100644 index 7d646dd9e..000000000 --- a/src/firejail/seccomp.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (C) 2014-2016 Firejail Authors - * - * This file is part of firejail project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -/* default seccomp filter - // seccomp - struct sock_filter filter[] = { - VALIDATE_ARCHITECTURE, - EXAMINE_SYSCALL, - BLACKLIST(SYS_mount), // mount/unmount filesystems - BLACKLIST(SYS_umount2), - BLACKLIST(SYS_ptrace), // trace processes - BLACKLIST(SYS_kexec_load), // loading a different kernel - BLACKLIST(SYS_open_by_handle_at), // open by handle - BLACKLIST(SYS_init_module), // kernel module handling - BLACKLIST(SYS_finit_module), - BLACKLIST(SYS_delete_module), - BLACKLIST(SYS_iopl), // io permissions - BLACKLIST(SYS_ioperm), - BLACKLIST(SYS_iopl), // io permissions - BLACKLIST(SYS_ni_syscall), - BLACKLIST(SYS_swapon), // swap on/off - BLACKLIST(SYS_swapoff), - BLACKLIST(SYS_syslog), // kernel printk control - RETURN_ALLOW - }; - - struct sock_fprog prog = { - .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])), - .filter = filter, - }; - - - if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { - perror("prctl(NO_NEW_PRIVS)"); - return 1; - } - if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) { - perror("prctl"); - return 1; - } -*/ - -#ifndef SECCOMP_H -#define SECCOMP_H -#include -#include -#include -#include -#include -#include -#include - -#include -#ifndef PR_SET_NO_NEW_PRIVS -# define PR_SET_NO_NEW_PRIVS 38 -#endif - -#if HAVE_SECCOMP_H -#include -#else -#define SECCOMP_MODE_FILTER 2 -#define SECCOMP_RET_KILL 0x00000000U -#define SECCOMP_RET_TRAP 0x00030000U -#define SECCOMP_RET_ALLOW 0x7fff0000U -#define SECCOMP_RET_ERRNO 0x00050000U -#define SECCOMP_RET_DATA 0x0000ffffU -struct seccomp_data { - int nr; - __u32 arch; - __u64 instruction_pointer; - __u64 args[6]; -}; -#endif - -#if defined(__i386__) -# define ARCH_NR AUDIT_ARCH_I386 -#elif defined(__x86_64__) -# define ARCH_NR AUDIT_ARCH_X86_64 -#elif defined(__arm__) -# define ARCH_NR AUDIT_ARCH_ARM -#else -# warning "Platform does not support seccomp filter yet" -# define ARCH_NR 0 -#endif - -#define VALIDATE_ARCHITECTURE \ - BPF_STMT(BPF_LD+BPF_W+BPF_ABS, (offsetof(struct seccomp_data, arch))), \ - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARCH_NR, 1, 0), \ - BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) - -#define VALIDATE_ARCHITECTURE_64 \ - BPF_STMT(BPF_LD+BPF_W+BPF_ABS, (offsetof(struct seccomp_data, arch))), \ - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, AUDIT_ARCH_X86_64, 1, 0), \ - BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) - -#define VALIDATE_ARCHITECTURE_32 \ - BPF_STMT(BPF_LD+BPF_W+BPF_ABS, (offsetof(struct seccomp_data, arch))), \ - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, AUDIT_ARCH_I386, 1, 0), \ - BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) - -#define EXAMINE_SYSCALL BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ - (offsetof(struct seccomp_data, nr))) - -#define EXAMINE_ARGUMENT(nr) BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ - (offsetof(struct seccomp_data, args[nr]))) - -#define ONLY(syscall_nr) \ - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, syscall_nr, 1, 0), \ - BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) - -#define BLACKLIST(syscall_nr) \ - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, syscall_nr, 0, 1), \ - BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL) - -#define WHITELIST(syscall_nr) \ - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, syscall_nr, 0, 1), \ - BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) - -#define BLACKLIST_ERRNO(syscall_nr, nr) \ - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, syscall_nr, 0, 1), \ - BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ERRNO | nr) - -#define RETURN_ALLOW \ - BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) - -#define RETURN_ERRNO(nr) \ - BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ERRNO | nr) - -#define KILL_PROCESS \ - BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL) - -#endif diff --git a/src/fnet/main.c b/src/fnet/main.c index ae780c2ea..88f71c4b3 100644 --- a/src/fnet/main.c +++ b/src/fnet/main.c @@ -31,9 +31,20 @@ static void usage(void) { } int main(int argc, char **argv) { +#if 0 +{ +system("cat /proc/self/status"); +int i; +for (i = 0; i < argc; i++) + printf("*%s* ", argv[i]); +printf("\n"); +} +#endif if (argc < 2) return 1; + + if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") ==0) { usage(); return 0; diff --git a/src/include/seccomp.h b/src/include/seccomp.h new file mode 100644 index 000000000..7d646dd9e --- /dev/null +++ b/src/include/seccomp.h @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2014-2016 Firejail Authors + * + * This file is part of firejail project + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +/* default seccomp filter + // seccomp + struct sock_filter filter[] = { + VALIDATE_ARCHITECTURE, + EXAMINE_SYSCALL, + BLACKLIST(SYS_mount), // mount/unmount filesystems + BLACKLIST(SYS_umount2), + BLACKLIST(SYS_ptrace), // trace processes + BLACKLIST(SYS_kexec_load), // loading a different kernel + BLACKLIST(SYS_open_by_handle_at), // open by handle + BLACKLIST(SYS_init_module), // kernel module handling + BLACKLIST(SYS_finit_module), + BLACKLIST(SYS_delete_module), + BLACKLIST(SYS_iopl), // io permissions + BLACKLIST(SYS_ioperm), + BLACKLIST(SYS_iopl), // io permissions + BLACKLIST(SYS_ni_syscall), + BLACKLIST(SYS_swapon), // swap on/off + BLACKLIST(SYS_swapoff), + BLACKLIST(SYS_syslog), // kernel printk control + RETURN_ALLOW + }; + + struct sock_fprog prog = { + .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])), + .filter = filter, + }; + + + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { + perror("prctl(NO_NEW_PRIVS)"); + return 1; + } + if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) { + perror("prctl"); + return 1; + } +*/ + +#ifndef SECCOMP_H +#define SECCOMP_H +#include +#include +#include +#include +#include +#include +#include + +#include +#ifndef PR_SET_NO_NEW_PRIVS +# define PR_SET_NO_NEW_PRIVS 38 +#endif + +#if HAVE_SECCOMP_H +#include +#else +#define SECCOMP_MODE_FILTER 2 +#define SECCOMP_RET_KILL 0x00000000U +#define SECCOMP_RET_TRAP 0x00030000U +#define SECCOMP_RET_ALLOW 0x7fff0000U +#define SECCOMP_RET_ERRNO 0x00050000U +#define SECCOMP_RET_DATA 0x0000ffffU +struct seccomp_data { + int nr; + __u32 arch; + __u64 instruction_pointer; + __u64 args[6]; +}; +#endif + +#if defined(__i386__) +# define ARCH_NR AUDIT_ARCH_I386 +#elif defined(__x86_64__) +# define ARCH_NR AUDIT_ARCH_X86_64 +#elif defined(__arm__) +# define ARCH_NR AUDIT_ARCH_ARM +#else +# warning "Platform does not support seccomp filter yet" +# define ARCH_NR 0 +#endif + +#define VALIDATE_ARCHITECTURE \ + BPF_STMT(BPF_LD+BPF_W+BPF_ABS, (offsetof(struct seccomp_data, arch))), \ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARCH_NR, 1, 0), \ + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) + +#define VALIDATE_ARCHITECTURE_64 \ + BPF_STMT(BPF_LD+BPF_W+BPF_ABS, (offsetof(struct seccomp_data, arch))), \ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, AUDIT_ARCH_X86_64, 1, 0), \ + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) + +#define VALIDATE_ARCHITECTURE_32 \ + BPF_STMT(BPF_LD+BPF_W+BPF_ABS, (offsetof(struct seccomp_data, arch))), \ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, AUDIT_ARCH_I386, 1, 0), \ + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) + +#define EXAMINE_SYSCALL BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ + (offsetof(struct seccomp_data, nr))) + +#define EXAMINE_ARGUMENT(nr) BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ + (offsetof(struct seccomp_data, args[nr]))) + +#define ONLY(syscall_nr) \ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, syscall_nr, 1, 0), \ + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) + +#define BLACKLIST(syscall_nr) \ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, syscall_nr, 0, 1), \ + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL) + +#define WHITELIST(syscall_nr) \ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, syscall_nr, 0, 1), \ + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) + +#define BLACKLIST_ERRNO(syscall_nr, nr) \ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, syscall_nr, 0, 1), \ + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ERRNO | nr) + +#define RETURN_ALLOW \ + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) + +#define RETURN_ERRNO(nr) \ + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ERRNO | nr) + +#define KILL_PROCESS \ + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL) + +#endif -- cgit v1.2.3-54-g00ecf