aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar smitsohu <smitsohu@gmail.com>2021-07-24 13:42:06 +0200
committerLibravatar smitsohu <smitsohu@gmail.com>2021-07-24 15:27:22 +0200
commitee31d6b817e3777e625f23f460aa1daeda3637f7 (patch)
tree227eee9196775c5452cf6f572792fb274b0cd8f1
parenttweaks (diff)
downloadfirejail-ee31d6b817e3777e625f23f460aa1daeda3637f7.tar.gz
firejail-ee31d6b817e3777e625f23f460aa1daeda3637f7.tar.zst
firejail-ee31d6b817e3777e625f23f460aa1daeda3637f7.zip
organize program startup
fixes a number of smaller issues: * enable allow-debuggers option for Firejail login shells * dhcp: noblacklist /sbin and /usr/sbin also when configuring a Firejail login shell * don't print error when built with disable-suid: firejail --nonewprivs --quiet firejail * don't process appimage option twice * no unnecessary argument parsing when run via firecfg symbolic link * process quiet option earlier, so it is available to init_cfg
-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 374afed11..a59d508e5 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -988,24 +988,16 @@ int main(int argc, char **argv, char **envp) {
988 int arg_caps_cmdline = 0; // caps requested on command line (used to break out of --chroot) 988 int arg_caps_cmdline = 0; // caps requested on command line (used to break out of --chroot)
989 char **ptr; 989 char **ptr;
990 990
991#ifndef HAVE_SUID
992 if (geteuid() != 0) {
993 fprintf(stderr, "Error: Firejail needs to be SUID.\n");
994 fprintf(stderr, "Assuming firejail is installed in /usr/bin, execute the following command as root:\n");
995 fprintf(stderr, " chmod u+s /usr/bin/firejail\n");
996 }
997#endif
998
999 // sanitize the umask 991 // sanitize the umask
1000 orig_umask = umask(022); 992 orig_umask = umask(022);
1001 993
1002 // check standard streams before printing anything
1003 fix_std_streams();
1004
1005 // drop permissions by default and rise them when required 994 // drop permissions by default and rise them when required
1006 EUID_INIT(); 995 EUID_INIT();
1007 EUID_USER(); 996 EUID_USER();
1008 997
998 // check standard streams before opening any file
999 fix_std_streams();
1000
1009 // argument count should be larger than 0 1001 // argument count should be larger than 0
1010 if (argc == 0 || !argv || strlen(argv[0]) == 0) { 1002 if (argc == 0 || !argv || strlen(argv[0]) == 0) {
1011 fprintf(stderr, "Error: argv is invalid\n"); 1003 fprintf(stderr, "Error: argv is invalid\n");
@@ -1015,16 +1007,6 @@ int main(int argc, char **argv, char **envp) {
1015 exit(1); 1007 exit(1);
1016 } 1008 }
1017 1009
1018 // Stash environment variables
1019 for (i = 0, ptr = envp; ptr && *ptr && i < MAX_ENVS; i++, ptr++)
1020 env_store(*ptr, SETENV);
1021
1022 // sanity check for environment variables
1023 if (i >= MAX_ENVS) {
1024 fprintf(stderr, "Error: too many environment variables\n");
1025 exit(1);
1026 }
1027
1028 // sanity check for arguments 1010 // sanity check for arguments
1029 for (i = 0; i < argc; i++) { 1011 for (i = 0; i < argc; i++) {
1030 if (*argv[i] == 0) { 1012 if (*argv[i] == 0) {
@@ -1037,82 +1019,29 @@ int main(int argc, char **argv, char **envp) {
1037 } 1019 }
1038 } 1020 }
1039 1021
1022 // Stash environment variables
1023 for (i = 0, ptr = envp; ptr && *ptr && i < MAX_ENVS; i++, ptr++)
1024 env_store(*ptr, SETENV);
1025
1026 // sanity check for environment variables
1027 if (i >= MAX_ENVS) {
1028 fprintf(stderr, "Error: too many environment variables\n");
1029 exit(1);
1030 }
1031
1040 // Reapply a minimal set of environment variables 1032 // Reapply a minimal set of environment variables
1041 env_apply_whitelist(); 1033 env_apply_whitelist();
1042 1034
1043 // check if the user is allowed to use firejail 1035 // process --quiet
1044 init_cfg(argc, argv);
1045
1046 // get starting timestamp, process --quiet
1047 timetrace_start();
1048 const char *env_quiet = env_get("FIREJAIL_QUIET"); 1036 const char *env_quiet = env_get("FIREJAIL_QUIET");
1049 if (check_arg(argc, argv, "--quiet", 1) || (env_quiet && strcmp(env_quiet, "yes") == 0)) 1037 if (check_arg(argc, argv, "--quiet", 1) || (env_quiet && strcmp(env_quiet, "yes") == 0))
1050 arg_quiet = 1; 1038 arg_quiet = 1;
1051 1039
1052 // cleanup at exit 1040 // check if the user is allowed to use firejail
1053 EUID_ROOT(); 1041 init_cfg(argc, argv);
1054 atexit(clear_atexit);
1055
1056 // build /run/firejail directory structure
1057 preproc_build_firejail_dir();
1058 const char *container_name = env_get("container");
1059 if (!container_name || strcmp(container_name, "firejail")) {
1060 lockfd_directory = open(RUN_DIRECTORY_LOCK_FILE, O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR);
1061 if (lockfd_directory != -1) {
1062 int rv = fchown(lockfd_directory, 0, 0);
1063 (void) rv;
1064 flock(lockfd_directory, LOCK_EX);
1065 }
1066 preproc_clean_run();
1067 flock(lockfd_directory, LOCK_UN);
1068 close(lockfd_directory);
1069 }
1070 EUID_USER();
1071
1072 // --ip=dhcp - we need access to /sbin and /usr/sbin directories in order to run ISC DHCP client (dhclient)
1073 // these paths are disabled in disable-common.inc
1074 if ((i = check_arg(argc, argv, "--ip", 0)) != 0) {
1075 if (strncmp(argv[i] + 4, "=dhcp", 5) == 0) {
1076 profile_add("noblacklist /sbin");
1077 profile_add("noblacklist /usr/sbin");
1078 }
1079 }
1080
1081 // for appimages we need to remove "include disable-shell.inc from the profile
1082 // a --profile command can show up before --appimage
1083 if (check_arg(argc, argv, "--appimage", 1))
1084 arg_appimage = 1;
1085
1086 // process allow-debuggers
1087 if (check_arg(argc, argv, "--allow-debuggers", 1)) {
1088 // check kernel version
1089 struct utsname u;
1090 int rv = uname(&u);
1091 if (rv != 0)
1092 errExit("uname");
1093 int major;
1094 int minor;
1095 if (2 != sscanf(u.release, "%d.%d", &major, &minor)) {
1096 fprintf(stderr, "Error: cannot extract Linux kernel version: %s\n", u.version);
1097 exit(1);
1098 }
1099 if (major < 4 || (major == 4 && minor < 8)) {
1100 fprintf(stderr, "Error: --allow-debuggers is disabled on Linux kernels prior to 4.8. "
1101 "A bug in ptrace call allows a full bypass of the seccomp filter. "
1102 "Your current kernel version is %d.%d.\n", major, minor);
1103 exit(1);
1104 }
1105
1106 arg_allow_debuggers = 1;
1107 char *cmd = strdup("noblacklist ${PATH}/strace");
1108 if (!cmd)
1109 errExit("strdup");
1110 profile_add(cmd);
1111 }
1112 1042
1113 // profile builder 1043 // get starting timestamp
1114 if (check_arg(argc, argv, "--build", 0)) // supports both --build and --build=filename 1044 timetrace_start();
1115 run_builder(argc, argv); // this function will not return
1116 1045
1117 // check argv[0] symlink wrapper if this is not a login shell 1046 // check argv[0] symlink wrapper if this is not a login shell
1118 if (*argv[0] != '-') 1047 if (*argv[0] != '-')
@@ -1137,15 +1066,40 @@ int main(int argc, char **argv, char **envp) {
1137 __builtin_unreachable(); 1066 __builtin_unreachable();
1138 } 1067 }
1139 } 1068 }
1140 EUID_ASSERT();
1141 1069
1070 // profile builder
1071 if (check_arg(argc, argv, "--build", 0)) // supports both --build and --build=filename
1072 run_builder(argc, argv); // this function will not return
1142 1073
1143 // check firejail directories
1144 EUID_ROOT(); 1074 EUID_ROOT();
1145 delete_run_files(sandbox_pid); 1075#ifndef HAVE_SUID
1076 if (geteuid() != 0) {
1077 fprintf(stderr, "Error: Firejail needs to be SUID.\n");
1078 fprintf(stderr, "Assuming firejail is installed in /usr/bin, execute the following command as root:\n");
1079 fprintf(stderr, " chmod u+s /usr/bin/firejail\n");
1080 }
1081#endif
1082
1083 // build /run/firejail directory structure
1084 preproc_build_firejail_dir();
1085 const char *container_name = env_get("container");
1086 if (!container_name || strcmp(container_name, "firejail")) {
1087 lockfd_directory = open(RUN_DIRECTORY_LOCK_FILE, O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR);
1088 if (lockfd_directory != -1) {
1089 int rv = fchown(lockfd_directory, 0, 0);
1090 (void) rv;
1091 flock(lockfd_directory, LOCK_EX);
1092 }
1093 preproc_clean_run();
1094 flock(lockfd_directory, LOCK_UN);
1095 close(lockfd_directory);
1096 }
1097
1098 delete_run_files(getpid());
1099 atexit(clear_atexit);
1146 EUID_USER(); 1100 EUID_USER();
1147 1101
1148 //check if the parent is sshd daemon 1102 // check if the parent is sshd daemon
1149 int parent_sshd = 0; 1103 int parent_sshd = 0;
1150 { 1104 {
1151 pid_t ppid = getppid(); 1105 pid_t ppid = getppid();
@@ -1202,7 +1156,8 @@ int main(int argc, char **argv, char **envp) {
1202 } 1156 }
1203 EUID_ASSERT(); 1157 EUID_ASSERT();
1204 1158
1205 // is this a login shell, or a command passed by sshd, insert command line options from /etc/firejail/login.users 1159 // is this a login shell, or a command passed by sshd,
1160 // insert command line options from /etc/firejail/login.users
1206 if (*argv[0] == '-' || parent_sshd) { 1161 if (*argv[0] == '-' || parent_sshd) {
1207 if (argc == 1) 1162 if (argc == 1)
1208 login_shell = 1; 1163 login_shell = 1;
@@ -1254,6 +1209,47 @@ int main(int argc, char **argv, char **envp) {
1254#endif 1209#endif
1255 EUID_ASSERT(); 1210 EUID_ASSERT();
1256 1211
1212 // --ip=dhcp - we need access to /sbin and /usr/sbin directories in order to run ISC DHCP client (dhclient)
1213 // these paths are disabled in disable-common.inc
1214 if ((i = check_arg(argc, argv, "--ip", 0)) != 0) {
1215 if (strncmp(argv[i] + 4, "=dhcp", 5) == 0) {
1216 profile_add("noblacklist /sbin");
1217 profile_add("noblacklist /usr/sbin");
1218 }
1219 }
1220
1221 // process allow-debuggers
1222 if (check_arg(argc, argv, "--allow-debuggers", 1)) {
1223 // check kernel version
1224 struct utsname u;
1225 int rv = uname(&u);
1226 if (rv != 0)
1227 errExit("uname");
1228 int major;
1229 int minor;
1230 if (2 != sscanf(u.release, "%d.%d", &major, &minor)) {
1231 fprintf(stderr, "Error: cannot extract Linux kernel version: %s\n", u.version);
1232 exit(1);
1233 }
1234 if (major < 4 || (major == 4 && minor < 8)) {
1235 fprintf(stderr, "Error: --allow-debuggers is disabled on Linux kernels prior to 4.8. "
1236 "A bug in ptrace call allows a full bypass of the seccomp filter. "
1237 "Your current kernel version is %d.%d.\n", major, minor);
1238 exit(1);
1239 }
1240
1241 arg_allow_debuggers = 1;
1242 char *cmd = strdup("noblacklist ${PATH}/strace");
1243 if (!cmd)
1244 errExit("strdup");
1245 profile_add(cmd);
1246 }
1247
1248 // for appimages we need to remove "include disable-shell.inc from the profile
1249 // a --profile command can show up before --appimage
1250 if (check_arg(argc, argv, "--appimage", 1))
1251 arg_appimage = 1;
1252
1257 // check for force-nonewprivs in /etc/firejail/firejail.config file 1253 // check for force-nonewprivs in /etc/firejail/firejail.config file
1258 if (checkcfg(CFG_FORCE_NONEWPRIVS)) 1254 if (checkcfg(CFG_FORCE_NONEWPRIVS))
1259 arg_nonewprivs = 1; 1255 arg_nonewprivs = 1;
@@ -2652,8 +2648,9 @@ int main(int argc, char **argv, char **envp) {
2652 //************************************* 2648 //*************************************
2653 else if (strncmp(argv[i], "--timeout=", 10) == 0) 2649 else if (strncmp(argv[i], "--timeout=", 10) == 0)
2654 cfg.timeout = extract_timeout(argv[i] + 10); 2650 cfg.timeout = extract_timeout(argv[i] + 10);
2655 else if (strcmp(argv[i], "--appimage") == 0) 2651 else if (strcmp(argv[i], "--appimage") == 0) {
2656 arg_appimage = 1; 2652 // already handled
2653 }
2657 else if (strcmp(argv[i], "--shell=none") == 0) { 2654 else if (strcmp(argv[i], "--shell=none") == 0) {
2658 arg_shell_none = 1; 2655 arg_shell_none = 1;
2659 if (cfg.shell) { 2656 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 8fcaf3f7b..2ff2d2973 100644
--- a/src/firejail/util.c
+++ b/src/firejail/util.c
@@ -1516,8 +1516,7 @@ void check_homedir(const char *dir) {
1516 exit(1); 1516 exit(1);
1517 } 1517 }
1518 // symlinks are rejected in many places 1518 // symlinks are rejected in many places
1519 if (has_link(dir)) { 1519 if (has_link(dir))
1520 fprintf(stderr, "No full support for symbolic links in path of user directory.\n" 1520 fmessage("No full support for symbolic links in path of user directory.\n"
1521 "Please provide resolved path in password database (/etc/passwd).\n\n"); 1521 "Please provide resolved path in password database (/etc/passwd).\n\n");
1522 }
1523} 1522}