diff src/http/ngx_http_core_module.c @ 4477:7033faf6dc3c

Added disable_symlinks directive. To completely disable symlinks (disable_symlinks on) we use openat(O_NOFOLLOW) for each path component to avoid races. To allow symlinks with the same owner (disable_symlinks if_not_owner), use openat() (followed by fstat()) and fstatat(AT_SYMLINK_NOFOLLOW), and then compare uids between fstat() and fstatat(). As there is a race between openat() and fstatat() we don't know if openat() in fact opened symlink or not. Therefore, we have to compare uids even if fstatat() reports the opened component isn't a symlink (as we don't know whether it was symlink during openat() or not). Default value is off, i.e. symlinks are allowed.
author Andrey Belov <defan@nginx.com>
date Mon, 13 Feb 2012 16:29:04 +0000
parents 41f640a693de
children d11f86a16e3b
line wrap: on
line diff
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -187,6 +187,18 @@ static ngx_str_t  ngx_http_gzip_private 
 #endif
 
 
+#if (NGX_HAVE_OPENAT)
+
+static ngx_conf_enum_t  ngx_http_core_disable_symlinks[] = {
+    { ngx_string("off"), NGX_DISABLE_SYMLINKS_OFF },
+    { ngx_string("if_not_owner"), NGX_DISABLE_SYMLINKS_NOTOWNER },
+    { ngx_string("on"), NGX_DISABLE_SYMLINKS_ON },
+    { ngx_null_string, 0 }
+};
+
+#endif
+
+
 static ngx_command_t  ngx_http_core_commands[] = {
 
     { ngx_string("variables_hash_max_size"),
@@ -764,6 +776,17 @@ static ngx_command_t  ngx_http_core_comm
 
 #endif
 
+#if (NGX_HAVE_OPENAT)
+
+    { ngx_string("disable_symlinks"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_enum_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_core_loc_conf_t, disable_symlinks),
+      &ngx_http_core_disable_symlinks },
+
+#endif
+
       ngx_null_command
 };
 
@@ -1297,6 +1320,9 @@ ngx_http_core_try_files_phase(ngx_http_r
         of.test_only = 1;
         of.errors = clcf->open_file_cache_errors;
         of.events = clcf->open_file_cache_events;
+#if (NGX_HAVE_OPENAT)
+        of.disable_symlinks = clcf->disable_symlinks;
+#endif
 
         if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
             != NGX_OK)
@@ -3344,6 +3370,10 @@ ngx_http_core_create_loc_conf(ngx_conf_t
 #endif
 #endif
 
+#if (NGX_HAVE_OPENAT)
+    clcf->disable_symlinks = NGX_CONF_UNSET_UINT;
+#endif
+
     return clcf;
 }
 
@@ -3623,6 +3653,11 @@ ngx_http_core_merge_loc_conf(ngx_conf_t 
 #endif
 #endif
 
+#if (NGX_HAVE_OPENAT)
+    ngx_conf_merge_uint_value(conf->disable_symlinks, prev->disable_symlinks,
+                              NGX_DISABLE_SYMLINKS_OFF);
+#endif
+
     return NGX_CONF_OK;
 }