Deleted
Added
1 2/* 3 * Copyright (C) Igor Sysoev 4 * Copyright (C) NGINX, Inc. 5 */ 6 7#include <nxt_main.h> 8#include <nxt_main_process.h> 9 10#if (NXT_HAVE_CLONE) 11#include <nxt_clone.h> 12#endif 13 14#include <signal.h> 15 |
16#if (NXT_HAVE_PR_SET_NO_NEW_PRIVS) 17#include <sys/prctl.h> 18#endif 19 20#if (NXT_HAVE_PIVOT_ROOT) 21#include <mntent.h> 22#endif 23 |
24static nxt_int_t nxt_process_setup(nxt_task_t *task, nxt_process_t *process); 25static nxt_int_t nxt_process_child_fixup(nxt_task_t *task, 26 nxt_process_t *process); 27static nxt_int_t nxt_process_send_created(nxt_task_t *task, 28 nxt_process_t *process); 29static nxt_int_t nxt_process_send_ready(nxt_task_t *task, 30 nxt_process_t *process); 31static void nxt_process_created_ok(nxt_task_t *task, nxt_port_recv_msg_t *msg, 32 void *data); 33static void nxt_process_created_error(nxt_task_t *task, 34 nxt_port_recv_msg_t *msg, void *data); 35 |
36#if (NXT_HAVE_ISOLATION_ROOTFS) 37static nxt_int_t nxt_process_chroot(nxt_task_t *task, const char *path); 38#endif |
39 |
40#if (NXT_HAVE_PIVOT_ROOT) 41static nxt_int_t nxt_process_pivot_root(nxt_task_t *task, const char *rootfs); 42static nxt_int_t nxt_process_private_mount(nxt_task_t *task, 43 const char *rootfs); 44#endif 45 46#if (NXT_HAVE_PIVOT_ROOT) 47static int nxt_pivot_root(const char *new_root, const char *old_root); 48#endif 49 |
50/* A cached process pid. */ 51nxt_pid_t nxt_pid; 52 53/* An original parent process pid. */ 54nxt_pid_t nxt_ppid; 55 56/* A cached process effective uid */ 57nxt_uid_t nxt_euid; --- 453 unchanged lines hidden (view full) --- 511 } 512 513 ret = nxt_credential_setuid(task, process->user_cred); 514 if (nxt_slow_path(ret != NXT_OK)) { 515 return NXT_ERROR; 516 } 517 } 518 |
519#if (NXT_HAVE_PR_SET_NO_NEW_PRIVS) 520 if (nxt_slow_path(process->isolation.new_privs == 0 521 && prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != 0)) 522 { 523 nxt_alert(task, "failed to set no_new_privs %E", nxt_errno); 524 return NXT_ERROR; 525 } 526#endif 527 |
528 return NXT_OK; 529} 530 531 |
532#if (NXT_HAVE_ISOLATION_ROOTFS) 533 534 535#if (NXT_HAVE_PIVOT_ROOT) && (NXT_HAVE_CLONE_NEWNS) 536 537 538nxt_int_t 539nxt_process_change_root(nxt_task_t *task, nxt_process_t *process) 540{ 541 char *rootfs; 542 nxt_int_t ret; 543 544 rootfs = (char *) process->isolation.rootfs; 545 546 nxt_debug(task, "change root: %s", rootfs); 547 548 if (NXT_CLONE_MNT(process->isolation.clone.flags)) { 549 ret = nxt_process_pivot_root(task, rootfs); 550 } else { 551 ret = nxt_process_chroot(task, rootfs); 552 } 553 554 if (nxt_fast_path(ret == NXT_OK)) { 555 if (nxt_slow_path(chdir("/") < 0)) { 556 nxt_alert(task, "chdir(\"/\") %E", nxt_errno); 557 return NXT_ERROR; 558 } 559 } 560 561 return ret; 562} 563 564 565#else 566 567 568nxt_int_t 569nxt_process_change_root(nxt_task_t *task, nxt_process_t *process) 570{ 571 char *rootfs; 572 573 rootfs = (char *) process->isolation.rootfs; 574 575 nxt_debug(task, "change root: %s", rootfs); 576 577 if (nxt_fast_path(nxt_process_chroot(task, rootfs) == NXT_OK)) { 578 if (nxt_slow_path(chdir("/") < 0)) { 579 nxt_alert(task, "chdir(\"/\") %E", nxt_errno); 580 return NXT_ERROR; 581 } 582 583 return NXT_OK; 584 } 585 586 return NXT_ERROR; 587} 588 589 590#endif 591 592 593#endif 594 595 596#if (NXT_HAVE_ISOLATION_ROOTFS) 597 |
598static nxt_int_t |
599nxt_process_chroot(nxt_task_t *task, const char *path) 600{ 601 if (nxt_slow_path(chroot(path) < 0)) { 602 nxt_alert(task, "chroot(%s) %E", path, nxt_errno); 603 return NXT_ERROR; 604 } 605 606 return NXT_OK; 607} 608 609 610void 611nxt_process_unmount_all(nxt_task_t *task, nxt_process_t *process) 612{ 613 size_t i, n; 614 nxt_array_t *mounts; 615 nxt_fs_mount_t *mnt; 616 617 nxt_debug(task, "unmount all (%s)", process->name); 618 619 mounts = process->isolation.mounts; 620 n = mounts->nelts; 621 mnt = mounts->elts; 622 623 for (i = 0; i < n; i++) { 624 nxt_fs_unmount(mnt[i].dst); 625 } 626} 627 628#endif 629 630 631#if (NXT_HAVE_PIVOT_ROOT) && (NXT_HAVE_CLONE_NEWNS) 632 633/* 634 * pivot_root(2) can only be safely used with containers, otherwise it can 635 * umount(2) the global root filesystem and screw up the machine. 636 */ 637 638static nxt_int_t 639nxt_process_pivot_root(nxt_task_t *task, const char *path) 640{ 641 /* 642 * This implementation makes use of a kernel trick that works for ages 643 * and now documented in Linux kernel 5. 644 * https://lore.kernel.org/linux-man/87r24piwhm.fsf@x220.int.ebiederm.org/T/ 645 */ 646 647 if (nxt_slow_path(mount("", "/", "", MS_SLAVE|MS_REC, "") != 0)) { 648 nxt_alert(task, "failed to make / a slave mount %E", nxt_errno); 649 return NXT_ERROR; 650 } 651 652 if (nxt_slow_path(nxt_process_private_mount(task, path) != NXT_OK)) { 653 return NXT_ERROR; 654 } 655 656 if (nxt_slow_path(mount(path, path, "bind", MS_BIND|MS_REC, "") != 0)) { 657 nxt_alert(task, "error bind mounting rootfs %E", nxt_errno); 658 return NXT_ERROR; 659 } 660 661 if (nxt_slow_path(chdir(path) != 0)) { 662 nxt_alert(task, "failed to chdir(%s) %E", path, nxt_errno); 663 return NXT_ERROR; 664 } 665 666 if (nxt_slow_path(nxt_pivot_root(".", ".") != 0)) { 667 nxt_alert(task, "failed to pivot_root %E", nxt_errno); 668 return NXT_ERROR; 669 } 670 671 /* 672 * Make oldroot a slave mount to avoid unmounts getting propagated to the 673 * host. 674 */ 675 if (nxt_slow_path(mount("", ".", "", MS_SLAVE | MS_REC, NULL) != 0)) { 676 nxt_alert(task, "failed to bind mount rootfs %E", nxt_errno); 677 return NXT_ERROR; 678 } 679 680 if (nxt_slow_path(umount2(".", MNT_DETACH) != 0)) { 681 nxt_alert(task, "failed to umount old root directory %E", nxt_errno); 682 return NXT_ERROR; 683 } 684 685 return NXT_OK; 686} 687 688 689static nxt_int_t 690nxt_process_private_mount(nxt_task_t *task, const char *rootfs) 691{ 692 char *parent_mnt; 693 FILE *procfile; 694 u_char **mounts; 695 size_t len; 696 uint8_t *shared; 697 nxt_int_t ret, index, nmounts; 698 struct mntent *ent; 699 700 static const char *mount_path = "/proc/self/mounts"; 701 702 ret = NXT_ERROR; 703 ent = NULL; 704 shared = NULL; 705 procfile = NULL; 706 parent_mnt = NULL; 707 708 nmounts = 256; 709 710 mounts = nxt_malloc(nmounts * sizeof(uintptr_t)); 711 if (nxt_slow_path(mounts == NULL)) { 712 goto fail; 713 } 714 715 shared = nxt_malloc(nmounts); 716 if (nxt_slow_path(shared == NULL)) { 717 goto fail; 718 } 719 720 procfile = setmntent(mount_path, "r"); 721 if (nxt_slow_path(procfile == NULL)) { 722 nxt_alert(task, "failed to open %s %E", mount_path, nxt_errno); 723 724 goto fail; 725 } 726 727 index = 0; 728 729again: 730 731 for ( ; index < nmounts; index++) { 732 ent = getmntent(procfile); 733 if (ent == NULL) { 734 nmounts = index; 735 break; 736 } 737 738 mounts[index] = (u_char *) strdup(ent->mnt_dir); 739 shared[index] = hasmntopt(ent, "shared") != NULL; 740 } 741 742 if (ent != NULL) { 743 /* there are still entries to be read */ 744 745 nmounts *= 2; 746 mounts = nxt_realloc(mounts, nmounts); 747 if (nxt_slow_path(mounts == NULL)) { 748 goto fail; 749 } 750 751 shared = nxt_realloc(shared, nmounts); 752 if (nxt_slow_path(shared == NULL)) { 753 goto fail; 754 } 755 756 goto again; 757 } 758 759 for (index = 0; index < nmounts; index++) { 760 if (nxt_strcmp(mounts[index], rootfs) == 0) { 761 parent_mnt = (char *) rootfs; 762 break; 763 } 764 } 765 766 if (parent_mnt == NULL) { 767 len = nxt_strlen(rootfs); 768 769 parent_mnt = nxt_malloc(len + 1); 770 if (parent_mnt == NULL) { 771 goto fail; 772 } 773 774 nxt_memcpy(parent_mnt, rootfs, len); 775 parent_mnt[len] = '\0'; 776 777 if (parent_mnt[len - 1] == '/') { 778 parent_mnt[len - 1] = '\0'; 779 len--; 780 } 781 782 for ( ;; ) { 783 for (index = 0; index < nmounts; index++) { 784 if (nxt_strcmp(mounts[index], parent_mnt) == 0) { 785 goto found; 786 } 787 } 788 789 if (len == 1 && parent_mnt[0] == '/') { 790 nxt_alert(task, "parent mount not found"); 791 goto fail; 792 } 793 794 /* parent dir */ 795 while (parent_mnt[len - 1] != '/' && len > 0) { 796 len--; 797 } 798 799 if (nxt_slow_path(len == 0)) { 800 nxt_alert(task, "parent mount not found"); 801 goto fail; 802 } 803 804 if (len == 1) { 805 parent_mnt[len] = '\0'; /* / */ 806 } else { 807 parent_mnt[len - 1] = '\0'; /* /<path> */ 808 } 809 } 810 } 811 812found: 813 814 if (shared[index]) { 815 if (nxt_slow_path(mount("", parent_mnt, "", MS_PRIVATE, "") != 0)) { 816 nxt_alert(task, "mount(\"\", \"%s\", MS_PRIVATE) %E", parent_mnt, 817 nxt_errno); 818 819 goto fail; 820 } 821 } 822 823 ret = NXT_OK; 824 825fail: 826 827 if (procfile != NULL) { 828 endmntent(procfile); 829 } 830 831 if (mounts != NULL) { 832 for (index = 0; index < nmounts; index++) { 833 nxt_free(mounts[index]); 834 } 835 836 nxt_free(mounts); 837 } 838 839 if (shared != NULL) { 840 nxt_free(shared); 841 } 842 843 if (parent_mnt != NULL && parent_mnt != rootfs) { 844 nxt_free(parent_mnt); 845 } 846 847 return ret; 848} 849 850 851static int 852nxt_pivot_root(const char *new_root, const char *old_root) 853{ 854 return syscall(__NR_pivot_root, new_root, old_root); 855} 856 857#endif 858 859 860static nxt_int_t |
861nxt_process_send_ready(nxt_task_t *task, nxt_process_t *process) 862{ 863 nxt_int_t ret; 864 nxt_port_t *main_port; 865 nxt_runtime_t *rt; 866 867 rt = task->thread->runtime; 868 --- 331 unchanged lines hidden --- |