/* ----- EXPORTED from interface.master: ----- */ int sb2show__execve_mods__( char *file, char *const *orig_argv, char *const *orig_envp, char **new_file, char ***new_argv, char ***new_envp) { int ret = 0; char *tmp, *binaryname; if (!sb2_global_vars_initialized__) sb2_initialize_global_variables(); SB_LOG(SB_LOGLEVEL_DEBUG, "%s '%s'", __func__, orig_argv[0]); if (!file) return(ret); tmp = strdup(file); binaryname = strdup(basename(tmp)); /* basename may modify *tmp */ free(tmp); *new_envp = prepare_envp_for_do_exec(file, binaryname, orig_envp); ret = prepare_exec("sb2show_exec", NULL/*exec_policy_name*/, file, 0, orig_argv, orig_envp, NULL, new_file, new_argv, new_envp); if (!*new_file) *new_file = strdup(file); if (!*new_argv) *new_argv = duplicate_argv(orig_argv); if (!*new_envp) *new_envp = duplicate_argv(orig_envp); return(ret); }
int launch_app_with_nice(const char *file, char *const argv[], pid_t *pid, int _nice) { int ret; int _pid; if (file == NULL || access(file, X_OK) != 0) { PRT_TRACE_ERR("launch app error: Invalid input"); errno = EINVAL; return -1; } if (pid && (*pid > 0 && kill(*pid, 0) != -1)) return *pid; _pid = fork(); if (_pid == -1) { PRT_TRACE_ERR("fork error: %s", strerror(errno)); /* keep errno */ return -1; } if (_pid > 0) { /* parent */ if (pid) *pid = _pid; return _pid; } /* child */ prepare_exec(); ret = nice(_nice); if (ret == -1 && errno != 0) PRT_TRACE_ERR("nice error: %s", strerror(errno)); ret = execvp(file, argv); /* If failed... */ PRT_TRACE_ERR("exec. error: %s", strerror(errno)); return -2; }
static int prepare_hashbang( char **mapped_file, /* In: script, out: mapped script interpreter */ char *orig_file, char ***argvp, char ***envpp, const char *exec_policy_name) { int argc, fd, c, i, j, n; char ch; char *mapped_interpreter = NULL; char **new_argv = NULL; char hashbang[SBOX_MAXPATH]; /* only 60 needed on linux, just be safe */ char interpreter[SBOX_MAXPATH]; char *interp_arg = NULL; char *tmp = NULL, *mapped_binaryname = NULL; int result = 0; if ((fd = open_nomap(*mapped_file, O_RDONLY)) < 0) { /* unexpected error, just run it */ return 0; } if ((c = read(fd, &hashbang[0], SBOX_MAXPATH - 1)) < 2) { /* again unexpected error, close fd and run it */ close_nomap_nolog(fd); return 0; } argc = elem_count(*argvp); /* extra element for hashbang argument */ new_argv = calloc(argc + 3, sizeof(char *)); /* skip any initial whitespace following "#!" */ for (i = 2; (hashbang[i] == ' ' || hashbang[i] == '\t') && i < c; i++) ; for (n = 0, j = i; i < c; i++) { ch = hashbang[i]; if (hashbang[i] == 0 || hashbang[i] == ' ' || hashbang[i] == '\t' || hashbang[i] == '\n') { hashbang[i] = 0; if (i > j) { if (n == 0) { char *ptr = &hashbang[j]; strcpy(interpreter, ptr); new_argv[n++] = strdup(interpreter); } else { /* this was the one and only * allowed argument for the * interpreter */ interp_arg = strdup(&hashbang[j]); new_argv[n++] = interp_arg; break; } } j = i + 1; } if (ch == '\n' || ch == 0) break; } new_argv[n++] = strdup(orig_file); /* the unmapped script path */ for (i = 1; (*argvp)[i] != NULL && i < argc; ) { new_argv[n++] = (*argvp)[i++]; } new_argv[n] = NULL; /* Now we need to update __SB2_ORIG_BINARYNAME to point to * the unmapped script interpreter (exec_map_script_interpreter * may change it again (not currently, but in the future) */ change_environment_variable( *envpp, "__SB2_ORIG_BINARYNAME=", interpreter); /* script interpreter mapping in C */ exec_policy_handle_t eph = find_exec_policy_handle(exec_policy_name); int c_mapping_result_code; const char *c_new_exec_policy_name = NULL; c_mapping_result_code = exec_map_script_interpreter(eph, exec_policy_name, interpreter, interp_arg, *mapped_file, orig_file, new_argv, &c_new_exec_policy_name, &mapped_interpreter); SB_LOG(SB_LOGLEVEL_DEBUG, "back from exec_map_script_interpreter => %d (%s)", c_mapping_result_code, (mapped_interpreter ? mapped_interpreter : "<NULL>")); switch (c_mapping_result_code) { case 0: /* exec arguments were modified, argv has been modified */ SB_LOG(SB_LOGLEVEL_DEBUG, "%s: <0> argv has been updated", __func__); break; case 1: SB_LOG(SB_LOGLEVEL_DEBUG, "%s: <1> argv was not modified", __func__); break; case 2: SB_LOG(SB_LOGLEVEL_DEBUG, "%s: <2> Use ordinary path mapping", __func__); if (mapped_interpreter) free(mapped_interpreter); mapped_interpreter = NULL; { mapping_results_t mapping_result; clear_mapping_results_struct(&mapping_result); sbox_map_path_for_exec("script_interp", interpreter, &mapping_result); if (mapping_result.mres_result_buf) { mapped_interpreter = strdup(mapping_result.mres_result_buf); } if (mapping_result.mres_exec_policy_name) c_new_exec_policy_name = strdup(mapping_result.mres_exec_policy_name); else c_new_exec_policy_name = NULL; free_mapping_results(&mapping_result); } SB_LOG(SB_LOGLEVEL_DEBUG, "%s: " "interpreter=%s mapped_interpreter=%s policy=%s", __func__, interpreter, mapped_interpreter, c_new_exec_policy_name ? c_new_exec_policy_name : "NULL"); break; case -1: SB_LOG(SB_LOGLEVEL_DEBUG, "%s: <-1> exec denied", __func__); if (mapped_interpreter) free(mapped_interpreter); mapped_interpreter = NULL; return(-1); default: SB_LOG(SB_LOGLEVEL_ERROR, "%s: Unsupported result %d", __func__, c_mapping_result_code); return(-1); } exec_policy_name = c_new_exec_policy_name; if (!mapped_interpreter) { SB_LOG(SB_LOGLEVEL_ERROR, "failed to map script interpreter=%s", interpreter); return(-1); } /* * Binaryname (the one expected by the rules) comes still from * the interpreter name so we set it here. Note that it is now * basename of the mapped interpreter (not the original one)! */ tmp = strdup(mapped_interpreter); mapped_binaryname = strdup(basename(tmp)); change_environment_variable(*envpp, "__SB2_BINARYNAME=", mapped_binaryname); free(mapped_binaryname); free(tmp); SB_LOG(SB_LOGLEVEL_DEBUG, "prepare_hashbang(): interpreter=%s," "mapped_interpreter=%s", interpreter, mapped_interpreter); /* feed this through prepare_exec to let it deal with * cpu transparency etc. */ result = prepare_exec("run_hashbang", exec_policy_name, mapped_interpreter, 1/*file_has_been_mapped, and rue&policy exist*/, new_argv, *envpp, (enum binary_type*)NULL, mapped_file, argvp, envpp); SB_LOG(SB_LOGLEVEL_DEBUG, "prepare_hashbang done: mapped_file='%s'", *mapped_file); return(result); }
int do_exec(int *result_errno_ptr, const char *exec_fn_name, const char *orig_file, char *const *orig_argv, char *const *orig_envp) { char *new_file = NULL; char **new_argv = NULL; char **new_envp = NULL; int result; PROCESSCLOCK(clk1) START_PROCESSCLOCK(SB_LOGLEVEL_INFO, &clk1, "do_exec"); if (getenv("SBOX_DISABLE_MAPPING")) { /* just run it, don't worry, be happy! */ } else { int r; char **my_envp_copy = NULL; /* used only for debug log */ char *tmp, *binaryname; enum binary_type type; tmp = strdup(orig_file); binaryname = strdup(basename(tmp)); /* basename may modify *tmp */ free(tmp); if (SB_LOG_IS_ACTIVE(SB_LOGLEVEL_DEBUG)) { char *buf = strvec_to_string(orig_argv); SB_LOG(SB_LOGLEVEL_DEBUG, "EXEC/Orig.args: %s : %s", orig_file, buf); free(buf); /* create a copy of intended environment for logging, * before preprocessing */ my_envp_copy = prepare_envp_for_do_exec(orig_file, binaryname, orig_envp); } new_envp = prepare_envp_for_do_exec(orig_file, binaryname, orig_envp); r = prepare_exec(exec_fn_name, NULL/*exec_policy_name: not yet known*/, orig_file, 0, orig_argv, orig_envp, &type, &new_file, &new_argv, &new_envp); if (SB_LOG_IS_ACTIVE(SB_LOGLEVEL_DEBUG)) { /* find out and log if preprocessing did something */ compare_and_log_strvec_changes("argv", orig_argv, new_argv); compare_and_log_strvec_changes("envp", my_envp_copy, new_envp); } if (r < 0) { SB_LOG(SB_LOGLEVEL_DEBUG, "EXEC denied by prepare_exec(), %s", orig_file); *result_errno_ptr = errno; STOP_AND_REPORT_PROCESSCLOCK(SB_LOGLEVEL_INFO, &clk1, "Exec denied"); return(r); /* exec denied */ } if (check_envp_has_ld_preload_and_ld_library_path( new_envp ? new_envp : orig_envp) == 0) { SB_LOG(SB_LOGLEVEL_ERROR, "exec(%s) failed, internal configuration error: " "LD_LIBRARY_PATH and/or LD_PRELOAD were not set " "by exec mapping logic", orig_file); *result_errno_ptr = EINVAL; STOP_AND_REPORT_PROCESSCLOCK(SB_LOGLEVEL_INFO, &clk1, "Config error"); return(-1); } } errno = *result_errno_ptr; /* restore to orig.value */ STOP_AND_REPORT_PROCESSCLOCK(SB_LOGLEVEL_INFO, &clk1, orig_file); result = sb_next_execve( (new_file ? new_file : orig_file), (new_argv ? new_argv : orig_argv), (new_envp ? new_envp : orig_envp)); *result_errno_ptr = errno; SB_LOG(SB_LOGLEVEL_DEBUG, "EXEC failed (%s), errno=%d", orig_file, *result_errno_ptr); return(result); }