From 89fa2a7562e84338d88ea83777861f00e545135d Mon Sep 17 00:00:00 2001 From: smitsohu Date: Sat, 15 Dec 2018 17:00:49 +0100 Subject: enforce nonewprivs instead of seccomp for chroot sandboxes currently users are able to specify a seccomp filter of their choosing, leaving the real defense to nonewprivs anyway. --- src/firejail/main.c | 25 +++++++++++++++---------- src/firejail/sandbox.c | 46 ++++++++++++++++++++++------------------------ src/firejail/seccomp.c | 6 ------ src/man/firejail.txt | 12 ++++++------ 4 files changed, 43 insertions(+), 46 deletions(-) diff --git a/src/firejail/main.c b/src/firejail/main.c index f35b2a925..9aff4e4e5 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c @@ -866,7 +866,6 @@ int main(int argc, char **argv) { int lockfd_directory = -1; int option_cgroup = 0; int custom_profile = 0; // custom profile loaded - int arg_seccomp_cmdline = 0; // seccomp requested on command line (used to break out of --chroot) int arg_caps_cmdline = 0; // caps requested on command line (used to break out of --chroot) // drop permissions by default and rise them when required @@ -1153,7 +1152,6 @@ int main(int argc, char **argv) { } arg_seccomp = 1; cfg.seccomp_list = seccomp_check_list(argv[i] + 10); - arg_seccomp_cmdline = 1; } else exit_err_feature("seccomp"); @@ -1166,7 +1164,6 @@ int main(int argc, char **argv) { } arg_seccomp = 1; cfg.seccomp_list_drop = seccomp_check_list(argv[i] + 15); - arg_seccomp_cmdline = 1; } else exit_err_feature("seccomp"); @@ -1179,7 +1176,6 @@ int main(int argc, char **argv) { } arg_seccomp = 1; cfg.seccomp_list_keep = seccomp_check_list(argv[i] + 15); - arg_seccomp_cmdline = 1; } else exit_err_feature("seccomp"); @@ -2278,12 +2274,21 @@ int main(int argc, char **argv) { } EUID_ASSERT(); - // exit for --chroot sandboxes when secomp or caps are explicitly specified on command line - if (getuid() != 0 && cfg.chrootdir && (arg_seccomp_cmdline || arg_caps_cmdline)) { - fprintf(stderr, "Error: for chroot sandboxes, default seccomp and capabilities filters are\n" - "enabled by default. Please remove all --seccomp and --caps options from the\n" - "command line.\n"); - exit(1); + // exit chroot, overlay and appimage sandboxes when caps are explicitly specified on command line + if (getuid() != 0 && arg_caps_cmdline) { + char *opt = NULL; + if (cfg.chrootdir) + opt = "chroot"; + else if (arg_overlay) + opt = "overlay"; + else if (arg_appimage) + opt = "appimage"; + + if (opt) { + fprintf(stderr, "Error: all capabilities are dropped for %s by default.\n" + "Please remove --caps options from the command line.\n", opt); + exit(1); + } } // prog_index could still be -1 if no program was specified diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 2113ef70f..6a9977455 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c @@ -39,6 +39,9 @@ #ifndef PR_SET_NO_NEW_PRIVS # define PR_SET_NO_NEW_PRIVS 38 #endif +#ifndef PR_GET_NO_NEW_PRIVS +# define PR_GET_NO_NEW_PRIVS 39 +#endif #ifdef HAVE_APPARMOR #include @@ -46,10 +49,7 @@ #include -#ifdef HAVE_SECCOMP -int enforce_seccomp = 0; -#endif - +static int force_nonewprivs = 0; static int monitored_pid = 0; static void sandbox_handler(int sig){ @@ -539,23 +539,17 @@ void start_application(int no_sandbox, FILE *fp) { } static void enforce_filters(void) { - // force default seccomp inside the chroot, no keep or drop list - // the list build on top of the default drop list is kept intact + // enforce NO_NEW_PRIVS arg_nonewprivs = 1; - arg_seccomp = 1; -#ifdef HAVE_SECCOMP - enforce_seccomp = 1; -#endif + force_nonewprivs = 1; // disable all capabilities - if (arg_caps_default_filter || arg_caps_list) - fwarning("all capabilities disabled for a regular user in chroot\n"); + fmessage("\n** Warning: dropping all Linux capabilities **\n"); arg_caps_drop_all = 1; // drop all supplementary groups; /etc/group file inside chroot // is controlled by a regular usr arg_nogroups = 1; - fmessage("\n** Warning: dropping all Linux capabilities **\n"); } int sandbox(void* sandbox_arg) { @@ -754,24 +748,17 @@ int sandbox(void* sandbox_arg) { // need ld.so.preload if tracing or seccomp with any non-default lists bool need_preload = arg_trace || arg_tracelog || arg_seccomp_postexec; - // for --appimage, --chroot and --overlay* we replace the seccomp filter with the default one - // we also drop all capabilities + // for --appimage, --chroot and --overlay* we force NO_NEW_PRIVS + // and drop all capabilities if (getuid() != 0 && (arg_appimage || cfg.chrootdir || arg_overlay)) { enforce_filters(); need_preload = arg_trace || arg_tracelog; - arg_seccomp = 1; } // trace pre-install if (need_preload) fs_trace_preload(); - // state of nonewprivs - save_nonewprivs(); - - // save original umask - save_umask(); - // store hosts file if (cfg.hosts_file) fs_store_hosts_file(); @@ -1043,9 +1030,15 @@ int sandbox(void* sandbox_arg) { if (arg_x11_xorg) x11_xorg(); + // save original umask + save_umask(); + //**************************** // set security filters //**************************** + // save state of nonewprivs + save_nonewprivs(); + // set capabilities set_caps(); @@ -1145,8 +1138,13 @@ int sandbox(void* sandbox_arg) { if (arg_nonewprivs) { prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); - if (prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0) != 1) - fwarning("NO_NEW_PRIVS disabled, it requires a Linux kernel version 3.5 or newer.\n"); + if (prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0) != 1) { + fwarning("cannot set NO_NEW_PRIVS, it requires a Linux kernel version 3.5 or newer.\n"); + if (force_nonewprivs) { + fprintf(stderr, "Error: NO_NEW_PRIVS required for this sandbox, exiting ...\n"); + exit(1); + } + } else if (arg_debug) printf("NO_NEW_PRIVS set\n"); } diff --git a/src/firejail/seccomp.c b/src/firejail/seccomp.c index 7be7b3950..974e36ba7 100644 --- a/src/firejail/seccomp.c +++ b/src/firejail/seccomp.c @@ -31,7 +31,6 @@ typedef struct filter_list { static FilterList *filter_list_head = NULL; static int err_printed = 0; -extern int enforce_seccomp; char *seccomp_check_list(const char *str) { assert(str); @@ -74,11 +73,6 @@ int seccomp_install_filters(void) { if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &fl->prog)) { - if (enforce_seccomp) { - fprintf(stderr, "Error: a seccomp-enabled Linux kernel is required, exiting...\n"); - exit(1); - } - if (!err_printed) fwarning("seccomp disabled, it requires a Linux kernel version 3.5 or newer.\n"); err_printed = 1; diff --git a/src/man/firejail.txt b/src/man/firejail.txt index 66663be35..9c1133756 100644 --- a/src/man/firejail.txt +++ b/src/man/firejail.txt @@ -100,8 +100,8 @@ $ firejail --allusers Enable AppArmor confinement. For more information, please see \fBAPPARMOR\fR section below. .TP \fB\-\-appimage -Sandbox an AppImage (https://appimage.org/) application. If the sandbox is started as a -regular user, default seccomp and capabilities filters are enabled. +Sandbox an AppImage (https://appimage.org/) application. If the sandbox is started +as a regular user, nonewprivs and a default capabilities filter are enabled. .br .br @@ -275,7 +275,7 @@ Example: \fB\-\-chroot=dirname Chroot the sandbox into a root filesystem. Unlike the regular filesystem container, the system directories are mounted read-write. If the sandbox is started as a -regular user, default seccomp and capabilities filters are enabled. +regular user, nonewprivs and a default capabilities filter are enabled. .br .br @@ -1287,7 +1287,7 @@ Similar to \-\-output, but stderr is also stored. Mount a filesystem overlay on top of the current filesystem. Unlike the regular filesystem container, the system directories are mounted read-write. All filesystem modifications go into the overlay. Directories /run, /tmp and /dev are not covered by the overlay. The overlay is stored in $HOME/.firejail/ directory. -If the sandbox is started as a regular user, default seccomp and capabilities filters are enabled. +If the sandbox is started as a regular user, nonewprivs and a default capabilities filter are enabled. .br .br @@ -1307,7 +1307,7 @@ Mount a filesystem overlay on top of the current filesystem. Unlike the regular the system directories are mounted read-write. All filesystem modifications go into the overlay. Directories /run, /tmp and /dev are not covered by the overlay. The overlay is stored in $HOME/.firejail/ directory. The created overlay can be reused between multiple sessions. -If the sandbox is started as a regular user, default seccomp and capabilities filters are enabled. +If the sandbox is started as a regular user, nonewprivs and a default capabilities filter are enabled. .br .br @@ -1325,7 +1325,7 @@ $ firejail \-\-overlay-named=jail1 firefox \fB\-\-overlay-tmpfs Mount a filesystem overlay on top of the current filesystem. All filesystem modifications are discarded when the sandbox is closed. Directories /run, /tmp and /dev are not covered by the overlay. -If the sandbox is started as a regular user, default seccomp and capabilities filters are enabled. +If the sandbox is started as a regular user, nonewprivs and a default capabilities filter are enabled. .br .br -- cgit v1.2.3-54-g00ecf