aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Topi Miettinen <toiwoton@gmail.com>2020-02-18 20:38:00 +0200
committerLibravatar Topi Miettinen <topimiettinen@users.noreply.github.com>2020-02-22 08:27:24 +0000
commit1ad2d54c014a49f6ad0b487dd0d9b361cb4d299e (patch)
tree415eb19d90e2ed1de7236c784c1e28d3acfbcaab
parentWhitelist more /usr/share for okular and others (diff)
downloadfirejail-1ad2d54c014a49f6ad0b487dd0d9b361cb4d299e.tar.gz
firejail-1ad2d54c014a49f6ad0b487dd0d9b361cb4d299e.tar.zst
firejail-1ad2d54c014a49f6ad0b487dd0d9b361cb4d299e.zip
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.
-rw-r--r--README2
-rw-r--r--README.md2
-rwxr-xr-xconfigure18
-rw-r--r--configure.ac10
-rw-r--r--src/common.mk.in3
-rw-r--r--src/fcopy/main.c57
-rw-r--r--src/firejail/firejail.h3
-rw-r--r--src/firejail/fs_bin.c1
-rw-r--r--src/firejail/fs_dev.c4
-rw-r--r--src/firejail/fs_etc.c2
-rw-r--r--src/firejail/fs_home.c14
-rw-r--r--src/firejail/fs_hostname.c1
-rw-r--r--src/firejail/fs_lib.c1
-rw-r--r--src/firejail/fs_lib2.c1
-rw-r--r--src/firejail/fs_var.c2
-rw-r--r--src/firejail/fs_whitelist.c13
-rw-r--r--src/firejail/pulseaudio.c1
-rw-r--r--src/firejail/restrict_users.c4
-rw-r--r--src/firejail/sandbox.c29
-rw-r--r--src/firejail/selinux.c73
20 files changed, 224 insertions, 17 deletions
diff --git a/README b/README
index d33fa3e81..61d94bec9 100644
--- a/README
+++ b/README
@@ -29,7 +29,7 @@ development libraries and pkg-config are required when using --apparmor
29 29
30$ sudo apt-get install git build-essential libapparmor-dev pkg-config 30$ sudo apt-get install git build-essential libapparmor-dev pkg-config
31 31
32 32For --selinux option, add libselinux1-dev (libselinux-devel for Fedora).
33 33
34Maintainer: 34Maintainer:
35- netblue30 (netblue30@yahoo.com) 35- netblue30 (netblue30@yahoo.com)
diff --git a/README.md b/README.md
index 4391ac331..dce1f9cfb 100644
--- a/README.md
+++ b/README.md
@@ -87,7 +87,7 @@ development libraries and pkg-config are required when using --apparmor
87````` 87`````
88$ sudo apt-get install git build-essential libapparmor-dev pkg-config 88$ sudo apt-get install git build-essential libapparmor-dev pkg-config
89````` 89`````
90 90For --selinux option, add libselinux1-dev (libselinux-devel for Fedora).
91 91
92## Running the sandbox 92## Running the sandbox
93 93
diff --git a/configure b/configure
index 94f719710..53ea8f19d 100755
--- a/configure
+++ b/configure
@@ -628,6 +628,7 @@ HAVE_SECCOMP_H
628EGREP 628EGREP
629GREP 629GREP
630CPP 630CPP
631HAVE_SELINUX
631HAVE_CONTRIB_INSTALL 632HAVE_CONTRIB_INSTALL
632HAVE_GCOV 633HAVE_GCOV
633BUSYBOX_WORKAROUND 634BUSYBOX_WORKAROUND
@@ -721,6 +722,7 @@ enable_fatal_warnings
721enable_busybox_workaround 722enable_busybox_workaround
722enable_gcov 723enable_gcov
723enable_contrib_install 724enable_contrib_install
725enable_selinux
724' 726'
725 ac_precious_vars='build_alias 727 ac_precious_vars='build_alias
726host_alias 728host_alias
@@ -1365,6 +1367,7 @@ Optional Features:
1365 --enable-gcov Gcov instrumentation 1367 --enable-gcov Gcov instrumentation
1366 --enable-contrib-install 1368 --enable-contrib-install
1367 install contrib scripts 1369 install contrib scripts
1370 --enable-selinux SELinux labeling support
1368 1371
1369Some influential environment variables: 1372Some influential environment variables:
1370 CC C compiler command 1373 CC C compiler command
@@ -3695,6 +3698,20 @@ else
3695fi 3698fi
3696 3699
3697 3700
3701HAVE_SELINUX=""
3702# Check whether --enable-selinux was given.
3703if test "${enable_selinux+set}" = set; then :
3704 enableval=$enable_selinux;
3705fi
3706
3707if test "x$enable_selinux" = "xyes"; then :
3708
3709 HAVE_SELINUX="-DHAVE_SELINUX"
3710 EXTRA_LDFLAGS+=" -lselinux "
3711
3712
3713fi
3714
3698# checking pthread library 3715# checking pthread library
3699{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lpthread" >&5 3716{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lpthread" >&5
3700$as_echo_n "checking for main in -lpthread... " >&6; } 3717$as_echo_n "checking for main in -lpthread... " >&6; }
@@ -5364,5 +5381,6 @@ echo " EXTRA_CFLAGS: $EXTRA_CFLAGS"
5364echo " fatal warnings: $HAVE_FATAL_WARNINGS" 5381echo " fatal warnings: $HAVE_FATAL_WARNINGS"
5365echo " Gcov instrumentation: $HAVE_GCOV" 5382echo " Gcov instrumentation: $HAVE_GCOV"
5366echo " Install contrib scripts: $HAVE_CONTRIB_INSTALL" 5383echo " Install contrib scripts: $HAVE_CONTRIB_INSTALL"
5384echo " SELinux labeling support: $HAVE_SELINUX"
5367echo " Install as a SUID executable: $HAVE_SUID" 5385echo " Install as a SUID executable: $HAVE_SUID"
5368echo 5386echo
diff --git a/configure.ac b/configure.ac
index 8ee2fbadc..3c9f901cb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -184,6 +184,15 @@ AS_IF([test "x$enable_contrib_install" = "xno"],
184) 184)
185AC_SUBST(HAVE_CONTRIB_INSTALL) 185AC_SUBST(HAVE_CONTRIB_INSTALL)
186 186
187HAVE_SELINUX=""
188AC_ARG_ENABLE([selinux],
189 AS_HELP_STRING([--enable-selinux], [SELinux labeling support]))
190AS_IF([test "x$enable_selinux" = "xyes"], [
191 HAVE_SELINUX="-DHAVE_SELINUX"
192 EXTRA_LDFLAGS+=" -lselinux "
193 AC_SUBST(HAVE_SELINUX)
194])
195
187# checking pthread library 196# checking pthread library
188AC_CHECK_LIB([pthread], [main], [], AC_MSG_ERROR([*** POSIX thread support not installed ***])) 197AC_CHECK_LIB([pthread], [main], [], AC_MSG_ERROR([*** POSIX thread support not installed ***]))
189AC_CHECK_HEADER(pthread.h,,AC_MSG_ERROR([*** POSIX thread support not installed ***])) 198AC_CHECK_HEADER(pthread.h,,AC_MSG_ERROR([*** POSIX thread support not installed ***]))
@@ -223,5 +232,6 @@ echo " EXTRA_CFLAGS: $EXTRA_CFLAGS"
223echo " fatal warnings: $HAVE_FATAL_WARNINGS" 232echo " fatal warnings: $HAVE_FATAL_WARNINGS"
224echo " Gcov instrumentation: $HAVE_GCOV" 233echo " Gcov instrumentation: $HAVE_GCOV"
225echo " Install contrib scripts: $HAVE_CONTRIB_INSTALL" 234echo " Install contrib scripts: $HAVE_CONTRIB_INSTALL"
235echo " SELinux labeling support: $HAVE_SELINUX"
226echo " Install as a SUID executable: $HAVE_SUID" 236echo " Install as a SUID executable: $HAVE_SUID"
227echo 237echo
diff --git a/src/common.mk.in b/src/common.mk.in
index 1464ab9b2..945815a40 100644
--- a/src/common.mk.in
+++ b/src/common.mk.in
@@ -24,6 +24,7 @@ HAVE_OVERLAYFS=@HAVE_OVERLAYFS@
24HAVE_FIRETUNNEL=@HAVE_FIRETUNNEL@ 24HAVE_FIRETUNNEL=@HAVE_FIRETUNNEL@
25HAVE_PRIVATE_HOME=@HAVE_PRIVATE_HOME@ 25HAVE_PRIVATE_HOME=@HAVE_PRIVATE_HOME@
26HAVE_GCOV=@HAVE_GCOV@ 26HAVE_GCOV=@HAVE_GCOV@
27HAVE_SELINUX=@HAVE_SELINUX@
27 28
28H_FILE_LIST = $(sort $(wildcard *.[h])) 29H_FILE_LIST = $(sort $(wildcard *.[h]))
29C_FILE_LIST = $(sort $(wildcard *.c)) 30C_FILE_LIST = $(sort $(wildcard *.c))
@@ -32,7 +33,7 @@ BINOBJS = $(foreach file, $(OBJS), $file)
32 33
33CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' $(HAVE_GCOV) 34CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' $(HAVE_GCOV)
34CFLAGS += -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' -DBINDIR='"$(bindir)"' 35CFLAGS += -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' -DBINDIR='"$(bindir)"'
35CFLAGS += $(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) 36CFLAGS += $(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)
36CFLAGS += -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security 37CFLAGS += -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security
37LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread 38LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread
38EXTRA_LDFLAGS +=@EXTRA_LDFLAGS@ 39EXTRA_LDFLAGS +=@EXTRA_LDFLAGS@
diff --git a/src/fcopy/main.c b/src/fcopy/main.c
index 5c4a76753..83d9c17e6 100644
--- a/src/fcopy/main.c
+++ b/src/fcopy/main.c
@@ -24,6 +24,15 @@
24#include <errno.h> 24#include <errno.h>
25#include <pwd.h> 25#include <pwd.h>
26 26
27#if HAVE_SELINUX
28#include <sys/stat.h>
29#include <sys/types.h>
30
31#include <selinux/context.h>
32#include <selinux/label.h>
33#include <selinux/selinux.h>
34#endif
35
27int arg_quiet = 0; 36int arg_quiet = 0;
28int arg_debug = 0; 37int arg_debug = 0;
29static int arg_follow_link = 0; 38static int arg_follow_link = 0;
@@ -36,6 +45,52 @@ static unsigned file_cnt = 0;
36static char *outpath = NULL; 45static char *outpath = NULL;
37static char *inpath = NULL; 46static char *inpath = NULL;
38 47
48#if HAVE_SELINUX
49static struct selabel_handle *label_hnd = NULL;
50static int selinux_enabled = -1;
51#endif
52
53// copy from firejail/selinux.c
54static void selinux_relabel_path(const char *path, const char *inside_path)
55{
56#if HAVE_SELINUX
57 char procfs_path[64];
58 char *fcon = NULL;
59 int fd;
60 struct stat st;
61
62 if (selinux_enabled == -1)
63 selinux_enabled = is_selinux_enabled();
64
65 if (!selinux_enabled)
66 return;
67
68 if (!label_hnd)
69 label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
70
71 /* Open the file as O_PATH, to pin it while we determine and adjust the label */
72 fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
73 if (fd < 0)
74 return;
75 if (fstat(fd, &st) < 0)
76 goto close;
77
78 if (selabel_lookup_raw(label_hnd, &fcon, inside_path, st.st_mode) == 0) {
79 sprintf(procfs_path, "/proc/self/fd/%i", fd);
80 if (arg_debug)
81 printf("Relabeling %s as %s (%s)\n", path, inside_path, fcon);
82
83 setfilecon_raw(procfs_path, fcon);
84 }
85 freecon(fcon);
86 close:
87 close(fd);
88#else
89 (void) path;
90 (void) inside_path;
91#endif
92}
93
39// modified version of the function from util.c 94// modified version of the function from util.c
40static void copy_file(const char *srcname, const char *destname, mode_t mode, uid_t uid, gid_t gid) { 95static void copy_file(const char *srcname, const char *destname, mode_t mode, uid_t uid, gid_t gid) {
41 assert(srcname); 96 assert(srcname);
@@ -87,6 +142,8 @@ static void copy_file(const char *srcname, const char *destname, mode_t mode, ui
87 close(src); 142 close(src);
88 close(dst); 143 close(dst);
89 144
145 selinux_relabel_path(destname, srcname);
146
90 return; 147 return;
91 148
92errexit: 149errexit:
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index 4dc580a5e..66328a55e 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -833,4 +833,7 @@ extern pid_t dhclient4_pid;
833extern pid_t dhclient6_pid; 833extern pid_t dhclient6_pid;
834void dhcp_start(void); 834void dhcp_start(void);
835 835
836// selinux.c
837void selinux_relabel_path(const char *path, const char *inside_path);
838
836#endif 839#endif
diff --git a/src/firejail/fs_bin.c b/src/firejail/fs_bin.c
index 7150fd3eb..a48d6cf67 100644
--- a/src/firejail/fs_bin.c
+++ b/src/firejail/fs_bin.c
@@ -309,5 +309,6 @@ void fs_private_bin_list(void) {
309 } 309 }
310 i++; 310 i++;
311 } 311 }
312 selinux_relabel_path(RUN_BIN_DIR, "/bin");
312 fmessage("%d %s installed in %0.2f ms\n", prog_cnt, (prog_cnt == 1)? "program": "programs", timetrace_end()); 313 fmessage("%d %s installed in %0.2f ms\n", prog_cnt, (prog_cnt == 1)? "program": "programs", timetrace_end());
313} 314}
diff --git a/src/firejail/fs_dev.c b/src/firejail/fs_dev.c
index 63911ab9e..500b6bf1b 100644
--- a/src/firejail/fs_dev.c
+++ b/src/firejail/fs_dev.c
@@ -167,6 +167,7 @@ static void create_link(const char *oldpath, const char *newpath) {
167static void empty_dev_shm(void) { 167static void empty_dev_shm(void) {
168 // create an empty /dev/shm directory 168 // create an empty /dev/shm directory
169 mkdir_attr("/dev/shm", 01777, 0, 0); 169 mkdir_attr("/dev/shm", 01777, 0, 0);
170 selinux_relabel_path("/dev/shm", "/dev/shm");
170 fs_logger("mkdir /dev/shm"); 171 fs_logger("mkdir /dev/shm");
171 fs_logger("create /dev/shm"); 172 fs_logger("create /dev/shm");
172} 173}
@@ -276,10 +277,13 @@ void fs_private_dev(void){
276 // pseudo-terminal 277 // pseudo-terminal
277 mkdir_attr("/dev/pts", 0755, 0, 0); 278 mkdir_attr("/dev/pts", 0755, 0, 0);
278 fs_logger("mkdir /dev/pts"); 279 fs_logger("mkdir /dev/pts");
280 selinux_relabel_path("/dev/pts", "/dev/pts");
279 fs_logger("create /dev/pts"); 281 fs_logger("create /dev/pts");
280 create_char_dev("/dev/pts/ptmx", 0666, 5, 2); //"mknod -m 666 /dev/pts/ptmx c 5 2"); 282 create_char_dev("/dev/pts/ptmx", 0666, 5, 2); //"mknod -m 666 /dev/pts/ptmx c 5 2");
283 selinux_relabel_path("/dev/pts/ptmx", "/dev/pts/ptmx");
281 fs_logger("mknod /dev/pts/ptmx"); 284 fs_logger("mknod /dev/pts/ptmx");
282 create_link("/dev/pts/ptmx", "/dev/ptmx"); 285 create_link("/dev/pts/ptmx", "/dev/ptmx");
286 selinux_relabel_path("/dev/ptmx", "/dev/ptmx");
283 287
284// code before github issue #351 288// code before github issue #351
285 // mount -vt devpts -o newinstance -o ptmxmode=0666 devpts //dev/pts 289 // mount -vt devpts -o newinstance -o ptmxmode=0666 devpts //dev/pts
diff --git a/src/firejail/fs_etc.c b/src/firejail/fs_etc.c
index 76bcb751e..271e46855 100644
--- a/src/firejail/fs_etc.c
+++ b/src/firejail/fs_etc.c
@@ -59,6 +59,7 @@ void fs_machineid(void) {
59 if (set_perms(RUN_MACHINEID, 0, 0, 0444)) 59 if (set_perms(RUN_MACHINEID, 0, 0, 0444))
60 errExit("set_perms"); 60 errExit("set_perms");
61 61
62 selinux_relabel_path(RUN_MACHINEID, "/etc/machine-id");
62 63
63 struct stat s; 64 struct stat s;
64 if (stat("/etc/machine-id", &s) == 0) { 65 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
154 155
155 // create /run/firejail/mnt/etc directory 156 // create /run/firejail/mnt/etc directory
156 mkdir_attr(private_run_dir, 0755, 0, 0); 157 mkdir_attr(private_run_dir, 0755, 0, 0);
158 selinux_relabel_path(private_run_dir, private_dir);
157 fs_logger2("tmpfs", private_dir); 159 fs_logger2("tmpfs", private_dir);
158 160
159 fs_logger_print(); // save the current log 161 fs_logger_print(); // save the current log
diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c
index bdfaba480..bec22e5a6 100644
--- a/src/firejail/fs_home.c
+++ b/src/firejail/fs_home.c
@@ -60,6 +60,7 @@ static void skel(const char *homedir, uid_t u, gid_t g) {
60 touch_file_as_user(fname, 0644); 60 touch_file_as_user(fname, 0644);
61 fs_logger2("touch", fname); 61 fs_logger2("touch", fname);
62 } 62 }
63 selinux_relabel_path(fname, fname);
63 free(fname); 64 free(fname);
64 } 65 }
65 // csh 66 // csh
@@ -85,6 +86,7 @@ static void skel(const char *homedir, uid_t u, gid_t g) {
85 touch_file_as_user(fname, 0644); 86 touch_file_as_user(fname, 0644);
86 fs_logger2("touch", fname); 87 fs_logger2("touch", fname);
87 } 88 }
89 selinux_relabel_path(fname, fname);
88 free(fname); 90 free(fname);
89 } 91 }
90 // bash etc. 92 // bash etc.
@@ -105,6 +107,7 @@ static void skel(const char *homedir, uid_t u, gid_t g) {
105 fs_logger("clone /etc/skel/.bashrc"); 107 fs_logger("clone /etc/skel/.bashrc");
106 fs_logger2("clone", fname); 108 fs_logger2("clone", fname);
107 } 109 }
110 selinux_relabel_path(fname, fname);
108 free(fname); 111 free(fname);
109 } 112 }
110} 113}
@@ -139,6 +142,7 @@ static int store_xauthority(void) {
139 142
140 copy_file_as_user(src, dest, getuid(), getgid(), 0600); // regular user 143 copy_file_as_user(src, dest, getuid(), getgid(), 0600); // regular user
141 fs_logger2("clone", dest); 144 fs_logger2("clone", dest);
145 selinux_relabel_path(dest, src);
142 free(src); 146 free(src);
143 return 1; // file copied 147 return 1; // file copied
144 } 148 }
@@ -185,6 +189,7 @@ static int store_asoundrc(void) {
185 errExit("fopen"); 189 errExit("fopen");
186 190
187 copy_file_as_user(src, dest, getuid(), getgid(), 0644); // regular user 191 copy_file_as_user(src, dest, getuid(), getgid(), 0644); // regular user
192 selinux_relabel_path(dest, src);
188 fs_logger2("clone", dest); 193 fs_logger2("clone", dest);
189 free(src); 194 free(src);
190 return 1; // file copied 195 return 1; // file copied
@@ -208,6 +213,7 @@ static void copy_xauthority(void) {
208 } 213 }
209 214
210 copy_file_as_user(src, dest, getuid(), getgid(), S_IRUSR | S_IWUSR); // regular user 215 copy_file_as_user(src, dest, getuid(), getgid(), S_IRUSR | S_IWUSR); // regular user
216 selinux_relabel_path(dest, src);
211 fs_logger2("clone", dest); 217 fs_logger2("clone", dest);
212 free(dest); 218 free(dest);
213 219
@@ -313,6 +319,7 @@ void fs_private_homedir(void) {
313 printf("Mounting a new /root directory\n"); 319 printf("Mounting a new /root directory\n");
314 if (mount("tmpfs", "/root", "tmpfs", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_STRICTATIME, "mode=700,gid=0") < 0) 320 if (mount("tmpfs", "/root", "tmpfs", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_STRICTATIME, "mode=700,gid=0") < 0)
315 errExit("mounting /root directory"); 321 errExit("mounting /root directory");
322 selinux_relabel_path("/root", "/root");
316 fs_logger("tmpfs /root"); 323 fs_logger("tmpfs /root");
317 } 324 }
318 if (u == 0 && !arg_allusers) { 325 if (u == 0 && !arg_allusers) {
@@ -321,6 +328,7 @@ void fs_private_homedir(void) {
321 printf("Mounting a new /home directory\n"); 328 printf("Mounting a new /home directory\n");
322 if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_STRICTATIME, "mode=755,gid=0") < 0) 329 if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_STRICTATIME, "mode=755,gid=0") < 0)
323 errExit("mounting /home directory"); 330 errExit("mounting /home directory");
331 selinux_relabel_path("/home", "/home");
324 fs_logger("tmpfs /home"); 332 fs_logger("tmpfs /home");
325 } 333 }
326 334
@@ -355,6 +363,7 @@ void fs_private(void) {
355 fwarning("allusers option disabled by private or whitelist option\n"); 363 fwarning("allusers option disabled by private or whitelist option\n");
356 if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_STRICTATIME, "mode=755,gid=0") < 0) 364 if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_STRICTATIME, "mode=755,gid=0") < 0)
357 errExit("mounting /home directory"); 365 errExit("mounting /home directory");
366 selinux_relabel_path("/home", "/home");
358 fs_logger("tmpfs /home"); 367 fs_logger("tmpfs /home");
359 } 368 }
360 369
@@ -378,6 +387,8 @@ void fs_private(void) {
378 } 387 }
379 if (chown(homedir, u, g) < 0) 388 if (chown(homedir, u, g) < 0)
380 errExit("chown"); 389 errExit("chown");
390 selinux_relabel_path(homedir, homedir);
391
381 fs_logger2("mkdir", homedir); 392 fs_logger2("mkdir", homedir);
382 fs_logger2("tmpfs", homedir); 393 fs_logger2("tmpfs", homedir);
383 } 394 }
@@ -542,6 +553,7 @@ void fs_private_home_list(void) {
542 553
543 // create /run/firejail/mnt/home directory 554 // create /run/firejail/mnt/home directory
544 mkdir_attr(RUN_HOME_DIR, 0755, uid, gid); 555 mkdir_attr(RUN_HOME_DIR, 0755, uid, gid);
556 selinux_relabel_path(RUN_HOME_DIR, "/home");
545 fs_logger_print(); // save the current log 557 fs_logger_print(); // save the current log
546 558
547 if (arg_debug) 559 if (arg_debug)
@@ -604,6 +616,7 @@ void fs_private_home_list(void) {
604 printf("Mounting a new /root directory\n"); 616 printf("Mounting a new /root directory\n");
605 if (mount("tmpfs", "/root", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME, "mode=700,gid=0") < 0) 617 if (mount("tmpfs", "/root", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME, "mode=700,gid=0") < 0)
606 errExit("mounting /root directory"); 618 errExit("mounting /root directory");
619 selinux_relabel_path("/root", "/root");
607 fs_logger("tmpfs /root"); 620 fs_logger("tmpfs /root");
608 } 621 }
609 if (uid == 0 && !arg_allusers) { 622 if (uid == 0 && !arg_allusers) {
@@ -612,6 +625,7 @@ void fs_private_home_list(void) {
612 printf("Mounting a new /home directory\n"); 625 printf("Mounting a new /home directory\n");
613 if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME, "mode=755,gid=0") < 0) 626 if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME, "mode=755,gid=0") < 0)
614 errExit("mounting /home directory"); 627 errExit("mounting /home directory");
628 selinux_relabel_path("/home", "/home");
615 fs_logger("tmpfs /home"); 629 fs_logger("tmpfs /home");
616 } 630 }
617 631
diff --git a/src/firejail/fs_hostname.c b/src/firejail/fs_hostname.c
index fd5e1bbd3..5d6fddf8e 100644
--- a/src/firejail/fs_hostname.c
+++ b/src/firejail/fs_hostname.c
@@ -96,6 +96,7 @@ void fs_resolvconf(void) {
96 printf("mirroring /etc directory\n"); 96 printf("mirroring /etc directory\n");
97 if (mkdir(RUN_DNS_ETC, 0755)) 97 if (mkdir(RUN_DNS_ETC, 0755))
98 errExit("mkdir"); 98 errExit("mkdir");
99 selinux_relabel_path(RUN_DNS_ETC, "/etc");
99 fs_logger("tmpfs /etc"); 100 fs_logger("tmpfs /etc");
100 101
101 DIR *dir = opendir("/etc"); 102 DIR *dir = opendir("/etc");
diff --git a/src/firejail/fs_lib.c b/src/firejail/fs_lib.c
index c539ce83c..64444bba2 100644
--- a/src/firejail/fs_lib.c
+++ b/src/firejail/fs_lib.c
@@ -326,6 +326,7 @@ void fs_private_lib(void) {
326 326
327 // create /run/firejail/mnt/lib directory 327 // create /run/firejail/mnt/lib directory
328 mkdir_attr(RUN_LIB_DIR, 0755, 0, 0); 328 mkdir_attr(RUN_LIB_DIR, 0755, 0, 0);
329 selinux_relabel_path(RUN_LIB_DIR, "/usr/lib");
329 330
330 // install standard C libraries 331 // install standard C libraries
331 if (arg_debug || arg_debug_private_lib) 332 if (arg_debug || arg_debug_private_lib)
diff --git a/src/firejail/fs_lib2.c b/src/firejail/fs_lib2.c
index 2982c4cbb..b2ae07f3e 100644
--- a/src/firejail/fs_lib2.c
+++ b/src/firejail/fs_lib2.c
@@ -109,6 +109,7 @@ void fslib_install_stdc(void) {
109 109
110 if (stat("/lib/x86_64-linux-gnu", &s) == 0) { // Debian & friends 110 if (stat("/lib/x86_64-linux-gnu", &s) == 0) { // Debian & friends
111 mkdir_attr(RUN_LIB_DIR "/x86_64-linux-gnu", 0755, 0, 0); 111 mkdir_attr(RUN_LIB_DIR "/x86_64-linux-gnu", 0755, 0, 0);
112 selinux_relabel_path(RUN_LIB_DIR "/x86_64-linux-gnu", "/lib/x86_64-linux-gnu");
112 stdclib = "/lib/x86_64-linux-gnu"; 113 stdclib = "/lib/x86_64-linux-gnu";
113 } 114 }
114 115
diff --git a/src/firejail/fs_var.c b/src/firejail/fs_var.c
index 303d6f9aa..cafe9fa49 100644
--- a/src/firejail/fs_var.c
+++ b/src/firejail/fs_var.c
@@ -223,9 +223,11 @@ void fs_var_cache(void) {
223 } 223 }
224 224
225 mkdir_attr("/var/cache/lighttpd/compress", 0755, uid, gid); 225 mkdir_attr("/var/cache/lighttpd/compress", 0755, uid, gid);
226 selinux_relabel_path("/var/cache/lighttpd/compress", "/var/cache/lighttpd/compress");
226 fs_logger("mkdir /var/cache/lighttpd/compress"); 227 fs_logger("mkdir /var/cache/lighttpd/compress");
227 228
228 mkdir_attr("/var/cache/lighttpd/uploads", 0755, uid, gid); 229 mkdir_attr("/var/cache/lighttpd/uploads", 0755, uid, gid);
230 selinux_relabel_path("/var/cache/lighttpd/uploads", "/var/cache/lighttpd/uploads");
229 fs_logger("/var/cache/lighttpd/uploads"); 231 fs_logger("/var/cache/lighttpd/uploads");
230 } 232 }
231} 233}
diff --git a/src/firejail/fs_whitelist.c b/src/firejail/fs_whitelist.c
index be5bcc4c0..c5b066b12 100644
--- a/src/firejail/fs_whitelist.c
+++ b/src/firejail/fs_whitelist.c
@@ -734,6 +734,7 @@ void fs_whitelist(void) {
734 printf("Mounting tmpfs on /tmp directory\n"); 734 printf("Mounting tmpfs on /tmp directory\n");
735 if (mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=1777,gid=0") < 0) 735 if (mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=1777,gid=0") < 0)
736 errExit("mounting tmpfs on /tmp"); 736 errExit("mounting tmpfs on /tmp");
737 selinux_relabel_path("/tmp", "/tmp");
737 fs_logger("tmpfs /tmp"); 738 fs_logger("tmpfs /tmp");
738 739
739 // pam-tmpdir - issue #2685 740 // pam-tmpdir - issue #2685
@@ -745,8 +746,10 @@ void fs_whitelist(void) {
745 if (strcmp(env, pamtmpdir) == 0) { 746 if (strcmp(env, pamtmpdir) == 0) {
746 // create empty user-owned /tmp/user/$uid directory 747 // create empty user-owned /tmp/user/$uid directory
747 mkdir_attr("/tmp/user", 0711, 0, 0); 748 mkdir_attr("/tmp/user", 0711, 0, 0);
749 selinux_relabel_path("/tmp/user", "/tmp/user");
748 fs_logger("mkdir /tmp/user"); 750 fs_logger("mkdir /tmp/user");
749 mkdir_attr(pamtmpdir, 0700, getuid(), 0); 751 mkdir_attr(pamtmpdir, 0700, getuid(), 0);
752 selinux_relabel_path(pamtmpdir, pamtmpdir);
750 fs_logger2("mkdir", pamtmpdir); 753 fs_logger2("mkdir", pamtmpdir);
751 } 754 }
752 free(pamtmpdir); 755 free(pamtmpdir);
@@ -774,6 +777,7 @@ void fs_whitelist(void) {
774 printf("Mounting tmpfs on /media directory\n"); 777 printf("Mounting tmpfs on /media directory\n");
775 if (mount("tmpfs", "/media", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=755,gid=0") < 0) 778 if (mount("tmpfs", "/media", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=755,gid=0") < 0)
776 errExit("mounting tmpfs on /media"); 779 errExit("mounting tmpfs on /media");
780 selinux_relabel_path("/media", "/media");
777 fs_logger("tmpfs /media"); 781 fs_logger("tmpfs /media");
778 782
779 // autowhitelist home directory if it is masked by the tmpfs 783 // autowhitelist home directory if it is masked by the tmpfs
@@ -798,6 +802,7 @@ void fs_whitelist(void) {
798 printf("Mounting tmpfs on /mnt directory\n"); 802 printf("Mounting tmpfs on /mnt directory\n");
799 if (mount("tmpfs", "/mnt", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=755,gid=0") < 0) 803 if (mount("tmpfs", "/mnt", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=755,gid=0") < 0)
800 errExit("mounting tmpfs on /mnt"); 804 errExit("mounting tmpfs on /mnt");
805 selinux_relabel_path("/mnt", "/mnt");
801 fs_logger("tmpfs /mnt"); 806 fs_logger("tmpfs /mnt");
802 807
803 // autowhitelist home directory if it is masked by the tmpfs 808 // autowhitelist home directory if it is masked by the tmpfs
@@ -822,6 +827,7 @@ void fs_whitelist(void) {
822 printf("Mounting tmpfs on /var directory\n"); 827 printf("Mounting tmpfs on /var directory\n");
823 if (mount("tmpfs", "/var", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=755,gid=0") < 0) 828 if (mount("tmpfs", "/var", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=755,gid=0") < 0)
824 errExit("mounting tmpfs on /var"); 829 errExit("mounting tmpfs on /var");
830 selinux_relabel_path("/var", "/var");
825 fs_logger("tmpfs /var"); 831 fs_logger("tmpfs /var");
826 832
827 // autowhitelist home directory if it is masked by the tmpfs 833 // autowhitelist home directory if it is masked by the tmpfs
@@ -846,6 +852,7 @@ void fs_whitelist(void) {
846 printf("Mounting tmpfs on /dev directory\n"); 852 printf("Mounting tmpfs on /dev directory\n");
847 if (mount("tmpfs", "/dev", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=755,gid=0") < 0) 853 if (mount("tmpfs", "/dev", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=755,gid=0") < 0)
848 errExit("mounting tmpfs on /dev"); 854 errExit("mounting tmpfs on /dev");
855 selinux_relabel_path("/dev", "/dev");
849 fs_logger("tmpfs /dev"); 856 fs_logger("tmpfs /dev");
850 857
851 // autowhitelist home directory if it is masked by the tmpfs 858 // autowhitelist home directory if it is masked by the tmpfs
@@ -870,6 +877,7 @@ void fs_whitelist(void) {
870 printf("Mounting tmpfs on /opt directory\n"); 877 printf("Mounting tmpfs on /opt directory\n");
871 if (mount("tmpfs", "/opt", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=755,gid=0") < 0) 878 if (mount("tmpfs", "/opt", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=755,gid=0") < 0)
872 errExit("mounting tmpfs on /opt"); 879 errExit("mounting tmpfs on /opt");
880 selinux_relabel_path("/opt", "/opt");
873 fs_logger("tmpfs /opt"); 881 fs_logger("tmpfs /opt");
874 882
875 // autowhitelist home directory if it is masked by the tmpfs 883 // autowhitelist home directory if it is masked by the tmpfs
@@ -894,6 +902,7 @@ void fs_whitelist(void) {
894 printf("Mounting tmpfs on /srv directory\n"); 902 printf("Mounting tmpfs on /srv directory\n");
895 if (mount("tmpfs", "/srv", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=755,gid=0") < 0) 903 if (mount("tmpfs", "/srv", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=755,gid=0") < 0)
896 errExit("mounting tmpfs on /srv"); 904 errExit("mounting tmpfs on /srv");
905 selinux_relabel_path("/srv", "/srv");
897 fs_logger("tmpfs /srv"); 906 fs_logger("tmpfs /srv");
898 907
899 // autowhitelist home directory if it is masked by the tmpfs 908 // autowhitelist home directory if it is masked by the tmpfs
@@ -918,6 +927,7 @@ void fs_whitelist(void) {
918 printf("Mounting tmpfs on /etc directory\n"); 927 printf("Mounting tmpfs on /etc directory\n");
919 if (mount("tmpfs", "/etc", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=755,gid=0") < 0) 928 if (mount("tmpfs", "/etc", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=755,gid=0") < 0)
920 errExit("mounting tmpfs on /etc"); 929 errExit("mounting tmpfs on /etc");
930 selinux_relabel_path("/etc", "/etc");
921 fs_logger("tmpfs /etc"); 931 fs_logger("tmpfs /etc");
922 932
923 // autowhitelist home directory if it is masked by the tmpfs 933 // autowhitelist home directory if it is masked by the tmpfs
@@ -942,6 +952,7 @@ void fs_whitelist(void) {
942 printf("Mounting tmpfs on /usr/share directory\n"); 952 printf("Mounting tmpfs on /usr/share directory\n");
943 if (mount("tmpfs", "/usr/share", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=755,gid=0") < 0) 953 if (mount("tmpfs", "/usr/share", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=755,gid=0") < 0)
944 errExit("mounting tmpfs on /usr/share"); 954 errExit("mounting tmpfs on /usr/share");
955 selinux_relabel_path("/usr/share", "/usr/share");
945 fs_logger("tmpfs /usr/share"); 956 fs_logger("tmpfs /usr/share");
946 957
947 // autowhitelist home directory if it is masked by the tmpfs 958 // autowhitelist home directory if it is masked by the tmpfs
@@ -966,6 +977,7 @@ void fs_whitelist(void) {
966 printf("Mounting tmpfs on /sys/module directory\n"); 977 printf("Mounting tmpfs on /sys/module directory\n");
967 if (mount("tmpfs", "/sys/module", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=755,gid=0") < 0) 978 if (mount("tmpfs", "/sys/module", "tmpfs", MS_NOSUID | MS_STRICTATIME, "mode=755,gid=0") < 0)
968 errExit("mounting tmpfs on /sys/module"); 979 errExit("mounting tmpfs on /sys/module");
980 selinux_relabel_path("/sys/module", "/sys/module");
969 fs_logger("tmpfs /sys/module"); 981 fs_logger("tmpfs /sys/module");
970 } 982 }
971 else 983 else
@@ -989,6 +1001,7 @@ void fs_whitelist(void) {
989 errExit("asprintf"); 1001 errExit("asprintf");
990 if (mount("tmpfs", runuser, "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME, options) < 0) 1002 if (mount("tmpfs", runuser, "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME, options) < 0)
991 errExit("mounting tmpfs on /run/user/<uid>"); 1003 errExit("mounting tmpfs on /run/user/<uid>");
1004 selinux_relabel_path(runuser, runuser);
992 free(options); 1005 free(options);
993 fs_logger2("tmpfs", runuser); 1006 fs_logger2("tmpfs", runuser);
994 1007
diff --git a/src/firejail/pulseaudio.c b/src/firejail/pulseaudio.c
index 57095a53c..a8fb838ab 100644
--- a/src/firejail/pulseaudio.c
+++ b/src/firejail/pulseaudio.c
@@ -87,6 +87,7 @@ void pulseaudio_init(void) {
87 // create the new user pulseaudio directory 87 // create the new user pulseaudio directory
88 if (mkdir(RUN_PULSE_DIR, 0700) == -1) 88 if (mkdir(RUN_PULSE_DIR, 0700) == -1)
89 errExit("mkdir"); 89 errExit("mkdir");
90 selinux_relabel_path(RUN_PULSE_DIR, RUN_PULSE_DIR);
90 // mount it nosuid, noexec, nodev 91 // mount it nosuid, noexec, nodev
91 fs_remount(RUN_PULSE_DIR, MOUNT_NOEXEC, 0); 92 fs_remount(RUN_PULSE_DIR, MOUNT_NOEXEC, 0);
92 93
diff --git a/src/firejail/restrict_users.c b/src/firejail/restrict_users.c
index b51172219..5ebb0e9ec 100644
--- a/src/firejail/restrict_users.c
+++ b/src/firejail/restrict_users.c
@@ -97,6 +97,7 @@ static void sanitize_home(void) {
97 // mount tmpfs in the new home 97 // mount tmpfs in the new home
98 if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME, "mode=755,gid=0") < 0) 98 if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME, "mode=755,gid=0") < 0)
99 errExit("mount tmpfs"); 99 errExit("mount tmpfs");
100 selinux_relabel_path("/home", "/home");
100 fs_logger("tmpfs /home"); 101 fs_logger("tmpfs /home");
101 102
102 // create user home directory 103 // create user home directory
@@ -105,6 +106,7 @@ static void sanitize_home(void) {
105 errExit("mkpath"); 106 errExit("mkpath");
106 if (mkdir(cfg.homedir, 0755) == -1) 107 if (mkdir(cfg.homedir, 0755) == -1)
107 errExit("mkdir"); 108 errExit("mkdir");
109 selinux_relabel_path(cfg.homedir, cfg.homedir);
108 } 110 }
109 fs_logger2("mkdir", cfg.homedir); 111 fs_logger2("mkdir", cfg.homedir);
110 112
@@ -152,11 +154,13 @@ static void sanitize_run(void) {
152 // mount tmpfs on /run/user 154 // mount tmpfs on /run/user
153 if (mount("tmpfs", "/run/user", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME, "mode=755,gid=0") < 0) 155 if (mount("tmpfs", "/run/user", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME, "mode=755,gid=0") < 0)
154 errExit("mount tmpfs"); 156 errExit("mount tmpfs");
157 selinux_relabel_path("/run/user", "/run/user");
155 fs_logger("tmpfs /run/user"); 158 fs_logger("tmpfs /run/user");
156 159
157 // create new user directory 160 // create new user directory
158 if (mkdir(runuser, 0700) == -1) 161 if (mkdir(runuser, 0700) == -1)
159 errExit("mkdir"); 162 errExit("mkdir");
163 selinux_relabel_path(runuser, runuser);
160 fs_logger2("mkdir", runuser); 164 fs_logger2("mkdir", runuser);
161 165
162 // set mode and ownership 166 // set mode and ownership
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c
index 4f53cafcc..d1d98f636 100644
--- a/src/firejail/sandbox.c
+++ b/src/firejail/sandbox.c
@@ -848,20 +848,6 @@ int sandbox(void* sandbox_arg) {
848 if (arg_private_dev) 848 if (arg_private_dev)
849 fs_private_dev(); 849 fs_private_dev();
850 850
851 if (arg_private_etc) {
852 if (cfg.chrootdir)
853 fwarning("private-etc feature is disabled in chroot\n");
854 else if (arg_overlay)
855 fwarning("private-etc feature is disabled in overlay\n");
856 else {
857 fs_private_dir_list("/etc", RUN_ETC_DIR, cfg.etc_private_keep);
858 fs_private_dir_list("/usr/etc", RUN_USR_ETC_DIR, cfg.etc_private_keep); // openSUSE
859 // create /etc/ld.so.preload file again
860 if (need_preload)
861 fs_trace_preload();
862 }
863 }
864
865 if (arg_private_opt) { 851 if (arg_private_opt) {
866 if (cfg.chrootdir) 852 if (cfg.chrootdir)
867 fwarning("private-opt feature is disabled in chroot\n"); 853 fwarning("private-opt feature is disabled in chroot\n");
@@ -964,6 +950,21 @@ int sandbox(void* sandbox_arg) {
964 else if (arg_disable_mnt) 950 else if (arg_disable_mnt)
965 fs_mnt(0); 951 fs_mnt(0);
966 952
953 // Install new /etc last, so we can use it as long as possible
954 if (arg_private_etc) {
955 if (cfg.chrootdir)
956 fwarning("private-etc feature is disabled in chroot\n");
957 else if (arg_overlay)
958 fwarning("private-etc feature is disabled in overlay\n");
959 else {
960 fs_private_dir_list("/etc", RUN_ETC_DIR, cfg.etc_private_keep);
961 fs_private_dir_list("/usr/etc", RUN_USR_ETC_DIR, cfg.etc_private_keep); // openSUSE
962 // create /etc/ld.so.preload file again
963 if (need_preload)
964 fs_trace_preload();
965 }
966 }
967
967 //**************************** 968 //****************************
968 // apply the profile file 969 // apply the profile file
969 //**************************** 970 //****************************
diff --git a/src/firejail/selinux.c b/src/firejail/selinux.c
new file mode 100644
index 000000000..52d6788ef
--- /dev/null
+++ b/src/firejail/selinux.c
@@ -0,0 +1,73 @@
1/*
2 * Copyright (C) 2020 Firejail and systemd authors
3 *
4 * This file is part of firejail project, from systemd selinux-util.c
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#if HAVE_SELINUX
21#include "firejail.h"
22
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <fcntl.h>
26
27#include <selinux/context.h>
28#include <selinux/label.h>
29#include <selinux/selinux.h>
30
31static struct selabel_handle *label_hnd = NULL;
32static int selinux_enabled = -1;
33#endif
34
35void selinux_relabel_path(const char *path, const char *inside_path)
36{
37#if HAVE_SELINUX
38 char procfs_path[64];
39 char *fcon = NULL;
40 int fd;
41 struct stat st;
42
43 if (selinux_enabled == -1)
44 selinux_enabled = is_selinux_enabled();
45
46 if (!selinux_enabled && arg_debug)
47 return;
48
49 if (!label_hnd)
50 label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
51
52 /* Open the file as O_PATH, to pin it while we determine and adjust the label */
53 fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
54 if (fd < 0)
55 return;
56 if (fstat(fd, &st) < 0)
57 goto close;
58
59 if (selabel_lookup_raw(label_hnd, &fcon, inside_path, st.st_mode) == 0) {
60 sprintf(procfs_path, "/proc/self/fd/%i", fd);
61 if (arg_debug)
62 printf("Relabeling %s as %s (%s)\n", path, inside_path, fcon);
63
64 setfilecon_raw(procfs_path, fcon);
65 }
66 freecon(fcon);
67 close:
68 close(fd);
69#else
70 (void) path;
71 (void) inside_path;
72#endif
73}