Skip to content

Commit

Permalink
Add keep-xattrs option
Browse files Browse the repository at this point in the history
By default, firejail preserves only xattrs for bind-mounted files. To
preserve xattrs on copied files (produced by private-bin, private-etc
and private-home options) it's possible to use keep-xattrs option.

keep-xattrs is very useful in systems with signature-based IMA appraisal
enabled (especially, when IMA policy prohibits running unsigned
binaries).
  • Loading branch information
dseight committed May 10, 2022
1 parent 055168c commit 624517b
Show file tree
Hide file tree
Showing 12 changed files with 38 additions and 8 deletions.
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|deterministic-exit-code|deterministic-shutdown|disable-mnt|ipc-namespace|keep-config-pulse|keep-dev-shm|keep-fd|keep-var-tmp|machine-id|memory-deny-write-execute|netfilter|no3d|noautopulse|nodbus|nodvd|nogroups|noinput|nonewprivs|noprinters|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-fd|keep-xattrs|keep-var-tmp|machine-id|memory-deny-write-execute|netfilter|no3d|noautopulse|nodbus|nodvd|nogroups|noinput|nonewprivs|noprinters|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
2 changes: 1 addition & 1 deletion src/firejail/dhcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ void dhcp_store_exec(void) {
}
}

sbox_run(SBOX_ROOT| SBOX_SECCOMP, 4, PATH_FCOPY, "--follow-link", dhclient_path, RUN_MNT_DIR);
sbox_run(SBOX_ROOT| SBOX_SECCOMP, 6, PATH_FCOPY, "--follow-link", "--keep-xattrs", cfg.keep_xattrs, dhclient_path, RUN_MNT_DIR);
}

void dhcp_start(void) {
Expand Down
1 change: 1 addition & 0 deletions src/firejail/firejail.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ typedef struct config_t {
#define MAX_PROFILE_IGNORE 32
char *profile_ignore[MAX_PROFILE_IGNORE];
char *keep_fd; // inherit file descriptors to sandbox
char *keep_xattrs; // keep xattrs on copied files
char *chrootdir; // chroot directory
char *home_private; // private home directory
char *home_private_keep; // keep list for private home directory
Expand Down
4 changes: 2 additions & 2 deletions src/firejail/fs_bin.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ static void duplicate(char *fname) {
if (valid_full_path_file(actual_path)) {
// solving problems such as /bin/sh -> /bin/dash
// copy the real file pointed by symlink
sbox_run(SBOX_ROOT| SBOX_SECCOMP, 3, PATH_FCOPY, actual_path, RUN_BIN_DIR);
sbox_run(SBOX_ROOT| SBOX_SECCOMP, 5, PATH_FCOPY, "--keep-xattrs", cfg.keep_xattrs, actual_path, RUN_BIN_DIR);
prog_cnt++;
char *f = strrchr(actual_path, '/');
if (f && *(++f) !='\0')
Expand All @@ -198,7 +198,7 @@ static void duplicate(char *fname) {
}

// copy a file or a symlink
sbox_run(SBOX_ROOT| SBOX_SECCOMP, 3, PATH_FCOPY, full_path, RUN_BIN_DIR);
sbox_run(SBOX_ROOT| SBOX_SECCOMP, 5, PATH_FCOPY, "--keep-xattrs", cfg.keep_xattrs, full_path, RUN_BIN_DIR);
prog_cnt++;
free(full_path);
report_duplication(fname);
Expand Down
4 changes: 2 additions & 2 deletions src/firejail/fs_etc.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,9 @@ static void duplicate(const char *fname, const char *private_dir, const char *pr
// this will solve problems such as NixOS #4887
// don't follow links to dynamic directories such as /proc
if (strcmp(src, "/etc/mtab") == 0)
sbox_run(SBOX_ROOT | SBOX_SECCOMP, 3, PATH_FCOPY, src, dst);
sbox_run(SBOX_ROOT | SBOX_SECCOMP, 5, PATH_FCOPY, "--keep-xattrs", cfg.keep_xattrs, src, dst);
else
sbox_run(SBOX_ROOT | SBOX_SECCOMP, 4, PATH_FCOPY, "--follow-link", src, dst);
sbox_run(SBOX_ROOT | SBOX_SECCOMP, 6, PATH_FCOPY, "--follow-link", "--keep-xattrs", cfg.keep_xattrs, src, dst);

free(dst);
fs_logger2("clone", src);
Expand Down
4 changes: 2 additions & 2 deletions src/firejail/fs_home.c
Original file line number Diff line number Diff line change
Expand Up @@ -569,11 +569,11 @@ static void duplicate(char *name) {
if (asprintf(&path, "%s/%s", RUN_HOME_DIR, ptr) == -1)
errExit("asprintf");
create_empty_dir_as_user(path, 0755);
sbox_run(SBOX_USER| SBOX_CAPS_NONE | SBOX_SECCOMP, 3, PATH_FCOPY, fname, path);
sbox_run(SBOX_USER| SBOX_CAPS_NONE | SBOX_SECCOMP, 5, PATH_FCOPY, "--keep-xattrs", cfg.keep_xattrs, fname, path);
free(path);
}
else
sbox_run(SBOX_USER| SBOX_CAPS_NONE | SBOX_SECCOMP, 3, PATH_FCOPY, fname, RUN_HOME_DIR);
sbox_run(SBOX_USER| SBOX_CAPS_NONE | SBOX_SECCOMP, 5, PATH_FCOPY, "--keep-xattrs", cfg.keep_xattrs, fname, RUN_HOME_DIR);
fs_logger2("clone", fname);
fs_logger_print(); // save the current log

Expand Down
8 changes: 8 additions & 0 deletions src/firejail/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1885,6 +1885,10 @@ int main(int argc, char **argv, char **envp) {
profile_list_augment(&cfg.keep_fd, add);
}
}
else if (strncmp(argv[i], "--keep-xattrs=", 14) == 0) {
const char *xattr = argv[i] + 14;
profile_list_augment(&cfg.keep_xattrs, xattr);
}
#ifdef HAVE_CHROOT
else if (strncmp(argv[i], "--chroot=", 9) == 0) {
if (checkcfg(CFG_CHROOT)) {
Expand Down Expand Up @@ -2972,6 +2976,10 @@ int main(int argc, char **argv, char **envp) {
}
EUID_ASSERT();

// make sure that the xattr list is not null
if (!cfg.keep_xattrs)
cfg.keep_xattrs = "";

// block X11 sockets
if (arg_x11_block)
x11_block();
Expand Down
5 changes: 5 additions & 0 deletions src/firejail/profile.c
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,11 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
}
return 0;
}
if (strncmp(ptr, "keep-xattrs ", 12) == 0) {
const char *xattr = ptr + 12;
profile_list_augment(&cfg.keep_xattrs, xattr);
return 0;
}
if (strncmp(ptr, "xephyr-screen ", 14) == 0) {
#ifdef HAVE_X11
if (checkcfg(CFG_X11)) {
Expand Down
1 change: 1 addition & 0 deletions src/firejail/usage.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ static char *usage_str =
" --keep-config-pulse - disable automatic ~/.config/pulse init.\n"
" --keep-dev-shm - /dev/shm directory is untouched (even with --private-dev).\n"
" --keep-fd - inherit open file descriptors to sandbox.\n"
" --keep-xattrs=name,name,name - copy the specified extended attributes to the sandbox.\n"
" --keep-var-tmp - /var/tmp directory is untouched.\n"
" --list - list all sandboxes.\n"
#ifdef HAVE_FILE_TRANSFER
Expand Down
4 changes: 4 additions & 0 deletions src/man/firejail-profile.txt
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,10 @@ Enable IPC namespace.
\fBkeep-fd
Inherit open file descriptors to sandbox.

.TP
\fBkeep-xattrs name,name,name
Copy the specified extended attributes to the sandbox.

.TP
\fBname sandboxname
Set sandbox name. Example:
Expand Down
10 changes: 10 additions & 0 deletions src/man/firejail.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1123,6 +1123,16 @@ Example:
.br
$ firejail --keep-fd=3,4,5

.TP
\fB\-\-keep-xattrs=name,name,name
Copy the specified extended attributes. By default, none of the xattrs are copied for files in private-bin, private-etc and private-home. Attributes are always preserved for bind-mounted files. See xattr(7) for details.
.br

.br
Example:
.br
$ firejail --keep-xattrs=security.ima,security.SMACK64

.TP
\fB\-\-keep-var-tmp
/var/tmp directory is untouched.
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 @@ -105,6 +105,7 @@ _firejail_args=(
'--keep-config-pulse[disable automatic ~/.config/pulse init]'
'--keep-dev-shm[/dev/shm directory is untouched (even with --private-dev)]'
'--keep-fd[inherit open file descriptors to sandbox]'
'*--keep-xattrs=-[copy the specified extended attributes to the sandbox]'
'--keep-var-tmp[/var/tmp directory is untouched]'
'--machine-id[spoof /etc/machine-id with a random id]'
'--memory-deny-write-execute[seccomp filter to block attempts to create memory mappings that are both writable and executable]'
Expand Down

0 comments on commit 624517b

Please sign in to comment.