diff options
author | 2019-11-12 15:11:17 +0100 | |
---|---|---|
committer | 2019-11-12 15:11:17 +0100 | |
commit | b6e77213ebbb04e322ab860cd7a141e0d544cc7e (patch) | |
tree | e32ae0b8ed6c5ca6f277f9e58bbb9f99dd1ff3ad /src/firejail/fs_home.c | |
parent | private-cache warning messages - #2968 (diff) | |
download | firejail-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.c | 63 |
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 | } |