Add support for SELinux labeling

Running `firejail --noprofile --private-bin=bash,ls ls -1Za /usr/bin`
shows that the SELinux labels are not correct:
```
user_u:object_r:user_tmpfs_t:s0 .
     system_u:object_r:usr_t:s0 ..
user_u:object_r:user_tmpfs_t:s0 bash
user_u:object_r:user_tmpfs_t:s0 ls
```

After fixing this:
```
       system_u:object_r:bin_t:s0 .
       system_u:object_r:usr_t:s0 ..
system_u:object_r:shell_exec_t:s0 bash
       system_u:object_r:bin_t:s0 ls
```

Most copied files and created directories should now have correct
labels (bind mounted objects keep their labels). This is useful to
avoid having to change the SELinux rules when using Firejail.
This commit is contained in:
Topi Miettinen 2020-02-18 20:38:00 +02:00 committed by Topi Miettinen
parent 12c361b32f
commit 1ad2d54c01
20 changed files with 224 additions and 17 deletions

2
README
View file

@ -29,7 +29,7 @@ development libraries and pkg-config are required when using --apparmor
$ sudo apt-get install git build-essential libapparmor-dev pkg-config
For --selinux option, add libselinux1-dev (libselinux-devel for Fedora).
Maintainer:
- netblue30 (netblue30@yahoo.com)

View file

@ -87,7 +87,7 @@ development libraries and pkg-config are required when using --apparmor
`````
$ sudo apt-get install git build-essential libapparmor-dev pkg-config
`````
For --selinux option, add libselinux1-dev (libselinux-devel for Fedora).
## Running the sandbox

18
configure vendored
View file

@ -628,6 +628,7 @@ HAVE_SECCOMP_H
EGREP
GREP
CPP
HAVE_SELINUX
HAVE_CONTRIB_INSTALL
HAVE_GCOV
BUSYBOX_WORKAROUND
@ -721,6 +722,7 @@ enable_fatal_warnings
enable_busybox_workaround
enable_gcov
enable_contrib_install
enable_selinux
'
ac_precious_vars='build_alias
host_alias
@ -1365,6 +1367,7 @@ Optional Features:
--enable-gcov Gcov instrumentation
--enable-contrib-install
install contrib scripts
--enable-selinux SELinux labeling support
Some influential environment variables:
CC C compiler command
@ -3695,6 +3698,20 @@ else
fi
HAVE_SELINUX=""
# Check whether --enable-selinux was given.
if test "${enable_selinux+set}" = set; then :
enableval=$enable_selinux;
fi
if test "x$enable_selinux" = "xyes"; then :
HAVE_SELINUX="-DHAVE_SELINUX"
EXTRA_LDFLAGS+=" -lselinux "
fi
# checking pthread library
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lpthread" >&5
$as_echo_n "checking for main in -lpthread... " >&6; }
@ -5364,5 +5381,6 @@ echo " EXTRA_CFLAGS: $EXTRA_CFLAGS"
echo " fatal warnings: $HAVE_FATAL_WARNINGS"
echo " Gcov instrumentation: $HAVE_GCOV"
echo " Install contrib scripts: $HAVE_CONTRIB_INSTALL"
echo " SELinux labeling support: $HAVE_SELINUX"
echo " Install as a SUID executable: $HAVE_SUID"
echo

View file

@ -184,6 +184,15 @@ AS_IF([test "x$enable_contrib_install" = "xno"],
)
AC_SUBST(HAVE_CONTRIB_INSTALL)
HAVE_SELINUX=""
AC_ARG_ENABLE([selinux],
AS_HELP_STRING([--enable-selinux], [SELinux labeling support]))
AS_IF([test "x$enable_selinux" = "xyes"], [
HAVE_SELINUX="-DHAVE_SELINUX"
EXTRA_LDFLAGS+=" -lselinux "
AC_SUBST(HAVE_SELINUX)
])
# checking pthread library
AC_CHECK_LIB([pthread], [main], [], AC_MSG_ERROR([*** POSIX thread support not installed ***]))
AC_CHECK_HEADER(pthread.h,,AC_MSG_ERROR([*** POSIX thread support not installed ***]))
@ -223,5 +232,6 @@ echo " EXTRA_CFLAGS: $EXTRA_CFLAGS"
echo " fatal warnings: $HAVE_FATAL_WARNINGS"
echo " Gcov instrumentation: $HAVE_GCOV"
echo " Install contrib scripts: $HAVE_CONTRIB_INSTALL"
echo " SELinux labeling support: $HAVE_SELINUX"
echo " Install as a SUID executable: $HAVE_SUID"
echo

View file

@ -24,6 +24,7 @@ HAVE_OVERLAYFS=@HAVE_OVERLAYFS@
HAVE_FIRETUNNEL=@HAVE_FIRETUNNEL@
HAVE_PRIVATE_HOME=@HAVE_PRIVATE_HOME@
HAVE_GCOV=@HAVE_GCOV@
HAVE_SELINUX=@HAVE_SELINUX@
H_FILE_LIST = $(sort $(wildcard *.[h]))
C_FILE_LIST = $(sort $(wildcard *.c))
@ -32,7 +33,7 @@ BINOBJS = $(foreach file, $(OBJS), $file)
CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' $(HAVE_GCOV)
CFLAGS += -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' -DBINDIR='"$(bindir)"'
CFLAGS += $(HAVE_X11) $(HAVE_PRIVATE_HOME) $(HAVE_APPARMOR) $(HAVE_OVERLAYFS) $(HAVE_FIRETUNNEL) $(HAVE_SECCOMP) $(HAVE_GLOBALCFG) $(HAVE_SECCOMP_H) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_FILE_TRANSFER) $(HAVE_WHITELIST)
CFLAGS += $(HAVE_X11) $(HAVE_PRIVATE_HOME) $(HAVE_APPARMOR) $(HAVE_OVERLAYFS) $(HAVE_FIRETUNNEL) $(HAVE_SECCOMP) $(HAVE_GLOBALCFG) $(HAVE_SECCOMP_H) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_FILE_TRANSFER) $(HAVE_WHITELIST) $(HAVE_SELINUX)
CFLAGS += -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security
LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread
EXTRA_LDFLAGS +=@EXTRA_LDFLAGS@

View file

@ -24,6 +24,15 @@
#include <errno.h>
#include <pwd.h>
#if HAVE_SELINUX
#include <sys/stat.h>
#include <sys/types.h>
#include <selinux/context.h>
#include <selinux/label.h>
#include <selinux/selinux.h>
#endif
int arg_quiet = 0;
int arg_debug = 0;
static int arg_follow_link = 0;
@ -36,6 +45,52 @@ static unsigned file_cnt = 0;
static char *outpath = NULL;
static char *inpath = NULL;
#if HAVE_SELINUX
static struct selabel_handle *label_hnd = NULL;
static int selinux_enabled = -1;
#endif
// copy from firejail/selinux.c
static void selinux_relabel_path(const char *path, const char *inside_path)
{
#if HAVE_SELINUX
char procfs_path[64];
char *fcon = NULL;
int fd;
struct stat st;
if (selinux_enabled == -1)
selinux_enabled = is_selinux_enabled();
if (!selinux_enabled)
return;
if (!label_hnd)
label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
/* Open the file as O_PATH, to pin it while we determine and adjust the label */
fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
if (fd < 0)
return;
if (fstat(fd, &st) < 0)
goto close;
if (selabel_lookup_raw(label_hnd, &fcon, inside_path, st.st_mode) == 0) {
sprintf(procfs_path, "/proc/self/fd/%i", fd);
if (arg_debug)
printf("Relabeling %s as %s (%s)\n", path, inside_path, fcon);
setfilecon_raw(procfs_path, fcon);
}
freecon(fcon);
close:
close(fd);
#else
(void) path;
(void) inside_path;
#endif
}
// modified version of the function from util.c
static void copy_file(const char *srcname, const char *destname, mode_t mode, uid_t uid, gid_t gid) {
assert(srcname);
@ -87,6 +142,8 @@ static void copy_file(const char *srcname, const char *destname, mode_t mode, ui
close(src);
close(dst);
selinux_relabel_path(destname, srcname);
return;
errexit:

View file

@ -833,4 +833,7 @@ extern pid_t dhclient4_pid;
extern pid_t dhclient6_pid;
void dhcp_start(void);
// selinux.c
void selinux_relabel_path(const char *path, const char *inside_path);
#endif

View file

@ -309,5 +309,6 @@ void fs_private_bin_list(void) {
}
i++;
}
selinux_relabel_path(RUN_BIN_DIR, "/bin");
fmessage("%d %s installed in %0.2f ms\n", prog_cnt, (prog_cnt == 1)? "program": "programs", timetrace_end());
}

View file

@ -167,6 +167,7 @@ static void create_link(const char *oldpath, const char *newpath) {
static void empty_dev_shm(void) {
// create an empty /dev/shm directory
mkdir_attr("/dev/shm", 01777, 0, 0);
selinux_relabel_path("/dev/shm", "/dev/shm");
fs_logger("mkdir /dev/shm");
fs_logger("create /dev/shm");
}
@ -276,10 +277,13 @@ void fs_private_dev(void){
// pseudo-terminal
mkdir_attr("/dev/pts", 0755, 0, 0);
fs_logger("mkdir /dev/pts");
selinux_relabel_path("/dev/pts", "/dev/pts");
fs_logger("create /dev/pts");
create_char_dev("/dev/pts/ptmx", 0666, 5, 2); //"mknod -m 666 /dev/pts/ptmx c 5 2");
selinux_relabel_path("/dev/pts/ptmx", "/dev/pts/ptmx");
fs_logger("mknod /dev/pts/ptmx");
create_link("/dev/pts/ptmx", "/dev/ptmx");
selinux_relabel_path("/dev/ptmx", "/dev/ptmx");
// code before github issue #351
// mount -vt devpts -o newinstance -o ptmxmode=0666 devpts //dev/pts

View file

@ -59,6 +59,7 @@ void fs_machineid(void) {
if (set_perms(RUN_MACHINEID, 0, 0, 0444))
errExit("set_perms");
selinux_relabel_path(RUN_MACHINEID, "/etc/machine-id");
struct stat s;
if (stat("/etc/machine-id", &s) == 0) {
@ -154,6 +155,7 @@ void fs_private_dir_list(const char *private_dir, const char *private_run_dir, c
// create /run/firejail/mnt/etc directory
mkdir_attr(private_run_dir, 0755, 0, 0);
selinux_relabel_path(private_run_dir, private_dir);
fs_logger2("tmpfs", private_dir);
fs_logger_print(); // save the current log

View file

@ -60,6 +60,7 @@ static void skel(const char *homedir, uid_t u, gid_t g) {
touch_file_as_user(fname, 0644);
fs_logger2("touch", fname);
}
selinux_relabel_path(fname, fname);
free(fname);
}
// csh
@ -85,6 +86,7 @@ static void skel(const char *homedir, uid_t u, gid_t g) {
touch_file_as_user(fname, 0644);
fs_logger2("touch", fname);
}
selinux_relabel_path(fname, fname);
free(fname);
}
// bash etc.
@ -105,6 +107,7 @@ static void skel(const char *homedir, uid_t u, gid_t g) {
fs_logger("clone /etc/skel/.bashrc");
fs_logger2("clone", fname);
}
selinux_relabel_path(fname, fname);
free(fname);
}
}
@ -139,6 +142,7 @@ static int store_xauthority(void) {
copy_file_as_user(src, dest, getuid(), getgid(), 0600); // regular user
fs_logger2("clone", dest);
selinux_relabel_path(dest, src);
free(src);
return 1; // file copied
}
@ -185,6 +189,7 @@ static int store_asoundrc(void) {
errExit("fopen");
copy_file_as_user(src, dest, getuid(), getgid(), 0644); // regular user
selinux_relabel_path(dest, src);
fs_logger2("clone", dest);
free(src);
return 1; // file copied
@ -208,6 +213,7 @@ static void copy_xauthority(void) {
}
copy_file_as_user(src, dest, getuid(), getgid(), S_IRUSR | S_IWUSR); // regular user
selinux_relabel_path(dest, src);
fs_logger2("clone", dest);
free(dest);
@ -313,6 +319,7 @@ void fs_private_homedir(void) {
printf("Mounting a new /root directory\n");
if (mount("tmpfs", "/root", "tmpfs", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_STRICTATIME, "mode=700,gid=0") < 0)
errExit("mounting /root directory");
selinux_relabel_path("/root", "/root");
fs_logger("tmpfs /root");
}
if (u == 0 && !arg_allusers) {
@ -321,6 +328,7 @@ void fs_private_homedir(void) {
printf("Mounting a new /home directory\n");
if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_STRICTATIME, "mode=755,gid=0") < 0)
errExit("mounting /home directory");
selinux_relabel_path("/home", "/home");
fs_logger("tmpfs /home");
}
@ -355,6 +363,7 @@ void fs_private(void) {
fwarning("allusers option disabled by private or whitelist option\n");
if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_STRICTATIME, "mode=755,gid=0") < 0)
errExit("mounting /home directory");
selinux_relabel_path("/home", "/home");
fs_logger("tmpfs /home");
}
@ -378,6 +387,8 @@ void fs_private(void) {
}
if (chown(homedir, u, g) < 0)
errExit("chown");
selinux_relabel_path(homedir, homedir);
fs_logger2("mkdir", homedir);
fs_logger2("tmpfs", homedir);
}
@ -542,6 +553,7 @@ void fs_private_home_list(void) {
// create /run/firejail/mnt/home directory
mkdir_attr(RUN_HOME_DIR, 0755, uid, gid);
selinux_relabel_path(RUN_HOME_DIR, "/home");
fs_logger_print(); // save the current log
if (arg_debug)
@ -604,6 +616,7 @@ void fs_private_home_list(void) {
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) {
@ -612,6 +625,7 @@ void fs_private_home_list(void) {
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");
}

View file

@ -96,6 +96,7 @@ void fs_resolvconf(void) {
printf("mirroring /etc directory\n");
if (mkdir(RUN_DNS_ETC, 0755))
errExit("mkdir");
selinux_relabel_path(RUN_DNS_ETC, "/etc");
fs_logger("tmpfs /etc");
DIR *dir = opendir("/etc");

View file

@ -326,6 +326,7 @@ void fs_private_lib(void) {
// create /run/firejail/mnt/lib directory
mkdir_attr(RUN_LIB_DIR, 0755, 0, 0);
selinux_relabel_path(RUN_LIB_DIR, "/usr/lib");
// install standard C libraries
if (arg_debug || arg_debug_private_lib)

View file

@ -109,6 +109,7 @@ void fslib_install_stdc(void) {
if (stat("/lib/x86_64-linux-gnu", &s) == 0) { // Debian & friends
mkdir_attr(RUN_LIB_DIR "/x86_64-linux-gnu", 0755, 0, 0);
selinux_relabel_path(RUN_LIB_DIR "/x86_64-linux-gnu", "/lib/x86_64-linux-gnu");
stdclib = "/lib/x86_64-linux-gnu";
}

View file

@ -223,9 +223,11 @@ void fs_var_cache(void) {
}
mkdir_attr("/var/cache/lighttpd/compress", 0755, uid, gid);
selinux_relabel_path("/var/cache/lighttpd/compress", "/var/cache/lighttpd/compress");
fs_logger("mkdir /var/cache/lighttpd/compress");
mkdir_attr("/var/cache/lighttpd/uploads", 0755, uid, gid);
selinux_relabel_path("/var/cache/lighttpd/uploads", "/var/cache/lighttpd/uploads");
fs_logger("/var/cache/lighttpd/uploads");
}
}

View file

@ -734,6 +734,7 @@ void fs_whitelist(void) {
printf("Mounting tmpfs on /tmp directory\n");
if (mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=1777,gid=0") < 0)
errExit("mounting tmpfs on /tmp");
selinux_relabel_path("/tmp", "/tmp");
fs_logger("tmpfs /tmp");
// pam-tmpdir - issue #2685
@ -745,8 +746,10 @@ void fs_whitelist(void) {
if (strcmp(env, pamtmpdir) == 0) {
// create empty user-owned /tmp/user/$uid directory
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);
}
free(pamtmpdir);
@ -774,6 +777,7 @@ void fs_whitelist(void) {
printf("Mounting tmpfs on /media directory\n");
if (mount("tmpfs", "/media", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=755,gid=0") < 0)
errExit("mounting tmpfs on /media");
selinux_relabel_path("/media", "/media");
fs_logger("tmpfs /media");
// autowhitelist home directory if it is masked by the tmpfs
@ -798,6 +802,7 @@ void fs_whitelist(void) {
printf("Mounting tmpfs on /mnt directory\n");
if (mount("tmpfs", "/mnt", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=755,gid=0") < 0)
errExit("mounting tmpfs on /mnt");
selinux_relabel_path("/mnt", "/mnt");
fs_logger("tmpfs /mnt");
// autowhitelist home directory if it is masked by the tmpfs
@ -822,6 +827,7 @@ void fs_whitelist(void) {
printf("Mounting tmpfs on /var directory\n");
if (mount("tmpfs", "/var", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=755,gid=0") < 0)
errExit("mounting tmpfs on /var");
selinux_relabel_path("/var", "/var");
fs_logger("tmpfs /var");
// autowhitelist home directory if it is masked by the tmpfs
@ -846,6 +852,7 @@ void fs_whitelist(void) {
printf("Mounting tmpfs on /dev directory\n");
if (mount("tmpfs", "/dev", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=755,gid=0") < 0)
errExit("mounting tmpfs on /dev");
selinux_relabel_path("/dev", "/dev");
fs_logger("tmpfs /dev");
// autowhitelist home directory if it is masked by the tmpfs
@ -870,6 +877,7 @@ void fs_whitelist(void) {
printf("Mounting tmpfs on /opt directory\n");
if (mount("tmpfs", "/opt", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=755,gid=0") < 0)
errExit("mounting tmpfs on /opt");
selinux_relabel_path("/opt", "/opt");
fs_logger("tmpfs /opt");
// autowhitelist home directory if it is masked by the tmpfs
@ -894,6 +902,7 @@ void fs_whitelist(void) {
printf("Mounting tmpfs on /srv directory\n");
if (mount("tmpfs", "/srv", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=755,gid=0") < 0)
errExit("mounting tmpfs on /srv");
selinux_relabel_path("/srv", "/srv");
fs_logger("tmpfs /srv");
// autowhitelist home directory if it is masked by the tmpfs
@ -918,6 +927,7 @@ void fs_whitelist(void) {
printf("Mounting tmpfs on /etc directory\n");
if (mount("tmpfs", "/etc", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=755,gid=0") < 0)
errExit("mounting tmpfs on /etc");
selinux_relabel_path("/etc", "/etc");
fs_logger("tmpfs /etc");
// autowhitelist home directory if it is masked by the tmpfs
@ -942,6 +952,7 @@ void fs_whitelist(void) {
printf("Mounting tmpfs on /usr/share directory\n");
if (mount("tmpfs", "/usr/share", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=755,gid=0") < 0)
errExit("mounting tmpfs on /usr/share");
selinux_relabel_path("/usr/share", "/usr/share");
fs_logger("tmpfs /usr/share");
// autowhitelist home directory if it is masked by the tmpfs
@ -966,6 +977,7 @@ void fs_whitelist(void) {
printf("Mounting tmpfs on /sys/module directory\n");
if (mount("tmpfs", "/sys/module", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=755,gid=0") < 0)
errExit("mounting tmpfs on /sys/module");
selinux_relabel_path("/sys/module", "/sys/module");
fs_logger("tmpfs /sys/module");
}
else
@ -989,6 +1001,7 @@ void fs_whitelist(void) {
errExit("asprintf");
if (mount("tmpfs", runuser, "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME, options) < 0)
errExit("mounting tmpfs on /run/user/<uid>");
selinux_relabel_path(runuser, runuser);
free(options);
fs_logger2("tmpfs", runuser);

View file

@ -87,6 +87,7 @@ void pulseaudio_init(void) {
// create the new user pulseaudio directory
if (mkdir(RUN_PULSE_DIR, 0700) == -1)
errExit("mkdir");
selinux_relabel_path(RUN_PULSE_DIR, RUN_PULSE_DIR);
// mount it nosuid, noexec, nodev
fs_remount(RUN_PULSE_DIR, MOUNT_NOEXEC, 0);

View file

@ -97,6 +97,7 @@ static void sanitize_home(void) {
// mount tmpfs in the new home
if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME, "mode=755,gid=0") < 0)
errExit("mount tmpfs");
selinux_relabel_path("/home", "/home");
fs_logger("tmpfs /home");
// create user home directory
@ -105,6 +106,7 @@ static void sanitize_home(void) {
errExit("mkpath");
if (mkdir(cfg.homedir, 0755) == -1)
errExit("mkdir");
selinux_relabel_path(cfg.homedir, cfg.homedir);
}
fs_logger2("mkdir", cfg.homedir);
@ -152,11 +154,13 @@ static void sanitize_run(void) {
// mount tmpfs on /run/user
if (mount("tmpfs", "/run/user", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME, "mode=755,gid=0") < 0)
errExit("mount tmpfs");
selinux_relabel_path("/run/user", "/run/user");
fs_logger("tmpfs /run/user");
// create new user directory
if (mkdir(runuser, 0700) == -1)
errExit("mkdir");
selinux_relabel_path(runuser, runuser);
fs_logger2("mkdir", runuser);
// set mode and ownership

View file

@ -848,20 +848,6 @@ int sandbox(void* sandbox_arg) {
if (arg_private_dev)
fs_private_dev();
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 {
fs_private_dir_list("/etc", RUN_ETC_DIR, cfg.etc_private_keep);
fs_private_dir_list("/usr/etc", RUN_USR_ETC_DIR, cfg.etc_private_keep); // openSUSE
// create /etc/ld.so.preload file again
if (need_preload)
fs_trace_preload();
}
}
if (arg_private_opt) {
if (cfg.chrootdir)
fwarning("private-opt feature is disabled in chroot\n");
@ -964,6 +950,21 @@ int sandbox(void* sandbox_arg) {
else if (arg_disable_mnt)
fs_mnt(0);
// Install new /etc last, so we can use it as long as possible
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 {
fs_private_dir_list("/etc", RUN_ETC_DIR, cfg.etc_private_keep);
fs_private_dir_list("/usr/etc", RUN_USR_ETC_DIR, cfg.etc_private_keep); // openSUSE
// create /etc/ld.so.preload file again
if (need_preload)
fs_trace_preload();
}
}
//****************************
// apply the profile file
//****************************

73
src/firejail/selinux.c Normal file
View file

@ -0,0 +1,73 @@
/*
* Copyright (C) 2020 Firejail and systemd authors
*
* This file is part of firejail project, from systemd selinux-util.c
*
* 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.
*/
#if HAVE_SELINUX
#include "firejail.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <selinux/context.h>
#include <selinux/label.h>
#include <selinux/selinux.h>
static struct selabel_handle *label_hnd = NULL;
static int selinux_enabled = -1;
#endif
void selinux_relabel_path(const char *path, const char *inside_path)
{
#if HAVE_SELINUX
char procfs_path[64];
char *fcon = NULL;
int fd;
struct stat st;
if (selinux_enabled == -1)
selinux_enabled = is_selinux_enabled();
if (!selinux_enabled && arg_debug)
return;
if (!label_hnd)
label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
/* Open the file as O_PATH, to pin it while we determine and adjust the label */
fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
if (fd < 0)
return;
if (fstat(fd, &st) < 0)
goto close;
if (selabel_lookup_raw(label_hnd, &fcon, inside_path, st.st_mode) == 0) {
sprintf(procfs_path, "/proc/self/fd/%i", fd);
if (arg_debug)
printf("Relabeling %s as %s (%s)\n", path, inside_path, fcon);
setfilecon_raw(procfs_path, fcon);
}
freecon(fcon);
close:
close(fd);
#else
(void) path;
(void) inside_path;
#endif
}