Jak wykonać chroot z przestrzeniami nazw Linux?

14

Po przeczytaniu o przestrzeniach nazw Linuksa miałem wrażenie, że są one, wśród wielu innych funkcji, alternatywą dla chroot. Na przykład w tym artykule :

Inne zastosowania [przestrzeni nazw] obejmują [...] chroot () - izolację stylu procesu od części hierarchii pojedynczego katalogu.

Jednak gdy klonuję przestrzeń nazw montowania, na przykład za pomocą następującego polecenia, nadal widzę całe oryginalne drzewo główne.

unshare --mount -- /bin/bash

Rozumiem, że jestem teraz w stanie wykonać dodatkowe montowania w nowej przestrzeni nazw, które nie są współużytkowane z oryginalną przestrzenią nazw, a zatem zapewnia izolację, ale wciąż jest to ten sam katalog główny, np. /etcWciąż jest taki sam dla obu przestrzeni nazw. Czy nadal muszę chrootzmienić root lub czy istnieje alternatywa?

Spodziewałem się, że to pytanie dostarczy odpowiedzi, ale odpowiedź tylko się chrootpowtórzy.

EDYCJA 1

Był już usunięty komentarz, który wspomniał pivot_root. Ponieważ jest to faktycznie część linux/fs/namespace.c, jest to faktycznie część implementacji przestrzeni nazw. Sugeruje to, że zmiana katalogu głównego tylko za pomocą unsharei mountnie jest możliwa, ale przestrzenie nazw zapewniają własną - bardziej sprytną - wersję chroot. Nadal nie rozumiem tego podejścia, które zasadniczo różni się od niego chroot, nawet po przeczytaniu kodu źródłowego (w sensie np. Bezpieczeństwa lub lepszej izolacji).

EDYCJA 2

To nie jest duplikat tego pytania . Po wykonaniu wszystkich poleceń z odpowiedzi mam osobne /tmp/tmp.vyM9IwnKuY (lub podobne), ale katalog główny jest nadal taki sam!

koalo
źródło
Odnośnie różnicy między pivot_rooti chroot: Rzuciłem okiem na źródła Dockera i stwierdziłem, że jeśli nie powiedzie się pivot_root, to wraca do chroot, tj. Mechanizmy te są uważane za co najmniej podobne pod względem funkcjonalności do celów konteneryzacji.
Danila Kiver

Odpowiedzi:

13

Wprowadzenie przestrzeni nazw montowania przed skonfigurowaniem a chrootpozwala uniknąć zaśmiecania przestrzeni nazw hosta dodatkowymi montowaniami, np /proc. Dla . Możesz użyć chrootwewnątrz przestrzeni nazw montowania jako przyjemnego i prostego hacka.

Myślę, że zrozumienie pivot_rootma wiele zalet , ale ma trochę krzywej uczenia się. Dokumentacja nie wyjaśnia wszystkiego ... chociaż istnieje przykład użycia w man 8 pivot_root(dla polecenia powłoki). man 2 pivot_root(dla wywołania systemowego) może być jaśniejsze, jeśli zrobiłby to samo i zawierał przykładowy program C.

Jak korzystać z pivot_root

Natychmiast po wejściu w przestrzeń nazw montowania potrzebujesz także mount --make-rslave /lub jej odpowiednika. W przeciwnym razie wszystkie zmiany montowania zostaną propagowane do montowań w oryginalnej przestrzeni nazw, w tym pivot_root. Nie chcesz tego :).

Jeśli użyłeś unshare --mountpolecenia, pamiętaj, że mount --make-rprivatedomyślnie jest to udokumentowane . AFAICS to złe ustawienie domyślne i nie chcesz tego w kodzie produkcyjnym. Na przykład w tym momencie przestanie ejectdziałać na zamontowanym dysku DVD lub USB w obszarze nazw hosta. DVD lub USB pozostałyby zamontowane wewnątrz prywatnego drzewa montowania, a jądro nie pozwoliłoby na wysunięcie DVD.

Gdy to zrobisz, możesz zamontować np. /procKatalog, którego będziesz używać. Taki sam sposób, w jaki byś to zrobił chroot.

W przeciwieństwie do użycia chroot, pivot_rootwymaga, aby nowy główny system plików był punktem podłączenia. Jeśli nie jest to jeden już można zaspokoić to po prostu stosując zamontować wiążą: mount --rbind new_root new_root.

Użyj pivot_root- a następnie umountstarego systemu plików root z opcją -l/ MNT_DETACH. ( Nie potrzebujesz umount -R, co może potrwać dłużej. ).

Technicznie korzystanie z pivot_rootogólnie musi również obejmować korzystanie chroot; to nie jest „albo-albo”.

Zgodnie man 2 pivot_rootz definicją jest to definiowane tylko jako zamiana katalogu głównego przestrzeni nazw montowania. Nie jest zdefiniowane, aby zmieniać katalog fizyczny, na który wskazuje katalog główny procesu. Lub bieżący katalog roboczy ( /proc/self/cwd). Zdarza się, że tak się dzieje, ale jest to włamanie do obsługi wątków jądra. Strona twierdzi, że może się to zmienić w przyszłości.

Zwykle chcesz tę sekwencję:

chdir(new_root);            // cd new_root
pivot_root(".", put_old);   // pivot_root . put_old
chroot(".");                // chroot .

Stanowisko chrootw tej sekwencji to kolejny subtelny szczegół . Chociaż pivot_rootchodzi o zmianę rozmieszczenia przestrzeni nazw montowania, kod jądra wydaje się znaleźć główny system plików, aby się przenieść, patrząc na katalog główny root dla procesu, który chrootustawia.

Dlaczego warto korzystać z pivot_root

Zasadniczo sensowne jest stosowanie pivot_rootdla bezpieczeństwa i izolacji. Lubię myśleć o teorii bezpieczeństwa opartego na możliwościach . Przekazujesz listę konkretnych potrzebnych zasobów, a proces nie może uzyskać dostępu do innych zasobów. W tym przypadku mówimy o systemach plików przekazanych do przestrzeni nazw montowania. Ten pomysł ogólnie dotyczy funkcji „przestrzeni nazw” Linuksa, chociaż prawdopodobnie nie wyrażam tego zbyt dobrze.

chrootustawia tylko katalog główny procesu, ale proces nadal odnosi się do przestrzeni nazw pełnego montowania. Jeśli proces zachowuje uprawnienia do wykonywania chroot, może wykonać kopię zapasową przestrzeni nazw systemu plików. Jak wyszczególniono w man 2 chroot„superużytkownik może uciec z„ więzienia chroot ”do ...”.

Innym prowokującym do myślenia sposobem cofnięcia chrootjest nsenter --mount=/proc/self/ns/mnt. Jest to być może silniejszy argument za zasadą. nsenter/ setns()koniecznie ponownie ładuje katalog główny procesu, z katalogu głównego przestrzeni nazw montowania ... chociaż fakt, że działa to, gdy oba odnoszą się do różnych katalogów fizycznych, może być uważany za błąd jądra. (Uwaga techniczna: w katalogu głównym może być zamontowanych wiele systemów plików jedna nad drugą; setns()używa górnego, ostatnio zamontowanego).

To pokazuje jedną zaletę połączenia przestrzeni nazw montowania z „przestrzenią nazw PID”. Przebywanie w przestrzeni nazw PID uniemożliwiłoby wejście do przestrzeni nazw montowania nieskończonego procesu. Zapobiega również wejściu do katalogu głównego nieskończonego procesu ( /proc/$PID/root). I oczywiście przestrzeń nazw PID zapobiega również zabiciu dowolnego procesu, który jest poza nią :-).

sourcejedi
źródło
To już bardzo pomaga. Nadal nie jestem pewien, co masz na myśli przez „mount u góry przestrzeni nazw”. Czy istnieje sposób, aby to zmienić?
koalo
1
@koalo edytowane :-). ps nie wiem, dlaczego potrzebujesz fstab dla „make-rslave” / „make-rprivate”. systemd's switch-root.c po prostu działamount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL)
sourcejedi
1
@koalo, a następnie programiści jądra Linuksa używali „rootfs”, kiedy nazwali czwartą rzecz :-P. unix.stackexchange.com/questions/152029/…
sourcejedi
1
Ta odpowiedź i inne autorstwa @sourcejedi były wyjątkowo pomocne, zapytałbym: „pivot_root: nie mogę umount put_old as busy”, ale odpowiedź już była tutaj, bądź leniwy, bo siła nie zadziałaumount -l ./oldroot
kamera
1
Niedawno wprowadzono aktualizację strony podręcznika pivot_root (2) z kilkoma objaśnieniami, a teraz zawiera ona przykładowy program. Może chcesz zaktualizować swoją odpowiedź, aby to odzwierciedlić? Strona podręcznika wyjaśnia teraz także fajną pivot_root(".", ".")sztuczkę, która jest w rzeczywistości najłatwiejszym sposobem użycia pivot_rootw większości przypadków (nie jest to chrootkonieczne).
Philipp Wendler