diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 0f13afc51dd..eb485b8a2a8 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -7,6 +7,13 @@ assignees: '' --- + + ### Description _Describe the bug_ @@ -15,7 +22,7 @@ _Describe the bug_ _Steps to reproduce the behavior_ -1. Run in bash `LANG=C firejail PROGRAM` (`LANG=C` to get English messages that can be understood by everybody) +1. Run in bash `LC_ALL=C firejail PROGRAM` (`LC_ALL=C` to get a consistent output in English that can be understood by everybody) 2. Click on '....' 3. Scroll down to '....' 4. See error `ERROR` @@ -30,7 +37,7 @@ _What actually happened_ ### Behavior without a profile -_What changed calling `firejail --noprofile /path/to/program` in a terminal?_ +_What changed calling `LC_ALL=C firejail --noprofile /path/to/program` in a terminal?_ ### Additional context @@ -44,6 +51,12 @@ _Any other detail that may help to understand/debug the problem_ ### Checklist + + - [ ] The issues is caused by firejail (i.e. running the program by path (e.g. `/usr/bin/vlc`) "fixes" it). - [ ] I can reproduce the issue without custom modifications (e.g. globals.local). - [ ] The program has a profile. (If not, request one in `https://github.com/netblue30/firejail/issues/1139`) @@ -55,7 +68,7 @@ _Any other detail that may help to understand/debug the problem_ ### Log
-Output of firejail /path/to/program +Output of LC_ALL=C firejail /path/to/program

``` @@ -66,7 +79,7 @@ output goes here

-Output of firejail --debug /path/to/program +Output of LC_ALL=C firejail --debug /path/to/program

``` diff --git a/README.md b/README.md index 0623d946305..40c6e9d98bf 100644 --- a/README.md +++ b/README.md @@ -267,4 +267,5 @@ $ ./profstats *.profile ### New profiles: -clion-eap, lifeograph, io.github.lainsce.Notejot, rednotebook, zim, microsoft-edge-beta, ncdu2, gallery-dl, yt-dlp +clion-eap, lifeograph, io.github.lainsce.Notejot, rednotebook, zim, microsoft-edge-beta, ncdu2, gallery-dl, yt-dlp, goldendict, bundle, +cmake, make, meson, pip, codium diff --git a/RELNOTES b/RELNOTES index f52ce09f149..3f92c89c771 100644 --- a/RELNOTES +++ b/RELNOTES @@ -1,13 +1,16 @@ firejail (0.9.67) baseline; urgency=low * work in progress + * exit code: distinguish fatal signals by adding 128 * deprecated --disable-whitelist at compile time * deprecated whitelist=yes/no in /etc/firejail/firejail.config + * new condition: ALLOW_TRAY * remove (some) environment variables with auth-tokens * new includes: whitelist-run-common.inc, disable-X11.inc * removed includes: disable-passwordmgr.inc * new profiles: microsoft-edge-beta, clion-eap, lifeograph, zim * new profiles: io.github.lainsce.Notejot, rednotebook, gallery-dl - * new profiles: yt-dlp + * new profiles: yt-dlp, goldendict, goldendict, bundle, cmake + * new profiles: make, meson, pip, codium -- netblue30 Thu, 29 Jul 2021 09:00:00 -0500 firejail (0.9.66) baseline; urgency=low diff --git a/contrib/vim/syntax/firejail.vim b/contrib/vim/syntax/firejail.vim index d07690ee23f..fa80a9c0062 100644 --- a/contrib/vim/syntax/firejail.vim +++ b/contrib/vim/syntax/firejail.vim @@ -72,7 +72,7 @@ syn match fjCommandNoCond /quiet$/ contained " Conditionals grabbed from: src/firejail/profile.c " Generate list with: awk -- 'BEGIN {process=0;} /^Cond conditionals\[\] = \{$/ {process=1;} /\t*\{"[^"]+".*/ { if (process) {print gensub(/^\t*\{"([^"]+)".*$/, "\\1", 1);} } /^\t\{ NULL, NULL \}$/ {process=0;}' src/firejail/profile.c | sort -u | tr $'\n' '|' -syn match fjConditional /\v\?(BROWSER_ALLOW_DRM|BROWSER_DISABLE_U2F|HAS_APPIMAGE|HAS_NET|HAS_NODBUS|HAS_NOSOUND|HAS_X11) ?:/ nextgroup=fjCommand skipwhite contained +syn match fjConditional /\v\?(ALLOW_TRAY|BROWSER_ALLOW_DRM|BROWSER_DISABLE_U2F|HAS_APPIMAGE|HAS_NET|HAS_NODBUS|HAS_NOSOUND|HAS_X11) ?:/ nextgroup=fjCommand skipwhite contained " A line is either a command, a conditional or a comment syn match fjStatement /^/ nextgroup=fjCommand,fjCommandNoCond,fjConditional,fjComment diff --git a/etc/firejail.config b/etc/firejail.config index aec152b8587..7912b746c36 100644 --- a/etc/firejail.config +++ b/etc/firejail.config @@ -2,6 +2,9 @@ # keyword-argument pairs, one per line. Most features are enabled by default. # Use 'yes' or 'no' as configuration values. +# Allow programs to display a tray icon +# allow-tray no + # Enable AppArmor functionality, default enabled. # apparmor yes diff --git a/etc/inc/allow-common-devel.inc b/etc/inc/allow-common-devel.inc index 011bbe226b8..4e460fc102f 100644 --- a/etc/inc/allow-common-devel.inc +++ b/etc/inc/allow-common-devel.inc @@ -27,5 +27,8 @@ noblacklist ${HOME}/.python-history noblacklist ${HOME}/.python_history noblacklist ${HOME}/.pythonhist +# Ruby +noblacklist ${HOME}/.bundle + # Rust -noblacklist ${HOME}/.cargo/* +noblacklist ${HOME}/.cargo diff --git a/etc/inc/allow-ruby.inc b/etc/inc/allow-ruby.inc index a8c70121902..00276cac7e2 100644 --- a/etc/inc/allow-ruby.inc +++ b/etc/inc/allow-ruby.inc @@ -4,3 +4,4 @@ include allow-ruby.local noblacklist ${PATH}/ruby noblacklist /usr/lib/ruby +noblacklist /usr/lib64/ruby diff --git a/etc/inc/disable-interpreters.inc b/etc/inc/disable-interpreters.inc index 5d8a236fbf8..804869e2aba 100644 --- a/etc/inc/disable-interpreters.inc +++ b/etc/inc/disable-interpreters.inc @@ -48,6 +48,7 @@ blacklist /usr/share/php* # Ruby blacklist ${PATH}/ruby blacklist /usr/lib/ruby +blacklist /usr/lib64/ruby # Programs using python: deluge, firefox addons, filezilla, cherrytree, xchat, hexchat, libreoffice, scribus # Python 2 diff --git a/etc/inc/disable-programs.inc b/etc/inc/disable-programs.inc index e77ceb41c86..6734e220a6a 100644 --- a/etc/inc/disable-programs.inc +++ b/etc/inc/disable-programs.inc @@ -49,8 +49,9 @@ blacklist ${HOME}/.bibletime blacklist ${HOME}/.bitcoin blacklist ${HOME}/.blobby blacklist ${HOME}/.bogofilter +blacklist ${HOME}/.bundle blacklist ${HOME}/.bzf -blacklist ${HOME}/.cargo/* +blacklist ${HOME}/.cargo blacklist ${HOME}/.claws-mail blacklist ${HOME}/.cliqz blacklist ${HOME}/.clion* @@ -142,6 +143,7 @@ blacklist ${HOME}/.config/SubDownloader blacklist ${HOME}/.config/Thunar blacklist ${HOME}/.config/Twitch blacklist ${HOME}/.config/Unknown Organization +blacklist ${HOME}/.config/VSCodium blacklist ${HOME}/.config/VirtualBox blacklist ${HOME}/.config/Whalebird blacklist ${HOME}/.config/Wire @@ -496,6 +498,7 @@ blacklist ${HOME}/.frogatto blacklist ${HOME}/.frozen-bubble blacklist ${HOME}/.funnyboat blacklist ${HOME}/.gallery-dl.conf +blacklist ${HOME}/.geekbench5 blacklist ${HOME}/.gimp* blacklist ${HOME}/.gist blacklist ${HOME}/.gitconfig diff --git a/etc/profile-a-l/amule.profile b/etc/profile-a-l/amule.profile index 3ce05c5bcc3..e82c145d108 100644 --- a/etc/profile-a-l/amule.profile +++ b/etc/profile-a-l/amule.profile @@ -32,6 +32,7 @@ nosound notv nou2f novideo +# Add netlink protocol to use UPnP protocol unix,inet,inet6 seccomp shell none diff --git a/etc/profile-a-l/build-systems-common.profile b/etc/profile-a-l/build-systems-common.profile new file mode 100644 index 00000000000..1b199d612b7 --- /dev/null +++ b/etc/profile-a-l/build-systems-common.profile @@ -0,0 +1,66 @@ +# Firejail profile for build-systems-common +# This file is overwritten after every install/update +# Persistent local customizations +include build-systems-common.local +# Persistent global definitions +# added by caller profile +#include globals.local + +ignore noexec ${HOME} +ignore noexec /tmp + +# Allow /bin/sh (blacklisted by disable-shell.inc) +include allow-bin-sh.inc + +# Allows files commonly used by IDEs +include allow-common-devel.inc + +# Allow ssh (blacklisted by disable-common.inc) +#include allow-ssh.inc + +blacklist ${RUNUSER} + +include disable-common.inc +include disable-exec.inc +include disable-interpreters.inc +include disable-programs.inc +include disable-shell.inc +include disable-X11.inc +include disable-xdg.inc + +#whitelist ${HOME}/Projects +#include whitelist-common.inc + +whitelist /usr/share/pkgconfig +include whitelist-run-common.inc +include whitelist-usr-share-common.inc +include whitelist-var-common.inc + +caps.drop all +ipc-namespace +machine-id +# net none +netfilter +no3d +nodvd +nogroups +noinput +nonewprivs +noroot +nosound +notv +nou2f +novideo +protocol unix,inet,inet6 +seccomp +seccomp.block-secondary +shell none +tracelog + +disable-mnt +private-cache +private-dev +private-tmp + +dbus-user none +dbus-system none diff --git a/etc/profile-a-l/bundle.profile b/etc/profile-a-l/bundle.profile new file mode 100644 index 00000000000..bb82022b155 --- /dev/null +++ b/etc/profile-a-l/bundle.profile @@ -0,0 +1,23 @@ +# Firejail profile for bundle +# Description: Ruby Dependency Management +# This file is overwritten after every install/update +quiet +# Persistent local customizations +include bundle.local +# Persistent global definitions +include globals.local + +noblacklist ${HOME}/.bundle + +# Allow ruby (blacklisted by disable-interpreters.inc) +include allow-ruby.inc + +#whitelist ${HOME}/.bundle +#whitelist ${HOME}/.gem +#whitelist ${HOME}/.local/share/gem +whitelist /usr/share/gems +whitelist /usr/share/ruby +whitelist /usr/share/rubygems + +# Redirect +include build-systems-common.profile diff --git a/etc/profile-a-l/cargo.profile b/etc/profile-a-l/cargo.profile index ff46cd42915..4c8afd8950e 100644 --- a/etc/profile-a-l/cargo.profile +++ b/etc/profile-a-l/cargo.profile @@ -7,66 +7,18 @@ include cargo.local # Persistent global definitions include globals.local -ignore noexec ${HOME} -ignore noexec /tmp - -blacklist /tmp/.X11-unix -blacklist ${RUNUSER} +ignore read-only ${HOME}/.cargo/bin noblacklist ${HOME}/.cargo/credentials noblacklist ${HOME}/.cargo/credentials.toml -# Allows files commonly used by IDEs -include allow-common-devel.inc - -# Allow ssh (blacklisted by disable-common.inc) -#include allow-ssh.inc - -include disable-common.inc -include disable-exec.inc -include disable-interpreters.inc -include disable-programs.inc -include disable-xdg.inc - -#mkdir ${HOME}/.cargo -#whitelist ${HOME}/YOUR_CARGO_PROJECTS #whitelist ${HOME}/.cargo #whitelist ${HOME}/.rustup -#include whitelist-common.inc -whitelist /usr/share/pkgconfig -include whitelist-runuser-common.inc -include whitelist-usr-share-common.inc -include whitelist-var-common.inc -caps.drop all -ipc-namespace -machine-id -netfilter -no3d -nodvd -nogroups -noinput -nonewprivs -noroot -nosound -notv -nou2f -novideo -protocol unix,inet,inet6 -seccomp -seccomp.block-secondary -shell none -tracelog - -disable-mnt #private-bin cargo,rustc -private-cache -private-dev private-etc alternatives,ca-certificates,crypto-policies,group,host.conf,hostname,hosts,ld.so.cache,ld.so.conf,ld.so.conf.d,ld.so.preload,locale,locale.alias,locale.conf,localtime,magic,magic.mgc,nsswitch.conf,passwd,pki,protocols,resolv.conf,rpc,services,ssl -private-tmp - -dbus-user none -dbus-system none memory-deny-write-execute -read-write ${HOME}/.cargo/bin + +# Redirect +include build-systems-common.profile diff --git a/etc/profile-a-l/cheese.profile b/etc/profile-a-l/cheese.profile index 53d22163171..978d727f4c1 100644 --- a/etc/profile-a-l/cheese.profile +++ b/etc/profile-a-l/cheese.profile @@ -9,17 +9,24 @@ include globals.local noblacklist ${VIDEOS} noblacklist ${PICTURES} +include allow-python3.inc + include disable-common.inc include disable-devel.inc include disable-exec.inc include disable-interpreters.inc include disable-programs.inc +include disable-shell.inc include disable-xdg.inc whitelist ${VIDEOS} whitelist ${PICTURES} +whitelist /run/udev/data +whitelist /usr/libexec/gstreamer-1.0/gst-plugin-scanner whitelist /usr/share/gnome-video-effects +whitelist /usr/share/gstreamer-1.0 include whitelist-common.inc +include whitelist-run-common.inc include whitelist-runuser-common.inc include whitelist-usr-share-common.inc include whitelist-var-common.inc @@ -30,21 +37,26 @@ machine-id net none nodvd nogroups +noinput nonewprivs noroot +nosound notv nou2f protocol unix seccomp +seccomp.block-secondary shell none tracelog disable-mnt private-bin cheese private-cache +private-dev private-etc alternatives,clutter-1.0,dconf,drirc,fonts,gtk-3.0,ld.so.preload private-tmp dbus-user filter +dbus-user.own org.gnome.Cheese dbus-user.talk ca.desrt.dconf dbus-system none diff --git a/etc/profile-a-l/cmake.profile b/etc/profile-a-l/cmake.profile new file mode 100644 index 00000000000..26cc2a00a4c --- /dev/null +++ b/etc/profile-a-l/cmake.profile @@ -0,0 +1,13 @@ +# Firejail profile for cargo +# Description: The Rust package manager +# This file is overwritten after every install/update +quiet +# Persistent local customizations +include cargo.local +# Persistent global definitions +include globals.local + +memory-deny-write-execute + +# Redirect +include build-systems-common.profile diff --git a/etc/profile-a-l/codium.profile b/etc/profile-a-l/codium.profile new file mode 100644 index 00000000000..9ff87ed8af7 --- /dev/null +++ b/etc/profile-a-l/codium.profile @@ -0,0 +1,10 @@ +# Firejail profile alias for VSCodium +# This file is overwritten after every install/update +# Persistent local customizations +include codium.local +# Persistent global definitions +# added by included profile +#include globals.local + +# Redirect +include vscodium.profile diff --git a/etc/profile-a-l/geekbench.profile b/etc/profile-a-l/geekbench.profile index 60f2f338db9..4812e13683d 100644 --- a/etc/profile-a-l/geekbench.profile +++ b/etc/profile-a-l/geekbench.profile @@ -6,6 +6,10 @@ include geekbench.local # Persistent global definitions include globals.local +noblacklist ${HOME}/.geekbench5 +noblacklist /sbin +noblacklist /usr/sbin + include disable-common.inc include disable-devel.inc include disable-exec.inc @@ -13,6 +17,8 @@ include disable-interpreters.inc include disable-programs.inc include disable-xdg.inc +mkdir ${HOME}/.geekbench5 +whitelist ${HOME}/.geekbench5 include whitelist-common.inc include whitelist-usr-share-common.inc include whitelist-var-common.inc @@ -39,16 +45,14 @@ shell none tracelog disable-mnt -private-bin bash,geekbenc*,sh +#private-bin bash,geekbench*,sh -- #4576 private-cache private-dev private-etc alternatives,group,ld.so.preload,lsb-release,passwd -private-lib gcc/*/*/libstdc++.so.* -private-opt none private-tmp dbus-user none dbus-system none -#memory-deny-write-execute - breaks on Arch (see issue #1803) read-only ${HOME} +read-write ${HOME}/.geekbench5 diff --git a/etc/profile-a-l/inkscape.profile b/etc/profile-a-l/inkscape.profile index 5e54b544166..e0015e69a38 100644 --- a/etc/profile-a-l/inkscape.profile +++ b/etc/profile-a-l/inkscape.profile @@ -1,6 +1,7 @@ # Firejail profile for inkscape # Description: Vector-based drawing program # This file is overwritten after every install/update +quiet # Persistent local customizations include inkscape.local # Persistent global definitions diff --git a/etc/profile-m-z/make.profile b/etc/profile-m-z/make.profile new file mode 100644 index 00000000000..7e9638fe409 --- /dev/null +++ b/etc/profile-m-z/make.profile @@ -0,0 +1,13 @@ +# Firejail profile for make +# Description: GNU make utility to maintain groups of programs +# This file is overwritten after every install/update +quiet +# Persistent local customizations +include make.local +# Persistent global definitions +include globals.local + +memory-deny-write-execute + +# Redirect +include build-systems-common.profile diff --git a/etc/profile-m-z/meson.profile b/etc/profile-m-z/meson.profile new file mode 100644 index 00000000000..b4909a9d872 --- /dev/null +++ b/etc/profile-m-z/meson.profile @@ -0,0 +1,14 @@ +# Firejail profile for meson +# Description: A high productivity build system +# This file is overwritten after every install/update +quiet +# Persistent local customizations +include meson.local +# Persistent global definitions +include globals.local + +# Allow python3 (blacklisted by disable-interpreters.inc) +include allow-python3.inc + +# Redirect +include build-systems-common.profile diff --git a/etc/profile-m-z/musixmatch.profile b/etc/profile-m-z/musixmatch.profile index dac90cfa5f9..aab2ac19d78 100644 --- a/etc/profile-m-z/musixmatch.profile +++ b/etc/profile-m-z/musixmatch.profile @@ -29,7 +29,7 @@ notv nou2f novideo protocol unix,inet,inet6,netlink -seccomp +seccomp !chroot disable-mnt private-dev diff --git a/etc/profile-m-z/nheko.profile b/etc/profile-m-z/nheko.profile index 035ad086a9a..2f305dae965 100644 --- a/etc/profile-m-z/nheko.profile +++ b/etc/profile-m-z/nheko.profile @@ -51,11 +51,10 @@ private-dev private-etc alsa,alternatives,asound.conf,ca-certificates,crypto-policies,fonts,gtk-2.0,gtk-3.0,host.conf,hostname,hosts,ld.so.cache,ld.so.conf,ld.so.conf.d,ld.so.preload,locale,locale.alias,locale.conf,mime.types,nsswitch.conf,pki,pulse,resolv.conf,selinux,ssl,X11,xdg private-tmp - -# Add the next lines to your nheko.local to enable notification support. -#ignore dbus-user none -#dbus-user filter +dbus-user filter +dbus-user.talk org.freedesktop.secrets +# Add the next line to your nheko.local to enable notification support. #dbus-user.talk org.freedesktop.Notifications +# Add the next line to your nheko.local to enable tray icon support. #dbus-user.talk org.kde.StatusNotifierWatcher -dbus-user none dbus-system none diff --git a/etc/profile-m-z/pandoc.profile b/etc/profile-m-z/pandoc.profile index b8e8a750f57..460f60beb3a 100644 --- a/etc/profile-m-z/pandoc.profile +++ b/etc/profile-m-z/pandoc.profile @@ -11,6 +11,8 @@ blacklist ${RUNUSER} noblacklist ${DOCUMENTS} +include allow-bin-sh.inc + include disable-common.inc include disable-devel.inc include disable-exec.inc @@ -19,6 +21,7 @@ include disable-programs.inc include disable-shell.inc include disable-xdg.inc +include whitelist-runuser-common.inc # breaks pdf output #include whitelist-var-common.inc @@ -39,12 +42,12 @@ nou2f novideo protocol unix seccomp +seccomp.block-secondary shell none tracelog x11 none disable-mnt -private-bin context,latex,mktexfmt,pandoc,pdflatex,pdfroff,prince,weasyprint,wkhtmltopdf private-cache private-dev private-etc alternatives,ld.so.preload,texlive,texmf diff --git a/etc/profile-m-z/pip.profile b/etc/profile-m-z/pip.profile new file mode 100644 index 00000000000..a0926371fac --- /dev/null +++ b/etc/profile-m-z/pip.profile @@ -0,0 +1,18 @@ +# Firejail profile for pip +# Description: package manager for Python packages +# This file is overwritten after every install/update +quiet +# Persistent local customizations +include meson.local +# Persistent global definitions +include globals.local + +ignore read-only ${HOME}/.local/lib + +# Allow python3 (blacklisted by disable-interpreters.inc) +include allow-python3.inc + +#whitelist ${HOME}/.local/lib/python* + +# Redirect +include build-systems-common.profile diff --git a/etc/profile-m-z/vscodium.profile b/etc/profile-m-z/vscodium.profile index a4a4fb7d83b..9c0a887b2fc 100644 --- a/etc/profile-m-z/vscodium.profile +++ b/etc/profile-m-z/vscodium.profile @@ -1,4 +1,4 @@ -# Firejail profile alias for Visual Studio Code +# Firejail profile alias for VSCodium # This file is overwritten after every install/update # Persistent local customizations include vscodium.local @@ -7,6 +7,8 @@ include vscodium.local #include globals.local noblacklist ${HOME}/.VSCodium +noblacklist ${HOME}/.config/VSCodium +noblacklist ${HOME}/.vscode-oss # Redirect include code.profile diff --git a/src/fbuilder/build_fs.c b/src/fbuilder/build_fs.c index 019c3ac5abb..8700e0ba16c 100644 --- a/src/fbuilder/build_fs.c +++ b/src/fbuilder/build_fs.c @@ -182,12 +182,12 @@ static void var_callback(char *ptr) { void build_var(const char *fname, FILE *fp) { assert(fname); - var_skip = filedb_load_whitelist(var_skip, "whitelist-var-common.inc", "allow /var/"); + var_skip = filedb_load_whitelist(var_skip, "whitelist-var-common.inc", "whitelist /var/"); process_files(fname, "/var", var_callback); // always whitelist /var if (var_out) - filedb_print(var_out, "allow /var/", fp); + filedb_print(var_out, "whitelist /var/", fp); fprintf(fp, "include whitelist-var-common.inc\n"); } @@ -222,12 +222,12 @@ static void share_callback(char *ptr) { void build_share(const char *fname, FILE *fp) { assert(fname); - share_skip = filedb_load_whitelist(share_skip, "whitelist-usr-share-common.inc", "allow /usr/share/"); + share_skip = filedb_load_whitelist(share_skip, "whitelist-usr-share-common.inc", "whitelist /usr/share/"); process_files(fname, "/usr/share", share_callback); // always whitelist /usr/share if (share_out) - filedb_print(share_out, "allow /usr/share/", fp); + filedb_print(share_out, "whitelist /usr/share/", fp); fprintf(fp, "include whitelist-usr-share-common.inc\n"); } diff --git a/src/fbuilder/build_home.c b/src/fbuilder/build_home.c index c85474779c2..0fe0ffef60d 100644 --- a/src/fbuilder/build_home.c +++ b/src/fbuilder/build_home.c @@ -140,7 +140,7 @@ void build_home(const char *fname, FILE *fp) { assert(fname); // load whitelist common - db_skip = filedb_load_whitelist(db_skip, "whitelist-common.inc", "allow ${HOME}/"); + db_skip = filedb_load_whitelist(db_skip, "whitelist-common.inc", "whitelist ${HOME}/"); // find user home directory struct passwd *pw = getpwuid(getuid()); @@ -168,7 +168,7 @@ void build_home(const char *fname, FILE *fp) { // print the out list if any if (db_out) { - filedb_print(db_out, "allow ${HOME}/", fp); + filedb_print(db_out, "whitelist ${HOME}/", fp); fprintf(fp, "include whitelist-common.inc\n"); } else diff --git a/src/fbuilder/build_profile.c b/src/fbuilder/build_profile.c index 0b9a997398d..c945d725339 100644 --- a/src/fbuilder/build_profile.c +++ b/src/fbuilder/build_profile.c @@ -92,7 +92,7 @@ void build_profile(int argc, char **argv, int index, FILE *fp) { if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { if (fp == stdout) - printf("--- Built profile beings after this line ---\n"); + printf("--- Built profile begins after this line ---\n"); fprintf(fp, "# Save this file as \"application.profile\" (change \"application\" with the\n"); fprintf(fp, "# program name) in ~/.config/firejail directory. Firejail will find it\n"); fprintf(fp, "# automatically every time you sandbox your application.\n#\n"); diff --git a/src/fcopy/main.c b/src/fcopy/main.c index 31810de9ac5..f279af89fc9 100644 --- a/src/fcopy/main.c +++ b/src/fcopy/main.c @@ -88,7 +88,8 @@ static void selinux_relabel_path(const char *path, const char *inside_path) { if (arg_debug) printf("Relabeling %s as %s (%s)\n", path, inside_path, fcon); - setfilecon_raw(procfs_path, fcon); + if (setfilecon_raw(procfs_path, fcon) != 0 && arg_debug) + printf("Cannot relabel %s: %s\n", path, strerror(errno)); } freecon(fcon); close: diff --git a/src/firecfg/firecfg.config b/src/firecfg/firecfg.config index a544e25f22a..aad22ec7a5e 100644 --- a/src/firecfg/firecfg.config +++ b/src/firecfg/firecfg.config @@ -151,6 +151,7 @@ clocks cmus code code-oss +codium cola colorful com.github.bleakgrey.tootle diff --git a/src/firejail/checkcfg.c b/src/firejail/checkcfg.c index 06e6f0ccb9a..e5d837bbbf5 100644 --- a/src/firejail/checkcfg.c +++ b/src/firejail/checkcfg.c @@ -58,6 +58,7 @@ int checkcfg(int val) { cfg_val[CFG_XPRA_ATTACH] = 0; cfg_val[CFG_SECCOMP_ERROR_ACTION] = -1; cfg_val[CFG_BROWSER_ALLOW_DRM] = 0; + cfg_val[CFG_ALLOW_TRAY] = 0; // open configuration file const char *fname = SYSCONFDIR "/firejail.config"; @@ -122,6 +123,7 @@ int checkcfg(int val) { PARSE_YESNO(CFG_XPRA_ATTACH, "xpra-attach") PARSE_YESNO(CFG_BROWSER_DISABLE_U2F, "browser-disable-u2f") PARSE_YESNO(CFG_BROWSER_ALLOW_DRM, "browser-allow-drm") + PARSE_YESNO(CFG_ALLOW_TRAY, "allow-tray") #undef PARSE_YESNO // netfilter diff --git a/src/firejail/env.c b/src/firejail/env.c index ad16de03730..4c0d729a1f8 100644 --- a/src/firejail/env.c +++ b/src/firejail/env.c @@ -22,6 +22,7 @@ #include #include #include +#include typedef struct env_t { struct env_t *next; diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index f554a32044f..bf51a4c9315 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -564,7 +564,7 @@ typedef struct { // mountinfo.c MountData *get_last_mount(void); -int get_mount_id(const char *path); +int get_mount_id(int fd); char **build_mount_array(const int mount_id, const char *path); // fs_var.c @@ -622,7 +622,8 @@ void caps_print_filter(pid_t pid) __attribute__((noreturn)); void caps_drop_dac_override(void); // fs_trace.c -void fs_trace_preload(void); +void fs_trace_touch_preload(void); +void fs_trace_touch_or_store_preload(void); void fs_tracefile(void); void fs_trace(void); @@ -802,6 +803,7 @@ enum { CFG_NAME_CHANGE, CFG_SECCOMP_ERROR_ACTION, // CFG_FILE_COPY_LIMIT - file copy limit handled using setenv/getenv + CFG_ALLOW_TRAY, CFG_MAX // this should always be the last entry }; extern char *xephyr_screen; diff --git a/src/firejail/fs.c b/src/firejail/fs.c index 7e0a6e347a1..1a9a8df0deb 100644 --- a/src/firejail/fs.c +++ b/src/firejail/fs.c @@ -199,8 +199,6 @@ static void disable_file(OPERATION op, const char *filename) { } fs_tmpfs(fname, uid); - EUID_USER(); // fs_tmpfs returns with EUID 0 - selinux_relabel_path(fname, fname); } else @@ -281,6 +279,8 @@ static void globbing(OPERATION op, const char *pattern, const char *noblacklist[ // blacklist files or directories by mounting empty files on top of them void fs_blacklist(void) { + EUID_ASSERT(); + ProfileEntry *entry = cfg.profile; if (!entry) return; @@ -292,7 +292,6 @@ void fs_blacklist(void) { if (noblacklist == NULL) errExit("failed allocating memory for noblacklist entries"); - EUID_USER(); while (entry) { OPERATION op = OPERATION_MAX; char *ptr; @@ -468,8 +467,6 @@ void fs_blacklist(void) { for (i = 0; i < noblacklist_c; i++) free(noblacklist[i]); free(noblacklist); - - EUID_ROOT(); } //*********************************************** @@ -478,7 +475,7 @@ void fs_blacklist(void) { // mount a writable tmpfs on directory; requires a resolved path void fs_tmpfs(const char *dir, unsigned check_owner) { - EUID_USER(); + EUID_ASSERT(); assert(dir); if (arg_debug) printf("Mounting tmpfs on %s, check owner: %s\n", dir, (check_owner)? "yes": "no"); @@ -503,12 +500,13 @@ void fs_tmpfs(const char *dir, unsigned check_owner) { errExit("fstatvfs"); unsigned long flags = buf.f_flag & ~(MS_RDONLY|MS_BIND|MS_REMOUNT); // mount via the symbolic link in /proc/self/fd - EUID_ROOT(); char *proc; if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1) errExit("asprintf"); + EUID_ROOT(); if (mount("tmpfs", proc, "tmpfs", flags|MS_NOSUID|MS_NODEV, options) < 0) errExit("mounting tmpfs"); + EUID_USER(); // check the last mount operation MountData *mdata = get_last_mount(); if (strcmp(mdata->fstype, "tmpfs") != 0 || strcmp(mdata->dir, dir) != 0) @@ -634,34 +632,30 @@ static void fs_remount_simple(const char *path, OPERATION op) { } // remount recursively; requires a resolved path -static void fs_remount_rec(const char *dir, OPERATION op) { +static void fs_remount_rec(const char *path, OPERATION op) { EUID_ASSERT(); - assert(dir); + assert(op < OPERATION_MAX); + assert(path); - struct stat s; - if (stat(dir, &s) != 0) - return; - if (!S_ISDIR(s.st_mode)) { - // no need to search in /proc/self/mountinfo for submounts if not a directory - fs_remount_simple(dir, op); + // no need to search /proc/self/mountinfo for submounts if not a directory + int fd = open(path, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); + if (fd < 0) { + fs_remount_simple(path, op); return; } - // get mount point of the directory - int mountid = get_mount_id(dir); - if (mountid == -1) - return; - if (mountid == -2) { - // falling back to a simple remount on old kernels - static int mount_warning = 0; - if (!mount_warning) { - fwarning("read-only, read-write and noexec options are not applied recursively\n"); - mount_warning = 1; - } - fs_remount_simple(dir, op); + + // get mount id of the directory + int mountid = get_mount_id(fd); + close(fd); + if (mountid < 0) { + // falling back to a simple remount + fwarning("%s %s not applied recursively\n", opstr[op], path); + fs_remount_simple(path, op); return; } + // build array with all mount points that need to get remounted - char **arr = build_mount_array(mountid, dir); + char **arr = build_mount_array(mountid, path); assert(arr); // remount char **tmp = arr; diff --git a/src/firejail/fs_dev.c b/src/firejail/fs_dev.c index d8bb1aded15..694d0a3793e 100644 --- a/src/firejail/fs_dev.c +++ b/src/firejail/fs_dev.c @@ -329,8 +329,10 @@ void fs_dev_disable_sound(void) { } // disable all jack sockets in /dev/shm + EUID_USER(); glob_t globbuf; int globerr = glob("/dev/shm/jack*", GLOB_NOSORT, NULL, &globbuf); + EUID_ROOT(); if (globerr) return; diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c index 45889b27f95..8d8530d813b 100644 --- a/src/firejail/fs_home.c +++ b/src/firejail/fs_home.c @@ -394,14 +394,16 @@ void fs_private(void) { } if (chown(homedir, u, g) < 0) errExit("chown"); - fs_logger2("mkdir", homedir); fs_logger2("tmpfs", homedir); } - else + else { // mask user home directory // the directory should be owned by the current user + EUID_USER(); fs_tmpfs(homedir, 1); + EUID_ROOT(); + } selinux_relabel_path(homedir, homedir); } @@ -563,12 +565,13 @@ void fs_private_home_list(void) { int xflag = store_xauthority(); int aflag = store_asoundrc(); - // create /run/firejail/mnt/home directory EUID_ROOT(); + // create /run/firejail/mnt/home directory mkdir_attr(RUN_HOME_DIR, 0755, uid, gid); selinux_relabel_path(RUN_HOME_DIR, homedir); - fs_logger_print(); // save the current log + // save the current log + fs_logger_print(); EUID_USER(); // copy the list of files in the new home directory diff --git a/src/firejail/fs_trace.c b/src/firejail/fs_trace.c index 9463fbcd0c4..28852a68966 100644 --- a/src/firejail/fs_trace.c +++ b/src/firejail/fs_trace.c @@ -25,19 +25,26 @@ #include #include -void fs_trace_preload(void) { +// create an empty /etc/ld.so.preload +void fs_trace_touch_preload(void) { + create_empty_file_as_root("/etc/ld.so.preload", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +} + +void fs_trace_touch_or_store_preload(void) { struct stat s; - // create an empty /etc/ld.so.preload - if (stat("/etc/ld.so.preload", &s)) { - if (arg_debug) - printf("Creating an empty /etc/ld.so.preload file\n"); - FILE *fp = fopen("/etc/ld.so.preload", "wxe"); - if (!fp) - errExit("fopen"); - SET_PERMS_STREAM(fp, 0, 0, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH); - fclose(fp); - fs_logger("touch /etc/ld.so.preload"); + if (stat("/etc/ld.so.preload", &s) != 0) { + fs_trace_touch_preload(); + return; + } + + if (s.st_size == 0) + return; + + // create a copy of /etc/ld.so.preload + if (copy_file("/etc/ld.so.preload", RUN_LDPRELOAD_FILE, 0, 0, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) { + fprintf(stderr, "Error: cannot copy /etc/ld.so.preload file\n"); + exit(1); } } @@ -82,7 +89,7 @@ void fs_trace(void) { if (arg_debug) printf("Create the new ld.so.preload file\n"); - FILE *fp = fopen(RUN_LDPRELOAD_FILE, "we"); + FILE *fp = fopen(RUN_LDPRELOAD_FILE, "ae"); if (!fp) errExit("fopen"); const char *prefix = RUN_FIREJAIL_LIB_DIR; diff --git a/src/firejail/fs_whitelist.c b/src/firejail/fs_whitelist.c index 943f275de58..7afebed1fce 100644 --- a/src/firejail/fs_whitelist.c +++ b/src/firejail/fs_whitelist.c @@ -105,6 +105,7 @@ static int whitelist_mkpath(const char* path, mode_t mode) { } static void whitelist_file(int dirfd, const char *relpath, const char *path) { + EUID_ASSERT(); assert(relpath && path); // open mount source, using a file descriptor that refers to the @@ -130,12 +131,9 @@ static void whitelist_file(int dirfd, const char *relpath, const char *path) { } // create mount target as root, except if inside home or run/user/$UID directory - int userprivs = 0; - if ((strncmp(path, cfg.homedir, homedir_len) == 0 && path[homedir_len] == '/') || - (strncmp(path, runuser, runuser_len) == 0 && path[runuser_len] == '/')) { - EUID_USER(); - userprivs = 1; - } + if ((strncmp(path, cfg.homedir, homedir_len) != 0 || path[homedir_len] != '/') && + (strncmp(path, runuser, runuser_len) != 0 || path[runuser_len] != '/')) + EUID_ROOT(); // create path of the mount target int fd2 = whitelist_mkpath(path, 0755); @@ -146,8 +144,7 @@ static void whitelist_file(int dirfd, const char *relpath, const char *path) { if (arg_debug || arg_debug_whitelists) printf("Debug %d: skip whitelist %s\n", __LINE__, path); close(fd); - if (userprivs) - EUID_ROOT(); + EUID_USER(); return; } @@ -166,8 +163,7 @@ static void whitelist_file(int dirfd, const char *relpath, const char *path) { } close(fd); close(fd2); - if (userprivs) - EUID_ROOT(); + EUID_USER(); return; } fd3 = openat(fd2, file, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); @@ -184,19 +180,17 @@ static void whitelist_file(int dirfd, const char *relpath, const char *path) { } close(fd); close(fd2); - if (userprivs) - EUID_ROOT(); + EUID_USER(); return; } - close(fd2); - if (userprivs) - EUID_ROOT(); if (arg_debug || arg_debug_whitelists) printf("Whitelisting %s\n", path); + EUID_ROOT(); if (bind_mount_by_fd(fd, fd3)) errExit("mount bind"); + EUID_USER(); // check the last mount operation MountData *mptr = get_last_mount(); // will do exit(1) if the mount cannot be found #ifdef TEST_MOUNTINFO @@ -219,22 +213,19 @@ static void whitelist_file(int dirfd, const char *relpath, const char *path) { } static void whitelist_symlink(const char *link, const char *target) { + EUID_ASSERT(); assert(link && target); // create files as root, except if inside home or run/user/$UID directory - int userprivs = 0; - if ((strncmp(link, cfg.homedir, homedir_len) == 0 && link[homedir_len] == '/') || - (strncmp(link, runuser, runuser_len) == 0 && link[runuser_len] == '/')) { - EUID_USER(); - userprivs = 1; - } + if ((strncmp(link, cfg.homedir, homedir_len) != 0 || link[homedir_len] != '/') && + (strncmp(link, runuser, runuser_len) != 0 || link[runuser_len] != '/')) + EUID_ROOT(); int fd = whitelist_mkpath(link, 0755); if (fd == -1) { if (arg_debug || arg_debug_whitelists) printf("Debug %d: cannot create symbolic link %s\n", __LINE__, link); - if (userprivs) - EUID_ROOT(); + EUID_USER(); return; } @@ -252,8 +243,7 @@ static void whitelist_symlink(const char *link, const char *target) { printf("Created symbolic link %s -> %s\n", link, target); close(fd); - if (userprivs) - EUID_ROOT(); + EUID_USER(); } static void globbing(const char *pattern) { @@ -330,10 +320,11 @@ static void tmpfs_topdirs(const TopDir *topdirs) { // init tmpfs if (strcmp(topdirs[i].path, "/run") == 0) { // restore /run/firejail directory - if (mkdir(RUN_FIREJAIL_DIR, 0755) == -1) - errExit("mkdir"); + EUID_ROOT(); + mkdir_attr(RUN_FIREJAIL_DIR, 0755, 0, 0); if (bind_mount_fd_to_path(fd, RUN_FIREJAIL_DIR)) errExit("mount bind"); + EUID_USER(); close(fd); fs_logger2("whitelist", RUN_FIREJAIL_DIR); @@ -351,12 +342,14 @@ static void tmpfs_topdirs(const TopDir *topdirs) { errExit("asprintf"); if (strcmp(env, pamtmpdir) == 0) { // create empty user-owned /tmp/user/$UID directory + EUID_ROOT(); mkdir_attr("/tmp/user", 0711, 0, 0); selinux_relabel_path("/tmp/user", "/tmp/user"); fs_logger("mkdir /tmp/user"); mkdir_attr(pamtmpdir, 0700, getuid(), 0); selinux_relabel_path(pamtmpdir, pamtmpdir); fs_logger2("mkdir", pamtmpdir); + EUID_USER(); } free(pamtmpdir); } @@ -374,11 +367,8 @@ static void tmpfs_topdirs(const TopDir *topdirs) { } // user home directory - if (tmpfs_home) { - EUID_USER(); + if (tmpfs_home) fs_private(); // checks owner if outside /home - EUID_ROOT(); - } // /run/user/$UID directory if (tmpfs_runuser) { @@ -402,6 +392,7 @@ static int reject_topdir(const char *dir) { // keep track of whitelist top level directories by adding them to an array // open each directory static TopDir *add_topdir(const char *dir, TopDir *topdirs, const char *path) { + EUID_ASSERT(); assert(dir && path); // /proc and /sys are not allowed @@ -516,6 +507,8 @@ static char *extract_topdir(const char *path) { } void fs_whitelist(void) { + EUID_ASSERT(); + ProfileEntry *entry = cfg.profile; if (!entry) return; @@ -536,7 +529,6 @@ void fs_whitelist(void) { errExit("calloc"); // verify whitelist files, extract symbolic links, etc. - EUID_USER(); while (entry) { int nowhitelist_flag = 0; @@ -630,7 +622,7 @@ void fs_whitelist(void) { if (!fname) { if (arg_debug || arg_debug_whitelists) { printf("Removed path: %s\n", entry->data); - printf("\texpanded: %s\n", new_name); + printf("\tnew_name: %s\n", new_name); printf("\trealpath: (null)\n"); printf("\t%s\n", strerror(errno)); } @@ -712,7 +704,6 @@ void fs_whitelist(void) { free(nowhitelist); // mount tmpfs on all top level directories - EUID_ROOT(); tmpfs_topdirs(topdirs); // go through profile rules again, and interpret whitelist commands diff --git a/src/firejail/main.c b/src/firejail/main.c index a99249be9c3..cc5186204b8 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c @@ -32,6 +32,8 @@ #include #include #include + +#include #include #include #include diff --git a/src/firejail/mountinfo.c b/src/firejail/mountinfo.c index 64a94bd849a..304f80eee46 100644 --- a/src/firejail/mountinfo.c +++ b/src/firejail/mountinfo.c @@ -19,6 +19,7 @@ */ #include "firejail.h" +#include #include #ifndef O_PATH @@ -151,53 +152,71 @@ MountData *get_last_mount(void) { return &mdata; } -// Extract the mount id from /proc/self/fdinfo and return it. -int get_mount_id(const char *path) { +// Returns mount id, or -1 if fd refers to a procfs or sysfs file +static int get_mount_id_from_handle(int fd) { EUID_ASSERT(); - assert(path); - int fd = open(path, O_PATH|O_CLOEXEC); - if (fd == -1) - return -1; + char *proc; + if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1) + errExit("asprintf"); + struct file_handle *fh = malloc(sizeof *fh); + if (!fh) + errExit("malloc"); + fh->handle_bytes = 0; + + int rv = -1; + int tmp; + if (name_to_handle_at(-1, proc, fh, &tmp, AT_SYMLINK_FOLLOW) != -1) { + fprintf(stderr, "Error: unexpected result from name_to_handle_at\n"); + exit(1); + } + if (errno == EOVERFLOW && fh->handle_bytes) + rv = tmp; + + free(proc); + free(fh); + return rv; +} + +// Returns mount id, or -1 on kernels < 3.15 +static int get_mount_id_from_fdinfo(int fd) { + EUID_ASSERT(); + int rv = -1; - char *fdinfo; - if (asprintf(&fdinfo, "/proc/self/fdinfo/%d", fd) == -1) + char *proc; + if (asprintf(&proc, "/proc/self/fdinfo/%d", fd) == -1) errExit("asprintf"); EUID_ROOT(); - FILE *fp = fopen(fdinfo, "re"); + FILE *fp = fopen(proc, "re"); EUID_USER(); - free(fdinfo); if (!fp) goto errexit; - // read the file char buf[MAX_BUF]; - if (fgets(buf, MAX_BUF, fp) == NULL) - goto errexit; - do { + while (fgets(buf, MAX_BUF, fp)) { if (strncmp(buf, "mnt_id:", 7) == 0) { - char *ptr = buf + 7; - while (*ptr != '\0' && (*ptr == ' ' || *ptr == '\t')) { - ptr++; - } - if (*ptr == '\0') + if (sscanf(buf + 7, "%d", &rv) != 1) goto errexit; - fclose(fp); - close(fd); - return atoi(ptr); + break; } - } while (fgets(buf, MAX_BUF, fp)); + } - // fallback, kernels older than 3.15 don't expose the mount id in this place + free(proc); fclose(fp); - close(fd); - return -2; + return rv; errexit: fprintf(stderr, "Error: cannot read proc file\n"); exit(1); } +int get_mount_id(int fd) { + int rv = get_mount_id_from_fdinfo(fd); + if (rv < 0) + rv = get_mount_id_from_handle(fd); + return rv; +} + // Check /proc/self/mountinfo if path contains any mounts points. // Returns an array that can be iterated over for recursive remounting. char **build_mount_array(const int mount_id, const char *path) { diff --git a/src/firejail/profile.c b/src/firejail/profile.c index 059100fcb99..5390249eada 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c @@ -175,6 +175,10 @@ static int check_allow_drm(void) { return checkcfg(CFG_BROWSER_ALLOW_DRM) != 0; } +static int check_allow_tray(void) { + return checkcfg(CFG_ALLOW_TRAY) != 0; +} + Cond conditionals[] = { {"HAS_APPIMAGE", check_appimage}, {"HAS_NET", check_netoptions}, @@ -184,6 +188,7 @@ Cond conditionals[] = { {"HAS_X11", check_x11}, {"BROWSER_DISABLE_U2F", check_disable_u2f}, {"BROWSER_ALLOW_DRM", check_allow_drm}, + {"ALLOW_TRAY", check_allow_tray}, { NULL, NULL } }; @@ -630,7 +635,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { #endif return 0; } - else if (strncmp(ptr, "netns ", 6) == 0) { + else if (strncmp(ptr, "netns ", 6) == 0) { #ifdef HAVE_NETWORK if (checkcfg(CFG_NETWORK)) { arg_netns = ptr + 6; @@ -981,10 +986,10 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { warning_feature_disabled("seccomp"); return 0; } - if (strncmp(ptr, "seccomp.32.drop ", 13) == 0) { + if (strncmp(ptr, "seccomp.32.drop ", 16) == 0) { if (checkcfg(CFG_SECCOMP)) { arg_seccomp32 = 1; - cfg.seccomp_list_drop32 = seccomp_check_list(ptr + 13); + cfg.seccomp_list_drop32 = seccomp_check_list(ptr + 16); } else warning_feature_disabled("seccomp"); @@ -1001,10 +1006,10 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { warning_feature_disabled("seccomp"); return 0; } - if (strncmp(ptr, "seccomp.32.keep ", 13) == 0) { + if (strncmp(ptr, "seccomp.32.keep ", 16) == 0) { if (checkcfg(CFG_SECCOMP)) { arg_seccomp32 = 1; - cfg.seccomp_list_keep32 = seccomp_check_list(ptr + 13); + cfg.seccomp_list_keep32 = seccomp_check_list(ptr + 16); } else warning_feature_disabled("seccomp"); diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 995827fb78b..b776a0cc538 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c @@ -798,7 +798,7 @@ int sandbox(void* sandbox_arg) { // trace pre-install if (need_preload) - fs_trace_preload(); + fs_trace_touch_or_store_preload(); // store hosts file if (cfg.hosts_file) @@ -814,8 +814,11 @@ int sandbox(void* sandbox_arg) { //**************************** // trace pre-install, this time inside chroot //**************************** - if (need_preload) - fs_trace_preload(); + if (need_preload) { + int rv = unlink(RUN_LDPRELOAD_FILE); + (void) rv; + fs_trace_touch_or_store_preload(); + } } else #endif @@ -992,7 +995,7 @@ int sandbox(void* sandbox_arg) { // create /etc/ld.so.preload file again if (need_preload) - fs_trace_preload(); + fs_trace_touch_preload(); // openSUSE configuration is split between /etc and /usr/etc // process private-etc a second time @@ -1004,10 +1007,12 @@ int sandbox(void* sandbox_arg) { // apply the profile file //**************************** // apply all whitelist commands ... + EUID_USER(); fs_whitelist(); // ... followed by blacklist commands fs_blacklist(); // mkdir and mkfile are processed all over again + EUID_ROOT(); //**************************** // nosound/no3d/notv/novideo and fix for pulseaudio 7.0 diff --git a/src/firejail/selinux.c b/src/firejail/selinux.c index 6969e7a3dbc..fa59882ed74 100644 --- a/src/firejail/selinux.c +++ b/src/firejail/selinux.c @@ -21,6 +21,7 @@ #include "firejail.h" #include #include +#include #include #ifndef O_PATH @@ -57,7 +58,17 @@ void selinux_relabel_path(const char *path, const char *inside_path) /* Open the file as O_PATH, to pin it while we determine and adjust the label * Defeat symlink races by not allowing symbolic links */ + int called_as_root = 0; + if (geteuid() == 0) + called_as_root = 1; + if (called_as_root) + EUID_USER(); + fd = safer_openat(-1, path, O_NOFOLLOW|O_CLOEXEC|O_PATH); + + if (called_as_root) + EUID_ROOT(); + if (fd < 0) return; if (fstat(fd, &st) < 0) @@ -68,8 +79,16 @@ void selinux_relabel_path(const char *path, const char *inside_path) if (arg_debug) printf("Relabeling %s as %s (%s)\n", path, inside_path, fcon); - setfilecon_raw(procfs_path, fcon); + if (!called_as_root) + EUID_ROOT(); + + if (setfilecon_raw(procfs_path, fcon) != 0 && arg_debug) + printf("Cannot relabel %s: %s\n", path, strerror(errno)); + + if (!called_as_root) + EUID_USER(); } + freecon(fcon); close: close(fd); diff --git a/src/firejail/util.c b/src/firejail/util.c index 094a68c6083..f0df45eb2a3 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c @@ -459,31 +459,21 @@ int is_dir(const char *fname) { if (*fname == '\0') return 0; - int called_as_root = 0; - if (geteuid() == 0) - called_as_root = 1; - - if (called_as_root) - EUID_USER(); - // if fname doesn't end in '/', add one int rv; struct stat s; if (fname[strlen(fname) - 1] == '/') - rv = stat(fname, &s); + rv = stat_as_user(fname, &s); else { char *tmp; if (asprintf(&tmp, "%s/", fname) == -1) { fprintf(stderr, "Error: cannot allocate memory, %s:%d\n", __FILE__, __LINE__); errExit("asprintf"); } - rv = stat(tmp, &s); + rv = stat_as_user(tmp, &s); free(tmp); } - if (called_as_root) - EUID_ROOT(); - if (rv == -1) return 0; diff --git a/src/man/firejail-profile.txt b/src/man/firejail-profile.txt index a76fd376562..a1eccaa5eab 100644 --- a/src/man/firejail-profile.txt +++ b/src/man/firejail-profile.txt @@ -174,7 +174,7 @@ Example: "?HAS_APPIMAGE: whitelist ${HOME}/special/appimage/dir" This example will load the whitelist profile line only if the \-\-appimage option has been specified on the command line. -Currently the only conditionals supported this way are HAS_APPIMAGE, HAS_NET, HAS_NODBUS, HAS_NOSOUND, HAS_PRIVATE and HAS_X11. The conditionals BROWSER_DISABLE_U2F and BROWSER_ALLOW_DRM +Currently the only conditionals supported this way are HAS_APPIMAGE, HAS_NET, HAS_NODBUS, HAS_NOSOUND, HAS_PRIVATE and HAS_X11. The conditionals ALLOW_TRAY, BROWSER_DISABLE_U2F and BROWSER_ALLOW_DRM can be enabled or disabled globally in Firejail's configuration file. The profile line may be any profile line that you would normally use in a profile \fBexcept\fR for "quiet" and "include" lines. diff --git a/test/utils/build.exp b/test/utils/build.exp index 104ac037c56..b9733c137c9 100755 --- a/test/utils/build.exp +++ b/test/utils/build.exp @@ -13,7 +13,7 @@ after 100 send -- "firejail --build cat ~/_firejail-test-file\r" expect { timeout {puts "TESTING ERROR 0\n";exit} - "allow $\{HOME\}/_firejail-test-file" + "whitelist $\{HOME\}/_firejail-test-file" } expect { timeout {puts "TESTING ERROR 1\n";exit}