From 7f3b6c19a0a87bfd240af7c0c9d61ae907668ce6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=B7=D0=B0=D0=BB=D0=B8=D1=8F=20=D0=A1=D0=BC=D0=B0?= =?UTF-8?q?=D1=80=D0=B0=D0=B3=D0=B4=D0=BE=D0=B2=D0=B0?= Date: Mon, 25 Jul 2022 17:16:53 +0500 Subject: [PATCH] Add support for custom AppArmor profiles (--apparmor=) --- contrib/vim/syntax/firejail.vim | 2 +- src/firejail/firejail.h | 1 + src/firejail/main.c | 9 ++++++++- src/firejail/profile.c | 11 +++++++++++ src/firejail/sandbox.c | 2 +- src/firejail/usage.c | 4 +++- src/man/firejail-profile.txt | 6 +++++- src/man/firejail.txt | 8 +++++++- src/zsh_completion/_firejail.in | 3 ++- 9 files changed, 39 insertions(+), 7 deletions(-) diff --git a/contrib/vim/syntax/firejail.vim b/contrib/vim/syntax/firejail.vim index 9099a0808f3..0c8ebdbd8b2 100644 --- a/contrib/vim/syntax/firejail.vim +++ b/contrib/vim/syntax/firejail.vim @@ -52,7 +52,7 @@ syn match fjVar /\v\$\{(CFG|DESKTOP|DOCUMENTS|DOWNLOADS|HOME|MUSIC|PATH|PICTURES " Commands grabbed from: src/firejail/profile.c " 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|restrict-namespaces|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|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 +syn match fjCommand /\v(apparmor|bind|blacklist|blacklist-nolog|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 /ignore / nextgroup=fjCommand,fjCommandNoCond skipwhite contained diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 167b6a843fe..0a4dffb75f9 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -338,6 +338,7 @@ extern int arg_writable_run_user; // writable /run/user extern int arg_writable_var_log; // writable /var/log extern int arg_appimage; // appimage extern int arg_apparmor; // apparmor +extern char *apparmor_profile; // apparmor profile extern int arg_allow_debuggers; // allow debuggers extern int arg_x11_block; // block X11 extern int arg_x11_xorg; // use X11 security extension diff --git a/src/firejail/main.c b/src/firejail/main.c index 55f6231388a..29c25dfc509 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c @@ -133,6 +133,7 @@ int arg_writable_run_user = 0; // writable /run/user int arg_writable_var_log = 0; // writable /var/log int arg_appimage = 0; // appimage int arg_apparmor = 0; // apparmor +char *apparmor_profile = NULL; // apparmor profile int arg_allow_debuggers = 0; // allow debuggers int arg_x11_block = 0; // block X11 int arg_x11_xorg = 0; // use X11 security extension @@ -1287,8 +1288,14 @@ int main(int argc, char **argv, char **envp) { // filtering //************************************* #ifdef HAVE_APPARMOR - else if (strcmp(argv[i], "--apparmor") == 0) + else if (strcmp(argv[i], "--apparmor") == 0) { arg_apparmor = 1; + apparmor_profile = "firejail-default"; + } + else if (strncmp(argv[i], "--apparmor=", 11) == 0) { + arg_apparmor = 1; + apparmor_profile = argv[i] + 11; + } #endif else if (strncmp(argv[i], "--protocol=", 11) == 0) { if (checkcfg(CFG_SECCOMP)) { diff --git a/src/firejail/profile.c b/src/firejail/profile.c index dc1aff49aee..82f8a393b74 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c @@ -939,6 +939,17 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { if (strcmp(ptr, "apparmor") == 0) { #ifdef HAVE_APPARMOR arg_apparmor = 1; + apparmor_profile = "firejail-default"; +#endif + return 0; + } + + if (strncmp(ptr, "apparmor ", 9) == 0) { +#ifdef HAVE_APPARMOR + arg_apparmor = 1; + apparmor_profile = strdup(ptr + 9); + if (!apparmor_profile) + errExit("strdup"); #endif return 0; } diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index b1b3407b499..9299268a378 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c @@ -130,7 +130,7 @@ static void set_caps(void) { static void set_apparmor(void) { EUID_ASSERT(); if (checkcfg(CFG_APPARMOR) && arg_apparmor) { - if (aa_change_onexec("firejail-default")) { + if (aa_stack_onexec(apparmor_profile)) { fwarning("Cannot confine the application using AppArmor.\n" "Maybe firejail-default AppArmor profile is not loaded into the kernel.\n" "As root, run \"aa-enforce firejail-default\" to load it.\n"); diff --git a/src/firejail/usage.c b/src/firejail/usage.c index c3c17393cdc..e11081eed95 100644 --- a/src/firejail/usage.c +++ b/src/firejail/usage.c @@ -30,7 +30,9 @@ static char *usage_str = " -- - signal the end of options and disables further option processing.\n" " --allow-debuggers - allow tools such as strace and gdb inside the sandbox.\n" " --allusers - all user home directories are visible inside the sandbox.\n" - " --apparmor - enable AppArmor confinement.\n" + " --apparmor - enable AppArmor confinement with the default profile.\n" + " --apparmor=profile_name - enable AppArmor confinement with a\n" + "\tcustom profile.\n" " --apparmor.print=name|pid - print apparmor status.\n" " --appimage - sandbox an AppImage application.\n" #ifdef HAVE_NETWORK diff --git a/src/man/firejail-profile.txt b/src/man/firejail-profile.txt index be1f55f0fc7..0b0c64ec60f 100644 --- a/src/man/firejail-profile.txt +++ b/src/man/firejail-profile.txt @@ -478,7 +478,11 @@ Allow tools such as strace and gdb inside the sandbox by whitelisting system cal #ifdef HAVE_APPARMOR .TP \fBapparmor -Enable AppArmor confinement. +Enable AppArmor confinement with the "firejail-default" AppArmor profile. +.TP +\fBapparmor profile_name +Enable AppArmor confinement with a custom AppArmor profile. +Note that the profile in question must already be loaded into the kernel. #endif .TP \fBcaps diff --git a/src/man/firejail.txt b/src/man/firejail.txt index 087d1c85a8b..b783795f21a 100644 --- a/src/man/firejail.txt +++ b/src/man/firejail.txt @@ -122,7 +122,13 @@ $ firejail --allusers #ifdef HAVE_APPARMOR .TP \fB\-\-apparmor -Enable AppArmor confinement. For more information, please see \fBAPPARMOR\fR section below. +Enable AppArmor confinement with the "firejail-default" AppArmor profile. +For more information, please see \fBAPPARMOR\fR section below. +.TP +\fB\-\-apparmor=profile_name +Enable AppArmor confinement with a custom AppArmor profile. +Note that profile in question must already be loaded into the kernel. +For more information, please see \fBAPPARMOR\fR section below. .TP \fB\-\-apparmor.print=name|pid Print the AppArmor confinement status for the sandbox identified by name or by PID. diff --git a/src/zsh_completion/_firejail.in b/src/zsh_completion/_firejail.in index 605000e310c..2b67c2a00a2 100644 --- a/src/zsh_completion/_firejail.in +++ b/src/zsh_completion/_firejail.in @@ -171,7 +171,8 @@ _firejail_args=( '--writable-var-log[use the real /var/log directory, not a clone]' #ifdef HAVE_APPARMOR - '--apparmor[enable AppArmor confinement]' + '--apparmor[enable AppArmor confinement with the default profile]' + '--apparmor=-[enable AppArmor confinement with a custom profile]: :' '--apparmor.print=-[print apparmor status name|pid]:firejail:_all_firejails' #endif