From 752f66bf7d70fae2bf05fbf5941ff4be52b2b9a5 Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Wed, 13 Dec 2017 20:40:53 +0300 Subject: Retain CAP_NET_RAW capability for transparent proxying. The capability is retained automatically in unprivileged worker processes after changing UID if transparent proxying is enabled at least once in nginx configuration. The feature is only available in Linux. --- src/os/unix/ngx_process_cycle.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'src/os/unix/ngx_process_cycle.c') diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c index a20a515c7..40654b3a2 100644 --- a/src/os/unix/ngx_process_cycle.c +++ b/src/os/unix/ngx_process_cycle.c @@ -839,12 +839,44 @@ ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker) ccf->username, ccf->group); } +#if (NGX_HAVE_PR_SET_KEEPCAPS && NGX_HAVE_CAPABILITIES) + if (ccf->transparent && ccf->user) { + if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) { + ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, + "prctl(PR_SET_KEEPCAPS, 1) failed"); + /* fatal */ + exit(2); + } + } +#endif + if (setuid(ccf->user) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "setuid(%d) failed", ccf->user); /* fatal */ exit(2); } + +#if (NGX_HAVE_CAPABILITIES) + if (ccf->transparent && ccf->user) { + struct __user_cap_data_struct data; + struct __user_cap_header_struct header; + + ngx_memzero(&header, sizeof(struct __user_cap_header_struct)); + ngx_memzero(&data, sizeof(struct __user_cap_data_struct)); + + header.version = _LINUX_CAPABILITY_VERSION_3; + data.effective = CAP_TO_MASK(CAP_NET_RAW); + data.permitted = data.effective; + + if (capset(&header, &data) == -1) { + ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, + "capset() failed"); + /* fatal */ + exit(2); + } + } +#endif } if (worker >= 0) { -- cgit v1.2.3