Mercurial > hg > nginx
comparison src/core/ngx_open_file_cache.c @ 4480:5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
This includes non-absolute pathnames, multiple slashes and trailing
slashes. In collaboration with Valentin Bartenev.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Wed, 15 Feb 2012 12:18:55 +0000 |
parents | 5e6436812c9a |
children | f78a29a2f9e6 |
comparison
equal
deleted
inserted
replaced
4479:5e6436812c9a | 4480:5a3cb84545e5 |
---|---|
560 | 560 |
561 return fd; | 561 return fd; |
562 | 562 |
563 #else | 563 #else |
564 | 564 |
565 u_char *p, *cp, *end; | 565 u_char *p, *cp, *end; |
566 ngx_fd_t at_fd; | 566 ngx_fd_t at_fd; |
567 ngx_str_t at_name; | 567 ngx_str_t at_name; |
568 ngx_file_info_t fi; | |
568 | 569 |
569 if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_OFF) { | 570 if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_OFF) { |
570 fd = ngx_open_file(name->data, mode, create, access); | 571 fd = ngx_open_file(name->data, mode, create, access); |
571 | 572 |
572 if (fd == NGX_INVALID_FILE) { | 573 if (fd == NGX_INVALID_FILE) { |
576 } | 577 } |
577 | 578 |
578 return fd; | 579 return fd; |
579 } | 580 } |
580 | 581 |
581 at_fd = ngx_openat_file(AT_FDCWD, "/", NGX_FILE_RDONLY|NGX_FILE_NONBLOCK, | 582 p = name->data; |
582 NGX_FILE_OPEN, 0); | 583 end = p + name->len; |
583 | 584 |
584 if (at_fd == NGX_INVALID_FILE) { | 585 at_fd = AT_FDCWD; |
585 of->err = ngx_errno; | |
586 of->failed = ngx_openat_file_n; | |
587 return NGX_INVALID_FILE; | |
588 } | |
589 | |
590 at_name = *name; | 586 at_name = *name; |
591 at_name.len = 1; | 587 |
592 | 588 if (p[0] == '/') { |
593 end = name->data + name->len; | 589 at_fd = ngx_openat_file(at_fd, "/", |
594 p = name->data + 1; | 590 NGX_FILE_RDONLY|NGX_FILE_NONBLOCK, |
591 NGX_FILE_OPEN, 0); | |
592 | |
593 if (at_fd == NGX_FILE_ERROR) { | |
594 of->err = ngx_errno; | |
595 of->failed = ngx_openat_file_n; | |
596 return NGX_FILE_ERROR; | |
597 } | |
598 | |
599 at_name.len = 1; | |
600 p++; | |
601 } | |
595 | 602 |
596 for ( ;; ) { | 603 for ( ;; ) { |
597 cp = ngx_strlchr(p, end, '/'); | 604 cp = ngx_strlchr(p, end, '/'); |
598 if (cp == NULL) { | 605 if (cp == NULL) { |
599 break; | 606 break; |
600 } | 607 } |
601 | 608 |
609 if (cp == p) { | |
610 p++; | |
611 continue; | |
612 } | |
613 | |
602 *cp = '\0'; | 614 *cp = '\0'; |
603 | 615 |
604 if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER) { | 616 if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER) { |
605 fd = ngx_openat_file_owner(at_fd, p, | 617 fd = ngx_openat_file_owner(at_fd, p, |
606 NGX_FILE_RDONLY|NGX_FILE_NONBLOCK, | 618 NGX_FILE_RDONLY|NGX_FILE_NONBLOCK, |
626 } | 638 } |
627 | 639 |
628 p = cp + 1; | 640 p = cp + 1; |
629 at_fd = fd; | 641 at_fd = fd; |
630 at_name.len = cp - at_name.data; | 642 at_name.len = cp - at_name.data; |
643 } | |
644 | |
645 if (p == end && at_fd != AT_FDCWD) { | |
646 | |
647 /* | |
648 * If pathname ends with a trailing slash, check if last path | |
649 * component is a directory; if not, fail with ENOTDIR as per | |
650 * POSIX. | |
651 * | |
652 * We use separate check instead of O_DIRECTORY in the loop above, | |
653 * as O_DIRECTORY doesn't work on FreeBSD 8. | |
654 * | |
655 * Note this returns already opened file descriptor, with different | |
656 * mode/create/access. This is believed to be safe as we don't | |
657 * use this codepath to create directories. | |
658 */ | |
659 | |
660 if (ngx_fd_info(at_fd, &fi) == NGX_FILE_ERROR) { | |
661 of->err = ngx_errno; | |
662 of->failed = ngx_fd_info_n; | |
663 fd = NGX_INVALID_FILE; | |
664 | |
665 goto failed; | |
666 } | |
667 | |
668 if (ngx_is_dir(&fi)) { | |
669 return at_fd; | |
670 } | |
671 | |
672 of->err = ENOTDIR; | |
673 of->failed = ngx_openat_file_n; | |
674 fd = NGX_INVALID_FILE; | |
675 | |
676 goto failed; | |
631 } | 677 } |
632 | 678 |
633 if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER) { | 679 if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER) { |
634 fd = ngx_openat_file_owner(at_fd, p, mode, create, access, log); | 680 fd = ngx_openat_file_owner(at_fd, p, mode, create, access, log); |
635 | 681 |