[nginx] svn commit: r4481 - trunk/src/core
mdounin at mdounin.ru
mdounin at mdounin.ru
Wed Feb 15 12:18:55 UTC 2012
Author: mdounin
Date: 2012-02-15 12:18:55 +0000 (Wed, 15 Feb 2012)
New Revision: 4481
Log:
Disable symlinks: fixed edge cases of path handling.
This includes non-absolute pathnames, multiple slashes and trailing
slashes. In collaboration with Valentin Bartenev.
Modified:
trunk/src/core/ngx_open_file_cache.c
Modified: trunk/src/core/ngx_open_file_cache.c
===================================================================
--- trunk/src/core/ngx_open_file_cache.c 2012-02-15 12:17:24 UTC (rev 4480)
+++ trunk/src/core/ngx_open_file_cache.c 2012-02-15 12:18:55 UTC (rev 4481)
@@ -562,9 +562,10 @@
#else
- u_char *p, *cp, *end;
- ngx_fd_t at_fd;
- ngx_str_t at_name;
+ u_char *p, *cp, *end;
+ ngx_fd_t at_fd;
+ ngx_str_t at_name;
+ ngx_file_info_t fi;
if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_OFF) {
fd = ngx_open_file(name->data, mode, create, access);
@@ -578,27 +579,38 @@
return fd;
}
- at_fd = ngx_openat_file(AT_FDCWD, "/", NGX_FILE_RDONLY|NGX_FILE_NONBLOCK,
- NGX_FILE_OPEN, 0);
+ p = name->data;
+ end = p + name->len;
- if (at_fd == NGX_INVALID_FILE) {
- of->err = ngx_errno;
- of->failed = ngx_openat_file_n;
- return NGX_INVALID_FILE;
- }
-
+ at_fd = AT_FDCWD;
at_name = *name;
- at_name.len = 1;
- end = name->data + name->len;
- p = name->data + 1;
+ if (p[0] == '/') {
+ at_fd = ngx_openat_file(at_fd, "/",
+ NGX_FILE_RDONLY|NGX_FILE_NONBLOCK,
+ NGX_FILE_OPEN, 0);
+ if (at_fd == NGX_FILE_ERROR) {
+ of->err = ngx_errno;
+ of->failed = ngx_openat_file_n;
+ return NGX_FILE_ERROR;
+ }
+
+ at_name.len = 1;
+ p++;
+ }
+
for ( ;; ) {
cp = ngx_strlchr(p, end, '/');
if (cp == NULL) {
break;
}
+ if (cp == p) {
+ p++;
+ continue;
+ }
+
*cp = '\0';
if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER) {
@@ -630,6 +642,40 @@
at_name.len = cp - at_name.data;
}
+ if (p == end && at_fd != AT_FDCWD) {
+
+ /*
+ * If pathname ends with a trailing slash, check if last path
+ * component is a directory; if not, fail with ENOTDIR as per
+ * POSIX.
+ *
+ * We use separate check instead of O_DIRECTORY in the loop above,
+ * as O_DIRECTORY doesn't work on FreeBSD 8.
+ *
+ * Note this returns already opened file descriptor, with different
+ * mode/create/access. This is believed to be safe as we don't
+ * use this codepath to create directories.
+ */
+
+ if (ngx_fd_info(at_fd, &fi) == NGX_FILE_ERROR) {
+ of->err = ngx_errno;
+ of->failed = ngx_fd_info_n;
+ fd = NGX_INVALID_FILE;
+
+ goto failed;
+ }
+
+ if (ngx_is_dir(&fi)) {
+ return at_fd;
+ }
+
+ of->err = ENOTDIR;
+ of->failed = ngx_openat_file_n;
+ fd = NGX_INVALID_FILE;
+
+ goto failed;
+ }
+
if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER) {
fd = ngx_openat_file_owner(at_fd, p, mode, create, access, log);
More information about the nginx-devel
mailing list