cleaned up old overlayfs code; the feature was disabled by default in 2021 because of security problems

This commit is contained in:
netblue30 2025-12-16 20:28:28 -05:00
parent f061dbd549
commit 489cc25c2f
15 changed files with 5 additions and 835 deletions

View file

@ -41,7 +41,6 @@ HAVE_LANDLOCK=@HAVE_LANDLOCK@
HAVE_NETWORK=@HAVE_NETWORK@
HAVE_ONLY_SYSCFG_PROFILES=@HAVE_ONLY_SYSCFG_PROFILES@
HAVE_OUTPUT=@HAVE_OUTPUT@
HAVE_OVERLAYFS=@HAVE_OVERLAYFS@
HAVE_PRIVATE_HOME=@HAVE_PRIVATE_HOME@
HAVE_PRIVATE_LIB=@HAVE_PRIVATE_LIB@
HAVE_SANDBOX_CHECK=@HAVE_SANDBOX_CHECK@
@ -62,7 +61,6 @@ MANFLAGS = \
$(HAVE_NETWORK) \
$(HAVE_ONLY_SYSCFG_PROFILES) \
$(HAVE_OUTPUT) \
$(HAVE_OVERLAYFS) \
$(HAVE_PRIVATE_HOME) \
$(HAVE_PRIVATE_LIB) \
$(HAVE_SANDBOX_CHECK) \

20
configure vendored
View file

@ -660,7 +660,6 @@ HAVE_PRIVATE_HOME
HAVE_MAN
HAVE_USERTMPFS
HAVE_OUTPUT
HAVE_OVERLAYFS
HAVE_DBUSPROXY
EXTRA_LDFLAGS
EXTRA_CFLAGS
@ -4316,24 +4315,6 @@ then :
fi
# The --overlay and related options are not supported anymore due to security
# concerns (see CVE-2021-26910 and #4178), issues on newer kernels (see #2799)
# and overall lack of interest in fixing and maintaining them.
#
# Support is unlikely to be restored for the foreseeable future unless someone
# picks up the work, as it would require auditing the overlayfs code to ensure
# that it is secure and that it works properly.
#
# It is highly recommended to leave this option disabled; the overlayfs code
# that remains is only intended for testing/debugging purposes.
HAVE_OVERLAYFS=""
#AC_ARG_ENABLE([overlayfs],
# [AS_HELP_STRING([--disable-overlayfs], [disable overlayfs])])
#AS_IF([test "x$enable_overlayfs" != "xno"], [
# HAVE_OVERLAYFS="-DHAVE_OVERLAYFS"
#])
HAVE_OUTPUT=""
# Check whether --enable-output was given.
@ -5799,7 +5780,6 @@ Features:
Landlock support: $HAVE_LANDLOCK
manpage support: $HAVE_MAN
network: $HAVE_NETWORK
overlayfs support: $HAVE_OVERLAYFS
private home support: $HAVE_PRIVATE_HOME
private lib support: $HAVE_PRIVATE_LIB
sandbox check: $HAVE_SANDBOX_CHECK

View file

@ -129,24 +129,6 @@ AS_IF([test "x$enable_dbusproxy" != "xno"], [
HAVE_DBUSPROXY="-DHAVE_DBUSPROXY"
])
# The --overlay and related options are not supported anymore due to security
# concerns (see CVE-2021-26910 and #4178), issues on newer kernels (see #2799)
# and overall lack of interest in fixing and maintaining them.
#
# Support is unlikely to be restored for the foreseeable future unless someone
# picks up the work, as it would require auditing the overlayfs code to ensure
# that it is secure and that it works properly.
#
# It is highly recommended to leave this option disabled; the overlayfs code
# that remains is only intended for testing/debugging purposes.
HAVE_OVERLAYFS=""
AC_SUBST([HAVE_OVERLAYFS])
#AC_ARG_ENABLE([overlayfs],
# [AS_HELP_STRING([--disable-overlayfs], [disable overlayfs])])
#AS_IF([test "x$enable_overlayfs" != "xno"], [
# HAVE_OVERLAYFS="-DHAVE_OVERLAYFS"
#])
HAVE_OUTPUT=""
AC_SUBST([HAVE_OUTPUT])
AC_ARG_ENABLE([output],
@ -330,7 +312,6 @@ Features:
Landlock support: $HAVE_LANDLOCK
manpage support: $HAVE_MAN
network: $HAVE_NETWORK
overlayfs support: $HAVE_OVERLAYFS
private home support: $HAVE_PRIVATE_HOME
private lib support: $HAVE_PRIVATE_LIB
sandbox check: $HAVE_SANDBOX_CHECK

View file

@ -33,8 +33,6 @@ notpm
notv
nou2f
novideo
overlay
overlay-tmpfs
private
private-cache
private-cwd

View file

@ -48,7 +48,6 @@ nice
noblacklist
noexec
nowhitelist
overlay-named
private
private-bin
private-cwd
@ -83,5 +82,4 @@ warn
whitelist
whitelist-ro
x11
xephyr-extra-params
xephyr-screen

View file

@ -115,7 +115,6 @@ int checkcfg(int val) {
PARSE_YESNO(CFG_RESTRICTED_NETWORK, "restricted-network")
PARSE_YESNO(CFG_TRACELOG, "tracelog")
PARSE_YESNO(CFG_XEPHYR_WINDOW_TITLE, "xephyr-window-title")
PARSE_YESNO(CFG_OVERLAYFS, "overlayfs")
PARSE_YESNO(CFG_PRIVATE_BIN, "private-bin")
PARSE_YESNO(CFG_PRIVATE_BIN_NO_LOCAL, "private-bin-no-local")
PARSE_YESNO(CFG_PRIVATE_CACHE, "private-cache")
@ -417,13 +416,6 @@ static const char *const compiletime_support =
"disabled"
#endif
"\n\t- overlayfs support is "
#ifdef HAVE_OVERLAYFS
"enabled"
#else
"disabled"
#endif
"\n\t- private-home support is "
#ifdef HAVE_PRIVATE_HOME
"enabled"

View file

@ -186,7 +186,6 @@ typedef struct config_t {
char *bin_private_lib; // executable list sent by private-bin to private-lib
char *lib_private_keep; // keep list for private bin directory
char *cwd; // current working directory
char *overlay_dir;
// networking
char *name; // sandbox name
@ -292,9 +291,6 @@ extern int arg_debug_whitelists; // print debug messages for whitelists
extern int arg_debug_private_lib; // print debug messages for private-lib
extern int arg_nonetwork; // --net=none
extern int arg_command; // -c
extern int arg_overlay; // overlay option
extern int arg_overlay_keep; // place overlay diff in a known directory
extern int arg_overlay_reuse; // allow the reuse of overlays
extern int arg_landlock_enforce; // enforce the Landlock ruleset
@ -472,11 +468,6 @@ void fs_private_tmp(void);
void fs_private_cache(void);
void fs_mnt(const int enforce);
// fs_overlayfs.c
char *fs_check_overlay_dir(const char *subdirname, int allow_reuse);
void fs_overlayfs(void);
int remove_overlay_directory(void);
// chroot.c
// chroot into an existing directory; mount existing /dev and update /etc/resolv.conf
void fs_check_chroot_dir(void);
@ -847,7 +838,6 @@ enum {
CFG_RESTRICTED_NETWORK,
CFG_FORCE_NONEWPRIVS,
CFG_XEPHYR_WINDOW_TITLE,
CFG_OVERLAYFS,
CFG_PRIVATE_BIN,
CFG_PRIVATE_BIN_NO_LOCAL,
CFG_PRIVATE_CACHE,

View file

@ -728,12 +728,6 @@ void fs_proc_sys_dev_boot(void) {
/* Mount a version of /sys that describes the network namespace */
if (arg_debug)
printf("Remounting /sys directory\n");
// sysfs not yet mounted in overlays, so don't try to unmount it
// expect that unmounting /sys fails in a chroot, no need to print a warning in that case
if (!arg_overlay) {
if (umount2("/sys", MNT_DETACH) < 0 && !cfg.chrootdir)
fwarning("failed to unmount /sys\n");
}
if (mount("sysfs", "/sys", "sysfs", MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REC, NULL) < 0)
fwarning("failed to mount /sys\n");
else

View file

@ -1,470 +0,0 @@
/*
* Copyright (C) 2014-2025 Firejail Authors
*
* This file is part of firejail project
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifdef HAVE_OVERLAYFS
#include "firejail.h"
#include "../include/gcov_wrapper.h"
#include <sys/mount.h>
#include <sys/wait.h>
#include <ftw.h>
#include <errno.h>
#include <fcntl.h>
#ifndef O_PATH
#define O_PATH 010000000
#endif
char *fs_check_overlay_dir(const char *subdirname, int allow_reuse) {
assert(subdirname);
EUID_ASSERT();
struct stat s;
char *dirname;
if (asprintf(&dirname, "%s/.firejail", cfg.homedir) == -1)
errExit("asprintf");
// check if ~/.firejail already exists
if (lstat(dirname, &s) == 0) {
if (!S_ISDIR(s.st_mode)) {
if (S_ISLNK(s.st_mode))
fprintf(stderr, "Error: %s is a symbolic link\n", dirname);
else
fprintf(stderr, "Error: %s is not a directory\n", dirname);
exit(1);
}
if (s.st_uid != getuid()) {
fprintf(stderr, "Error: %s is not owned by the current user\n", dirname);
exit(1);
}
}
else {
// create ~/.firejail directory
create_empty_dir_as_user(dirname, 0700);
if (stat(dirname, &s) == -1) {
fprintf(stderr, "Error: cannot create directory %s\n", dirname);
exit(1);
}
}
free(dirname);
// check overlay directory
if (asprintf(&dirname, "%s/.firejail/%s", cfg.homedir, subdirname) == -1)
errExit("asprintf");
if (lstat(dirname, &s) == 0) {
if (!S_ISDIR(s.st_mode)) {
if (S_ISLNK(s.st_mode))
fprintf(stderr, "Error: %s is a symbolic link\n", dirname);
else
fprintf(stderr, "Error: %s is not a directory\n", dirname);
exit(1);
}
if (s.st_uid != 0) {
fprintf(stderr, "Error: overlay directory %s is not owned by the root user\n", dirname);
exit(1);
}
if (allow_reuse == 0) {
fprintf(stderr, "Error: overlay directory exists, but reuse is not allowed\n");
exit(1);
}
}
return dirname;
}
// mount overlayfs on top of / directory
// mounting an overlay and chrooting into it:
//
// Old Ubuntu kernel
// # cd ~
// # mkdir -p overlay/root
// # mkdir -p overlay/diff
// # mount -t overlayfs -o lowerdir=/,upperdir=/root/overlay/diff overlayfs /root/overlay/root
// # chroot /root/overlay/root
// to shutdown, first exit the chroot and then unmount the overlay
// # exit
// # umount /root/overlay/root
//
// Kernels 3.18+
// # cd ~
// # mkdir -p overlay/root
// # mkdir -p overlay/diff
// # mkdir -p overlay/work
// # mount -t overlay -o lowerdir=/,upperdir=/root/overlay/diff,workdir=/root/overlay/work overlay /root/overlay/root
// # cat /etc/mtab | grep overlay
// /root/overlay /root/overlay/root overlay rw,relatime,lowerdir=/,upperdir=/root/overlay/diff,workdir=/root/overlay/work 0 0
// # chroot /root/overlay/root
// to shutdown, first exit the chroot and then unmount the overlay
// # exit
// # umount /root/overlay/root
// to do: fix the code below
#include <sys/utsname.h>
void fs_overlayfs(void) {
struct stat s;
// check kernel version
struct utsname u;
int rv = uname(&u);
if (rv != 0)
errExit("uname");
int major;
int minor;
if (2 != sscanf(u.release, "%d.%d", &major, &minor)) {
fprintf(stderr, "Error: cannot extract Linux kernel version: %s\n", u.version);
exit(1);
}
if (arg_debug)
printf("Linux kernel version %d.%d\n", major, minor);
int oldkernel = 0;
if (major < 3) {
fprintf(stderr, "Error: minimum kernel version required 3.x\n");
exit(1);
}
if (major == 3 && minor < 18)
oldkernel = 1;
// mounting an overlayfs on top of / seems to be broken for kernels > 4.19
// we disable overlayfs for now, pending fixing
if (major >= 4 &&minor >= 19) {
fprintf(stderr, "Error: OverlayFS disabled for Linux kernels 4.19 and newer, pending fixing.\n");
exit(1);
}
char *oroot = RUN_OVERLAY_ROOT;
mkdir_attr(oroot, 0755, 0, 0);
// set base for working and diff directories
char *basedir = RUN_MNT_DIR;
int basefd = -1;
if (arg_overlay_keep) {
basedir = cfg.overlay_dir;
assert(basedir);
// get a file descriptor for ~/.firejail, fails if there is any symlink
char *firejail;
if (asprintf(&firejail, "%s/.firejail", cfg.homedir) == -1)
errExit("asprintf");
int fd = safer_openat(-1, firejail, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
if (fd == -1)
errExit("safer_openat");
free(firejail);
// create basedir if it doesn't exist
// the new directory will be owned by root
const char *dirname = gnu_basename(basedir);
if (mkdirat(fd, dirname, 0755) == -1 && errno != EEXIST) {
perror("mkdir");
fprintf(stderr, "Error: cannot create overlay directory %s\n", basedir);
exit(1);
}
// open basedir
basefd = openat(fd, dirname, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
close(fd);
}
else {
basefd = open(basedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
}
if (basefd == -1) {
perror("open");
fprintf(stderr, "Error: cannot open overlay directory %s\n", basedir);
exit(1);
}
// confirm once more base is owned by root
if (fstat(basefd, &s) == -1)
errExit("fstat");
if (s.st_uid != 0) {
fprintf(stderr, "Error: overlay directory %s is not owned by the root user\n", basedir);
exit(1);
}
// confirm permissions of base are 0755
if (((S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) & s.st_mode) != (S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)) {
fprintf(stderr, "Error: invalid permissions on overlay directory %s\n", basedir);
exit(1);
}
// create diff and work directories inside base
// no need to check arg_overlay_reuse
char *odiff;
if (asprintf(&odiff, "%s/odiff", basedir) == -1)
errExit("asprintf");
// the new directory will be owned by root
if (mkdirat(basefd, "odiff", 0755) == -1 && errno != EEXIST) {
perror("mkdir");
fprintf(stderr, "Error: cannot create overlay directory %s\n", odiff);
exit(1);
}
ASSERT_PERMS(odiff, 0, 0, 0755);
char *owork;
if (asprintf(&owork, "%s/owork", basedir) == -1)
errExit("asprintf");
// the new directory will be owned by root
if (mkdirat(basefd, "owork", 0755) == -1 && errno != EEXIST) {
perror("mkdir");
fprintf(stderr, "Error: cannot create overlay directory %s\n", owork);
exit(1);
}
ASSERT_PERMS(owork, 0, 0, 0755);
// mount overlayfs
if (arg_debug)
printf("Mounting OverlayFS\n");
char *option;
if (oldkernel) { // old Ubuntu/OpenSUSE kernels
if (arg_overlay_keep) {
fprintf(stderr, "Error: option --overlay= not available for kernels older than 3.18\n");
exit(1);
}
if (asprintf(&option, "lowerdir=/,upperdir=%s", odiff) == -1)
errExit("asprintf");
if (mount("overlayfs", oroot, "overlayfs", MS_MGC_VAL, option) < 0)
errExit("mounting overlayfs");
}
else { // kernel 3.18 or newer
if (asprintf(&option, "lowerdir=/,upperdir=%s,workdir=%s", odiff, owork) == -1)
errExit("asprintf");
if (mount("overlay", oroot, "overlay", MS_MGC_VAL, option) < 0) {
fprintf(stderr, "Debug: running on kernel version %d.%d\n", major, minor);
errExit("mounting overlayfs");
}
//***************************
// issue #263 start code
// My setup has a separate mount point for /home. When the overlay is mounted,
// the overlay does not contain the original /home contents.
// I added code to create a second overlay for /home if the overlay home dir is empty and this seems to work
// @dshmgh, Jan 2016
{
char *overlayhome;
struct stat s;
char *hroot;
char *hdiff;
char *hwork;
// dons add debug
if (arg_debug) printf ("DEBUG: chroot dirs are oroot %s odiff %s owork %s\n",oroot,odiff,owork);
// BEFORE NEXT, WE NEED TO TEST IF /home has any contents or do we need to mount it?
// must create var for oroot/cfg.homedir
if (asprintf(&overlayhome, "%s%s", oroot, cfg.homedir) == -1)
errExit("asprintf");
if (arg_debug) printf ("DEBUG: overlayhome var holds ##%s##\n", overlayhome);
// if no homedir in overlay -- create another overlay for /home
if (stat(cfg.homedir, &s) == 0 && stat(overlayhome, &s) == -1) {
// no need to check arg_overlay_reuse
if (asprintf(&hdiff, "%s/hdiff", basedir) == -1)
errExit("asprintf");
// the new directory will be owned by root
if (mkdirat(basefd, "hdiff", 0755) == -1 && errno != EEXIST) {
perror("mkdir");
fprintf(stderr, "Error: cannot create overlay directory %s\n", hdiff);
exit(1);
}
ASSERT_PERMS(hdiff, 0, 0, 0755);
// no need to check arg_overlay_reuse
if (asprintf(&hwork, "%s/hwork", basedir) == -1)
errExit("asprintf");
// the new directory will be owned by root
if (mkdirat(basefd, "hwork", 0755) == -1 && errno != EEXIST) {
perror("mkdir");
fprintf(stderr, "Error: cannot create overlay directory %s\n", hwork);
exit(1);
}
ASSERT_PERMS(hwork, 0, 0, 0755);
// no homedir in overlay so now mount another overlay for /home
if (asprintf(&hroot, "%s/home", oroot) == -1)
errExit("asprintf");
if (asprintf(&option, "lowerdir=/home,upperdir=%s,workdir=%s", hdiff, hwork) == -1)
errExit("asprintf");
if (mount("overlay", hroot, "overlay", MS_MGC_VAL, option) < 0)
errExit("mounting overlayfs for mounted home directory");
printf("OverlayFS for /home configured in %s directory\n", basedir);
free(hroot);
free(hdiff);
free(hwork);
} // stat(overlayhome)
free(overlayhome);
}
// issue #263 end code
//***************************
}
fmessage("OverlayFS configured in %s directory\n", basedir);
close(basefd);
// /dev, /run and /tmp are not covered by the overlay
// mount-bind dev directory
if (arg_debug)
printf("Mounting /dev\n");
char *dev;
if (asprintf(&dev, "%s/dev", oroot) == -1)
errExit("asprintf");
if (mount("/dev", dev, NULL, MS_BIND|MS_REC, NULL) < 0)
errExit("mounting /dev");
fs_logger("whitelist /dev");
// mount-bind run directory
if (arg_debug)
printf("Mounting /run\n");
char *run;
if (asprintf(&run, "%s/run", oroot) == -1)
errExit("asprintf");
if (mount("/run", run, NULL, MS_BIND|MS_REC, NULL) < 0)
errExit("mounting /run");
fs_logger("whitelist /run");
// mount-bind tmp directory
if (arg_debug)
printf("Mounting /tmp\n");
char *tmp;
if (asprintf(&tmp, "%s/tmp", oroot) == -1)
errExit("asprintf");
if (mount("/tmp", tmp, NULL, MS_BIND|MS_REC, NULL) < 0)
errExit("mounting /tmp");
fs_logger("whitelist /tmp");
// chroot in the new filesystem
__gcov_flush();
if (chroot(oroot) == -1)
errExit("chroot");
// mount a new proc filesystem
if (arg_debug)
printf("Mounting /proc filesystem representing the PID namespace\n");
if (mount("proc", "/proc", "proc", MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_REC, NULL) < 0)
errExit("mounting /proc");
// update /var directory in order to support multiple sandboxes running on the same root directory
// if (!arg_private_dev)
// fs_dev_shm();
fs_var_lock();
if (!arg_keep_var_tmp)
fs_var_tmp();
if (!arg_writable_var_log)
fs_var_log();
fs_var_lib();
fs_var_cache();
fs_var_utmp();
fs_machineid();
// don't leak user information
restrict_users();
// when starting as root, firejail config is not disabled;
if (getuid() != 0)
disable_config();
// cleanup and exit
free(option);
free(odiff);
free(owork);
free(dev);
free(run);
free(tmp);
}
static int remove_callback(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {
(void) sb;
(void) typeflag;
(void) ftwbuf;
assert(fpath);
if (strcmp(fpath, ".") == 0) // rmdir would fail with EINVAL
return 0;
if (remove(fpath)) { // removes the link not the actual file
fprintf(stderr, "Error: cannot remove file: %s\n", strerror(errno));
exit(1);
}
return 0;
}
int remove_overlay_directory(void) {
EUID_ASSERT();
sleep(1);
char *path;
if (asprintf(&path, "%s/.firejail", cfg.homedir) == -1)
errExit("asprintf");
if (access(path, F_OK) == 0) {
pid_t child = fork();
if (child < 0)
errExit("fork");
if (child == 0) {
// open ~/.firejail
int fd = safer_openat(-1, path, O_PATH|O_NOFOLLOW|O_CLOEXEC);
if (fd == -1) {
fprintf(stderr, "Error: cannot open %s\n", path);
exit(1);
}
struct stat s;
if (fstat(fd, &s) == -1)
errExit("fstat");
if (!S_ISDIR(s.st_mode)) {
if (S_ISLNK(s.st_mode))
fprintf(stderr, "Error: %s is a symbolic link\n", path);
else
fprintf(stderr, "Error: %s is not a directory\n", path);
exit(1);
}
if (s.st_uid != getuid()) {
fprintf(stderr, "Error: %s is not owned by the current user\n", path);
exit(1);
}
// chdir to ~/.firejail
if (fchdir(fd) == -1)
errExit("fchdir");
close(fd);
EUID_ROOT();
// FTW_PHYS - do not follow symbolic links
if (nftw(".", remove_callback, 64, FTW_DEPTH | FTW_PHYS) == -1)
errExit("nftw");
EUID_USER();
// remove ~/.firejail
if (rmdir(path) == -1)
errExit("rmdir");
__gcov_flush();
_exit(0);
}
// wait for the child to finish
waitpid(child, NULL, 0);
// check if ~/.firejail was deleted
if (access(path, F_OK) == 0)
return 1;
}
return 0;
}
#endif // HAVE_OVERLAYFS

View file

@ -73,9 +73,6 @@ int arg_debug_whitelists = 0; // print debug messages for whitelists
int arg_debug_private_lib = 0; // print debug messages for private-lib
int arg_nonetwork = 0; // --net=none
int arg_command = 0; // -c
int arg_overlay = 0; // overlay option
int arg_overlay_keep = 0; // place overlay diff in a known directory
int arg_overlay_reuse = 0; // allow the reuse of overlays
int arg_landlock_enforce = 0; // enforce the Landlock ruleset
@ -375,19 +372,6 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
usage();
exit(0);
}
#ifdef HAVE_OVERLAYFS
else if (strcmp(argv[i], "--overlay-clean") == 0) {
if (checkcfg(CFG_OVERLAYFS)) {
if (remove_overlay_directory()) {
fprintf(stderr, "Error: cannot remove overlay directory\n");
exit(1);
}
}
else
exit_err_feature("overlayfs");
exit(0);
}
#endif
#ifdef HAVE_X11
else if (strcmp(argv[i], "--x11") == 0) {
if (checkcfg(CFG_X11)) {
@ -1794,78 +1778,6 @@ int main(int argc, char **argv, char **envp) {
}
else if (strcmp(argv[i], "--disable-mnt") == 0)
arg_disable_mnt = 1;
#ifdef HAVE_OVERLAYFS
else if (strcmp(argv[i], "--overlay") == 0) {
if (checkcfg(CFG_OVERLAYFS)) {
if (arg_overlay) {
fprintf(stderr, "Error: only one overlay command is allowed\n");
exit(1);
}
if (cfg.chrootdir) {
fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n");
exit(1);
}
arg_overlay = 1;
arg_overlay_keep = 1;
char *subdirname;
if (asprintf(&subdirname, "%d", getpid()) == -1)
errExit("asprintf");
cfg.overlay_dir = fs_check_overlay_dir(subdirname, arg_overlay_reuse);
free(subdirname);
}
else
exit_err_feature("overlayfs");
}
else if (strncmp(argv[i], "--overlay-named=", 16) == 0) {
if (checkcfg(CFG_OVERLAYFS)) {
if (arg_overlay) {
fprintf(stderr, "Error: only one overlay command is allowed\n");
exit(1);
}
if (cfg.chrootdir) {
fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n");
exit(1);
}
arg_overlay = 1;
arg_overlay_keep = 1;
arg_overlay_reuse = 1;
char *subdirname = argv[i] + 16;
if (*subdirname == '\0') {
fprintf(stderr, "Error: invalid overlay option\n");
exit(1);
}
// check name
invalid_filename(subdirname, 0); // no globbing
if (strstr(subdirname, "..") || strstr(subdirname, "/")) {
fprintf(stderr, "Error: invalid overlay name\n");
exit(1);
}
cfg.overlay_dir = fs_check_overlay_dir(subdirname, arg_overlay_reuse);
}
else
exit_err_feature("overlayfs");
}
else if (strcmp(argv[i], "--overlay-tmpfs") == 0) {
if (checkcfg(CFG_OVERLAYFS)) {
if (arg_overlay) {
fprintf(stderr, "Error: only one overlay command is allowed\n");
exit(1);
}
if (cfg.chrootdir) {
fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n");
exit(1);
}
arg_overlay = 1;
}
else
exit_err_feature("overlayfs");
}
#endif
else if (strncmp(argv[i], "--include=", 10) == 0) {
char *ppath = expand_macros(argv[i] + 10);
if (!ppath)
@ -1966,11 +1878,6 @@ int main(int argc, char **argv, char **envp) {
#ifdef HAVE_CHROOT
else if (strncmp(argv[i], "--chroot=", 9) == 0) {
if (checkcfg(CFG_CHROOT)) {
if (arg_overlay) {
fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n");
exit(1);
}
// extract chroot dirname
cfg.chrootdir = expand_macros(argv[i] + 9);
if (*cfg.chrootdir == '\0') {
@ -2889,8 +2796,6 @@ int main(int argc, char **argv, char **envp) {
char *opt = NULL;
if (arg_appimage)
opt = "appimage";
else if (arg_overlay)
opt = "overlay";
else if (cfg.chrootdir)
opt = "chroot";
@ -2909,11 +2814,7 @@ int main(int argc, char **argv, char **envp) {
// check user namespace (--noroot) options
if (arg_noroot) {
if (arg_overlay) {
fwarning("--overlay and --noroot are mutually exclusive, --noroot disabled...\n");
arg_noroot = 0;
}
else if (cfg.chrootdir) {
if (cfg.chrootdir) {
fwarning("--chroot and --noroot are mutually exclusive, --noroot disabled...\n");
arg_noroot = 0;
}
@ -3053,11 +2954,7 @@ int main(int argc, char **argv, char **envp) {
}
EUID_ASSERT();
if (arg_noroot && arg_overlay) {
fwarning("--overlay and --noroot are mutually exclusive, noroot disabled\n");
arg_noroot = 0;
}
else if (arg_noroot && cfg.chrootdir) {
if (arg_noroot && cfg.chrootdir) {
fwarning("--chroot and --noroot are mutually exclusive, noroot disabled\n");
arg_noroot = 0;
}

View file

@ -1510,82 +1510,6 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
return 0;
}
#ifdef HAVE_OVERLAYFS
if (strncmp(ptr, "overlay-named ", 14) == 0) {
if (checkcfg(CFG_OVERLAYFS)) {
if (arg_overlay) {
fprintf(stderr, "Error: only one overlay command is allowed\n");
exit(1);
}
if (cfg.chrootdir) {
fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n");
exit(1);
}
arg_overlay = 1;
arg_overlay_keep = 1;
arg_overlay_reuse = 1;
char *subdirname = ptr + 14;
if (*subdirname == '\0') {
fprintf(stderr, "Error: invalid overlay option\n");
exit(1);
}
// check name
invalid_filename(subdirname, 0); // no globbing
if (strstr(subdirname, "..") || strstr(subdirname, "/")) {
fprintf(stderr, "Error: invalid overlay name\n");
exit(1);
}
cfg.overlay_dir = fs_check_overlay_dir(subdirname, arg_overlay_reuse);
}
else
warning_feature_disabled("overlayfs");
return 0;
} else if (strcmp(ptr, "overlay-tmpfs") == 0) {
if (checkcfg(CFG_OVERLAYFS)) {
if (arg_overlay) {
fprintf(stderr, "Error: only one overlay command is allowed\n");
exit(1);
}
if (cfg.chrootdir) {
fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n");
exit(1);
}
arg_overlay = 1;
}
else
warning_feature_disabled("overlayfs");
return 0;
} else if (strcmp(ptr, "overlay") == 0) {
if (checkcfg(CFG_OVERLAYFS)) {
if (arg_overlay) {
fprintf(stderr, "Error: only one overlay command is allowed\n");
exit(1);
}
if (cfg.chrootdir) {
fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n");
exit(1);
}
arg_overlay = 1;
arg_overlay_keep = 1;
char *subdirname;
if (asprintf(&subdirname, "%d", getpid()) == -1)
errExit("asprintf");
cfg.overlay_dir = fs_check_overlay_dir(subdirname, arg_overlay_reuse);
free(subdirname);
}
else
warning_feature_disabled("overlayfs");
return 0;
}
#endif
// filesystem bind
if (strncmp(ptr, "bind ", 5) == 0) {
if (checkcfg(CFG_BIND)) {

View file

@ -709,8 +709,6 @@ int sandbox(void* sandbox_arg) {
fs_logger2int("sandbox pid:", (int) sandbox_pid);
if (cfg.chrootdir)
fs_logger("sandbox filesystem: chroot");
else if (arg_overlay)
fs_logger("sandbox filesystem: overlay");
else
fs_logger("sandbox filesystem: local");
fs_logger("install mount namespace");
@ -851,9 +849,9 @@ int sandbox(void* sandbox_arg) {
exit(rv);
}
// for --appimage, --chroot and --overlay* we force NO_NEW_PRIVS
// for --appimage, and --chroot we force NO_NEW_PRIVS
// and drop all capabilities
if (getuid() != 0 && (arg_appimage || cfg.chrootdir || arg_overlay))
if (getuid() != 0 && (arg_appimage || cfg.chrootdir))
enforce_filters();
// need ld.so.preload if tracing or seccomp with any non-default lists
@ -883,11 +881,6 @@ int sandbox(void* sandbox_arg) {
}
}
else
#endif
#ifdef HAVE_OVERLAYFS
if (arg_overlay)
fs_overlayfs();
else
#endif
fs_basic_fs();
@ -905,16 +898,12 @@ int sandbox(void* sandbox_arg) {
if (cfg.home_private) { // --private=
if (cfg.chrootdir)
fwarning("private=directory feature is disabled in chroot\n");
else if (arg_overlay)
fwarning("private=directory feature is disabled in overlay\n");
else
fs_private_homedir();
}
else if (cfg.home_private_keep) { // --private-home=
if (cfg.chrootdir)
fwarning("private-home= feature is disabled in chroot\n");
else if (arg_overlay)
fwarning("private-home= feature is disabled in overlay\n");
else
fs_private_home_list();
}
@ -929,8 +918,6 @@ int sandbox(void* sandbox_arg) {
if (arg_private_opt) {
if (cfg.chrootdir)
fwarning("private-opt feature is disabled in chroot\n");
else if (arg_overlay)
fwarning("private-opt feature is disabled in overlay\n");
else {
fs_private_dir_list("/opt", RUN_OPT_DIR, cfg.opt_private_keep);
}
@ -939,8 +926,6 @@ int sandbox(void* sandbox_arg) {
if (arg_private_srv) {
if (cfg.chrootdir)
fwarning("private-srv feature is disabled in chroot\n");
else if (arg_overlay)
fwarning("private-srv feature is disabled in overlay\n");
else {
fs_private_dir_list("/srv", RUN_SRV_DIR, cfg.srv_private_keep);
}
@ -950,8 +935,6 @@ int sandbox(void* sandbox_arg) {
if (arg_private_bin && !arg_appimage) {
if (cfg.chrootdir)
fwarning("private-bin feature is disabled in chroot\n");
else if (arg_overlay)
fwarning("private-bin feature is disabled in overlay\n");
else {
EUID_USER();
// for --x11=xorg we need to add xauth command
@ -971,8 +954,6 @@ int sandbox(void* sandbox_arg) {
if (arg_private_lib && !arg_appimage) {
if (cfg.chrootdir)
fwarning("private-lib feature is disabled in chroot\n");
else if (arg_overlay)
fwarning("private-lib feature is disabled in overlay\n");
else {
fs_private_lib();
}
@ -1029,8 +1010,6 @@ int sandbox(void* sandbox_arg) {
if (arg_private_etc) {
if (cfg.chrootdir)
fwarning("private-etc feature is disabled in chroot\n");
else if (arg_overlay)
fwarning("private-etc feature is disabled in overlay\n");
else {
/* Current /etc/passwd and /etc/group files are bind
* mounted filtered versions of originals. Leaving

View file

@ -198,14 +198,6 @@ static const char *const usage_str =
#ifdef HAVE_OUTPUT
" --output=logfile - stdout logging and log rotation.\n"
" --output-stderr=logfile - stdout and stderr logging and log rotation.\n"
#endif
#ifdef HAVE_OVERLAYFS
" --overlay - mount a filesystem overlay on top of the current filesystem.\n"
" --overlay-named=name - mount a filesystem overlay on top of the current\n"
"\tfilesystem, and store it in name directory.\n"
" --overlay-tmpfs - mount a temporary filesystem overlay on top of the\n"
"\tcurrent filesystem.\n"
" --overlay-clean - clean all overlays stored in $HOME/.firejail directory.\n"
#endif
" --private - temporary home directory.\n"
" --private=directory - use directory as user home.\n"

View file

@ -360,20 +360,6 @@ before the sandbox is started. The file is created if it doesn't already exist.
.TP
\fBnoexec file_or_directory
Remount the file or the directory noexec, nodev and nosuid.
#ifdef HAVE_OVERLAYFS
.TP
\fBoverlay
Mount a filesystem overlay on top of the current filesystem.
The overlay is stored in $HOME/.firejail/<PID> directory.
.TP
\fBoverlay-named name
Mount a filesystem overlay on top of the current filesystem.
The overlay is stored in $HOME/.firejail/name directory.
.TP
\fBoverlay-tmpfs
Mount a filesystem overlay on top of the current filesystem.
All filesystem modifications are discarded when the sandbox is closed.
#endif
.TP
\fBprivate
Mount new /root and /home/user directories in temporary

View file

@ -1977,7 +1977,7 @@ Child process initialized
Install a user namespace with a single user - the current user.
root user does not exist in the new namespace. This option
requires a Linux kernel version 3.8 or newer. The option
is not supported for \-\-chroot and \-\-overlay configurations,
is not supported for \-\-chroot and \-\-appimage configurations,
or for sandboxes started as root.
.br
@ -2084,74 +2084,6 @@ $ ls -l sandboxlog*
Similar to \-\-output, but stderr is also stored.
#endif
#ifdef HAVE_OVERLAYFS
.TP
\fB\-\-overlay
Mount a filesystem overlay on top of the current filesystem. Unlike the regular filesystem container,
the system directories are mounted read-write. All filesystem modifications go into the overlay.
Directories /run, /tmp and /dev are not covered by the overlay. The overlay is stored in $HOME/.firejail/<PID> directory.
If the sandbox is started as a regular user, nonewprivs and a default capabilities filter are enabled.
.br
.br
OverlayFS support is required in Linux kernel for this option to work.
OverlayFS was officially introduced in Linux kernel version 3.18.
This option is not available on Grsecurity systems.
.br
.br
Example:
.br
$ firejail \-\-overlay /usr/bin/firefox
.TP
\fB\-\-overlay-clean
Clean all overlays stored in $HOME/.firejail directory.
.br
.br
Example:
.br
$ firejail \-\-overlay-clean
.TP
\fB\-\-overlay-named=name
Mount a filesystem overlay on top of the current filesystem. Unlike the regular filesystem container,
the system directories are mounted read-write. All filesystem modifications go into the overlay.
Directories /run, /tmp and /dev are not covered by the overlay. The overlay is stored in $HOME/.firejail/<NAME> directory.
The created overlay can be reused between multiple sessions.
If the sandbox is started as a regular user, nonewprivs and a default capabilities filter are enabled.
.br
.br
OverlayFS support is required in Linux kernel for this option to work.
OverlayFS was officially introduced in Linux kernel version 3.18.
This option is not available on Grsecurity systems.
.br
.br
Example:
.br
$ firejail \-\-overlay-named=jail1 /usr/bin/firefox
.TP
\fB\-\-overlay-tmpfs
Mount a filesystem overlay on top of the current filesystem. All filesystem modifications
are discarded when the sandbox is closed. Directories /run, /tmp and /dev are not covered by the overlay.
If the sandbox is started as a regular user, nonewprivs and a default capabilities filter are enabled.
.br
.br
OverlayFS support is required in Linux kernel for this option to work.
OverlayFS was officially introduced in Linux kernel version 3.18.
This option is not available on Grsecurity systems.
.br
.br
Example:
.br
$ firejail \-\-overlay-tmpfs /usr/bin/firefox
#endif
.TP
\fB\-\-private
Mount new /root and /home/user directories in temporary
@ -3191,7 +3123,6 @@ Compile time support:
- file transfer support is enabled
- firetunnel support is enabled
- networking support is enabled
- overlayfs support is enabled
- private-home support is enabled
- seccomp-bpf support is enabled
- user namespace support is enabled