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

improve force-nonewprivs security guarantees #5271

Merged
merged 1 commit into from
Jul 31, 2022
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
22 changes: 15 additions & 7 deletions src/firejail/join.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,17 @@ static void extract_nogroups(ProcessHandle sandbox) {

if (process_rootfs_stat(sandbox, RUN_GROUPS_CFG, &s) == 0)
arg_nogroups = 1;
else if (errno != ENOENT)
errExit("stat");
}

static void extract_nonewprivs(ProcessHandle sandbox) {
struct stat s;

if (process_rootfs_stat(sandbox, RUN_NONEWPRIVS_CFG, &s) == 0)
arg_nonewprivs = 1;
else if (errno != ENOENT)
errExit("stat");
}

static void extract_caps(ProcessHandle sandbox) {
Expand Down Expand Up @@ -477,13 +481,6 @@ void join(pid_t pid, int argc, char **argv, int index) {
EUID_USER();
unpin_process(sandbox);

// set nonewprivs
if (arg_nonewprivs == 1) { // not available for uid 0
int rv = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
if (arg_debug && rv == 0)
printf("NO_NEW_PRIVS set\n");
}

int cwd = 0;
if (cfg.cwd) {
if (chdir(cfg.cwd) == 0)
Expand All @@ -503,6 +500,17 @@ void join(pid_t pid, int argc, char **argv, int index) {
}
}

// set nonewprivs
#ifndef HAVE_FORCE_NONEWPRIVS
if (arg_nonewprivs == 1) // not available for uid 0
#endif
{
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != 0)
errExit("prctl");
if (arg_debug)
printf("NO_NEW_PRIVS set\n");
}

// drop privileges
drop_privs(arg_nogroups);

Expand Down
3 changes: 2 additions & 1 deletion src/firejail/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1239,7 +1239,8 @@ int main(int argc, char **argv, char **envp) {
if (check_arg(argc, argv, "--appimage", 1))
arg_appimage = 1;

// check for force-nonewprivs in /etc/firejail/firejail.config file
// load configuration file /etc/firejail/firejail.config
// and check for force-nonewprivs
if (checkcfg(CFG_FORCE_NONEWPRIVS))
arg_nonewprivs = 1;

Expand Down
27 changes: 9 additions & 18 deletions src/firejail/sandbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@
#include <sys/apparmor.h>
#endif

static int force_nonewprivs = 0;
extern int just_run_the_shell;

static int monitored_pid = 0;
Expand Down Expand Up @@ -629,7 +628,6 @@ static void enforce_filters(void) {
fmessage("\n** Warning: dropping all Linux capabilities and setting NO_NEW_PRIVS prctl **\n\n");
// enforce NO_NEW_PRIVS
arg_nonewprivs = 1;
force_nonewprivs = 1;

// disable all capabilities
arg_caps_drop_all = 1;
Expand Down Expand Up @@ -832,14 +830,9 @@ int sandbox(void* sandbox_arg) {
exit(rv);
}

#ifdef HAVE_FORCE_NONEWPRIVS
bool always_enforce_filters = true;
#else
bool always_enforce_filters = false;
#endif
// for --appimage, --chroot and --overlay* we force NO_NEW_PRIVS
// and drop all capabilities
if (getuid() != 0 && (arg_appimage || cfg.chrootdir || arg_overlay || always_enforce_filters))
if (getuid() != 0 && (arg_appimage || cfg.chrootdir || arg_overlay))
enforce_filters();

// need ld.so.preload if tracing or seccomp with any non-default lists
Expand Down Expand Up @@ -1266,17 +1259,15 @@ int sandbox(void* sandbox_arg) {
//****************************************
// Set NO_NEW_PRIVS if desired
//****************************************
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("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);
}
#ifndef HAVE_FORCE_NONEWPRIVS
if (arg_nonewprivs)
#endif
{
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != 0) {
fprintf(stderr, "Error: cannot set NO_NEW_PRIVS, it requires a Linux kernel version 3.5 or newer.\n");
exit(1);
}
else if (arg_debug)
if (arg_debug)
printf("NO_NEW_PRIVS set\n");
}

Expand Down