diff options
author | Maxim Dounin <mdounin@mdounin.ru> | 2016-12-07 19:03:31 +0300 |
---|---|---|
committer | Maxim Dounin <mdounin@mdounin.ru> | 2016-12-07 19:03:31 +0300 |
commit | 23946be384c42478f3dbc661f60ac0903d1b97f2 (patch) | |
tree | ba5627ec51c71d53d63f042ca56b3cf3777d5428 /src | |
parent | 0a90c428b8be794b9244c8a5f0084f4d19feebbb (diff) | |
download | nginx-23946be384c42478f3dbc661f60ac0903d1b97f2.tar.gz nginx-23946be384c42478f3dbc661f60ac0903d1b97f2.zip |
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).
Diffstat (limited to 'src')
-rw-r--r-- | src/core/nginx.c | 48 |
1 files changed, 40 insertions, 8 deletions
diff --git a/src/core/nginx.c b/src/core/nginx.c index 60f8fe7d4..c5f09a553 100644 --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -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); @@ -495,10 +496,11 @@ ngx_add_inherited_sockets(ngx_cycle_t *cycle) char ** ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last) { - char **p, **env; - ngx_str_t *var; - ngx_uint_t i, n; - ngx_core_conf_t *ccf; + char **p, **env; + 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,14 +552,25 @@ 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; + } - if (env == 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; @@ -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) { |