Core: fixed environment on exit.

On exit environment allocated from a pool is no longer available, leading
to a segmentation fault if, for example, a library tries to use it from
an atexit() handler.

Fix is to allocate environment via ngx_alloc() instead, and explicitly
free it using a pool cleanup handler if it's no longer used (e.g., on
configuration reload).
This commit is contained in:
Maxim Dounin 2016-12-07 19:03:31 +03:00
parent 0a90c428b8
commit 23946be384

View File

@ -12,6 +12,7 @@
static void ngx_show_version_info(void);
static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle);
static void ngx_cleanup_environment(void *data);
static ngx_int_t ngx_get_options(int argc, char *const *argv);
static ngx_int_t ngx_process_options(ngx_cycle_t *cycle);
static ngx_int_t ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv);
@ -499,6 +500,7 @@ ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last)
ngx_str_t *var;
ngx_uint_t i, n;
ngx_core_conf_t *ccf;
ngx_pool_cleanup_t *cln;
ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
@ -550,16 +552,27 @@ tz_found:
if (last) {
env = ngx_alloc((*last + n + 1) * sizeof(char *), cycle->log);
if (env == NULL) {
return NULL;
}
*last = n;
} else {
env = ngx_palloc(cycle->pool, (n + 1) * sizeof(char *));
cln = ngx_pool_cleanup_add(cycle->pool, 0);
if (cln == NULL) {
return NULL;
}
env = ngx_alloc((n + 1) * sizeof(char *), cycle->log);
if (env == NULL) {
return NULL;
}
cln->handler = ngx_cleanup_environment;
cln->data = env;
}
n = 0;
for (i = 0; i < ccf->env.nelts; i++) {
@ -591,6 +604,25 @@ tz_found:
}
static void
ngx_cleanup_environment(void *data)
{
char **env = data;
if (environ == env) {
/*
* if the environment is still used, as it happens on exit,
* the only option is to leak it
*/
return;
}
ngx_free(env);
}
ngx_pid_t
ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv)
{