diff --git a/core/utils.c b/core/utils.c index f376dcbd..081f770d 100644 --- a/core/utils.c +++ b/core/utils.c @@ -371,17 +371,23 @@ void uwsgi_as_root() { } // now run the scripts needed by root - struct uwsgi_string_list *usl = uwsgi.exec_as_root; - while (usl) { + struct uwsgi_string_list *usl; + uwsgi_foreach(usl, uwsgi.exec_as_root) { uwsgi_log("running \"%s\" (as root)...\n", usl->value); int ret = uwsgi_run_command_and_wait(NULL, usl->value); if (ret != 0) { uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret); exit(1); } - usl = usl->next; } + uwsgi_foreach(usl, uwsgi.call_as_root) { + if (uwsgi_call_symbol(usl->value)) { + uwsgi_log("unaable to call function \"%s\"\n", usl->value); + } + } + + if (uwsgi.gidname) { struct group *ugroup = getgrnam(uwsgi.gidname); if (ugroup) { @@ -537,17 +543,21 @@ void uwsgi_as_root() { #endif // now run the scripts needed by the user - usl = uwsgi.exec_as_user; - while (usl) { + uwsgi_foreach(usl, uwsgi.exec_as_user) { uwsgi_log("running \"%s\" (as uid: %d gid: %d) ...\n", usl->value, (int) getuid(), (int) getgid()); int ret = uwsgi_run_command_and_wait(NULL, usl->value); if (ret != 0) { uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret); exit(1); } - usl = usl->next; } + uwsgi_foreach(usl, uwsgi.call_as_user) { + if (uwsgi_call_symbol(usl->value)) { + uwsgi_log("unaable to call function \"%s\"\n", usl->value); + } + } + // we could now patch the binary if (uwsgi.unprivileged_binary_patch) { uwsgi.argv[0] = uwsgi.unprivileged_binary_patch; @@ -3304,6 +3314,13 @@ error: return -1; } +int uwsgi_call_symbol(char *symbol) { + void (*func)(void) = dlsym(RTLD_DEFAULT, symbol); + if (!func) return -1; + func(); + return 0; +} + int uwsgi_plugin_modifier1(char *plugin) { int ret = -1; char *symbol_name = uwsgi_concat2(plugin, "_plugin"); diff --git a/core/uwsgi.c b/core/uwsgi.c index 7d03e576..9b1288f3 100644 --- a/core/uwsgi.c +++ b/core/uwsgi.c @@ -296,6 +296,7 @@ static struct uwsgi_option uwsgi_base_options[] = { #ifdef __linux__ {"unshare", required_argument, 0, "unshare() part of the processes and put it in a new namespace", uwsgi_opt_set_unshare, 0}, #endif + {"exec-pre-jail", required_argument, 0, "run the specified command before jailing", uwsgi_opt_add_string_list, &uwsgi.exec_pre_jail, 0}, {"exec-post-jail", required_argument, 0, "run the specified command after jailing", uwsgi_opt_add_string_list, &uwsgi.exec_post_jail, 0}, {"exec-in-jail", required_argument, 0, "run the specified command in jail after initialization", uwsgi_opt_add_string_list, &uwsgi.exec_in_jail, 0}, @@ -304,6 +305,18 @@ static struct uwsgi_option uwsgi_base_options[] = { {"exec-as-user-atexit", required_argument, 0, "run the specified command before app exit and reload", uwsgi_opt_add_string_list, &uwsgi.exec_as_user_atexit, 0}, {"exec-pre-app", required_argument, 0, "run the specified command before app loading", uwsgi_opt_add_string_list, &uwsgi.exec_pre_app, 0}, {"exec-post-app", required_argument, 0, "run the specified command after app loading", uwsgi_opt_add_string_list, &uwsgi.exec_post_app, 0}, + + {"call-pre-jail", required_argument, 0, "call the specified function before jailing", uwsgi_opt_add_string_list, &uwsgi.call_pre_jail, 0}, + {"call-post-jail", required_argument, 0, "call the specified function after jailing", uwsgi_opt_add_string_list, &uwsgi.call_post_jail, 0}, + {"call-in-jail", required_argument, 0, "call the specified function in jail after initialization", uwsgi_opt_add_string_list, &uwsgi.call_in_jail, 0}, + {"call-as-root", required_argument, 0, "call the specified function before privileges drop", uwsgi_opt_add_string_list, &uwsgi.call_as_root, 0}, + {"call-as-user", required_argument, 0, "call the specified function after privileges drop", uwsgi_opt_add_string_list, &uwsgi.call_as_user, 0}, + {"call-as-user-atexit", required_argument, 0, "call the specified function before app exit and reload", uwsgi_opt_add_string_list, &uwsgi.call_as_user_atexit, 0}, + {"call-pre-app", required_argument, 0, "call the specified function before app loading", uwsgi_opt_add_string_list, &uwsgi.call_pre_app, 0}, + {"call-post-app", required_argument, 0, "call the specified function after app loading", uwsgi_opt_add_string_list, &uwsgi.call_post_app, 0}, + + + {"ini", required_argument, 0, "load config from ini file", uwsgi_opt_load_ini, NULL, UWSGI_OPT_IMMEDIATE}, #ifdef UWSGI_YAML {"yaml", required_argument, 'y', "load config from yaml file", uwsgi_opt_load_yml, NULL, UWSGI_OPT_IMMEDIATE}, @@ -1322,15 +1335,21 @@ struct uwsgi_plugin unconfigured_plugin = { void uwsgi_exec_atexit(void) { if (getpid() == masterpid) { // now run exit scripts needed by the user - struct uwsgi_string_list *usl = uwsgi.exec_as_user_atexit; - while (usl) { + struct uwsgi_string_list *usl; + + uwsgi_foreach(usl, uwsgi.exec_as_user_atexit) { uwsgi_log("running \"%s\" (as uid: %d gid: %d) ...\n", usl->value, (int) getuid(), (int) getgid()); int ret = uwsgi_run_command_and_wait(NULL, usl->value); if (ret != 0) { uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret); } - usl = usl->next; } + + uwsgi_foreach(usl, uwsgi.call_as_user_atexit) { + if (uwsgi_call_symbol(usl->value)) { + uwsgi_log("unaable to call function \"%s\"\n", usl->value); + } + } } } @@ -2119,6 +2138,12 @@ int main(int argc, char *argv[], char *envp[]) { usl = usl->next; } + uwsgi_foreach(usl, uwsgi.call_pre_jail) { + if (uwsgi_call_symbol(usl->value)) { + uwsgi_log("unaable to call function \"%s\"\n", usl->value); + } + } + // we could now patch the binary if (uwsgi.privileged_binary_patch) { uwsgi.argv[0] = uwsgi.privileged_binary_patch; @@ -2171,6 +2196,23 @@ int uwsgi_start(void *v_argv) { } #endif + struct uwsgi_string_list *usl; + uwsgi_foreach(usl, uwsgi.exec_in_jail) { + uwsgi_log("running \"%s\" (in-jail)...\n", usl->value); + int ret = uwsgi_run_command_and_wait(NULL, usl->value); + if (ret != 0) { + uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret); + exit(1); + } + } + + uwsgi_foreach(usl, uwsgi.call_in_jail) { + if (uwsgi_call_symbol(usl->value)) { + uwsgi_log("unaable to call function \"%s\"\n", usl->value); + } + } + + uwsgi_file_write_do(uwsgi.file_write_list); if (!uwsgi.master_as_root && !uwsgi.chown_socket) { @@ -3229,6 +3271,12 @@ void uwsgi_init_all_apps() { usl = usl->next; } + uwsgi_foreach(usl, uwsgi.call_pre_app) { + if (uwsgi_call_symbol(usl->value)) { + uwsgi_log("unaable to call function \"%s\"\n", usl->value); + } + } + for (i = 0; i < 256; i++) { if (uwsgi.p[i]->init_apps) { @@ -3288,6 +3336,11 @@ void uwsgi_init_all_apps() { usl = usl->next; } + uwsgi_foreach(usl, uwsgi.call_post_app) { + if (uwsgi_call_symbol(usl->value)) { + uwsgi_log("unaable to call function \"%s\"\n", usl->value); + } + } } diff --git a/lib/linux_ns.c b/lib/linux_ns.c index ca65c445..3814d56c 100644 --- a/lib/linux_ns.c +++ b/lib/linux_ns.c @@ -82,6 +82,12 @@ void linux_namespace_start(void *argv) { usl = usl->next; } + uwsgi_foreach(usl, uwsgi.call_post_jail) { + if (uwsgi_call_symbol(usl->value)) { + uwsgi_log("unaable to call function \"%s\"\n", usl->value); + } + } + uwsgi_log("waiting for jailed master (pid: %d) death...\n", (int) pid); pid = waitpid(pid, &waitpid_status, 0); if (pid < 0) { diff --git a/uwsgi.h b/uwsgi.h index 2c36294b..4f591846 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -130,6 +130,7 @@ extern "C" { uwsgi.gp_cnt++;\ }\ +#define uwsgi_foreach(x, y) for(x=y;x;x = x->next) #ifndef __need_IOV_MAX @@ -1889,6 +1890,15 @@ struct uwsgi_server { struct uwsgi_string_list *exec_pre_app; struct uwsgi_string_list *exec_post_app; + struct uwsgi_string_list *call_pre_jail; + struct uwsgi_string_list *call_post_jail; + struct uwsgi_string_list *call_in_jail; + struct uwsgi_string_list *call_as_root; + struct uwsgi_string_list *call_as_user; + struct uwsgi_string_list *call_as_user_atexit; + struct uwsgi_string_list *call_pre_app; + struct uwsgi_string_list *call_post_app; + char *privileged_binary_patch; char *unprivileged_binary_patch; char *privileged_binary_patch_arg; @@ -3121,6 +3131,7 @@ void uwsgi_add_sockets_to_queue(int, int); void uwsgi_del_sockets_from_queue(int); int uwsgi_run_command_and_wait(char *, char *); +int uwsgi_call_symbol(char *); void uwsgi_manage_signal_cron(time_t); pid_t uwsgi_run_command(char *, int *, int);