aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/firejail/firejail.h2
-rw-r--r--src/firejail/fs.c84
-rw-r--r--src/firejail/main.c17
-rw-r--r--src/firejail/util.c4
4 files changed, 85 insertions, 22 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index 18199c122..a656dcf7c 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -333,7 +333,7 @@ void fs_basic_fs(void);
333void fs_overlayfs(void); 333void fs_overlayfs(void);
334// chroot into an existing directory; mount exiting /dev and update /etc/resolv.conf 334// chroot into an existing directory; mount exiting /dev and update /etc/resolv.conf
335void fs_chroot(const char *rootdir); 335void fs_chroot(const char *rootdir);
336int fs_check_chroot_dir(const char *rootdir); 336void fs_check_chroot_dir(const char *rootdir);
337void fs_private_tmp(void); 337void fs_private_tmp(void);
338 338
339// profile.c 339// profile.c
diff --git a/src/firejail/fs.c b/src/firejail/fs.c
index fa212bbd5..da63ecd00 100644
--- a/src/firejail/fs.c
+++ b/src/firejail/fs.c
@@ -837,17 +837,36 @@ void fs_overlayfs(void) {
837 837
838#ifdef HAVE_CHROOT 838#ifdef HAVE_CHROOT
839// return 1 if error 839// return 1 if error
840int fs_check_chroot_dir(const char *rootdir) { 840void fs_check_chroot_dir(const char *rootdir) {
841 assert(rootdir); 841 assert(rootdir);
842 struct stat s; 842 struct stat s;
843 char *name; 843 char *name;
844 844
845 if (strcmp(rootdir, "/tmp") == 0 || strcmp(rootdir, "/var/tmp") == 0) {
846 fprintf(stderr, "Error: invalid chroot directory\n");
847 exit(1);
848 }
849
850 // rootdir has to be owned by root
851 if (stat(rootdir, &s) != 0) {
852 fprintf(stderr, "Error: cannot find chroot directory\n");
853 exit(1);
854 }
855 if (s.st_uid != 0) {
856 fprintf(stderr, "Error: chroot directory should be owned by root\n");
857 exit(1);
858 }
859
845 // check /dev 860 // check /dev
846 if (asprintf(&name, "%s/dev", rootdir) == -1) 861 if (asprintf(&name, "%s/dev", rootdir) == -1)
847 errExit("asprintf"); 862 errExit("asprintf");
848 if (stat(name, &s) == -1) { 863 if (stat(name, &s) == -1) {
849 fprintf(stderr, "Error: cannot find /dev in chroot directory\n"); 864 fprintf(stderr, "Error: cannot find /dev in chroot directory\n");
850 return 1; 865 exit(1);
866 }
867 if (s.st_uid != 0) {
868 fprintf(stderr, "Error: chroot /dev directory should be owned by root\n");
869 exit(1);
851 } 870 }
852 free(name); 871 free(name);
853 872
@@ -856,7 +875,11 @@ int fs_check_chroot_dir(const char *rootdir) {
856 errExit("asprintf"); 875 errExit("asprintf");
857 if (stat(name, &s) == -1) { 876 if (stat(name, &s) == -1) {
858 fprintf(stderr, "Error: cannot find /var/tmp in chroot directory\n"); 877 fprintf(stderr, "Error: cannot find /var/tmp in chroot directory\n");
859 return 1; 878 exit(1);
879 }
880 if (s.st_uid != 0) {
881 fprintf(stderr, "Error: chroot /var/tmp directory should be owned by root\n");
882 exit(1);
860 } 883 }
861 free(name); 884 free(name);
862 885
@@ -865,29 +888,54 @@ int fs_check_chroot_dir(const char *rootdir) {
865 errExit("asprintf"); 888 errExit("asprintf");
866 if (stat(name, &s) == -1) { 889 if (stat(name, &s) == -1) {
867 fprintf(stderr, "Error: cannot find /proc in chroot directory\n"); 890 fprintf(stderr, "Error: cannot find /proc in chroot directory\n");
868 return 1; 891 exit(1);
892 }
893 if (s.st_uid != 0) {
894 fprintf(stderr, "Error: chroot /proc directory should be owned by root\n");
895 exit(1);
869 } 896 }
870 free(name); 897 free(name);
871 898
872 // check /proc 899 // check /tmp
873 if (asprintf(&name, "%s/tmp", rootdir) == -1) 900 if (asprintf(&name, "%s/tmp", rootdir) == -1)
874 errExit("asprintf"); 901 errExit("asprintf");
875 if (stat(name, &s) == -1) { 902 if (stat(name, &s) == -1) {
876 fprintf(stderr, "Error: cannot find /tmp in chroot directory\n"); 903 fprintf(stderr, "Error: cannot find /tmp in chroot directory\n");
877 return 1; 904 exit(1);
905 }
906 if (s.st_uid != 0) {
907 fprintf(stderr, "Error: chroot /tmp directory should be owned by root\n");
908 exit(1);
878 } 909 }
879 free(name); 910 free(name);
880 911
881 // check /bin/bash 912 // check /etc
882 if (asprintf(&name, "%s/bin/bash", rootdir) == -1) 913 if (asprintf(&name, "%s/etc", rootdir) == -1)
883 errExit("asprintf"); 914 errExit("asprintf");
884 if (stat(name, &s) == -1) { 915 if (stat(name, &s) == -1) {
885 fprintf(stderr, "Error: cannot find /bin/bash in chroot directory\n"); 916 fprintf(stderr, "Error: cannot find /etc in chroot directory\n");
886 return 1; 917 exit(1);
918 }
919 if (s.st_uid != 0) {
920 fprintf(stderr, "Error: chroot /etc directory should be owned by root\n");
921 exit(1);
887 } 922 }
888 free(name); 923 free(name);
889 924
890 return 0; 925 // check /etc/resolv.conf
926 if (asprintf(&name, "%s/etc/resolv.conf", rootdir) == -1)
927 errExit("asprintf");
928 if (stat(name, &s) == 0) {
929 if (s.st_uid != 0) {
930 fprintf(stderr, "Error: chroot /etc/resolv.conf should be owned by root\n");
931 exit(1);
932 }
933 }
934 if (is_link(name)) {
935 fprintf(stderr, "Error: invalid %s file\n", name);
936 exit(1);
937 }
938 free(name);
891} 939}
892 940
893// chroot into an existing directory; mount exiting /dev and update /etc/resolv.conf 941// chroot into an existing directory; mount exiting /dev and update /etc/resolv.conf
@@ -912,6 +960,10 @@ void fs_chroot(const char *rootdir) {
912 char *rundir; 960 char *rundir;
913 if (asprintf(&rundir, "%s/run", rootdir) == -1) 961 if (asprintf(&rundir, "%s/run", rootdir) == -1)
914 errExit("asprintf"); 962 errExit("asprintf");
963 if (is_link(rundir)) {
964 fprintf(stderr, "Error: invalid run directory inside chroot\n");
965 exit(1);
966 }
915 if (!is_dir(rundir)) { 967 if (!is_dir(rundir)) {
916 int rv = mkdir(rundir, 0755); 968 int rv = mkdir(rundir, 0755);
917 (void) rv; 969 (void) rv;
@@ -931,8 +983,14 @@ void fs_chroot(const char *rootdir) {
931 fprintf(stderr, "Error: invalid %s file\n", fname); 983 fprintf(stderr, "Error: invalid %s file\n", fname);
932 exit(1); 984 exit(1);
933 } 985 }
934 if (copy_file("/etc/resolv.conf", fname) == -1) 986 if (copy_file("/etc/resolv.conf", fname) == -1) // root needed
935 fprintf(stderr, "Warning: /etc/resolv.conf not initialized\n"); 987 fprintf(stderr, "Warning: /etc/resolv.conf not initialized\n");
988 else {
989 if (chown("/etc/resolv.conf", 0, 0) == -1)
990 errExit("chown");
991 if (chmod("/etc/resolv.conf", 0644) == -1)
992 errExit("chmod");
993 }
936 994
937 // chroot into the new directory 995 // chroot into the new directory
938 if (arg_debug) 996 if (arg_debug)
diff --git a/src/firejail/main.c b/src/firejail/main.c
index 9c1b73e7a..a7bd71356 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -885,6 +885,14 @@ int main(int argc, char **argv) {
885 fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n"); 885 fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n");
886 exit(1); 886 exit(1);
887 } 887 }
888
889 struct stat s;
890 if (stat("/proc/sys/kernel/grsecurity", &s) == 0) {
891 fprintf(stderr, "Error: --chroot option is not available on Grsecurity systems\n");
892 exit(1);
893 }
894
895
888 invalid_filename(argv[i] + 9); 896 invalid_filename(argv[i] + 9);
889 897
890 // extract chroot dirname 898 // extract chroot dirname
@@ -909,13 +917,10 @@ int main(int argc, char **argv) {
909 fprintf(stderr, "Error: invalid chroot directory\n"); 917 fprintf(stderr, "Error: invalid chroot directory\n");
910 exit(1); 918 exit(1);
911 } 919 }
912 free(rpath); 920 cfg.chrootdir = rpath;
913 921
914 // check chroot directory structure 922 // check chroot directory structure
915 if (fs_check_chroot_dir(cfg.chrootdir)) { 923 fs_check_chroot_dir(cfg.chrootdir);
916 fprintf(stderr, "Error: invalid chroot\n");
917 exit(1);
918 }
919 } 924 }
920#endif 925#endif
921 else if (strcmp(argv[i], "--private") == 0) 926 else if (strcmp(argv[i], "--private") == 0)
diff --git a/src/firejail/util.c b/src/firejail/util.c
index 21f9a73e3..5a6cb0296 100644
--- a/src/firejail/util.c
+++ b/src/firejail/util.c
@@ -228,9 +228,9 @@ void copy_file_as_user(const char *srcname, const char *destname, uid_t uid, gid
228 fprintf(stderr, "Warning: cannot copy %s\n", srcname); 228 fprintf(stderr, "Warning: cannot copy %s\n", srcname);
229 else { 229 else {
230 if (chown(destname, uid, gid) == -1) 230 if (chown(destname, uid, gid) == -1)
231 errExit("fchown"); 231 errExit("chown");
232 if (chmod(destname, mode) == -1) 232 if (chmod(destname, mode) == -1)
233 errExit("fchmod"); 233 errExit("chmod");
234 } 234 }
235 _exit(0); 235 _exit(0);
236 } 236 }