24 | 24 |
#if (NGX_HAVE_OPENAT)
|
25 | 25 |
static ngx_fd_t ngx_openat_file_owner(ngx_fd_t at_fd, const u_char *name,
|
26 | 26 |
ngx_int_t mode, ngx_int_t create, ngx_int_t access, ngx_log_t *log);
|
|
27 |
#if (NGX_HAVE_O_PATH)
|
|
28 |
static ngx_int_t ngx_file_o_path_info(ngx_fd_t fd, ngx_file_info_t *fi,
|
|
29 |
ngx_log_t *log);
|
|
30 |
#endif
|
27 | 31 |
#endif
|
28 | 32 |
static ngx_fd_t ngx_open_file_wrapper(ngx_str_t *name,
|
29 | 33 |
ngx_open_file_info_t *of, ngx_int_t mode, ngx_int_t create,
|
|
516 | 520 |
goto failed;
|
517 | 521 |
}
|
518 | 522 |
|
|
523 |
#if (NGX_HAVE_O_PATH)
|
|
524 |
if (ngx_file_o_path_info(fd, &fi, log) == NGX_ERROR) {
|
|
525 |
err = ngx_errno;
|
|
526 |
goto failed;
|
|
527 |
}
|
|
528 |
#else
|
519 | 529 |
if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) {
|
520 | 530 |
err = ngx_errno;
|
521 | 531 |
goto failed;
|
522 | 532 |
}
|
|
533 |
#endif
|
523 | 534 |
|
524 | 535 |
if (fi.st_uid != atfi.st_uid) {
|
525 | 536 |
err = NGX_ELOOP;
|
|
540 | 551 |
return NGX_INVALID_FILE;
|
541 | 552 |
}
|
542 | 553 |
|
|
554 |
|
|
555 |
#if (NGX_HAVE_O_PATH)
|
|
556 |
|
|
557 |
static ngx_int_t
|
|
558 |
ngx_file_o_path_info(ngx_fd_t fd, ngx_file_info_t *fi, ngx_log_t *log)
|
|
559 |
{
|
|
560 |
static ngx_uint_t use_fstat = 1;
|
|
561 |
|
|
562 |
/*
|
|
563 |
* In Linux 2.6.39 the O_PATH flag was introduced that allows to obtain
|
|
564 |
* a descriptor without actually opening file or directory. It requires
|
|
565 |
* less permissions for path components, but till Linux 3.6 fstat() returns
|
|
566 |
* EBADF on such descriptors, and fstatat() with the AT_EMPTY_PATH flag
|
|
567 |
* should be used instead.
|
|
568 |
*
|
|
569 |
* Three scenarios are handled in this function:
|
|
570 |
*
|
|
571 |
* 1) The kernel is newer than 3.6 or fstat() with O_PATH support was
|
|
572 |
* backported by vendor. Then fstat() is used.
|
|
573 |
*
|
|
574 |
* 2) The kernel is newer than 2.6.39 but older than 3.6. In this case
|
|
575 |
* the first call of fstat() returns EBADF and we fallback to fstatat()
|
|
576 |
* with AT_EMPTY_PATH which was introduced at the same time as O_PATH.
|
|
577 |
*
|
|
578 |
* 3) The kernel is older than 2.6.39 but nginx was build with O_PATH
|
|
579 |
* support. Since descriptors are opened with O_PATH|O_RDONLY flags
|
|
580 |
* and O_PATH is ignored by the kernel then the O_RDONLY flag is
|
|
581 |
* actually used. In this case fstat() just works.
|
|
582 |
*/
|
|
583 |
|
|
584 |
if (use_fstat) {
|
|
585 |
if (ngx_fd_info(fd, fi) != NGX_FILE_ERROR) {
|
|
586 |
return NGX_OK;
|
|
587 |
}
|
|
588 |
|
|
589 |
if (ngx_errno != NGX_EBADF) {
|
|
590 |
return NGX_ERROR;
|
|
591 |
}
|
|
592 |
|
|
593 |
ngx_log_error(NGX_LOG_NOTICE, log, 0,
|
|
594 |
"fstat(O_PATH) failed with EBADF, "
|
|
595 |
"switching to fstatat(AT_EMPTY_PATH)");
|
|
596 |
|
|
597 |
use_fstat = 0;
|
|
598 |
return ngx_file_o_path_info(fd, fi, log);
|
|
599 |
}
|
|
600 |
|
|
601 |
if (ngx_file_at_info(fd, "", fi, AT_EMPTY_PATH) != NGX_FILE_ERROR) {
|
|
602 |
return NGX_OK;
|
|
603 |
}
|
|
604 |
|
|
605 |
return NGX_ERROR;
|
|
606 |
}
|
|
607 |
|
543 | 608 |
#endif
|
|
609 |
|
|
610 |
#endif /* NGX_HAVE_OPENAT */
|
544 | 611 |
|
545 | 612 |
|
546 | 613 |
static ngx_fd_t
|