small feature

David CARLIER devnexen at gmail.com
Wed Oct 7 04:53:45 UTC 2015


Hi all,

I developed a small feature which puts nginx in chroot mode, off by default
and when you set a prefix path via -p, although OpenBSD team did already a
version far before me.

Hope it is useful.

Kind regards.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20151007/96515d1e/attachment.html>
-------------- next part --------------
diff -r 4b4aee40c508 src/core/nginx.c
--- a/src/core/nginx.c	Tue Oct 06 08:57:09 2015 +0300
+++ b/src/core/nginx.c	Wed Oct 07 05:49:50 2015 +0100
@@ -49,6 +49,13 @@
       offsetof(ngx_core_conf_t, master),
       NULL },
 
+    { ngx_string("chroot"),
+      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
+      ngx_conf_set_flag_slot,
+      0,
+      offsetof(ngx_core_conf_t, chroot),
+      NULL },
+
     { ngx_string("timer_resolution"),
       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
       ngx_conf_set_msec_slot,
@@ -967,6 +974,7 @@
 
     ccf->daemon = NGX_CONF_UNSET;
     ccf->master = NGX_CONF_UNSET;
+    ccf->chroot = NGX_CONF_UNSET;
     ccf->timer_resolution = NGX_CONF_UNSET_MSEC;
 
     ccf->worker_processes = NGX_CONF_UNSET;
@@ -984,6 +992,9 @@
         return NULL;
     }
 
+    ccf->chroot_directory.len = NGX_CONF_UNSET_UINT;
+    ccf->chroot_directory.data = NULL;
+
     return ccf;
 }
 
@@ -995,6 +1006,7 @@
 
     ngx_conf_init_value(ccf->daemon, 1);
     ngx_conf_init_value(ccf->master, 1);
+    ngx_conf_init_value(ccf->chroot, 0);
     ngx_conf_init_msec_value(ccf->timer_resolution, 0);
 
     ngx_conf_init_value(ccf->worker_processes, 1);
@@ -1014,7 +1026,6 @@
 
 #endif
 
-
     if (ccf->pid.len == 0) {
         ngx_str_set(&ccf->pid, NGX_PID_PATH);
     }
@@ -1063,6 +1074,19 @@
     }
 
 
+    if (ccf->chroot) {
+        if (ngx_prefix) {
+            ngx_uint_t ngx_prefixlen = ngx_strlen(ngx_prefix);
+            ccf->chroot_directory.len = ngx_prefixlen;
+            ccf->chroot_directory.data = ngx_palloc(cycle->pool, ngx_prefixlen + 1);
+            ngx_memcpy(ccf->chroot_directory.data, ngx_prefix, ngx_prefixlen);
+        } else if(ccf->chroot_directory.len == NGX_CONF_UNSET_UINT) {
+            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
+                    "in chroot mode the prefix path must be set ");
+            return NGX_CONF_ERROR;
+        }
+    }
+
     if (ccf->lock_file.len == 0) {
         ngx_str_set(&ccf->lock_file, NGX_LOCK_PATH);
     }
diff -r 4b4aee40c508 src/core/ngx_cycle.c
--- a/src/core/ngx_cycle.c	Tue Oct 06 08:57:09 2015 +0300
+++ b/src/core/ngx_cycle.c	Wed Oct 07 05:49:50 2015 +0100
@@ -1087,6 +1087,8 @@
     ngx_uint_t        i;
     ngx_list_part_t  *part;
     ngx_open_file_t  *file;
+    ngx_core_conf_t  *ccf = (ngx_core_conf_t *)ngx_get_conf(cycle->conf_ctx,
+            ngx_core_module);
 
     part = &cycle->open_files.part;
     file = part->elts;
@@ -1106,6 +1108,8 @@
             continue;
         }
 
+        ngx_adjust_path(ccf, cycle, &file[i].name);
+
         if (file[i].flush) {
             file[i].flush(&file[i], cycle->log);
         }
@@ -1278,6 +1282,34 @@
     return shm_zone;
 }
 
+void
+ngx_adjust_path(ngx_core_conf_t *ccf, ngx_cycle_t *cycle, ngx_str_t *path)
+{
+    if (!ccf->chroot)
+        return;
+
+    ngx_uint_t cpathlen = path->len;
+    u_char *cpath = path->data;
+    cpath[cpathlen] = '\0';
+
+    if (cycle->prefix.data != NULL) {
+        u_char *prefix = cycle->prefix.data;
+        prefix[cycle->prefix.len] = '\0';
+
+        if (ngx_strnstr(cpath, prefix, cycle->prefix.len)) {
+            cpath += cycle->prefix.len;
+            cpathlen -= cycle->prefix.len;
+        }
+    }
+
+    if (cpath[0] != '/') {
+        u_char *newpath = ngx_palloc(cycle->pool, cpathlen + 2);
+        newpath[0] = '/';
+        ngx_memcpy(newpath + 1, cpath, cpathlen);
+        path->data = newpath;
+        path->len = cpathlen + 1;
+    }
+}
 
 static void
 ngx_clean_old_cycles(ngx_event_t *ev)
diff -r 4b4aee40c508 src/core/ngx_cycle.h
--- a/src/core/ngx_cycle.h	Tue Oct 06 08:57:09 2015 +0300
+++ b/src/core/ngx_cycle.h	Wed Oct 07 05:49:50 2015 +0100
@@ -77,6 +77,7 @@
 typedef struct {
      ngx_flag_t               daemon;
      ngx_flag_t               master;
+     ngx_flag_t               chroot;
 
      ngx_msec_t               timer_resolution;
 
@@ -97,6 +98,7 @@
 
      ngx_str_t                working_directory;
      ngx_str_t                lock_file;
+     ngx_str_t				  chroot_directory;
 
      ngx_str_t                pid;
      ngx_str_t                oldpid;
@@ -119,6 +121,7 @@
 uint64_t ngx_get_cpu_affinity(ngx_uint_t n);
 ngx_shm_zone_t *ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name,
     size_t size, void *tag);
+void ngx_adjust_path(ngx_core_conf_t *, ngx_cycle_t *, ngx_str_t *);
 
 
 extern volatile ngx_cycle_t  *ngx_cycle;
diff -r 4b4aee40c508 src/core/ngx_file.c
--- a/src/core/ngx_file.c	Tue Oct 06 08:57:09 2015 +0300
+++ b/src/core/ngx_file.c	Wed Oct 07 05:49:50 2015 +0100
@@ -566,9 +566,12 @@
     ngx_err_t         err;
     ngx_uint_t        i;
     ngx_path_t      **path;
+    ngx_core_conf_t *ccf = (ngx_core_conf_t *)ngx_get_conf(cycle->conf_ctx,
+            ngx_core_module);
 
     path = cycle->paths.elts;
     for (i = 0; i < cycle->paths.nelts; i++) {
+        ngx_adjust_path(ccf, cycle, &path[i]->name);
 
         if (ngx_create_dir(path[i]->name.data, 0700) == NGX_FILE_ERROR) {
             err = ngx_errno;
diff -r 4b4aee40c508 src/http/modules/ngx_http_auth_basic_module.c
--- a/src/http/modules/ngx_http_auth_basic_module.c	Tue Oct 06 08:57:09 2015 +0300
+++ b/src/http/modules/ngx_http_auth_basic_module.c	Wed Oct 07 05:49:50 2015 +0100
@@ -441,6 +441,8 @@
 ngx_http_auth_basic_user_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     ngx_http_auth_basic_loc_conf_t *alcf = conf;
+    ngx_core_conf_t				   *ccf =
+        (ngx_core_conf_t *)ngx_get_conf(cf->cycle->conf_ctx, ngx_core_module);
 
     ngx_str_t                         *value;
     ngx_http_compile_complex_value_t   ccv;
@@ -453,6 +455,8 @@
 
     ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
 
+    ngx_adjust_path(ccf, cf->cycle, &value[1]);
+
     ccv.cf = cf;
     ccv.value = &value[1];
     ccv.complex_value = &alcf->user_file;
diff -r 4b4aee40c508 src/http/ngx_http_core_module.c
--- a/src/http/ngx_http_core_module.c	Tue Oct 06 08:57:09 2015 +0300
+++ b/src/http/ngx_http_core_module.c	Wed Oct 07 05:49:50 2015 +0100
@@ -4430,6 +4430,8 @@
 ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     ngx_http_core_loc_conf_t *clcf = conf;
+    ngx_core_conf_t          *ccf =
+        (ngx_core_conf_t *)ngx_get_conf(cf->cycle->conf_ctx, ngx_core_module);
 
     ngx_str_t                  *value;
     ngx_int_t                   alias;
@@ -4486,9 +4488,12 @@
         return NGX_CONF_ERROR;
     }
 
+    ngx_adjust_path(ccf, cf->cycle, &value[1]);
+
     clcf->alias = alias ? clcf->name.len : 0;
     clcf->root = value[1];
 
+
     if (!alias && clcf->root.data[clcf->root.len - 1] == '/') {
         clcf->root.len--;
     }
diff -r 4b4aee40c508 src/os/unix/ngx_process_cycle.c
--- a/src/os/unix/ngx_process_cycle.c	Tue Oct 06 08:57:09 2015 +0300
+++ b/src/os/unix/ngx_process_cycle.c	Wed Oct 07 05:49:50 2015 +0100
@@ -828,6 +828,28 @@
     }
 
     if (geteuid() == 0) {
+        if (ccf->chroot) {
+            u_char *chroot_directory = ccf->chroot_directory.data;
+            chroot_directory[ccf->chroot_directory.len] = '\0';
+
+            if (chroot((const char *)chroot_directory) == -1) {
+                ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
+                        "chroot(%s) failed", chroot_directory);
+                /* fatal */
+                exit(2);
+            }
+
+            if (chdir("/") == -1) {
+                ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
+                        "chdir failed");
+                /* fatal */
+                exit(2);
+            }
+
+            ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "chrooted into %s", chroot_directory);
+
+        }
+
         if (setgid(ccf->group) == -1) {
             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                           "setgid(%d) failed", ccf->group);


More information about the nginx-devel mailing list