diff --git a/nginx-1.20.1-chroot.patch b/nginx-1.20.1-chroot.patch new file mode 100644 index 0000000..3fa5299 --- /dev/null +++ b/nginx-1.20.1-chroot.patch @@ -0,0 +1,243 @@ +diff -uNp -ru nginx-1.20.1.orig/src/core/nginx.c nginx-1.20.1/src/core/nginx.c +--- nginx-1.20.1.orig/src/core/nginx.c Tue May 25 13:35:38 2021 ++++ nginx-1.20.1/src/core/nginx.c Tue May 25 17:49:28 2021 +@@ -182,7 +182,7 @@ ngx_module_t ngx_core_module = { + static ngx_uint_t ngx_show_help; + static ngx_uint_t ngx_show_version; + static ngx_uint_t ngx_show_configure; +-static u_char *ngx_prefix; ++u_char *ngx_prefix; + static u_char *ngx_error_log; + static u_char *ngx_conf_file; + static u_char *ngx_conf_params; +@@ -425,6 +425,8 @@ ngx_show_version_info(void) + ")" NGX_LINEFEED + " -g directives : set global directives out of configuration " + "file" NGX_LINEFEED NGX_LINEFEED ++ " -u : disable chroot(2) " ++ "file" NGX_LINEFEED NGX_LINEFEED + ); + } + +@@ -876,6 +878,10 @@ ngx_get_options(int argc, char *const *argv) + + ngx_log_stderr(0, "invalid option: \"-s %s\"", ngx_signal); + return NGX_ERROR; ++ ++ case 'u': ++ ngx_chrooted = 0; ++ break; + + default: + ngx_log_stderr(0, "invalid option: \"%c\"", *(p - 1)); +diff -uNp -ru nginx-1.20.1.orig/src/core/ngx_cycle.c nginx-1.20.1/src/core/ngx_cycle.c +--- nginx-1.20.1.orig/src/core/ngx_cycle.c Tue May 25 13:35:38 2021 ++++ nginx-1.20.1/src/core/ngx_cycle.c Tue May 25 17:49:09 2021 +@@ -1186,6 +1186,10 @@ ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user) + i = 0; + } + ++ if ((ngx_process == NGX_PROCESS_WORKER) && ngx_chrooted) { ++ ngx_strip_chroot(&file[i].name); ++ } ++ + if (file[i].name.len == 0) { + continue; + } +diff -uNp -ru nginx-1.20.1.orig/src/core/ngx_file.c nginx-1.20.1/src/core/ngx_file.c +--- nginx-1.20.1.orig/src/core/ngx_file.c Tue May 25 13:35:38 2021 ++++ nginx-1.20.1/src/core/ngx_file.c Tue May 25 17:49:09 2021 +@@ -597,12 +597,28 @@ ngx_add_path(ngx_conf_t *cf, ngx_path_t **slot) + ngx_int_t + ngx_create_paths(ngx_cycle_t *cycle, ngx_uid_t user) + { ++ u_char *prefix; + ngx_err_t err; + ngx_uint_t i; + ngx_path_t **path; + + path = cycle->paths.elts; + for (i = 0; i < cycle->paths.nelts; i++) { ++ ++ if (ngx_chrooted) { ++ if (ngx_prefix) ++ prefix = ngx_prefix; ++ else ++ prefix = NGX_PREFIX; ++ if (chdir(prefix) == -1) { ++ ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ++ "chdir(\"%s\") failed", prefix); ++ return NGX_ERROR; ++ } ++ ngx_strip_chroot(&path[i]->name); ++ path[i]->name.data++; ++ path[i]->name.len--; ++ } + + if (ngx_create_dir(path[i]->name.data, 0700) == NGX_FILE_ERROR) { + err = ngx_errno; +diff -uNp -ru nginx-1.20.1.orig/src/core/ngx_string.c nginx-1.20.1/src/core/ngx_string.c +--- nginx-1.20.1.orig/src/core/ngx_string.c Tue May 25 13:35:38 2021 ++++ nginx-1.20.1/src/core/ngx_string.c Tue May 25 17:49:09 2021 +@@ -2084,3 +2084,27 @@ ngx_memcpy(void *dst, const void *src, size_t n) + } + + #endif ++ ++void ++ngx_strip_chroot(ngx_str_t *path) ++{ ++ int plen; ++ u_char *prefix; ++ ++ if (ngx_prefix) ++ prefix = ngx_prefix; ++ else ++ prefix = NGX_PREFIX; ++ ++ if (prefix[strlen(prefix) - 1] == '/') ++ plen = strlen(prefix) - 1; ++ else ++ plen = strlen(prefix); ++ ++ if (!ngx_strncmp(path->data, prefix, strlen(prefix))) { ++ char *x, *buf = malloc(path->len); ++ x = ngx_cpystrn(buf, path->data + plen, path->len); ++ path->len = (x - buf); ++ path->data = buf; ++ } ++} +diff -uNp -ru nginx-1.20.1.orig/src/core/ngx_string.h nginx-1.20.1/src/core/ngx_string.h +--- nginx-1.20.1.orig/src/core/ngx_string.h Tue May 25 13:35:38 2021 ++++ nginx-1.20.1/src/core/ngx_string.h Tue May 25 17:49:09 2021 +@@ -234,5 +234,6 @@ void ngx_sort(void *base, size_t n, size_t size, + #define ngx_value_helper(n) #n + #define ngx_value(n) ngx_value_helper(n) + ++void ngx_strip_chroot(ngx_str_t *root); + + #endif /* _NGX_STRING_H_INCLUDED_ */ +diff -uNp -ru nginx-1.20.1.orig/src/http/modules/ngx_http_auth_basic_module.c nginx-1.20.1/src/http/modules/ngx_http_auth_basic_module.c +--- nginx-1.20.1.orig/src/http/modules/ngx_http_auth_basic_module.c Tue May 25 13:35:38 2021 ++++ nginx-1.20.1/src/http/modules/ngx_http_auth_basic_module.c Tue May 25 17:49:09 2021 +@@ -414,6 +414,10 @@ ngx_http_auth_basic_user_file(ngx_conf_t *cf, ngx_comm + + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + ++ if (ngx_chrooted) { ++ ngx_strip_chroot(&value[1]); ++ } ++ + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = &alcf->user_file; +diff -uNp -ru nginx-1.20.1.orig/src/http/ngx_http_core_module.c nginx-1.20.1/src/http/ngx_http_core_module.c +--- nginx-1.20.1.orig/src/http/ngx_http_core_module.c Tue May 25 13:35:38 2021 ++++ nginx-1.20.1/src/http/ngx_http_core_module.c Tue May 25 17:49:09 2021 +@@ -4351,6 +4351,10 @@ ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, + + value = cf->args->elts; + ++ if (ngx_chrooted && value[1].data != NULL) { ++ ngx_strip_chroot(&value[1]); ++ } ++ + if (ngx_strstr(value[1].data, "$document_root") + || ngx_strstr(value[1].data, "${document_root}")) + { +diff -uNp -ru nginx-1.20.1.orig/src/os/unix/ngx_process.h nginx-1.20.1/src/os/unix/ngx_process.h +--- nginx-1.20.1.orig/src/os/unix/ngx_process.h Tue May 25 13:35:38 2021 ++++ nginx-1.20.1/src/os/unix/ngx_process.h Tue May 25 17:49:09 2021 +@@ -78,6 +78,7 @@ void ngx_debug_point(void); + extern int ngx_argc; + extern char **ngx_argv; + extern char **ngx_os_argv; ++extern u_char *ngx_prefix; + + extern ngx_pid_t ngx_pid; + extern ngx_pid_t ngx_parent; +diff -uNp -ru nginx-1.20.1.orig/src/os/unix/ngx_process_cycle.c nginx-1.20.1/src/os/unix/ngx_process_cycle.c +--- nginx-1.20.1.orig/src/os/unix/ngx_process_cycle.c Tue May 25 13:35:38 2021 ++++ nginx-1.20.1/src/os/unix/ngx_process_cycle.c Tue May 25 17:49:09 2021 +@@ -46,6 +46,7 @@ sig_atomic_t ngx_reopen; + sig_atomic_t ngx_change_binary; + ngx_pid_t ngx_new_binary; + ngx_uint_t ngx_inherited; ++ngx_uint_t ngx_chrooted = 1; + ngx_uint_t ngx_daemonized; + + sig_atomic_t ngx_noaccept; +@@ -754,6 +755,8 @@ ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t + ngx_time_t *tp; + ngx_uint_t i; + ngx_cpuset_t *cpu_affinity; ++ struct passwd *pw; ++ struct stat stb; + struct rlimit rlmt; + ngx_core_conf_t *ccf; + ngx_listening_t *ls; +@@ -795,6 +798,53 @@ ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t + } + + if (geteuid() == 0) { ++ char *prefix; ++ ++ if (!ngx_chrooted) { ++ goto nochroot; ++ } ++ ++ if ((pw = getpwnam(ccf->username)) == NULL) { ++ ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ++ "getpwnam(%s) failed", ccf->username); ++ /* fatal */ ++ exit(2); ++ } ++ ++ if (ngx_prefix) ++ prefix = (char *)ngx_prefix; ++ else ++ prefix = pw->pw_dir; ++ ++ if (stat(prefix, &stb) == -1) { ++ ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ++ "stat(%s) failed", prefix); ++ /* fatal */ ++ exit(2); ++ } ++ ++ if (stb.st_uid != 0 || (stb.st_mode & (S_IWGRP|S_IWOTH)) != 0) { ++ ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ++ "bad privsep dir permissions on %s", prefix); ++ /* fatal */ ++ exit(2); ++ } ++ ++ if (chroot(prefix) == -1) { ++ ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ++ "chroot(%s) failed", prefix); ++ /* fatal */ ++ exit(2); ++ } ++ ++ if (chdir("/") == -1) { ++ ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ++ "chdir(\"/\") failed"); ++ /* fatal */ ++ exit(2); ++ } ++ ++nochroot: + if (setgid(ccf->group) == -1) { + ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, + "setgid(%d) failed", ccf->group); +diff -uNp -ru nginx-1.20.1.orig/src/os/unix/ngx_process_cycle.h nginx-1.20.1/src/os/unix/ngx_process_cycle.h +--- nginx-1.20.1.orig/src/os/unix/ngx_process_cycle.h Tue May 25 13:35:38 2021 ++++ nginx-1.20.1/src/os/unix/ngx_process_cycle.h Tue May 25 17:49:09 2021 +@@ -43,6 +43,7 @@ extern ngx_uint_t ngx_worker; + extern ngx_pid_t ngx_pid; + extern ngx_pid_t ngx_new_binary; + extern ngx_uint_t ngx_inherited; ++extern ngx_uint_t ngx_chrooted; + extern ngx_uint_t ngx_daemonized; + extern ngx_uint_t ngx_exiting; +