Klaus Demo nginx / 7b37384
Disable symlinks: use O_PATH to open path components. It was introduced in Linux 2.6.39, glibc 2.14 and allows to obtain file descriptors without actually opening files. Thus made it possible to traverse path with openat() syscalls without the need to have read permissions for path components. It is effectively emulates O_SEARCH which is missing on Linux. O_PATH is used in combination with O_RDONLY. The last one is ignored if O_PATH is used, but it allows nginx to not fail when it was built on modern system (i.e. glibc 2.14+) and run with a kernel older than 2.6.39. Then O_PATH is unknown to the kernel and ignored, while O_RDONLY is used. Sadly, fstat() is not working with O_PATH descriptors till Linux 3.6. As a workaround we fallback to fstatat() with the AT_EMPTY_PATH flag that was introduced at the same time as O_PATH. Valentin Bartenev 8 years ago
3 changed file(s) with 86 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
6565 EVENT_MODULES="$EVENT_MODULES $EPOLL_MODULE"
6666 EVENT_FOUND=YES
6767 fi
68
69
70 # O_PATH and AT_EMPTY_PATH were introduced in 2.6.39, glibc 2.14
71
72 ngx_feature="O_PATH"
73 ngx_feature_name="NGX_HAVE_O_PATH"
74 ngx_feature_run=no
75 ngx_feature_incs="#include <sys/types.h>
76 #include <sys/stat.h>
77 #include <fcntl.h>"
78 ngx_feature_path=
79 ngx_feature_libs=
80 ngx_feature_test="int fd; struct stat sb;
81 fd = openat(AT_FDCWD, \".\", O_PATH|O_DIRECTORY|O_NOFOLLOW);
82 if (fstatat(fd, \"\", &sb, AT_EMPTY_PATH) != 0) return 1"
83 . auto/feature
6884
6985
7086 # sendfile()
2424 #if (NGX_HAVE_OPENAT)
2525 static ngx_fd_t ngx_openat_file_owner(ngx_fd_t at_fd, const u_char *name,
2626 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
2731 #endif
2832 static ngx_fd_t ngx_open_file_wrapper(ngx_str_t *name,
2933 ngx_open_file_info_t *of, ngx_int_t mode, ngx_int_t create,
516520 goto failed;
517521 }
518522
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
519529 if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) {
520530 err = ngx_errno;
521531 goto failed;
522532 }
533 #endif
523534
524535 if (fi.st_uid != atfi.st_uid) {
525536 err = NGX_ELOOP;
540551 return NGX_INVALID_FILE;
541552 }
542553
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
543608 #endif
609
610 #endif /* NGX_HAVE_OPENAT */
544611
545612
546613 static ngx_fd_t
8989
9090 #elif defined(O_EXEC)
9191 #define NGX_FILE_SEARCH (O_EXEC|NGX_FILE_DIRECTORY)
92
93 #elif (NGX_HAVE_O_PATH)
94 #define NGX_FILE_SEARCH (O_PATH|O_RDONLY|NGX_FILE_DIRECTORY)
9295
9396 #else
9497 #define NGX_FILE_SEARCH (O_RDONLY|NGX_FILE_DIRECTORY)