Come eseguire chroot con spazi dei nomi Linux?


14

Dopo aver letto gli spazi dei nomi di Linux, ho avuto l'impressione che siano, tra molte altre funzionalità, un'alternativa al chroot. Ad esempio, in questo articolo :

Altri usi [degli spazi dei nomi] includono l'isolamento [...] in stile chroot () di un processo in una porzione della gerarchia di singole directory.

Tuttavia, quando clono lo spazio dei nomi mount, ad esempio con il seguente comando, vedo ancora l'intero albero radice originale.

unshare --mount -- /bin/bash

Capisco che ora sono in grado di eseguire ulteriori mount nel nuovo spazio dei nomi che non sono condivisi con lo spazio dei nomi originale e quindi questo fornisce isolamento, ma è sempre la stessa radice, ad esempio /etcè sempre la stessa per entrambi gli spazi dei nomi. Devo ancora chrootcambiare la radice o esiste un'alternativa?

Mi aspettavo che questa domanda potesse fornire una risposta, ma la risposta usa solo chroot, ancora una volta.

EDIT # 1

C'era un commento ora cancellato che menzionava pivot_root. Dal momento che questo è effettivamente parte di linux/fs/namespace.c, è in realtà parte dell'implementazione degli spazi dei nomi. Ciò suggerisce che cambiare la directory principale solo con unsharee mountnon è possibile, ma gli spazi dei nomi forniscono una versione più intelligente di chroot. Tuttavia non ho l'idea principale di questo approccio che lo rende sostanzialmente diverso chroot, anche dopo aver letto il codice sorgente (nel senso di sicurezza o isolamento migliore).

EDIT # 2

Questo non è un duplicato di questa domanda . Dopo aver eseguito tutti i comandi dalla risposta, ho separato /tmp/tmp.vyM9IwnKuY (o simile), ma la directory principale è sempre la stessa!


Per quanto riguarda la differenza tra pivot_roote chroot: ho dato un'occhiata alle fonti Docker e ho scoperto che se fallisce l'esecuzione pivot_root, ricade su chroot, cioè questi meccanismi sono considerati almeno simili nella funzionalità ai fini della containerizzazione.
Danila Kiver,

Risposte:


13

Immettendo uno spazio dei nomi di mount prima di impostare a chroot, si evita di ingombrare lo spazio dei nomi host con supporti aggiuntivi, ad esempio per /proc. È possibile utilizzare chrootall'interno di uno spazio dei nomi mount come un trucco semplice e piacevole.

Penso che ci siano vantaggi nella comprensione pivot_root, ma ha una curva di apprendimento. La documentazione non spiega completamente tutto ... sebbene ci sia un esempio di utilizzo in man 8 pivot_root(per il comando shell). man 2 pivot_root(per la chiamata di sistema) potrebbe essere più chiaro se facesse lo stesso e includesse un programma C di esempio.

Come usare pivot_root

Immediatamente dopo aver inserito lo spazio dei nomi di mount, è anche necessario mount --make-rslave /o equivalente. Altrimenti, tutte le modifiche del mount si propagano ai mount nello spazio dei nomi originale, incluso il file pivot_root. Non lo vuoi :).

Se hai utilizzato il unshare --mountcomando, nota che è documentato per essere applicato mount --make-rprivateper impostazione predefinita. AFAICS è un difetto di default e non lo vuoi nel codice di produzione. Ad esempio, a questo punto, smetterebbe ejectdi funzionare su un DVD o USB montato nello spazio dei nomi host. Il DVD o USB rimarrebbero montati all'interno dell'albero di montaggio privato e il kernel non ti permetterebbe di espellere il DVD.

Una volta fatto, puoi montare ad esempio la /procdirectory che utilizzerai. Allo stesso modo per te chroot.

A differenza di quando lo usi chroot, pivot_rootrichiede che il tuo nuovo filesystem di root sia un mount point. Se non è già uno, è possibile soddisfare questa semplicemente applicando montare un vicolo cieco: mount --rbind new_root new_root.

Usa pivot_root- e poi umountil vecchio filesystem di root, con l' opzione -l/ MNT_DETACH. ( Non è necessario umount -R, il che può richiedere più tempo. )

Tecnicamente, l'utilizzo in pivot_rootgenere deve comportare anche l'utilizzo chroot; non è "o-o".

Secondo man 2 pivot_root, è definito solo come scambio della radice dello spazio dei nomi di mount. Non è definito per cambiare la directory fisica a cui punta la radice del processo. O la directory di lavoro corrente ( /proc/self/cwd). Succede che lo fa , ma questo è un trucco per gestire i thread del kernel. La manpage dice che potrebbe cambiare in futuro.

Di solito vuoi questa sequenza:

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

La postura del chrootin questa sequenza è ancora un altro dettaglio sottile . Anche se il punto di pivot_rootè riorganizzare lo spazio dei nomi mount, il codice del kernel sembra trovare il filesystem di root da spostare guardando il root per processo, che è ciò che chrootimposta.

Perché usare pivot_root

In linea di principio, ha senso utilizzare pivot_rootper la sicurezza e l'isolamento. Mi piace pensare alla teoria della sicurezza basata sulle capacità . Si passa in un elenco delle risorse specifiche necessarie e il processo non può accedere ad altre risorse. In questo caso stiamo parlando dei filesystem passati a uno spazio dei nomi mount. Questa idea si applica generalmente alla funzionalità "namespace" di Linux, anche se probabilmente non la sto esprimendo molto bene.

chrootimposta solo la radice del processo, ma il processo fa ancora riferimento allo spazio dei nomi di montaggio completo. Se un processo mantiene il privilegio da eseguire chroot, può attraversare il backup dello spazio dei nomi del filesystem. Come spiegato in dettaglio man 2 chroot, "il superutente può scappare da una" prigione chroot "di ...".

Un altro modo stimolante per annullare chrootè nsenter --mount=/proc/self/ns/mnt. Questo è forse un argomento più forte per il principio. nsenter/ setns()Ricarica necessariamente la root del processo, dalla radice dello spazio dei nomi mount ... anche se il fatto che funzioni quando i due si riferiscono a diverse directory fisiche, potrebbe essere considerato un bug del kernel. (Nota tecnica: potrebbero esserci più filesystem montati uno sopra l'altro nella radice; setns()utilizza quello superiore, montato più di recente).

Ciò illustra un vantaggio della combinazione di uno spazio dei nomi mount con uno "spazio dei nomi PID". Essere all'interno di uno spazio dei nomi PID ti impedirebbe di entrare nello spazio dei nomi mount di un processo non definito. Ti impedisce anche di inserire la radice di un processo non confinato ( /proc/$PID/root). E ovviamente uno spazio dei nomi PID ti impedisce anche di uccidere qualsiasi processo al di fuori di esso :-).


Questo aiuta già molto. Tuttavia, non sono sicuro di cosa intendi con "il mount nella parte superiore dello spazio dei nomi". E c'è un modo per cambiarlo?
Koalo,

1
@koalo modificato :-). ps non so perché avresti bisogno di fstab per "make-rslave" / "make-rprivate". switch-root.c di systemd fa propriomount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL)
sourcejedi

1
@koalo e poi gli sviluppatori del kernel Linux hanno usato "rootfs" quando hanno chiamato una quarta cosa :-P. unix.stackexchange.com/questions/152029/…
sourcejedi

1
Questa risposta e altre di @sourcejedi sono state eccezionalmente utili, avrei chiesto "pivot_root: non riesco a mettere put_old così occupato" ma la risposta era già qui, sii pigro perché la forza non funzioneràumount -l ./oldroot
earcam

1
Di recente è stato aggiornato la pagina man pivot_root (2) con diversi chiarimenti e ora include un programma di esempio. Potresti voler aggiornare la tua risposta per riflettere questo? La pagina man ora spiega anche il bel pivot_root(".", ".")trucco, che in realtà è il modo più semplice da usare pivot_rootnella maggior parte dei casi (non chrootnecessario).
Philipp Wendler,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.