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 chroot
all'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 --mount
comando, nota che è documentato per essere applicato mount --make-rprivate
per impostazione predefinita. AFAICS è un difetto di default e non lo vuoi nel codice di produzione. Ad esempio, a questo punto, smetterebbe eject
di 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 /proc
directory che utilizzerai. Allo stesso modo per te chroot
.
A differenza di quando lo usi chroot
, pivot_root
richiede 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 umount
il 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_root
genere 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 chroot
in 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 chroot
imposta.
Perché usare pivot_root
In linea di principio, ha senso utilizzare pivot_root
per 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.
chroot
imposta 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 :-).
pivot_root
echroot
: ho dato un'occhiata alle fonti Docker e ho scoperto che se fallisce l'esecuzionepivot_root
, ricade suchroot
, cioè questi meccanismi sono considerati almeno simili nella funzionalità ai fini della containerizzazione.