aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--etc/disable-common.inc3
-rw-r--r--etc/firejail-default3
-rw-r--r--src/firejail/fs.c6
-rw-r--r--src/firejail/fs_home.c63
-rw-r--r--src/firejail/main.c2
5 files changed, 56 insertions, 21 deletions
diff --git a/etc/disable-common.inc b/etc/disable-common.inc
index 96957eeaf..b2837b443 100644
--- a/etc/disable-common.inc
+++ b/etc/disable-common.inc
@@ -315,6 +315,7 @@ blacklist ${HOME}/.config/keybase
315blacklist ${HOME}/.davfs2/secrets 315blacklist ${HOME}/.davfs2/secrets
316blacklist ${HOME}/.ecryptfs 316blacklist ${HOME}/.ecryptfs
317blacklist ${HOME}/.fetchmailrc 317blacklist ${HOME}/.fetchmailrc
318blacklist ${HOME}/.fscrypt
318blacklist ${HOME}/.git-credential-cache 319blacklist ${HOME}/.git-credential-cache
319blacklist ${HOME}/.git-credentials 320blacklist ${HOME}/.git-credentials
320blacklist ${HOME}/.gnome2/keyrings 321blacklist ${HOME}/.gnome2/keyrings
@@ -335,6 +336,7 @@ blacklist ${HOME}/.local/share/pki
335blacklist ${HOME}/.smbcredentials 336blacklist ${HOME}/.smbcredentials
336blacklist ${HOME}/.ssh 337blacklist ${HOME}/.ssh
337blacklist ${HOME}/.vaults 338blacklist ${HOME}/.vaults
339blacklist /.fscrypt
338blacklist /etc/davfs2/secrets 340blacklist /etc/davfs2/secrets
339blacklist /etc/group+ 341blacklist /etc/group+
340blacklist /etc/group- 342blacklist /etc/group-
@@ -348,6 +350,7 @@ blacklist /etc/shadow+
348blacklist /etc/shadow- 350blacklist /etc/shadow-
349blacklist /etc/ssh 351blacklist /etc/ssh
350blacklist /home/.ecryptfs 352blacklist /home/.ecryptfs
353blacklist /home/.fscrypt
351blacklist /var/backup 354blacklist /var/backup
352 355
353# cloud provider configuration 356# cloud provider configuration
diff --git a/etc/firejail-default b/etc/firejail-default
index e7831e145..56fce654c 100644
--- a/etc/firejail-default
+++ b/etc/firejail-default
@@ -97,6 +97,9 @@ deny /proc/@{PID}/oom_score_adj w,
97# Common backup directory 97# Common backup directory
98deny /**/.snapshots/ rwx, 98deny /**/.snapshots/ rwx,
99 99
100# fscrypt
101deny /**/.fscrypt/ rwx,
102
100########## 103##########
101# Allow all networking functionality, and control it from Firejail. 104# Allow all networking functionality, and control it from Firejail.
102########## 105##########
diff --git a/src/firejail/fs.c b/src/firejail/fs.c
index 3df551d4c..3e802efb5 100644
--- a/src/firejail/fs.c
+++ b/src/firejail/fs.c
@@ -1191,15 +1191,15 @@ void fs_private_cache(void) {
1191 // check if ~/.cache is a valid destination 1191 // check if ~/.cache is a valid destination
1192 struct stat s; 1192 struct stat s;
1193 if (lstat(cache, &s) == -1) { 1193 if (lstat(cache, &s) == -1) {
1194 fwarning("cannot find %s, tmpfs not mounted\n", cache); 1194 fwarning("skipping private-cache: cannot find %s\n", cache);
1195 free(cache); 1195 free(cache);
1196 return; 1196 return;
1197 } 1197 }
1198 if (!S_ISDIR(s.st_mode)) { 1198 if (!S_ISDIR(s.st_mode)) {
1199 if (S_ISLNK(s.st_mode)) 1199 if (S_ISLNK(s.st_mode))
1200 fwarning("%s is a symbolic link, tmpfs not mounted\n", cache); 1200 fwarning("skipping private-cache: %s is a symbolic link\n", cache);
1201 else 1201 else
1202 fwarning("%s is not a directory; cannot mount a tmpfs on top of it\n", cache); 1202 fwarning("skipping private-cache: %s is not a directory\n", cache);
1203 free(cache); 1203 free(cache);
1204 return; 1204 return;
1205 } 1205 }
diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c
index 25c167af1..2e8a8ad96 100644
--- a/src/firejail/fs_home.c
+++ b/src/firejail/fs_home.c
@@ -250,6 +250,9 @@ void fs_private_homedir(void) {
250 int xflag = store_xauthority(); 250 int xflag = store_xauthority();
251 int aflag = store_asoundrc(); 251 int aflag = store_asoundrc();
252 252
253 // home directory outside /home?
254 int oflag = (strncmp(homedir, "/home/", 6) != 0);
255
253 uid_t u = getuid(); 256 uid_t u = getuid();
254 gid_t g = getgid(); 257 gid_t g = getgid();
255 258
@@ -259,20 +262,33 @@ void fs_private_homedir(void) {
259 // get file descriptors for homedir and private_homedir, fails if there is any symlink 262 // get file descriptors for homedir and private_homedir, fails if there is any symlink
260 int src = safe_fd(private_homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); 263 int src = safe_fd(private_homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
261 if (src == -1) 264 if (src == -1)
262 errExit("safe_fd"); 265 errExit("opening private directory");
263 int dst = safe_fd(homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); 266 int dst = safe_fd(homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
264 if (dst == -1) 267 if (dst == -1)
265 errExit("safe_fd"); 268 errExit("opening home directory");
266 // check if new home directory is owned by the user 269 if (u != 0) {
267 struct stat s; 270 struct stat s;
268 if (fstat(src, &s) == -1) 271 // sometimes system users are assigned home directories like /, /proc, ...
269 errExit("fstat"); 272 // require that a home directory outside /home is owned by the user
270 if (s.st_uid != getuid()) { 273 if (oflag) {
271 fprintf(stderr, "Error: private directory is not owned by the current user\n"); 274 if (fstat(dst, &s) == -1)
272 exit(1); 275 errExit("fstat");
276 if (s.st_uid != u) {
277 fprintf(stderr, "Error: cannot mount private directory:\n"
278 "Home directory is not owned by the current user\n");
279 exit(1);
280 }
281 }
282 // check if new home directory is owned by the user
283 if (fstat(src, &s) == -1)
284 errExit("fstat");
285 if (s.st_uid != u) {
286 fprintf(stderr, "Error: private directory is not owned by the current user\n");
287 exit(1);
288 }
289 if ((S_IRWXU & s.st_mode) != S_IRWXU)
290 fwarning("no full permissions on private directory\n");
273 } 291 }
274 if ((S_IRWXU & s.st_mode) != S_IRWXU)
275 fwarning("no full permissions on private directory\n");
276 // mount via the links in /proc/self/fd 292 // mount via the links in /proc/self/fd
277 char *proc_src, *proc_dst; 293 char *proc_src, *proc_dst;
278 if (asprintf(&proc_src, "/proc/self/fd/%d", src) == -1) 294 if (asprintf(&proc_src, "/proc/self/fd/%d", src) == -1)
@@ -308,7 +324,7 @@ void fs_private_homedir(void) {
308 errExit("mounting home directory"); 324 errExit("mounting home directory");
309 fs_logger("tmpfs /root"); 325 fs_logger("tmpfs /root");
310 } 326 }
311 if (u == 0 || strncmp(homedir, "/home/", 6) != 0) { 327 if (oflag) {
312 // mask /home 328 // mask /home
313 if (arg_debug) 329 if (arg_debug)
314 printf("Mounting a new /home directory\n"); 330 printf("Mounting a new /home directory\n");
@@ -317,7 +333,6 @@ void fs_private_homedir(void) {
317 fs_logger("tmpfs /home"); 333 fs_logger("tmpfs /home");
318 } 334 }
319 335
320
321 skel(homedir, u, g); 336 skel(homedir, u, g);
322 if (xflag) 337 if (xflag)
323 copy_xauthority(); 338 copy_xauthority();
@@ -377,6 +392,7 @@ void fs_private(void) {
377 } 392 }
378 else 393 else
379 // user directory is outside /home, mask it as well 394 // user directory is outside /home, mask it as well
395 // check if directory is owned by the current user
380 fs_tmpfs(homedir, 1); 396 fs_tmpfs(homedir, 1);
381 } 397 }
382 398
@@ -385,7 +401,6 @@ void fs_private(void) {
385 copy_xauthority(); 401 copy_xauthority();
386 if (aflag) 402 if (aflag)
387 copy_asoundrc(); 403 copy_asoundrc();
388
389} 404}
390 405
391// check new private home directory (--private= option) - exit if it fails 406// check new private home directory (--private= option) - exit if it fails
@@ -531,6 +546,9 @@ void fs_private_home_list(void) {
531 int xflag = store_xauthority(); 546 int xflag = store_xauthority();
532 int aflag = store_asoundrc(); 547 int aflag = store_asoundrc();
533 548
549 // home directory outside /home?
550 int oflag = (strncmp(homedir, "/home/", 6) != 0);
551
534 uid_t uid = getuid(); 552 uid_t uid = getuid();
535 gid_t gid = getgid(); 553 gid_t gid = getgid();
536 554
@@ -563,7 +581,19 @@ void fs_private_home_list(void) {
563 581
564 int fd = safe_fd(homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); 582 int fd = safe_fd(homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
565 if (fd == -1) 583 if (fd == -1)
566 errExit("safe_fd"); 584 errExit("opening home directory");
585 if (uid != 0 && oflag) {
586 // home directory outside /home should be owned by the user
587 struct stat s;
588 if (fstat(fd, &s) == -1)
589 errExit("fstat");
590 if (s.st_uid != uid) {
591 fprintf(stderr, "Error: cannot mount private directory:\n"
592 "Home directory is not owned by the current user\n");
593 exit(1);
594 }
595 }
596 // mount using the file descriptor
567 char *proc; 597 char *proc;
568 if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1) 598 if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1)
569 errExit("asprintf"); 599 errExit("asprintf");
@@ -584,7 +614,7 @@ void fs_private_home_list(void) {
584 if (mount("tmpfs", "/root", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME, "mode=700,gid=0") < 0) 614 if (mount("tmpfs", "/root", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME, "mode=700,gid=0") < 0)
585 errExit("mounting home directory"); 615 errExit("mounting home directory");
586 } 616 }
587 if (uid == 0 || strncmp(homedir, "/home/", 6) != 0) { 617 if (oflag) {
588 // mask /home 618 // mask /home
589 if (arg_debug) 619 if (arg_debug)
590 printf("Mounting a new /home directory\n"); 620 printf("Mounting a new /home directory\n");
@@ -600,5 +630,4 @@ void fs_private_home_list(void) {
600 630
601 if (!arg_quiet) 631 if (!arg_quiet)
602 fprintf(stderr, "Home directory installed in %0.2f ms\n", timetrace_end()); 632 fprintf(stderr, "Home directory installed in %0.2f ms\n", timetrace_end());
603
604} 633}
diff --git a/src/firejail/main.c b/src/firejail/main.c
index 5b39dd491..1786cfac2 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -262,7 +262,7 @@ static int has_link(const char *dir) {
262 262
263static void check_homedir(void) { 263static void check_homedir(void) {
264 assert(cfg.homedir); 264 assert(cfg.homedir);
265 if (cfg.homedir[0] != '/' || cfg.homedir[1] == '\0') { // system users sometimes have root directory as home 265 if (cfg.homedir[0] != '/') {
266 fprintf(stderr, "Error: invalid user directory \"%s\"\n", cfg.homedir); 266 fprintf(stderr, "Error: invalid user directory \"%s\"\n", cfg.homedir);
267 exit(1); 267 exit(1);
268 } 268 }