mirror of
https://github.com/nginx/nginx.git
synced 2025-02-25 18:55:26 -06:00
Disable symlinks: fixed edge cases of path handling.
This includes non-absolute pathnames, multiple slashes and trailing slashes. In collaboration with Valentin Bartenev.
This commit is contained in:
parent
04015a48ca
commit
32b000bad7
@ -562,9 +562,10 @@ ngx_open_file_wrapper(ngx_str_t *name, ngx_open_file_info_t *of,
|
||||
|
||||
#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,20 +579,26 @@ ngx_open_file_wrapper(ngx_str_t *name, ngx_open_file_info_t *of,
|
||||
return fd;
|
||||
}
|
||||
|
||||
at_fd = ngx_openat_file(AT_FDCWD, "/", NGX_FILE_RDONLY|NGX_FILE_NONBLOCK,
|
||||
NGX_FILE_OPEN, 0);
|
||||
|
||||
if (at_fd == NGX_INVALID_FILE) {
|
||||
of->err = ngx_errno;
|
||||
of->failed = ngx_openat_file_n;
|
||||
return NGX_INVALID_FILE;
|
||||
}
|
||||
p = name->data;
|
||||
end = p + name->len;
|
||||
|
||||
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, '/');
|
||||
@ -599,6 +606,11 @@ ngx_open_file_wrapper(ngx_str_t *name, ngx_open_file_info_t *of,
|
||||
break;
|
||||
}
|
||||
|
||||
if (cp == p) {
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
|
||||
*cp = '\0';
|
||||
|
||||
if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER) {
|
||||
@ -630,6 +642,40 @@ ngx_open_file_wrapper(ngx_str_t *name, ngx_open_file_info_t *of,
|
||||
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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user