deprecated --private-home
Some checks failed
Build-extra / build-gcc (push) Has been cancelled
Build-extra / build-clang (push) Has been cancelled
Build / build (push) Has been cancelled
Check-C / scan-build (push) Has been cancelled
Check-C / cppcheck (push) Has been cancelled
Check-C / codeql-cpp (push) Has been cancelled
Check-Profiles / profile-checks (push) Has been cancelled
Codespell / codespell (push) Has been cancelled
Test / test-main (push) Has been cancelled
Test / test-fs (push) Has been cancelled
Test / test-environment (push) Has been cancelled
Test / test-utils (push) Has been cancelled
Test / test-network (push) Has been cancelled

This commit is contained in:
netblue30 2026-07-09 12:21:48 -04:00
parent a55ce9e1ae
commit e5eefcf5f7
11 changed files with 4 additions and 307 deletions

View file

@ -39,7 +39,6 @@ HAVE_LANDLOCK=@HAVE_LANDLOCK@
HAVE_NETWORK=@HAVE_NETWORK@
HAVE_ONLY_SYSCFG_PROFILES=@HAVE_ONLY_SYSCFG_PROFILES@
HAVE_OUTPUT=@HAVE_OUTPUT@
HAVE_PRIVATE_HOME=@HAVE_PRIVATE_HOME@
HAVE_PRIVATE_LIB=@HAVE_PRIVATE_LIB@
HAVE_SANDBOX_CHECK=@HAVE_SANDBOX_CHECK@
HAVE_SELINUX=@HAVE_SELINUX@

View file

@ -129,14 +129,6 @@ AS_IF([test "x$enable_output" != "xno"], [
HAVE_OUTPUT="-DHAVE_OUTPUT"
])
HAVE_PRIVATE_HOME=""
AC_SUBST([HAVE_PRIVATE_HOME])
AC_ARG_ENABLE([private-home],
[AS_HELP_STRING([--disable-private-home], [disable private home feature])])
AS_IF([test "x$enable_private_home" != "xno"], [
HAVE_PRIVATE_HOME="-DHAVE_PRIVATE_HOME"
])
HAVE_PRIVATE_LIB=""
AC_SUBST([HAVE_PRIVATE_LIB])
AC_ARG_ENABLE([private-lib],
@ -275,7 +267,6 @@ Features:
file transfer support: $HAVE_FILE_TRANSFER
Landlock support: $HAVE_LANDLOCK
network: $HAVE_NETWORK
private home support: $HAVE_PRIVATE_HOME
private lib support: $HAVE_PRIVATE_LIB
sandbox check: $HAVE_SANDBOX_CHECK
SELinux labeling support: $HAVE_SELINUX

View file

@ -113,7 +113,7 @@
# Enable or disable private-etc feature, default enabled.
# private-etc yes
# Enable or disable private-home feature, default enabled
# private-home feature was deprecated in firejail version 0.9.81
# private-home yes
# Enable or disable private-lib feature, default disabled

View file

@ -65,7 +65,6 @@ const char *const cfgstr[] = {
[CFG_PRIVATE_BIN_NO_LOCAL] = "private-bin-no-local",
[CFG_PRIVATE_CACHE] = "private-cache",
[CFG_PRIVATE_ETC] = "private-etc",
[CFG_PRIVATE_HOME] = "private-home",
[CFG_PRIVATE_LIB] = "private-lib",
[CFG_PRIVATE_OPT] = "private-opt",
[CFG_PRIVATE_SRV] = "private-srv",
@ -173,7 +172,6 @@ int checkcfg(int val) {
PARSE_YESNO(CFG_PRIVATE_BIN_NO_LOCAL, "private-bin-no-local")
PARSE_YESNO(CFG_PRIVATE_CACHE, "private-cache")
PARSE_YESNO(CFG_PRIVATE_ETC, "private-etc")
PARSE_YESNO(CFG_PRIVATE_HOME, "private-home")
PARSE_YESNO(CFG_PRIVATE_LIB, "private-lib")
PARSE_YESNO(CFG_PRIVATE_OPT, "private-opt")
PARSE_YESNO(CFG_PRIVATE_SRV, "private-srv")
@ -187,6 +185,8 @@ int checkcfg(int val) {
#undef PARSE_YESNO
else if (strncmp(ptr, "tracelog", 8) == 0)
; // tracelog feature was deprecated in firejail version 0.9.81
else if (strncmp(ptr, "private-home", 12) == 0)
; // tracelog feature was deprecated in firejail version 0.9.81
// netfilter
else if (strncmp(ptr, "netfilter-default ", 18) == 0) {
@ -466,13 +466,6 @@ static const char *const compiletime_support =
"disabled"
#endif
"\n\t- private-home support is "
#ifdef HAVE_PRIVATE_HOME
"enabled"
#else
"disabled"
#endif
"\n\t- private-lib support is "
#ifdef HAVE_PRIVATE_LIB
"enabled"

View file

@ -178,7 +178,6 @@ typedef struct config_t {
char *keep_fd; // inherit file descriptors to sandbox
char *chrootdir; // chroot directory
char *home_private; // private home directory
char *home_private_keep; // keep list for private home directory
char *etc_private_keep; // keep list for private etc directory
char *opt_private_keep; // keep list for private opt directory
char *srv_private_keep; // keep list for private srv directory
@ -658,7 +657,6 @@ void fs_private_homedir(void);
void fs_check_private_dir(void);
// check new private working directory (--private-cwd= option) - exit if it fails
void fs_check_private_cwd(const char *dir);
void fs_private_home_list(void);
// seccomp.c
@ -849,7 +847,6 @@ enum {
CFG_PRIVATE_BIN_NO_LOCAL,
CFG_PRIVATE_CACHE,
CFG_PRIVATE_ETC,
CFG_PRIVATE_HOME,
CFG_PRIVATE_LIB,
CFG_PRIVATE_OPT,
CFG_PRIVATE_SRV,

View file

@ -483,211 +483,3 @@ errout:
exit(1);
}
//***********************************************************************************
// --private-home
//***********************************************************************************
static char *check_dir_or_file(const char *name) {
EUID_ASSERT();
assert(name);
// basic checks
invalid_filename(name, 0); // no globbing
if (arg_debug)
printf("Private home: checking %s\n", name);
// expand home directory
char *fname = expand_macros(name);
assert(fname);
// If it doesn't start with '/', it must be relative to homedir
if (fname[0] != '/') {
char* tmp;
if (asprintf(&tmp, "%s/%s", cfg.homedir, fname) == -1)
errExit("asprintf");
free(fname);
fname = tmp;
}
// we allow only files in user home directory or symbolic links to files or directories owned by the user
struct stat s;
if (lstat(fname, &s) == 0 && S_ISLNK(s.st_mode)) {
if (strncmp(fname, cfg.homedir, strlen(cfg.homedir)) != 0 || fname[strlen(cfg.homedir)] != '/')
goto errexit;
if (stat(fname, &s) == 0) {
if (s.st_uid != getuid()) {
fprintf(stderr, "Error: symbolic link %s to file or directory not owned by the user\n", fname);
exit(1);
}
return fname;
}
else // dangling link
goto errexit;
}
else {
// check the file is in user home directory
char *rname = realpath(fname, NULL);
if (!rname || strncmp(rname, cfg.homedir, strlen(cfg.homedir)) != 0)
goto errexit;
// a full home directory is not allowed
char *ptr = rname + strlen(cfg.homedir);
if (*ptr != '/')
goto errexit;
// only top files and directories in user home are allowed
ptr = strchr(++ptr, '/');
if (ptr) {
fprintf(stderr, "Error: only top files and directories in user home are allowed\n");
exit(1);
}
free(fname);
return rname;
}
errexit:
fprintf(stderr, "Error: invalid file %s\n", name);
exit(1);
}
static void duplicate(char *name) {
EUID_ASSERT();
char *fname = check_dir_or_file(name);
if (arg_debug)
printf("Private home: duplicating %s\n", fname);
assert(strncmp(fname, cfg.homedir, strlen(cfg.homedir)) == 0);
struct stat s;
if (lstat(fname, &s) == -1) {
free(fname);
return;
}
else if (S_ISDIR(s.st_mode)) {
// create the directory in RUN_HOME_DIR
char *path;
char *ptr = strrchr(fname, '/');
ptr++;
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);
free(path);
}
else
sbox_run(SBOX_USER| SBOX_CAPS_NONE | SBOX_SECCOMP, 3, PATH_FCOPY, fname, RUN_HOME_DIR);
fs_logger2("clone", fname);
fs_logger_print(); // save the current log
free(fname);
}
// private mode (--private-home=list):
// mount homedir on top of /home/user,
// tmpfs on top of /root in nonroot mode,
// tmpfs on top of /tmp in root mode,
// set skel files,
// restore .Xauthority
void fs_private_home_list(void) {
char *homedir = cfg.homedir;
char *private_list = cfg.home_private_keep;
assert(homedir);
assert(private_list);
EUID_ASSERT();
timetrace_start();
uid_t uid = getuid();
gid_t gid = getgid();
int xflag = store_xauthority();
int aflag = store_asoundrc();
EUID_ROOT();
// create /run/firejail/mnt/home directory
mkdir_attr(RUN_HOME_DIR, 0755, uid, gid);
selinux_relabel_path(RUN_HOME_DIR, homedir);
// save the current log
fs_logger_print();
EUID_USER();
// copy the list of files in the new home directory
if (arg_debug)
printf("Copying files in the new home:\n");
char *dlist = strdup(cfg.home_private_keep);
if (!dlist)
errExit("strdup");
char *ptr = strtok(dlist, ",");
if (!ptr) {
fprintf(stderr, "Error: invalid private-home argument\n");
exit(1);
}
duplicate(ptr);
while ((ptr = strtok(NULL, ",")) != NULL)
duplicate(ptr);
fs_logger_print(); // save the current log
free(dlist);
if (arg_debug)
printf("Mount-bind %s on top of %s\n", RUN_HOME_DIR, homedir);
int fd = safer_openat(-1, homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
if (fd == -1)
errExit("opening home directory");
// home directory should be owned by the user
struct stat s;
if (fstat(fd, &s) == -1)
errExit("fstat");
if (s.st_uid != uid) {
fprintf(stderr, "Error: cannot mount private directory:\n"
"Home directory is not owned by the current user\n");
exit(1);
}
// mount using the file descriptor
EUID_ROOT();
if (bind_mount_path_to_fd(RUN_HOME_DIR, fd))
errExit("mount bind");
EUID_USER();
close(fd);
// check /proc/self/mountinfo to confirm the mount is ok
MountData *mptr = get_last_mount();
if (strcmp(mptr->dir, homedir) != 0 || strcmp(mptr->fstype, "tmpfs") != 0)
errLogExit("invalid private-home mount");
fs_logger2("tmpfs", homedir);
EUID_ROOT();
if (uid != 0) {
// mask /root
if (arg_debug)
printf("Mounting a new /root directory\n");
if (mount("tmpfs", "/root", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME, "mode=700,gid=0") < 0)
errExit("mounting /root directory");
selinux_relabel_path("/root", "/root");
fs_logger("tmpfs /root");
}
if (uid == 0 && !arg_allusers) {
// mask /home
if (arg_debug)
printf("Mounting a new /home directory\n");
if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME, "mode=755,gid=0") < 0)
errExit("mounting /home directory");
selinux_relabel_path("/home", "/home");
fs_logger("tmpfs /home");
}
// mask RUN_HOME_DIR, it is writable and not noexec
if (mount("tmpfs", RUN_HOME_DIR, "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME, "mode=755,gid=0") < 0)
errExit("mounting tmpfs");
EUID_USER();
if (!arg_keep_shell_rc)
skel(homedir);
if (xflag)
copy_xauthority();
if (aflag)
copy_asoundrc();
if (!arg_quiet)
fprintf(stderr, "Home directory installed in %0.2f ms\n", timetrace_end());
}

View file

@ -1865,11 +1865,6 @@ int main(int argc, char **argv, char **envp) {
arg_private = 1;
}
else if (strncmp(argv[i], "--private=", 10) == 0) {
if (cfg.home_private_keep) {
fprintf(stderr, "Error: a private list of files was already defined with --private-home option.\n");
exit(1);
}
// extract private home dirname
cfg.home_private = argv[i] + 10;
if (*cfg.home_private == '\0') {
@ -1885,30 +1880,6 @@ int main(int argc, char **argv, char **envp) {
}
arg_private = 1;
}
#ifdef HAVE_PRIVATE_HOME
else if (strncmp(argv[i], "--private-home=", 15) == 0) {
if (checkcfg(CFG_PRIVATE_HOME)) {
if (cfg.home_private) {
fprintf(stderr, "Error: a private home directory was already defined with --private option.\n");
exit(1);
}
// extract private home dirname
if (*(argv[i] + 15) == '\0') {
fprintf(stderr, "Error: invalid private-home option\n");
exit(1);
}
if (cfg.home_private_keep) {
if ( asprintf(&cfg.home_private_keep, "%s,%s", cfg.home_private_keep, argv[i] + 15) < 0 )
errExit("asprintf");
} else
cfg.home_private_keep = argv[i] + 15;
arg_private = 1;
}
else
exit_err_feature(argv[i], CFG_PRIVATE_HOME);
}
#endif
else if (strcmp(argv[i], "--private-dev") == 0) {
arg_private_dev = 1;
}

View file

@ -384,18 +384,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
return 0;
}
else if (strncmp(ptr, "private-home ", 13) == 0) {
#ifdef HAVE_PRIVATE_HOME
if (checkcfg(CFG_PRIVATE_HOME)) {
if (cfg.home_private_keep) {
if ( asprintf(&cfg.home_private_keep, "%s,%s", cfg.home_private_keep, ptr + 13) < 0 )
errExit("asprintf");
} else
cfg.home_private_keep = ptr + 13;
arg_private = 1;
}
else
warning_feature_disabled(fname, lineno, ptr, CFG_PRIVATE_HOME);
#endif
fprintf(stderr, "Warning: \"private-home\" feature was deprecated in firejail version 0.9.81\n");
return 0;
}
else if (strcmp(ptr, "tab") == 0) {

View file

@ -893,12 +893,6 @@ int sandbox(void* sandbox_arg) {
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
fs_private_home_list();
}
else // --private
fs_private();
EUID_ROOT();

View file

@ -411,17 +411,6 @@ the /etc directory, and must not contain the / character
expressed as foo/bar -- is disallowed).
All modifications are discarded when the sandbox is closed.
Multiple private-etc commands are allowed and they accumulate.
#ifdef HAVE_PRIVATE_HOME
.TP
\fBprivate\-home file,directory
Build a new user home in a temporary
filesystem, and copy the files and directories in the list in the
new home.
The files and directories in the list must be expressed as relative to
the current user's home directory.
All modifications are discarded when the sandbox is
closed.
#endif
#ifdef HAVE_PRIVATE_LIB
.TP
\fBprivate\-lib file,directory

View file

@ -2321,23 +2321,6 @@ $ firejail \-\-allow\-debuggers \-\-profile=/etc/firejail/transmission\-qt.profi
strace \-f \-\-trace=%file /usr/bin/transmission-qt 2>&1 | grep etc
See also \fB\-\-allow-debuggers\fR and \fB\-\-trace\fR.
#ifdef HAVE_PRIVATE_HOME
.TP
\fB\-\-private\-home=file,directory
Build a new user home in a temporary
filesystem, and copy the files and directories in the list in the
new home.
The files and directories in the list must be expressed as relative to
the current user's home directory.
All modifications are discarded when the sandbox is
closed.
.br
.br
Example:
.br
$ firejail \-\-private\-home=.mozilla /usr/bin/firefox
#endif
#ifdef HAVE_PRIVATE_LIB
.TP
\fB\-\-private\-lib=file,directory
@ -3275,7 +3258,6 @@ Compile time support:
- file transfer support is enabled
- firetunnel support is enabled
- networking support is enabled
- private-home support is enabled
- seccomp-bpf support is enabled
- user namespace support is enabled
- X11 sandboxing support is enabled