comparison src/core/nginx.c @ 6822:c045b4926b2c

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).
author Maxim Dounin <mdounin@mdounin.ru>
date Wed, 07 Dec 2016 19:03:31 +0300
parents 3b77efe05b92
children 97c99bb43737
comparison
equal deleted inserted replaced
6821:30b6f1ff192b 6822:c045b4926b2c
10 #include <nginx.h> 10 #include <nginx.h>
11 11
12 12
13 static void ngx_show_version_info(void); 13 static void ngx_show_version_info(void);
14 static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle); 14 static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle);
15 static void ngx_cleanup_environment(void *data);
15 static ngx_int_t ngx_get_options(int argc, char *const *argv); 16 static ngx_int_t ngx_get_options(int argc, char *const *argv);
16 static ngx_int_t ngx_process_options(ngx_cycle_t *cycle); 17 static ngx_int_t ngx_process_options(ngx_cycle_t *cycle);
17 static ngx_int_t ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv); 18 static ngx_int_t ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv);
18 static void *ngx_core_module_create_conf(ngx_cycle_t *cycle); 19 static void *ngx_core_module_create_conf(ngx_cycle_t *cycle);
19 static char *ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf); 20 static char *ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf);
493 494
494 495
495 char ** 496 char **
496 ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last) 497 ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last)
497 { 498 {
498 char **p, **env; 499 char **p, **env;
499 ngx_str_t *var; 500 ngx_str_t *var;
500 ngx_uint_t i, n; 501 ngx_uint_t i, n;
501 ngx_core_conf_t *ccf; 502 ngx_core_conf_t *ccf;
503 ngx_pool_cleanup_t *cln;
502 504
503 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); 505 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
504 506
505 if (last == NULL && ccf->environment) { 507 if (last == NULL && ccf->environment) {
506 return ccf->environment; 508 return ccf->environment;
548 } 550 }
549 } 551 }
550 552
551 if (last) { 553 if (last) {
552 env = ngx_alloc((*last + n + 1) * sizeof(char *), cycle->log); 554 env = ngx_alloc((*last + n + 1) * sizeof(char *), cycle->log);
555 if (env == NULL) {
556 return NULL;
557 }
558
553 *last = n; 559 *last = n;
554 560
555 } else { 561 } else {
556 env = ngx_palloc(cycle->pool, (n + 1) * sizeof(char *)); 562 cln = ngx_pool_cleanup_add(cycle->pool, 0);
557 } 563 if (cln == NULL) {
558 564 return NULL;
559 if (env == NULL) { 565 }
560 return NULL; 566
567 env = ngx_alloc((n + 1) * sizeof(char *), cycle->log);
568 if (env == NULL) {
569 return NULL;
570 }
571
572 cln->handler = ngx_cleanup_environment;
573 cln->data = env;
561 } 574 }
562 575
563 n = 0; 576 n = 0;
564 577
565 for (i = 0; i < ccf->env.nelts; i++) { 578 for (i = 0; i < ccf->env.nelts; i++) {
586 ccf->environment = env; 599 ccf->environment = env;
587 environ = env; 600 environ = env;
588 } 601 }
589 602
590 return env; 603 return env;
604 }
605
606
607 static void
608 ngx_cleanup_environment(void *data)
609 {
610 char **env = data;
611
612 if (environ == env) {
613
614 /*
615 * if the environment is still used, as it happens on exit,
616 * the only option is to leak it
617 */
618
619 return;
620 }
621
622 ngx_free(env);
591 } 623 }
592 624
593 625
594 ngx_pid_t 626 ngx_pid_t
595 ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv) 627 ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv)