Klaus Demo nginx / 04015a4
Disable symlinks: cleanup error handling. Notably this fixes NGX_INVALID_FILE/NGX_FILE_ERROR mess, and adds logging of close() errors. In collaboration with Valentin Bartenev. Maxim Dounin 10 years ago
1 changed file(s) with 75 addition(s) and 46 deletion(s). Raw diff Collapse all Expand all
2323 static void ngx_open_file_cache_cleanup(void *data);
2424 #if (NGX_HAVE_OPENAT)
2525 static ngx_fd_t ngx_openat_file_owner(ngx_fd_t at_fd, const u_char *name,
26 ngx_int_t mode, ngx_int_t create, ngx_int_t access);
26 ngx_int_t mode, ngx_int_t create, ngx_int_t access, ngx_log_t *log);
2727 #endif
2828 static ngx_fd_t ngx_open_file_wrapper(ngx_str_t *name,
2929 ngx_open_file_info_t *of, ngx_int_t mode, ngx_int_t create,
30 ngx_int_t access);
30 ngx_int_t access, ngx_log_t *log);
3131 static ngx_int_t ngx_file_info_wrapper(ngx_str_t *name,
32 ngx_open_file_info_t *of, ngx_file_info_t *fi);
32 ngx_open_file_info_t *of, ngx_file_info_t *fi, ngx_log_t *log);
3333 static ngx_int_t ngx_open_and_stat_file(ngx_str_t *name,
3434 ngx_open_file_info_t *of, ngx_log_t *log);
3535 static void ngx_open_file_add_event(ngx_open_file_cache_t *cache,
155155
156156 if (of->test_only) {
157157
158 if (ngx_file_info_wrapper(name, of, &fi) == NGX_FILE_ERROR) {
158 if (ngx_file_info_wrapper(name, of, &fi, pool->log)
159 == NGX_FILE_ERROR)
160 {
159161 return NGX_ERROR;
160162 }
161163
481483
482484 static ngx_fd_t
483485 ngx_openat_file_owner(ngx_fd_t at_fd, const u_char *name,
484 ngx_int_t mode, ngx_int_t create, ngx_int_t access)
486 ngx_int_t mode, ngx_int_t create, ngx_int_t access, ngx_log_t *log)
485487 {
486488 ngx_fd_t fd;
489 ngx_err_t err;
487490 ngx_file_info_t fi, atfi;
488491
489492 /*
507510 if (ngx_file_at_info(at_fd, name, &atfi, AT_SYMLINK_NOFOLLOW)
508511 == NGX_FILE_ERROR)
509512 {
510 ngx_close_file(fd);
511 return NGX_FILE_ERROR;
513 err = ngx_errno;
514 goto failed;
512515 }
513516
514517 if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) {
515 ngx_close_file(fd);
516 return NGX_FILE_ERROR;
518 err = ngx_errno;
519 goto failed;
517520 }
518521
519522 if (fi.st_uid != atfi.st_uid) {
520 ngx_close_file(fd);
521 ngx_set_errno(NGX_ELOOP);
522 return NGX_FILE_ERROR;
523 err = NGX_ELOOP;
524 goto failed;
523525 }
524526
525527 return fd;
528
529 failed:
530
531 if (ngx_close_file(fd) == NGX_FILE_ERROR) {
532 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
533 ngx_close_file_n " \"%V\" failed", name);
534 }
535
536 ngx_set_errno(err);
537
538 return NGX_INVALID_FILE;
526539 }
527540
528541 #endif
530543
531544 static ngx_fd_t
532545 ngx_open_file_wrapper(ngx_str_t *name, ngx_open_file_info_t *of,
533 ngx_int_t mode, ngx_int_t create, ngx_int_t access)
546 ngx_int_t mode, ngx_int_t create, ngx_int_t access, ngx_log_t *log)
534547 {
535548 ngx_fd_t fd;
536549
538551
539552 fd = ngx_open_file(name->data, mode, create, access);
540553
541 if (fd == NGX_FILE_ERROR) {
554 if (fd == NGX_INVALID_FILE) {
542555 of->err = ngx_errno;
543556 of->failed = ngx_open_file_n;
544 return NGX_FILE_ERROR;
557 return NGX_INVALID_FILE;
545558 }
546559
547560 return fd;
548561
549562 #else
550563
551 u_char *p, *cp, *end;
552 ngx_fd_t at_fd;
564 u_char *p, *cp, *end;
565 ngx_fd_t at_fd;
566 ngx_str_t at_name;
553567
554568 if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_OFF) {
555569 fd = ngx_open_file(name->data, mode, create, access);
556570
557 if (fd == NGX_FILE_ERROR) {
571 if (fd == NGX_INVALID_FILE) {
558572 of->err = ngx_errno;
559573 of->failed = ngx_open_file_n;
560 return NGX_FILE_ERROR;
574 return NGX_INVALID_FILE;
561575 }
562576
563577 return fd;
566580 at_fd = ngx_openat_file(AT_FDCWD, "/", NGX_FILE_RDONLY|NGX_FILE_NONBLOCK,
567581 NGX_FILE_OPEN, 0);
568582
569 if (at_fd == NGX_FILE_ERROR) {
583 if (at_fd == NGX_INVALID_FILE) {
570584 of->err = ngx_errno;
571585 of->failed = ngx_openat_file_n;
572 return NGX_FILE_ERROR;
573 }
586 return NGX_INVALID_FILE;
587 }
588
589 at_name = *name;
590 at_name.len = 1;
574591
575592 end = name->data + name->len;
576593 p = name->data + 1;
586603 if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER) {
587604 fd = ngx_openat_file_owner(at_fd, p,
588605 NGX_FILE_RDONLY|NGX_FILE_NONBLOCK,
589 NGX_FILE_OPEN, 0);
606 NGX_FILE_OPEN, 0, log);
590607
591608 } else {
592609 fd = ngx_openat_file(at_fd, p,
596613
597614 *cp = '/';
598615
599 ngx_close_file(at_fd);
600
601 if (fd == NGX_FILE_ERROR) {
616 if (fd == NGX_INVALID_FILE) {
602617 of->err = ngx_errno;
603618 of->failed = ngx_openat_file_n;
604 return NGX_FILE_ERROR;
619 goto failed;
620 }
621
622 if (at_fd != AT_FDCWD && ngx_close_file(at_fd) == NGX_FILE_ERROR) {
623 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
624 ngx_close_file_n " \"%V\" failed", at_name);
605625 }
606626
607627 p = cp + 1;
608628 at_fd = fd;
629 at_name.len = cp - at_name.data;
609630 }
610631
611632 if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER) {
612 fd = ngx_openat_file_owner(at_fd, p, mode, create, access);
633 fd = ngx_openat_file_owner(at_fd, p, mode, create, access, log);
613634
614635 } else {
615636 fd = ngx_openat_file(at_fd, p, mode|NGX_FILE_NOFOLLOW, create, access);
616637 }
617638
618 if (fd == NGX_FILE_ERROR) {
639 if (fd == NGX_INVALID_FILE) {
619640 of->err = ngx_errno;
620641 of->failed = ngx_openat_file_n;
621642 }
622643
623 ngx_close_file(at_fd);
644 failed:
645
646 if (at_fd != AT_FDCWD && ngx_close_file(at_fd) == NGX_FILE_ERROR) {
647 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
648 ngx_close_file_n " \"%V\" failed", at_name);
649 }
624650
625651 return fd;
626652 #endif
629655
630656 static ngx_int_t
631657 ngx_file_info_wrapper(ngx_str_t *name, ngx_open_file_info_t *of,
632 ngx_file_info_t *fi)
658 ngx_file_info_t *fi, ngx_log_t *log)
633659 {
634660 ngx_int_t rc;
635661
663689 }
664690
665691 fd = ngx_open_file_wrapper(name, of, NGX_FILE_RDONLY|NGX_FILE_NONBLOCK,
666 NGX_FILE_OPEN, 0);
667
668 if (fd == NGX_FILE_ERROR) {
692 NGX_FILE_OPEN, 0, log);
693
694 if (fd == NGX_INVALID_FILE) {
669695 return NGX_FILE_ERROR;
670696 }
671697
672 if (ngx_fd_info(fd, fi) == NGX_FILE_ERROR) {
698 rc = ngx_fd_info(fd, fi);
699
700 if (rc == NGX_FILE_ERROR) {
673701 of->err = ngx_errno;
674702 of->failed = ngx_fd_info_n;
675 ngx_close_file(fd);
676 return NGX_FILE_ERROR;
677 }
678
679 ngx_close_file(fd);
680
681 return NGX_OK;
703 }
704
705 if (ngx_close_file(fd) == NGX_FILE_ERROR) {
706 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
707 ngx_close_file_n " \"%V\" failed", name);
708 }
709
710 return rc;
682711 #endif
683712 }
684713
692721
693722 if (of->fd != NGX_INVALID_FILE) {
694723
695 if (ngx_file_info_wrapper(name, of, &fi) == NGX_FILE_ERROR) {
724 if (ngx_file_info_wrapper(name, of, &fi, log) == NGX_FILE_ERROR) {
696725 of->fd = NGX_INVALID_FILE;
697726 return NGX_ERROR;
698727 }
703732
704733 } else if (of->test_dir) {
705734
706 if (ngx_file_info_wrapper(name, of, &fi) == NGX_FILE_ERROR) {
735 if (ngx_file_info_wrapper(name, of, &fi, log) == NGX_FILE_ERROR) {
707736 of->fd = NGX_INVALID_FILE;
708737 return NGX_ERROR;
709738 }
721750 */
722751
723752 fd = ngx_open_file_wrapper(name, of, NGX_FILE_RDONLY|NGX_FILE_NONBLOCK,
724 NGX_FILE_OPEN, 0);
753 NGX_FILE_OPEN, 0, log);
725754
726755 } else {
727756 fd = ngx_open_file_wrapper(name, of, NGX_FILE_APPEND,
728757 NGX_FILE_CREATE_OR_OPEN,
729 NGX_FILE_DEFAULT_ACCESS);
758 NGX_FILE_DEFAULT_ACCESS, log);
730759 }
731760
732761 if (fd == NGX_INVALID_FILE) {