aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/firecfg/firecfg.config18
-rw-r--r--src/firejail/firejail.h19
-rw-r--r--src/firejail/fs.c224
-rw-r--r--src/firejail/pulseaudio.c6
-rw-r--r--src/firejail/sandbox.c2
-rw-r--r--src/firejail/x11.c6
-rw-r--r--src/firemon/firemon.c4
-rw-r--r--src/man/firejail-profile.txt3
-rw-r--r--src/man/firejail.txt4
9 files changed, 109 insertions, 177 deletions
diff --git a/src/firecfg/firecfg.config b/src/firecfg/firecfg.config
index 48789359d..b4efa3add 100644
--- a/src/firecfg/firecfg.config
+++ b/src/firecfg/firecfg.config
@@ -25,8 +25,8 @@ QOwnNotes
25Telegram 25Telegram
26Viber 26Viber
27VirtualBox 27VirtualBox
28Xephyr
29XMind 28XMind
29Xephyr
30abrowser 30abrowser
31akonadi_control 31akonadi_control
32akregator 32akregator
@@ -186,8 +186,8 @@ firefox-developer-edition
186firefox-esr 186firefox-esr
187firefox-nightly 187firefox-nightly
188firefox-wayland 188firefox-wayland
189flameshot
190flacsplt 189flacsplt
190flameshot
191flashpeak-slimjet 191flashpeak-slimjet
192flowblade 192flowblade
193font-manager 193font-manager
@@ -248,6 +248,7 @@ gnome-schedule
248gnome-system-log 248gnome-system-log
249gnome-twitch 249gnome-twitch
250gnome-weather 250gnome-weather
251godot
251goobox 252goobox
252google-chrome 253google-chrome
253google-chrome-beta 254google-chrome-beta
@@ -300,11 +301,15 @@ keepass2
300keepassx 301keepassx
301keepassx2 302keepassx2
302keepassxc 303keepassxc
304keepassxc-cli
305keepassxc-proxy
303kget 306kget
304kid3 307kid3
305kid3-cli 308kid3-cli
306kid3-qt 309kid3-qt
307kino 310kino
311klatexformula
312klatexformula_cmdl
308klavaro 313klavaro
309kmail 314kmail
310knotes 315knotes
@@ -322,6 +327,7 @@ less
322libreoffice 327libreoffice
323liferea 328liferea
324lincity-ng 329lincity-ng
330links
325linphone 331linphone
326lmms 332lmms
327lobase 333lobase
@@ -396,6 +402,7 @@ netactview
396nethack 402nethack
397netsurf 403netsurf
398neverball 404neverball
405newsbeuter
399newsboat 406newsboat
400nheko 407nheko
401nitroshare 408nitroshare
@@ -413,6 +420,7 @@ oggsplt
413okular 420okular
414onionshare-gui 421onionshare-gui
415open-invaders 422open-invaders
423openarena
416opencity 424opencity
417openshot 425openshot
418openshot-qt 426openshot-qt
@@ -422,6 +430,7 @@ opera-beta
422orage 430orage
423ostrichriders 431ostrichriders
424palemoon 432palemoon
433pandoc
425parole 434parole
426patch 435patch
427pavucontrol 436pavucontrol
@@ -466,6 +475,7 @@ redshift
466regextester 475regextester
467remmina 476remmina
468rhythmbox 477rhythmbox
478rhythmbox-client
469ricochet 479ricochet
470riot-desktop 480riot-desktop
471riot-web 481riot-web
@@ -521,6 +531,7 @@ sylpheed
521synfigstudio 531synfigstudio
522sysprof 532sysprof
523sysprof-cli 533sysprof-cli
534teams-for-linux
524teamspeak3 535teamspeak3
525teeworlds 536teeworlds
526telegram 537telegram
@@ -578,7 +589,9 @@ transmission-remote-gtk
578transmission-show 589transmission-show
579tremulous 590tremulous
580truecraft 591truecraft
592tshark
581tuxguitar 593tuxguitar
594udiskie
582uefitool 595uefitool
583uget-gtk 596uget-gtk
584unbound 597unbound
@@ -622,6 +635,7 @@ xfce4-dict
622xfce4-mixer 635xfce4-mixer
623xfce4-notes 636xfce4-notes
624xiphos 637xiphos
638xlinks
625xmms 639xmms
626xmr-stak 640xmr-stak
627xonotic 641xonotic
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index fd6cb9ff2..630adc3d7 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -364,16 +364,23 @@ void preproc_mount_mnt_dir(void);
364void preproc_clean_run(void); 364void preproc_clean_run(void);
365 365
366// fs.c 366// fs.c
367typedef enum {
368 BLACKLIST_FILE,
369 BLACKLIST_NOLOG,
370 MOUNT_READONLY,
371 MOUNT_TMPFS,
372 MOUNT_NOEXEC,
373 MOUNT_RDWR,
374 OPERATION_MAX
375} OPERATION;
376
367// blacklist files or directories by mounting empty files on top of them 377// blacklist files or directories by mounting empty files on top of them
368void fs_blacklist(void); 378void fs_blacklist(void);
369// mount a writable tmpfs 379// mount a writable tmpfs
370void fs_tmpfs(const char *dir, unsigned check_owner); 380void fs_tmpfs(const char *dir, unsigned check_owner);
371// remount a directory read-only 381// remount noexec/nodev/nosuid or read-only or read-write
372void fs_rdonly(const char *dir); 382void fs_remount(const char *dir, OPERATION op, unsigned check_mnt);
373void fs_rdonly_rec(const char *dir); 383void fs_remount_rec(const char *dir, OPERATION op, unsigned check_mnt);
374// remount a directory noexec, nodev and nosuid
375void fs_noexec(const char *dir);
376void fs_noexec_rec(const char *dir);
377// mount /proc and /sys directories 384// mount /proc and /sys directories
378void fs_proc_sys_dev_boot(void); 385void fs_proc_sys_dev_boot(void);
379// build a basic read-only filesystem 386// build a basic read-only filesystem
diff --git a/src/firejail/fs.c b/src/firejail/fs.c
index 411f2e778..14d7d7156 100644
--- a/src/firejail/fs.c
+++ b/src/firejail/fs.c
@@ -39,24 +39,17 @@
39//#define TEST_NO_BLACKLIST_MATCHING 39//#define TEST_NO_BLACKLIST_MATCHING
40 40
41 41
42static int mount_warning = 0;
43static void fs_rdwr(const char *dir);
44static void fs_rdwr_rec(const char *dir);
45
46
47
48//*********************************************** 42//***********************************************
49// process profile file 43// process profile file
50//*********************************************** 44//***********************************************
51typedef enum { 45static char *opstr[] = {
52 BLACKLIST_FILE, 46 [BLACKLIST_FILE] = "blacklist",
53 BLACKLIST_NOLOG, 47 [BLACKLIST_NOLOG] = "blacklist-nolog",
54 MOUNT_READONLY, 48 [MOUNT_READONLY] = "read-only",
55 MOUNT_TMPFS, 49 [MOUNT_TMPFS] = "tmpfs",
56 MOUNT_NOEXEC, 50 [MOUNT_NOEXEC] = "noexec",
57 MOUNT_RDWR, 51 [MOUNT_RDWR] = "read-write",
58 OPERATION_MAX 52};
59} OPERATION;
60 53
61typedef enum { 54typedef enum {
62 UNSUCCESSFUL, 55 UNSUCCESSFUL,
@@ -153,17 +146,9 @@ static void disable_file(OPERATION op, const char *filename) {
153 fs_logger2("blacklist-nolog", fname); 146 fs_logger2("blacklist-nolog", fname);
154 } 147 }
155 } 148 }
156 else if (op == MOUNT_READONLY) { 149 else if (op == MOUNT_READONLY || op == MOUNT_RDWR || op == MOUNT_NOEXEC) {
157 fs_rdonly_rec(fname); 150 fs_remount_rec(fname, op, 1);
158// todo: last_disable = SUCCESSFUL; 151 // todo: last_disable = SUCCESSFUL;
159 }
160 else if (op == MOUNT_RDWR) {
161 fs_rdwr_rec(fname);
162// todo: last_disable = SUCCESSFUL;
163 }
164 else if (op == MOUNT_NOEXEC) {
165 fs_noexec_rec(fname);
166// todo: last_disable = SUCCESSFUL;
167 } 152 }
168 else if (op == MOUNT_TMPFS) { 153 else if (op == MOUNT_TMPFS) {
169 if (S_ISDIR(s.st_mode)) { 154 if (S_ISDIR(s.st_mode)) {
@@ -493,145 +478,60 @@ void fs_tmpfs(const char *dir, unsigned check_owner) {
493 close(fd); 478 close(fd);
494} 479}
495 480
496// remount directory read-only 481void fs_remount(const char *dir, OPERATION op, unsigned check_mnt) {
497void fs_rdonly(const char *dir) {
498 assert(dir); 482 assert(dir);
499 // check directory exists 483 // check directory exists
500 struct stat s; 484 struct stat s;
501 int rv = stat(dir, &s); 485 int rv = stat(dir, &s);
502 if (rv == 0) { 486 if (rv == 0) {
503 unsigned long flags = 0; 487 unsigned long flags = 0;
504 get_mount_flags(dir, &flags); 488 if (get_mount_flags(dir, &flags) != 0) {
505 if ((flags & MS_RDONLY) == MS_RDONLY) 489 fwarning("cannot remount %s\n", dir);
506 return; 490 return;
507 flags |= MS_RDONLY;
508 if (arg_debug)
509 printf("Mounting read-only %s\n", dir);
510 // mount --bind /bin /bin
511 // mount --bind -o remount,ro /bin
512 if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 ||
513 mount(NULL, dir, NULL, flags|MS_BIND|MS_REMOUNT, NULL) < 0)
514 errExit("mount read-only");
515 fs_logger2("read-only", dir);
516 }
517}
518
519// remount directory read-only recursively
520void fs_rdonly_rec(const char *dir) {
521 assert(dir);
522 // get mount point of the directory
523 int mountid = get_mount_id(dir);
524 if (mountid == -1)
525 return;
526 if (mountid == -2) {
527 // falling back to a simple remount on old kernels
528 if (!mount_warning) {
529 fwarning("read-only, read-write and noexec options are not applied recursively\n");
530 mount_warning = 1;
531 } 491 }
532 fs_rdonly(dir); 492 if (op == MOUNT_RDWR) {
533 return; 493 // allow only user owned directories, except the user is root
534 } 494 if (getuid() != 0 && s.st_uid != getuid()) {
535 // build array with all mount points that need to get remounted 495 fwarning("you are not allowed to change %s to read-write\n", dir);
536 char **arr = build_mount_array(mountid, dir); 496 return;
537 assert(arr); 497 }
538 // remount 498 if ((flags & MS_RDONLY) == 0)
539 char **tmp = arr; 499 return;
540 while (*tmp) { 500 flags &= ~MS_RDONLY;
541 fs_rdonly(*tmp);
542 free(*tmp++);
543 }
544 free(arr);
545}
546
547// remount directory read-write
548static void fs_rdwr(const char *dir) {
549 assert(dir);
550 // check directory exists
551 struct stat s;
552 int rv = stat(dir, &s);
553 if (rv == 0) {
554 // allow only user owned directories, except the user is root
555 uid_t u = getuid();
556 if (u != 0 && s.st_uid != u) {
557 fwarning("you are not allowed to change %s to read-write\n", dir);
558 return;
559 } 501 }
560 unsigned long flags = 0; 502 else if (op == MOUNT_NOEXEC) {
561 get_mount_flags(dir, &flags); 503 if ((flags & (MS_NOEXEC|MS_NODEV|MS_NOSUID)) == (MS_NOEXEC|MS_NODEV|MS_NOSUID))
562 if ((flags & MS_RDONLY) == 0) 504 return;
563 return; 505 flags |= MS_NOEXEC|MS_NODEV|MS_NOSUID;
564 flags &= ~MS_RDONLY;
565 if (arg_debug)
566 printf("Mounting read-write %s\n", dir);
567 // mount --bind /bin /bin
568 // mount --bind -o remount,rw /bin
569 if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 ||
570 mount(NULL, dir, NULL, flags|MS_BIND|MS_REMOUNT, NULL) < 0)
571 errExit("mount read-write");
572 fs_logger2("read-write", dir);
573 // run a sanity check on /proc/self/mountinfo
574 MountData *mptr = get_last_mount();
575 size_t len = strlen(dir);
576 if (strncmp(mptr->dir, dir, len) != 0 ||
577 (*(mptr->dir + len) != '\0' && *(mptr->dir + len) != '/'))
578 errLogExit("invalid read-write mount");
579 }
580}
581
582// remount directory read-write recursively
583static void fs_rdwr_rec(const char *dir) {
584 assert(dir);
585 // get mount point of the directory
586 int mountid = get_mount_id(dir);
587 if (mountid == -1)
588 return;
589 if (mountid == -2) {
590 // falling back to a simple remount on old kernels
591 if (!mount_warning) {
592 fwarning("read-only, read-write and noexec options are not applied recursively\n");
593 mount_warning = 1;
594 } 506 }
595 fs_rdwr(dir); 507 else if (op == MOUNT_READONLY) {
596 return; 508 if ((flags & MS_RDONLY) == MS_RDONLY)
597 } 509 return;
598 // build array with all mount points that need to get remounted 510 flags |= MS_RDONLY;
599 char **arr = build_mount_array(mountid, dir); 511 }
600 assert(arr); 512 else
601 // remount 513 assert(0);
602 char **tmp = arr;
603 while (*tmp) {
604 fs_rdwr(*tmp);
605 free(*tmp++);
606 }
607 free(arr);
608}
609 514
610// remount directory noexec, nodev, nosuid
611void fs_noexec(const char *dir) {
612 assert(dir);
613 // check directory exists
614 struct stat s;
615 int rv = stat(dir, &s);
616 if (rv == 0) {
617 unsigned long flags = 0;
618 get_mount_flags(dir, &flags);
619 if ((flags & (MS_NOEXEC|MS_NODEV|MS_NOSUID)) == (MS_NOEXEC|MS_NODEV|MS_NOSUID))
620 return;
621 flags |= MS_NOEXEC|MS_NODEV|MS_NOSUID;
622 if (arg_debug) 515 if (arg_debug)
623 printf("Mounting noexec %s\n", dir); 516 printf("Mounting %s %s\n", opstr[op], dir);
624 // mount --bind /bin /bin 517 // mount --bind /bin /bin
625 // mount --bind -o remount,noexec /bin 518 // mount --bind -o remount,rw /bin
626 if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 || 519 if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 ||
627 mount(NULL, dir, NULL, flags|MS_BIND|MS_REMOUNT, NULL) < 0) 520 mount(NULL, dir, NULL, flags|MS_BIND|MS_REMOUNT, NULL) < 0)
628 errExit("mount noexec"); 521 errExit("remounting");
629 fs_logger2("noexec", dir); 522 if (check_mnt) {
523 // run a sanity check on /proc/self/mountinfo
524 MountData *mptr = get_last_mount();
525 size_t len = strlen(dir);
526 if (strncmp(mptr->dir, dir, len) != 0 ||
527 (*(mptr->dir + len) != '\0' && *(mptr->dir + len) != '/'))
528 errLogExit("invalid %s mount", opstr[op]);
529 }
530 fs_logger2(opstr[op], dir);
630 } 531 }
631} 532}
632 533
633// remount directory noexec, nodev, nosuid recursively 534void fs_remount_rec(const char *dir, OPERATION op, unsigned check_mnt) {
634void fs_noexec_rec(const char *dir) {
635 assert(dir); 535 assert(dir);
636 // get mount point of the directory 536 // get mount point of the directory
637 int mountid = get_mount_id(dir); 537 int mountid = get_mount_id(dir);
@@ -639,11 +539,12 @@ void fs_noexec_rec(const char *dir) {
639 return; 539 return;
640 if (mountid == -2) { 540 if (mountid == -2) {
641 // falling back to a simple remount on old kernels 541 // falling back to a simple remount on old kernels
542 static int mount_warning = 0;
642 if (!mount_warning) { 543 if (!mount_warning) {
643 fwarning("read-only, read-write and noexec options are not applied recursively\n"); 544 fwarning("read-only, read-write and noexec options are not applied recursively\n");
644 mount_warning = 1; 545 mount_warning = 1;
645 } 546 }
646 fs_noexec(dir); 547 fs_remount(dir, op, check_mnt);
647 return; 548 return;
648 } 549 }
649 // build array with all mount points that need to get remounted 550 // build array with all mount points that need to get remounted
@@ -652,7 +553,7 @@ void fs_noexec_rec(const char *dir) {
652 // remount 553 // remount
653 char **tmp = arr; 554 char **tmp = arr;
654 while (*tmp) { 555 while (*tmp) {
655 fs_noexec(*tmp); 556 fs_remount(*tmp, op, check_mnt);
656 free(*tmp++); 557 free(*tmp++);
657 } 558 }
658 free(arr); 559 free(arr);
@@ -818,28 +719,29 @@ static void disable_config(void) {
818 719
819 720
820// build a basic read-only filesystem 721// build a basic read-only filesystem
722// top level directories could be links, run no after-mount checks
821void fs_basic_fs(void) { 723void fs_basic_fs(void) {
822 uid_t uid = getuid(); 724 uid_t uid = getuid();
823 725
824 if (arg_debug) 726 if (arg_debug)
825 printf("Basic read-only filesystem:\n"); 727 printf("Basic read-only filesystem:\n");
826 if (!arg_writable_etc) { 728 if (!arg_writable_etc) {
827 fs_rdonly("/etc"); 729 fs_remount("/etc", MOUNT_READONLY, 0);
828 if (uid) 730 if (uid)
829 fs_noexec("/etc"); 731 fs_remount("/etc", MOUNT_NOEXEC, 0);
830 } 732 }
831 if (!arg_writable_var) { 733 if (!arg_writable_var) {
832 fs_rdonly("/var"); 734 fs_remount("/var", MOUNT_READONLY, 0);
833 if (uid) 735 if (uid)
834 fs_noexec("/var"); 736 fs_remount("/var", MOUNT_NOEXEC, 0);
835 } 737 }
836 fs_rdonly("/bin"); 738 fs_remount("/bin", MOUNT_READONLY, 0);
837 fs_rdonly("/sbin"); 739 fs_remount("/sbin", MOUNT_READONLY, 0);
838 fs_rdonly("/lib"); 740 fs_remount("/lib", MOUNT_READONLY, 0);
839 fs_rdonly("/lib64"); 741 fs_remount("/lib64", MOUNT_READONLY, 0);
840 fs_rdonly("/lib32"); 742 fs_remount("/lib32", MOUNT_READONLY, 0);
841 fs_rdonly("/libx32"); 743 fs_remount("/libx32", MOUNT_READONLY, 0);
842 fs_rdonly("/usr"); 744 fs_remount("/usr", MOUNT_READONLY, 0);
843 745
844 // update /var directory in order to support multiple sandboxes running on the same root directory 746 // update /var directory in order to support multiple sandboxes running on the same root directory
845 fs_var_lock(); 747 fs_var_lock();
@@ -848,7 +750,7 @@ void fs_basic_fs(void) {
848 if (!arg_writable_var_log) 750 if (!arg_writable_var_log)
849 fs_var_log(); 751 fs_var_log();
850 else 752 else
851 fs_rdwr("/var/log"); 753 fs_remount("/var/log", MOUNT_RDWR, 0);
852 754
853 fs_var_lib(); 755 fs_var_lib();
854 fs_var_cache(); 756 fs_var_cache();
diff --git a/src/firejail/pulseaudio.c b/src/firejail/pulseaudio.c
index e3f237b8e..b82473476 100644
--- a/src/firejail/pulseaudio.c
+++ b/src/firejail/pulseaudio.c
@@ -88,7 +88,7 @@ void pulseaudio_init(void) {
88 if (mkdir(RUN_PULSE_DIR, 0700) == -1) 88 if (mkdir(RUN_PULSE_DIR, 0700) == -1)
89 errExit("mkdir"); 89 errExit("mkdir");
90 // mount it nosuid, noexec, nodev 90 // mount it nosuid, noexec, nodev
91 fs_noexec(RUN_PULSE_DIR); 91 fs_remount(RUN_PULSE_DIR, MOUNT_NOEXEC, 0);
92 92
93 // create the new client.conf file 93 // create the new client.conf file
94 char *pulsecfg = NULL; 94 char *pulsecfg = NULL;
@@ -155,8 +155,10 @@ void pulseaudio_init(void) {
155 if (fstatvfs(fd, &vfs) == -1) 155 if (fstatvfs(fd, &vfs) == -1)
156 errExit("fstatvfs"); 156 errExit("fstatvfs");
157 if ((vfs.f_flag & MS_RDONLY) == MS_RDONLY) 157 if ((vfs.f_flag & MS_RDONLY) == MS_RDONLY)
158 fs_rdonly(RUN_PULSE_DIR); 158 fs_remount(RUN_PULSE_DIR, MOUNT_READONLY, 0);
159 // mount via the link in /proc/self/fd 159 // mount via the link in /proc/self/fd
160 if (arg_debug)
161 printf("Mounting %s on %s\n", RUN_PULSE_DIR, homeusercfg);
160 char *proc; 162 char *proc;
161 if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1) 163 if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1)
162 errExit("asprintf"); 164 errExit("asprintf");
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c
index 841d57c89..f91e5ab7c 100644
--- a/src/firejail/sandbox.c
+++ b/src/firejail/sandbox.c
@@ -1116,7 +1116,7 @@ int sandbox(void* sandbox_arg) {
1116 (void) rv; 1116 (void) rv;
1117 } 1117 }
1118 // make seccomp filters read-only 1118 // make seccomp filters read-only
1119 fs_rdonly(RUN_SECCOMP_DIR); 1119 fs_remount(RUN_SECCOMP_DIR, MOUNT_READONLY, 0);
1120#endif 1120#endif
1121 1121
1122 // set capabilities 1122 // set capabilities
diff --git a/src/firejail/x11.c b/src/firejail/x11.c
index 9d821d980..69a9a7bee 100644
--- a/src/firejail/x11.c
+++ b/src/firejail/x11.c
@@ -1169,7 +1169,7 @@ void x11_xorg(void) {
1169 umount("/tmp"); 1169 umount("/tmp");
1170 1170
1171 // remount RUN_XAUTHORITY_SEC_FILE noexec, nodev, nosuid 1171 // remount RUN_XAUTHORITY_SEC_FILE noexec, nodev, nosuid
1172 fs_noexec(RUN_XAUTHORITY_SEC_FILE); 1172 fs_remount(RUN_XAUTHORITY_SEC_FILE, MOUNT_NOEXEC, 0);
1173 1173
1174 // Ensure there is already a file in the usual location, so that bind-mount below will work. 1174 // Ensure there is already a file in the usual location, so that bind-mount below will work.
1175 char *dest; 1175 char *dest;
@@ -1202,9 +1202,11 @@ void x11_xorg(void) {
1202 if (fstatvfs(fd, &vfs) == -1) 1202 if (fstatvfs(fd, &vfs) == -1)
1203 errExit("fstatvfs"); 1203 errExit("fstatvfs");
1204 if ((vfs.f_flag & MS_RDONLY) == MS_RDONLY) 1204 if ((vfs.f_flag & MS_RDONLY) == MS_RDONLY)
1205 fs_rdonly(RUN_XAUTHORITY_SEC_FILE); 1205 fs_remount(RUN_XAUTHORITY_SEC_FILE, MOUNT_READONLY, 0);
1206 1206
1207 // mount via the link in /proc/self/fd 1207 // mount via the link in /proc/self/fd
1208 if (arg_debug)
1209 printf("Mounting %s on %s\n", RUN_XAUTHORITY_SEC_FILE, dest);
1208 char *proc; 1210 char *proc;
1209 if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1) 1211 if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1)
1210 errExit("asprintf"); 1212 errExit("asprintf");
diff --git a/src/firemon/firemon.c b/src/firemon/firemon.c
index e5f1b6f9a..b3c435d9e 100644
--- a/src/firemon/firemon.c
+++ b/src/firemon/firemon.c
@@ -83,7 +83,9 @@ int find_child(int id) {
83 return i; 83 return i;
84 } 84 }
85 85
86 return -1; 86 // if a second child is not found, return the first child pid
87 // this happens for processes sandboxed with --join
88 return first_child;
87} 89}
88 90
89// sleep and wait for a key to be pressed 91// sleep and wait for a key to be pressed
diff --git a/src/man/firejail-profile.txt b/src/man/firejail-profile.txt
index 8c9989970..f97261456 100644
--- a/src/man/firejail-profile.txt
+++ b/src/man/firejail-profile.txt
@@ -74,6 +74,9 @@ Child process initialized
74[...] 74[...]
75.RE 75.RE
76 76
77.SH Templates
78Templates for writing own profiles can be found in /usr/share/doc/firejail.
79
77.SH Scripting 80.SH Scripting
78Scripting commands: 81Scripting commands:
79 82
diff --git a/src/man/firejail.txt b/src/man/firejail.txt
index 67b84de0e..201339c8b 100644
--- a/src/man/firejail.txt
+++ b/src/man/firejail.txt
@@ -2318,9 +2318,9 @@ $ sudo firejail --writable-var-log
2318.TP 2318.TP
2319\fB\-\-x11 2319\fB\-\-x11
2320Sandbox the application using Xpra, Xephyr, Xvfb or Xorg security extension. 2320Sandbox the application using Xpra, Xephyr, Xvfb or Xorg security extension.
2321The sandbox will prevents screenshot and keylogger applications started inside the sandbox from accessing 2321The sandbox will prevent screenshot and keylogger applications started inside the sandbox from accessing
2322clients running outside the sandbox. 2322clients running outside the sandbox.
2323Firejail will try first Xpra, and if Xpra is not installed on the system, it will try to find Xephyr. 2323Firejail will try Xpra first, and if Xpra is not installed on the system, it will try to find Xephyr.
2324If all fails, Firejail will not attempt to use Xvfb or X11 security extension. 2324If all fails, Firejail will not attempt to use Xvfb or X11 security extension.
2325.br 2325.br
2326 2326