aboutsummaryrefslogtreecommitdiffstats
path: root/src/firejail/fs_home.c
diff options
context:
space:
mode:
authorLibravatar smitsohu <smitsohu@gmail.com>2019-11-12 15:11:17 +0100
committerLibravatar smitsohu <smitsohu@gmail.com>2019-11-12 15:11:17 +0100
commitb6e77213ebbb04e322ab860cd7a141e0d544cc7e (patch)
treee32ae0b8ed6c5ca6f277f9e58bbb9f99dd1ff3ad /src/firejail/fs_home.c
parentprivate-cache warning messages - #2968 (diff)
downloadfirejail-b6e77213ebbb04e322ab860cd7a141e0d544cc7e.tar.gz
firejail-b6e77213ebbb04e322ab860cd7a141e0d544cc7e.tar.zst
firejail-b6e77213ebbb04e322ab860cd7a141e0d544cc7e.zip
private-options: add homedir ownership check
Diffstat (limited to 'src/firejail/fs_home.c')
-rw-r--r--src/firejail/fs_home.c63
1 files changed, 46 insertions, 17 deletions
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}