aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/firejail/main.c189
-rw-r--r--src/firejail/no_sandbox.c3
-rw-r--r--src/firejail/util.c5
3 files changed, 96 insertions, 101 deletions
diff --git a/src/firejail/main.c b/src/firejail/main.c
index f64994e02..655e6e9d0 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -985,24 +985,16 @@ int main(int argc, char **argv, char **envp) {
985 int arg_caps_cmdline = 0; // caps requested on command line (used to break out of --chroot) 985 int arg_caps_cmdline = 0; // caps requested on command line (used to break out of --chroot)
986 char **ptr; 986 char **ptr;
987 987
988#ifndef HAVE_SUID
989 if (geteuid() != 0) {
990 fprintf(stderr, "Error: Firejail needs to be SUID.\n");
991 fprintf(stderr, "Assuming firejail is installed in /usr/bin, execute the following command as root:\n");
992 fprintf(stderr, " chmod u+s /usr/bin/firejail\n");
993 }
994#endif
995
996 // sanitize the umask 988 // sanitize the umask
997 orig_umask = umask(022); 989 orig_umask = umask(022);
998 990
999 // check standard streams before printing anything
1000 fix_std_streams();
1001
1002 // drop permissions by default and rise them when required 991 // drop permissions by default and rise them when required
1003 EUID_INIT(); 992 EUID_INIT();
1004 EUID_USER(); 993 EUID_USER();
1005 994
995 // check standard streams before opening any file
996 fix_std_streams();
997
1006 // argument count should be larger than 0 998 // argument count should be larger than 0
1007 if (argc == 0 || !argv || strlen(argv[0]) == 0) { 999 if (argc == 0 || !argv || strlen(argv[0]) == 0) {
1008 fprintf(stderr, "Error: argv is invalid\n"); 1000 fprintf(stderr, "Error: argv is invalid\n");
@@ -1012,16 +1004,6 @@ int main(int argc, char **argv, char **envp) {
1012 exit(1); 1004 exit(1);
1013 } 1005 }
1014 1006
1015 // Stash environment variables
1016 for (i = 0, ptr = envp; ptr && *ptr && i < MAX_ENVS; i++, ptr++)
1017 env_store(*ptr, SETENV);
1018
1019 // sanity check for environment variables
1020 if (i >= MAX_ENVS) {
1021 fprintf(stderr, "Error: too many environment variables\n");
1022 exit(1);
1023 }
1024
1025 // sanity check for arguments 1007 // sanity check for arguments
1026 for (i = 0; i < argc; i++) { 1008 for (i = 0; i < argc; i++) {
1027 if (*argv[i] == 0) { 1009 if (*argv[i] == 0) {
@@ -1034,82 +1016,29 @@ int main(int argc, char **argv, char **envp) {
1034 } 1016 }
1035 } 1017 }
1036 1018
1019 // Stash environment variables
1020 for (i = 0, ptr = envp; ptr && *ptr && i < MAX_ENVS; i++, ptr++)
1021 env_store(*ptr, SETENV);
1022
1023 // sanity check for environment variables
1024 if (i >= MAX_ENVS) {
1025 fprintf(stderr, "Error: too many environment variables\n");
1026 exit(1);
1027 }
1028
1037 // Reapply a minimal set of environment variables 1029 // Reapply a minimal set of environment variables
1038 env_apply_whitelist(); 1030 env_apply_whitelist();
1039 1031
1040 // check if the user is allowed to use firejail 1032 // process --quiet
1041 init_cfg(argc, argv);
1042
1043 // get starting timestamp, process --quiet
1044 timetrace_start();
1045 const char *env_quiet = env_get("FIREJAIL_QUIET"); 1033 const char *env_quiet = env_get("FIREJAIL_QUIET");
1046 if (check_arg(argc, argv, "--quiet", 1) || (env_quiet && strcmp(env_quiet, "yes") == 0)) 1034 if (check_arg(argc, argv, "--quiet", 1) || (env_quiet && strcmp(env_quiet, "yes") == 0))
1047 arg_quiet = 1; 1035 arg_quiet = 1;
1048 1036
1049 // cleanup at exit 1037 // check if the user is allowed to use firejail
1050 EUID_ROOT(); 1038 init_cfg(argc, argv);
1051 atexit(clear_atexit);
1052
1053 // build /run/firejail directory structure
1054 preproc_build_firejail_dir();
1055 const char *container_name = env_get("container");
1056 if (!container_name || strcmp(container_name, "firejail")) {
1057 lockfd_directory = open(RUN_DIRECTORY_LOCK_FILE, O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR);
1058 if (lockfd_directory != -1) {
1059 int rv = fchown(lockfd_directory, 0, 0);
1060 (void) rv;
1061 flock(lockfd_directory, LOCK_EX);
1062 }
1063 preproc_clean_run();
1064 flock(lockfd_directory, LOCK_UN);
1065 close(lockfd_directory);
1066 }
1067 EUID_USER();
1068
1069 // --ip=dhcp - we need access to /sbin and /usr/sbin directories in order to run ISC DHCP client (dhclient)
1070 // these paths are disabled in disable-common.inc
1071 if ((i = check_arg(argc, argv, "--ip", 0)) != 0) {
1072 if (strncmp(argv[i] + 4, "=dhcp", 5) == 0) {
1073 profile_add("noblacklist /sbin");
1074 profile_add("noblacklist /usr/sbin");
1075 }
1076 }
1077
1078 // for appimages we need to remove "include disable-shell.inc from the profile
1079 // a --profile command can show up before --appimage
1080 if (check_arg(argc, argv, "--appimage", 1))
1081 arg_appimage = 1;
1082
1083 // process allow-debuggers
1084 if (check_arg(argc, argv, "--allow-debuggers", 1)) {
1085 // check kernel version
1086 struct utsname u;
1087 int rv = uname(&u);
1088 if (rv != 0)
1089 errExit("uname");
1090 int major;
1091 int minor;
1092 if (2 != sscanf(u.release, "%d.%d", &major, &minor)) {
1093 fprintf(stderr, "Error: cannot extract Linux kernel version: %s\n", u.version);
1094 exit(1);
1095 }
1096 if (major < 4 || (major == 4 && minor < 8)) {
1097 fprintf(stderr, "Error: --allow-debuggers is disabled on Linux kernels prior to 4.8. "
1098 "A bug in ptrace call allows a full bypass of the seccomp filter. "
1099 "Your current kernel version is %d.%d.\n", major, minor);
1100 exit(1);
1101 }
1102
1103 arg_allow_debuggers = 1;
1104 char *cmd = strdup("noblacklist ${PATH}/strace");
1105 if (!cmd)
1106 errExit("strdup");
1107 profile_add(cmd);
1108 }
1109 1039
1110 // profile builder 1040 // get starting timestamp
1111 if (check_arg(argc, argv, "--build", 0)) // supports both --build and --build=filename 1041 timetrace_start();
1112 run_builder(argc, argv); // this function will not return
1113 1042
1114 // check argv[0] symlink wrapper if this is not a login shell 1043 // check argv[0] symlink wrapper if this is not a login shell
1115 if (*argv[0] != '-') 1044 if (*argv[0] != '-')
@@ -1134,15 +1063,40 @@ int main(int argc, char **argv, char **envp) {
1134 __builtin_unreachable(); 1063 __builtin_unreachable();
1135 } 1064 }
1136 } 1065 }
1137 EUID_ASSERT();
1138 1066
1067 // profile builder
1068 if (check_arg(argc, argv, "--build", 0)) // supports both --build and --build=filename
1069 run_builder(argc, argv); // this function will not return
1139 1070
1140 // check firejail directories
1141 EUID_ROOT(); 1071 EUID_ROOT();
1142 delete_run_files(sandbox_pid); 1072#ifndef HAVE_SUID
1073 if (geteuid() != 0) {
1074 fprintf(stderr, "Error: Firejail needs to be SUID.\n");
1075 fprintf(stderr, "Assuming firejail is installed in /usr/bin, execute the following command as root:\n");
1076 fprintf(stderr, " chmod u+s /usr/bin/firejail\n");
1077 }
1078#endif
1079
1080 // build /run/firejail directory structure
1081 preproc_build_firejail_dir();
1082 const char *container_name = env_get("container");
1083 if (!container_name || strcmp(container_name, "firejail")) {
1084 lockfd_directory = open(RUN_DIRECTORY_LOCK_FILE, O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR);
1085 if (lockfd_directory != -1) {
1086 int rv = fchown(lockfd_directory, 0, 0);
1087 (void) rv;
1088 flock(lockfd_directory, LOCK_EX);
1089 }
1090 preproc_clean_run();
1091 flock(lockfd_directory, LOCK_UN);
1092 close(lockfd_directory);
1093 }
1094
1095 delete_run_files(getpid());
1096 atexit(clear_atexit);
1143 EUID_USER(); 1097 EUID_USER();
1144 1098
1145 //check if the parent is sshd daemon 1099 // check if the parent is sshd daemon
1146 int parent_sshd = 0; 1100 int parent_sshd = 0;
1147 { 1101 {
1148 pid_t ppid = getppid(); 1102 pid_t ppid = getppid();
@@ -1199,7 +1153,8 @@ int main(int argc, char **argv, char **envp) {
1199 } 1153 }
1200 EUID_ASSERT(); 1154 EUID_ASSERT();
1201 1155
1202 // is this a login shell, or a command passed by sshd, insert command line options from /etc/firejail/login.users 1156 // is this a login shell, or a command passed by sshd,
1157 // insert command line options from /etc/firejail/login.users
1203 if (*argv[0] == '-' || parent_sshd) { 1158 if (*argv[0] == '-' || parent_sshd) {
1204 if (argc == 1) 1159 if (argc == 1)
1205 login_shell = 1; 1160 login_shell = 1;
@@ -1251,6 +1206,47 @@ int main(int argc, char **argv, char **envp) {
1251#endif 1206#endif
1252 EUID_ASSERT(); 1207 EUID_ASSERT();
1253 1208
1209 // --ip=dhcp - we need access to /sbin and /usr/sbin directories in order to run ISC DHCP client (dhclient)
1210 // these paths are disabled in disable-common.inc
1211 if ((i = check_arg(argc, argv, "--ip", 0)) != 0) {
1212 if (strncmp(argv[i] + 4, "=dhcp", 5) == 0) {
1213 profile_add("noblacklist /sbin");
1214 profile_add("noblacklist /usr/sbin");
1215 }
1216 }
1217
1218 // process allow-debuggers
1219 if (check_arg(argc, argv, "--allow-debuggers", 1)) {
1220 // check kernel version
1221 struct utsname u;
1222 int rv = uname(&u);
1223 if (rv != 0)
1224 errExit("uname");
1225 int major;
1226 int minor;
1227 if (2 != sscanf(u.release, "%d.%d", &major, &minor)) {
1228 fprintf(stderr, "Error: cannot extract Linux kernel version: %s\n", u.version);
1229 exit(1);
1230 }
1231 if (major < 4 || (major == 4 && minor < 8)) {
1232 fprintf(stderr, "Error: --allow-debuggers is disabled on Linux kernels prior to 4.8. "
1233 "A bug in ptrace call allows a full bypass of the seccomp filter. "
1234 "Your current kernel version is %d.%d.\n", major, minor);
1235 exit(1);
1236 }
1237
1238 arg_allow_debuggers = 1;
1239 char *cmd = strdup("noblacklist ${PATH}/strace");
1240 if (!cmd)
1241 errExit("strdup");
1242 profile_add(cmd);
1243 }
1244
1245 // for appimages we need to remove "include disable-shell.inc from the profile
1246 // a --profile command can show up before --appimage
1247 if (check_arg(argc, argv, "--appimage", 1))
1248 arg_appimage = 1;
1249
1254 // check for force-nonewprivs in /etc/firejail/firejail.config file 1250 // check for force-nonewprivs in /etc/firejail/firejail.config file
1255 if (checkcfg(CFG_FORCE_NONEWPRIVS)) 1251 if (checkcfg(CFG_FORCE_NONEWPRIVS))
1256 arg_nonewprivs = 1; 1252 arg_nonewprivs = 1;
@@ -2680,8 +2676,9 @@ int main(int argc, char **argv, char **envp) {
2680 //************************************* 2676 //*************************************
2681 else if (strncmp(argv[i], "--timeout=", 10) == 0) 2677 else if (strncmp(argv[i], "--timeout=", 10) == 0)
2682 cfg.timeout = extract_timeout(argv[i] + 10); 2678 cfg.timeout = extract_timeout(argv[i] + 10);
2683 else if (strcmp(argv[i], "--appimage") == 0) 2679 else if (strcmp(argv[i], "--appimage") == 0) {
2684 arg_appimage = 1; 2680 // already handled
2681 }
2685 else if (strcmp(argv[i], "--shell=none") == 0) { 2682 else if (strcmp(argv[i], "--shell=none") == 0) {
2686 arg_shell_none = 1; 2683 arg_shell_none = 1;
2687 if (cfg.shell) { 2684 if (cfg.shell) {
diff --git a/src/firejail/no_sandbox.c b/src/firejail/no_sandbox.c
index 665bef73d..0e5562d90 100644
--- a/src/firejail/no_sandbox.c
+++ b/src/firejail/no_sandbox.c
@@ -49,6 +49,7 @@ int check_namespace_virt(void) {
49 // check PID 1 container environment variable 49 // check PID 1 container environment variable
50 EUID_ROOT(); 50 EUID_ROOT();
51 FILE *fp = fopen("/proc/1/environ", "re"); 51 FILE *fp = fopen("/proc/1/environ", "re");
52 EUID_USER();
52 if (fp) { 53 if (fp) {
53 int c = 0; 54 int c = 0;
54 while (c != EOF) { 55 while (c != EOF) {
@@ -69,7 +70,6 @@ int check_namespace_virt(void) {
69 // found it 70 // found it
70 if (is_container(buf + 10)) { 71 if (is_container(buf + 10)) {
71 fclose(fp); 72 fclose(fp);
72 EUID_USER();
73 return 1; 73 return 1;
74 } 74 }
75 } 75 }
@@ -79,7 +79,6 @@ int check_namespace_virt(void) {
79 fclose(fp); 79 fclose(fp);
80 } 80 }
81 81
82 EUID_USER();
83 return 0; 82 return 0;
84} 83}
85 84
diff --git a/src/firejail/util.c b/src/firejail/util.c
index de31ebdd6..094a68c60 100644
--- a/src/firejail/util.c
+++ b/src/firejail/util.c
@@ -1513,8 +1513,7 @@ void check_homedir(const char *dir) {
1513 exit(1); 1513 exit(1);
1514 } 1514 }
1515 // symlinks are rejected in many places 1515 // symlinks are rejected in many places
1516 if (has_link(dir)) { 1516 if (has_link(dir))
1517 fprintf(stderr, "No full support for symbolic links in path of user directory.\n" 1517 fmessage("No full support for symbolic links in path of user directory.\n"
1518 "Please provide resolved path in password database (/etc/passwd).\n\n"); 1518 "Please provide resolved path in password database (/etc/passwd).\n\n");
1519 }
1520} 1519}