diff --git a/core/emperor.c b/core/emperor.c index 3944a01a..b59fb299 100644 --- a/core/emperor.c +++ b/core/emperor.c @@ -790,15 +790,10 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha } } +static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *); int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) { - int i; - char *colon = NULL; - int counter; - char **uenvs; - char *uef; - char **vassal_argv; pid_t pid; if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe)) { @@ -822,7 +817,17 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) { // TODO pre-start hook // a new uWSGI instance will start +#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL) + if (uwsgi.emperor_clone) { + char stack[PTHREAD_STACK_MIN]; + pid = clone((int (*)(void *))uwsgi_emperor_spawn_vassal, stack + PTHREAD_STACK_MIN, SIGCHLD | uwsgi.emperor_clone, (void *) n_ui); + } + else { +#endif pid = fork(); +#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL) + } +#endif if (pid < 0) { uwsgi_error("fork()") } @@ -857,6 +862,12 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) { return 0; } else { + uwsgi_emperor_spawn_vassal(n_ui); + } + return -1; +} + +static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) { if (uwsgi.emperor_tyrant) { uwsgi_log("[emperor-tyrant] dropping privileges to %d %d for instance %s\n", (int) n_ui->uid, (int) n_ui->gid, n_ui->name); @@ -879,7 +890,7 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) { unsetenv("UWSGI_RELOADS"); unsetenv("NOTIFY_SOCKET"); - uef = uwsgi_num2str(n_ui->pipe[1]); + char *uef = uwsgi_num2str(n_ui->pipe[1]); if (setenv("UWSGI_EMPEROR_FD", uef, 1)) { uwsgi_error("setenv()"); exit(1); @@ -905,7 +916,7 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) { free(uef); } - uenvs = environ; + char **uenvs = environ; while (*uenvs) { if (!strncmp(*uenvs, "UWSGI_VASSAL_", 13) && strchr(*uenvs, '=')) { char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0), *ne; @@ -942,17 +953,19 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) { close(n_ui->pipe_config[0]); } - counter = 4; + int counter = 4; struct uwsgi_string_list *uct = uwsgi.vassals_templates; while (uct) { counter += 2; uct = uct->next; } - vassal_argv = uwsgi_malloc(sizeof(char *) * counter); + char **vassal_argv = uwsgi_malloc(sizeof(char *) * counter); // set args vassal_argv[0] = uwsgi.binary_path; + char *colon = NULL; + if (uwsgi.emperor_broodlord) { colon = strchr(n_ui->name, ':'); if (colon) { @@ -1037,6 +1050,7 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) { } // close all of the unneded fd + int i; for (i = 3; i < (int) uwsgi.max_fd; i++) { if (uwsgi_fd_is_safe(i)) continue; if (n_ui->use_config) { @@ -1094,9 +1108,6 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) { uwsgi_log("[emperor] is the uwsgi binary in your system PATH ?\n"); // never here exit(UWSGI_EXILE_CODE); - } - - return -1; } void uwsgi_imperial_monitor_glob_init(struct uwsgi_emperor_scanner *ues) { diff --git a/core/utils.c b/core/utils.c index 4ebe5744..c46996ce 100644 --- a/core/utils.c +++ b/core/utils.c @@ -2413,7 +2413,7 @@ static int uwsgi_get_unshare_id(char *name) { return -1; } -void uwsgi_build_unshare(char *what) { +void uwsgi_build_unshare(char *what, int *mask) { char *list = uwsgi_str(what); @@ -2421,7 +2421,7 @@ void uwsgi_build_unshare(char *what) { while (p != NULL) { int u_id = uwsgi_get_unshare_id(p); if (u_id != -1) { - uwsgi.unshare |= u_id; + *mask |= u_id; } p = strtok(NULL, ","); } diff --git a/core/uwsgi.c b/core/uwsgi.c index 454dad9d..50d88c87 100644 --- a/core/uwsgi.c +++ b/core/uwsgi.c @@ -194,6 +194,9 @@ static struct uwsgi_option uwsgi_base_options[] = { {"emperor-on-demand-exec", required_argument, 0, "use the output of the specified command as on demand socket name (the vassal name is passed as the only argument)", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_exec, 0}, {"emperor-extra-extension", required_argument, 0, "allows the specified extension in the Emperor (vassal will be called with --config)", uwsgi_opt_add_string_list, &uwsgi.emperor_extra_extension, 0}, {"emperor-extra-ext", required_argument, 0, "allows the specified extension in the Emperor (vassal will be called with --config)", uwsgi_opt_add_string_list, &uwsgi.emperor_extra_extension, 0}, +#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL) + {"emperor-use-clone", required_argument, 0, "use clone() instead of fork() passing the specified unshare() flags", uwsgi_opt_set_unshare, &uwsgi.emperor_clone, 0}, +#endif {"imperial-monitor-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0}, {"imperial-monitors-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0}, {"vassals-inherit", required_argument, 0, "add config templates to vassals config", uwsgi_opt_add_string_list, &uwsgi.vassals_templates, 0}, @@ -295,7 +298,7 @@ static struct uwsgi_option uwsgi_base_options[] = { {"cap", required_argument, 0, "set process capability", uwsgi_opt_set_cap, NULL, 0}, #endif #ifdef __linux__ - {"unshare", required_argument, 0, "unshare() part of the processes and put it in a new namespace", uwsgi_opt_set_unshare, NULL, 0}, + {"unshare", required_argument, 0, "unshare() part of the processes and put it in a new namespace", uwsgi_opt_set_unshare, &uwsgi.unshare, 0}, #endif {"refork", no_argument, 0, "fork() again after privileges drop. Useful for jailing systems", uwsgi_opt_true, &uwsgi.refork, 0}, {"re-fork", no_argument, 0, "fork() again after privileges drop. Useful for jailing systems", uwsgi_opt_true, &uwsgi.refork, 0}, @@ -3785,8 +3788,8 @@ void uwsgi_opt_set_cap(char *opt, char *value, void *none) { } #endif #ifdef __linux__ -void uwsgi_opt_set_unshare(char *opt, char *value, void *none) { - uwsgi_build_unshare(value); +void uwsgi_opt_set_unshare(char *opt, char *value, void *mask) { + uwsgi_build_unshare(value, (int *) mask); } #endif diff --git a/uwsgi.h b/uwsgi.h index c9f0bc24..d329898d 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -1808,6 +1808,7 @@ struct uwsgi_server { #ifdef __linux__ int unshare; + int emperor_clone; #endif int refork; @@ -3283,7 +3284,7 @@ int uwsgi_is_bad_connection(int); int uwsgi_long2str2n(unsigned long long, char *, int); #ifdef __linux__ -void uwsgi_build_unshare(char *); +void uwsgi_build_unshare(char *, int *); #ifdef MADV_MERGEABLE void uwsgi_linux_ksm_map(void); #endif