diff --git a/src/core/nginx.c b/src/core/nginx.c index 60f8fe7..4bd244b 100644 --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -981,6 +981,7 @@ ngx_core_module_create_conf(ngx_cycle_t *cycle) ccf->daemon = NGX_CONF_UNSET; ccf->master = NGX_CONF_UNSET; + ccf->privileged_agent = NGX_CONF_UNSET; ccf->timer_resolution = NGX_CONF_UNSET_MSEC; ccf->worker_processes = NGX_CONF_UNSET; @@ -1009,6 +1010,7 @@ ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf) ngx_conf_init_value(ccf->daemon, 1); ngx_conf_init_value(ccf->master, 1); + ngx_conf_init_value(ccf->privileged_agent, 0); ngx_conf_init_msec_value(ccf->timer_resolution, 0); ngx_conf_init_value(ccf->worker_processes, 1); diff --git a/src/core/ngx_cycle.h b/src/core/ngx_cycle.h index c51b7ff..3261f90 100644 --- a/src/core/ngx_cycle.h +++ b/src/core/ngx_cycle.h @@ -22,6 +22,9 @@ #define NGX_DEBUG_POINTS_ABORT 2 +#define HAVE_PRIVILEGED_PROCESS_PATCH 1 + + typedef struct ngx_shm_zone_s ngx_shm_zone_t; typedef ngx_int_t (*ngx_shm_zone_init_pt) (ngx_shm_zone_t *zone, void *data); @@ -81,6 +84,7 @@ struct ngx_cycle_s { typedef struct { ngx_flag_t daemon; ngx_flag_t master; + ngx_flag_t privileged_agent; ngx_msec_t timer_resolution; diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c index 7cee1c5..c4f70d6 100644 --- a/src/os/unix/ngx_process_cycle.c +++ b/src/os/unix/ngx_process_cycle.c @@ -15,6 +15,8 @@ static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type); static void ngx_start_cache_manager_processes(ngx_cycle_t *cycle, ngx_uint_t respawn); +static void ngx_start_privileged_agent_processes(ngx_cycle_t *cycle, + ngx_uint_t respawn); static void ngx_pass_open_channel(ngx_cycle_t *cycle, ngx_channel_t *ch); static void ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo); static ngx_uint_t ngx_reap_children(ngx_cycle_t *cycle); @@ -24,6 +26,7 @@ static void ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker); static void ngx_worker_process_exit(ngx_cycle_t *cycle); static void ngx_channel_handler(ngx_event_t *ev); static void ngx_cache_manager_process_cycle(ngx_cycle_t *cycle, void *data); +static void ngx_privileged_agent_process_cycle(ngx_cycle_t *cycle, void *data); static void ngx_cache_manager_process_handler(ngx_event_t *ev); static void ngx_cache_loader_process_handler(ngx_event_t *ev); @@ -51,6 +54,8 @@ sig_atomic_t ngx_noaccept; ngx_uint_t ngx_noaccepting; ngx_uint_t ngx_restart; +ngx_uint_t ngx_is_privileged_agent; + static u_char master_process[] = "master process"; @@ -130,6 +135,7 @@ ngx_master_process_cycle(ngx_cycle_t *cycle) ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); ngx_start_cache_manager_processes(cycle, 0); + ngx_start_privileged_agent_processes(cycle, 0); ngx_new_binary = 0; delay = 0; @@ -224,6 +230,7 @@ ngx_master_process_cycle(ngx_cycle_t *cycle) ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); ngx_start_cache_manager_processes(cycle, 0); + ngx_start_privileged_agent_processes(cycle, 0); ngx_noaccepting = 0; continue; @@ -243,6 +250,7 @@ ngx_master_process_cycle(ngx_cycle_t *cycle) ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_JUST_RESPAWN); ngx_start_cache_manager_processes(cycle, 1); + ngx_start_privileged_agent_processes(cycle, 1); /* allow new processes to start */ ngx_msleep(100); @@ -257,6 +265,7 @@ ngx_master_process_cycle(ngx_cycle_t *cycle) ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); ngx_start_cache_manager_processes(cycle, 0); + ngx_start_privileged_agent_processes(cycle, 0); live = 1; } @@ -424,6 +433,34 @@ ngx_start_cache_manager_processes(ngx_cycle_t *cycle, ngx_uint_t respawn) static void +ngx_start_privileged_agent_processes(ngx_cycle_t *cycle, ngx_uint_t respawn) +{ + ngx_channel_t ch; + ngx_core_conf_t *ccf; + + ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, + ngx_core_module); + + if (!ccf->privileged_agent) { + return; + } + + ngx_spawn_process(cycle, ngx_privileged_agent_process_cycle, + "privileged agent process", "privileged agent process", + respawn ? NGX_PROCESS_JUST_RESPAWN : NGX_PROCESS_RESPAWN); + + ngx_memzero(&ch, sizeof(ngx_channel_t)); + + ch.command = NGX_CMD_OPEN_CHANNEL; + ch.pid = ngx_processes[ngx_process_slot].pid; + ch.slot = ngx_process_slot; + ch.fd = ngx_processes[ngx_process_slot].channel[0]; + + ngx_pass_open_channel(cycle, &ch); +} + + +static void ngx_pass_open_channel(ngx_cycle_t *cycle, ngx_channel_t *ch) { ngx_int_t i; @@ -827,7 +864,10 @@ ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker) } } - if (geteuid() == 0) { + /* + * privileged agent process has the same permission as master process + */ + if (!ngx_is_privileged_agent && geteuid() == 0) { if (setgid(ccf->group) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "setgid(%d) failed", ccf->group); @@ -1144,6 +1184,47 @@ ngx_cache_manager_process_cycle(ngx_cycle_t *cycle, void *data) static void +ngx_privileged_agent_process_cycle(ngx_cycle_t *cycle, void *data) +{ + char *name = data; + + /* + * Set correct process type since closing listening Unix domain socket + * in a master process also removes the Unix domain socket file. + */ + ngx_process = NGX_PROCESS_HELPER; + ngx_is_privileged_agent = 1; + + ngx_close_listening_sockets(cycle); + + /* Set a moderate number of connections for a helper process. */ + cycle->connection_n = 512; + + ngx_worker_process_init(cycle, -1); + + ngx_use_accept_mutex = 0; + + ngx_setproctitle(name); + + for ( ;; ) { + + if (ngx_terminate || ngx_quit) { + ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting"); + ngx_worker_process_exit(cycle); + } + + if (ngx_reopen) { + ngx_reopen = 0; + ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs"); + ngx_reopen_files(cycle, -1); + } + + ngx_process_events_and_timers(cycle); + } +} + + +static void ngx_cache_manager_process_handler(ngx_event_t *ev) { time_t next, n; diff --git a/src/os/unix/ngx_process_cycle.h b/src/os/unix/ngx_process_cycle.h index 69495d5..5149396 100644 --- a/src/os/unix/ngx_process_cycle.h +++ b/src/os/unix/ngx_process_cycle.h @@ -45,6 +45,7 @@ extern ngx_pid_t ngx_new_binary; extern ngx_uint_t ngx_inherited; extern ngx_uint_t ngx_daemonized; extern ngx_uint_t ngx_exiting; +extern ngx_uint_t ngx_is_privileged_agent; extern sig_atomic_t ngx_reap; extern sig_atomic_t ngx_sigio;