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

deterministic-shutdown option #4635

Merged
merged 1 commit into from
Nov 13, 2021
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
2 changes: 1 addition & 1 deletion contrib/vim/syntax/firejail.vim
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ syn match fjVar /\v\$\{(CFG|DESKTOP|DOCUMENTS|DOWNLOADS|HOME|MUSIC|PATH|PICTURES
" Generate list with: { rg -o 'strn?cmp\(ptr, "([^"]+) "' -r '$1' src/firejail/profile.c; echo private-lib; } | grep -vEx '(include|ignore|caps\.drop|caps\.keep|protocol|seccomp|seccomp\.drop|seccomp\.keep|env|rmenv|net|ip)' | sort -u | tr $'\n' '|' # private-lib is special-cased in the code and doesn't match the regex; grep-ed patterns are handled later with 'syn match nextgroup=' directives (except for include which is special-cased as a fjCommandNoCond keyword)
syn match fjCommand /\v(bind|blacklist|blacklist-nolog|cgroup|cpu|defaultgw|dns|hostname|hosts-file|ip6|iprange|join-or-start|mac|mkdir|mkfile|mtu|name|netfilter|netfilter6|netmask|nice|noblacklist|noexec|nowhitelist|overlay-named|private|private-bin|private-cwd|private-etc|private-home|private-lib|private-opt|private-srv|read-only|read-write|rlimit-as|rlimit-cpu|rlimit-fsize|rlimit-nofile|rlimit-nproc|rlimit-sigpending|timeout|tmpfs|veth-name|whitelist|xephyr-screen) / skipwhite contained
" Generate list with: rg -o 'strn?cmp\(ptr, "([^ "]*[^ ])"' -r '$1' src/firejail/profile.c | grep -vEx '(include|rlimit|quiet)' | sed -e 's/\./\\./' | sort -u | tr $'\n' '|' # include/rlimit are false positives, quiet is special-cased below
syn match fjCommand /\v(allow-debuggers|allusers|apparmor|caps|disable-mnt|ipc-namespace|keep-config-pulse|keep-dev-shm|keep-var-tmp|machine-id|memory-deny-write-execute|netfilter|no3d|noautopulse|nodbus|nodvd|nogroups|noinput|nonewprivs|noroot|nosound|notv|nou2f|novideo|overlay|overlay-tmpfs|private|private-cache|private-cwd|private-dev|private-lib|private-tmp|seccomp|seccomp\.32|seccomp\.block-secondary|tracelog|writable-etc|writable-run-user|writable-var|writable-var-log|x11)$/ contained
syn match fjCommand /\v(allow-debuggers|allusers|apparmor|caps|deterministic-exit-code|deterministic-shutdown|disable-mnt|ipc-namespace|keep-config-pulse|keep-dev-shm|keep-var-tmp|machine-id|memory-deny-write-execute|netfilter|no3d|noautopulse|nodbus|nodvd|nogroups|noinput|nonewprivs|noroot|nosound|notv|nou2f|novideo|overlay|overlay-tmpfs|private|private-cache|private-cwd|private-dev|private-lib|private-tmp|seccomp|seccomp\.32|seccomp\.block-secondary|tracelog|writable-etc|writable-run-user|writable-var|writable-var-log|x11)$/ contained
syn match fjCommand /ignore / nextgroup=fjCommand,fjCommandNoCond skipwhite contained
syn match fjCommand /caps\.drop / nextgroup=fjCapability,fjAll skipwhite contained
syn match fjCommand /caps\.keep / nextgroup=fjCapability skipwhite contained
Expand Down
1 change: 1 addition & 0 deletions etc/profile-a-l/akregator.profile
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,4 @@ private-bin akregator,akregatorstorageexporter,dbus-launch,kdeinit4,kdeinit4_shu
private-dev
private-tmp

deterministic-shutdown
1 change: 1 addition & 0 deletions etc/profile-a-l/default.profile
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,6 @@ seccomp
# dbus-user none
# dbus-system none

# deterministic-shutdown
# memory-deny-write-execute
# read-only ${HOME}
2 changes: 2 additions & 0 deletions etc/profile-a-l/dillo.profile
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,5 @@ tracelog

private-dev
private-tmp

deterministic-shutdown
1 change: 1 addition & 0 deletions etc/profile-a-l/ktorrent.profile
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,5 @@ private-dev
# private-lib - problems on Arch
private-tmp

deterministic-shutdown
# memory-deny-write-execute
1 change: 1 addition & 0 deletions etc/profile-m-z/server.profile
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ private-tmp
dbus-user none
# dbus-system none

# deterministic-shutdown
# memory-deny-write-execute
# read-only ${HOME}
# writable-run-user
Expand Down
1 change: 1 addition & 0 deletions etc/templates/profile.template
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ include globals.local
#dbus-user.talk org.freedesktop.Notifications
#dbus-system none

##deterministic-shutdown
##env VAR=VALUE
##join-or-start NAME
#memory-deny-write-execute
Expand Down
1 change: 1 addition & 0 deletions src/firejail/firejail.h
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,7 @@ extern int arg_nodvd; // --nodvd
extern int arg_nou2f; // --nou2f
extern int arg_noinput; // --noinput
extern int arg_deterministic_exit_code; // always exit with first child's exit status
extern int arg_deterministic_shutdown; // shut down the sandbox if first child dies

typedef enum {
DBUS_POLICY_ALLOW, // Allow unrestricted access to the bus
Expand Down
4 changes: 4 additions & 0 deletions src/firejail/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ int arg_nodvd = 0; // --nodvd
int arg_nou2f = 0; // --nou2f
int arg_noinput = 0; // --noinput
int arg_deterministic_exit_code = 0; // always exit with first child's exit status
int arg_deterministic_shutdown = 0; // shut down the sandbox if first child dies
DbusPolicy arg_dbus_user = DBUS_POLICY_ALLOW; // --dbus-user
DbusPolicy arg_dbus_system = DBUS_POLICY_ALLOW; // --dbus-system
const char *arg_dbus_log_file = NULL;
Expand Down Expand Up @@ -2765,6 +2766,9 @@ int main(int argc, char **argv, char **envp) {
else if (strcmp(argv[i], "--deterministic-exit-code") == 0) {
arg_deterministic_exit_code = 1;
}
else if (strcmp(argv[i], "--deterministic-shutdown") == 0) {
arg_deterministic_shutdown = 1;
}
else {
// double dash - positional params to follow
if (strcmp(argv[i], "--") == 0) {
Expand Down
5 changes: 5 additions & 0 deletions src/firejail/profile.c
Original file line number Diff line number Diff line change
Expand Up @@ -1597,6 +1597,11 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
return 0;
}

if (strcmp(ptr, "deterministic-shutdown") == 0) {
arg_deterministic_shutdown = 1;
return 0;
}

// rest of filesystem
if (strncmp(ptr, "blacklist ", 10) == 0)
ptr += 10;
Expand Down
21 changes: 9 additions & 12 deletions src/firejail/sandbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,15 @@ static int monitor_application(pid_t app_pid) {
if (arg_debug)
printf("Sandbox monitor: waitpid %d retval %d status %d\n", monitored_pid, rv, status);

if (arg_deterministic_shutdown) {
if (arg_debug)
printf("Sandbox monitor: monitored process died, shut down the sandbox\n");
kill(-1, SIGTERM);
usleep(100000);
kill(-1, SIGKILL);
break;
}

DIR *dir;
if (!(dir = opendir("/proc"))) {
// sleep 2 seconds and try again
Expand All @@ -377,18 +386,6 @@ static int monitor_application(pid_t app_pid) {
if ((pid_t) pid == dhclient4_pid || (pid_t) pid == dhclient6_pid)
continue;

// todo: make this generic
// Dillo browser leaves a dpid process running, we need to shut it down
int found = 0;
if (strcmp(cfg.command_name, "dillo") == 0) {
char *pidname = pid_proc_comm(pid);
if (pidname && strcmp(pidname, "dpid") == 0)
found = 1;
free(pidname);
}
if (found)
break;

monitored_pid = pid;
break;
}
Expand Down
1 change: 1 addition & 0 deletions src/firejail/usage.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ static char *usage_str =
" --defaultgw=address - configure default gateway.\n"
#endif
" --deterministic-exit-code - always exit with first child's status code.\n"
" --deterministic-shutdown - terminate orphan processes.\n"
" --dns=address - set DNS server.\n"
" --dns.print=name|pid - print DNS configuration.\n"
" --env=name=value - set environment variable.\n"
Expand Down
5 changes: 5 additions & 0 deletions src/man/firejail-profile.txt
Original file line number Diff line number Diff line change
Expand Up @@ -954,11 +954,16 @@ be created and configured using "ip netns".
Use this name for the interface connected to the bridge for --net=bridge_interface commands,
instead of the default one.
#endif

.SH Other
.TP
\fBdeterministic-exit-code
Always exit firejail with the first child's exit status. The default behavior is to use the exit status of the final child to exit, which can be nondeterministic.

.TP
\fBdeterministic-shutdown
Always shut down the sandbox after the first child has terminated. The default behavior is to keep the sandbox alive as long as it contains running processes.

.TP
\fBjoin-or-start sandboxname
Join the sandbox identified by name or start a new one.
Expand Down
6 changes: 6 additions & 0 deletions src/man/firejail.txt
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,12 @@ $ firejail \-\-net=eth0 \-\-defaultgw=10.10.20.1 firefox
\fB\-\-deterministic-exit-code
Always exit firejail with the first child's exit status. The default behavior is to use the exit status of the final child to exit, which can be nondeterministic.
.br

.TP
\fB\-\-deterministic-shutdown
Always shut down the sandbox after the first child has terminated. The default behavior is to keep the sandbox alive as long as it contains running processes.
.br

.TP
\fB\-\-disable-mnt
Blacklist /mnt, /media, /run/mount and /run/media access.
Expand Down
1 change: 1 addition & 0 deletions src/zsh_completion/_firejail.in
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ _firejail_args=(
'--cpu=-[set cpu affinity]: :->cpus'
'*--deny=-[deny access to directory or file]: :_files'
"--deterministic-exit-code[always exit with first child's status code]"
'--deterministic-shutdown[terminate orphan processes]'
'*--dns=-[set DNS server]: :'
'*--env=-[set environment variable]: :'
'--hostname=-[set sandbox hostname]: :'
Expand Down