Come faccio a sapere che sto correndo in un chroot?


47

Ho un'installazione unix che dovrebbe essere utilizzabile sia come chroot che come sistema autonomo. Se funziona come chroot, non voglio eseguire alcun servizio (cron, inetd e così via), perché potrebbero entrare in conflitto con il sistema host o essere ridondanti.

Come faccio a scrivere uno script di shell che si comporta diversamente a seconda che sia in esecuzione in un chroot? Il mio bisogno immediato è un moderno sistema Linux, con /procil chroot montato, e lo script funziona come root, ma anche le risposte più portatili sono benvenute. (Vedi Come faccio a sapere se sto eseguendo un chroot se / proc non è montato? Per il caso di Linux senza /proc.)

Più in generale, i suggerimenti che funzionano con altri metodi di contenimento sarebbero interessanti. La domanda pratica è: questo sistema dovrebbe eseguire servizi? (La risposta è no in un chroot e sì in macchine virtuali a tutti gli effetti; non conosco casi intermedi come jail o container.)

Risposte:


46

Quello che ho fatto qui è di verificare se la radice del initprocesso (PID 1) è la stessa della radice del processo corrente. Sebbene /proc/1/rootsia sempre un collegamento /(a meno che non initsia esso stesso chroot, ma non è un caso a cui tengo), seguirlo porta alla directory principale "master". Questa tecnica è usata in alcuni script di manutenzione in Debian, ad esempio per saltare l'avvio di udev dopo l'installazione in un chroot.

if [ "$(stat -c %d:%i /)" != "$(stat -c %d:%i /proc/1/root/.)" ]; then
  echo "We are chrooted!"
else
  echo "Business as usual"
fi

(A proposito, questo è ancora un altro esempio del perché chrootè inutile per la sicurezza se il processo chroot ha accesso root. I processi non root non possono leggere /proc/1/root, ma possono seguire /proc/1234/rootse c'è un processo in esecuzione con PID 1234 in esecuzione come lo stesso utente.)

Se non si dispone dei permessi di root, è possibile consultare /proc/1/mountinfoe /proc/$$/mountinfo(brevemente documentato nella documentazione filesystems/proc.txtdel kernel Linux ). Questo file è leggibile in tutto il mondo e contiene molte informazioni su ciascun punto di montaggio nella vista del processo del filesystem. I percorsi in quel file sono limitati dal chroot che influenza il processo di lettura, se presente. Se la lettura del processo /proc/1/mountinfoviene eseguita il chroot in un filesystem diverso dalla radice globale (supponendo che la radice di pid 1 sia la radice globale), allora non /appare alcuna voce per /proc/1/mountinfo. In caso la lettura processo /proc/1/mountinfoè chroot in una directory sul filesystem di root globale, allora una voce per /appare in /proc/1/mountinfo, ma con un diverso montaggio id. Per inciso, il campo radice ($4) indica dove si trova il chroot nel suo filesystem principale.

[ "$(awk '$5=="/" {print $1}' </proc/1/mountinfo)" != "$(awk '$5=="/" {print $1}' </proc/$$/mountinfo)" ]

Questa è una pura soluzione Linux. Potrebbe essere generalizzabile ad altre varianti di Unix con una sufficientemente simile /proc(Solaris ha una simile /proc/1/root, penso, ma non mountinfo).


1
Questo non funzionerà in OpenBSD perché ha PID casuali ; il processo di root non è praticamente mai PID 1. Ora sai perché!
Adam Katz,

@AdamKatz "... con un paio di ovvie eccezioni, ad esempio init (8)." Quindi che cos'è?
Muru,

@muru: aw, schifo. Mi hai abbattuto. Non sono sicuro del motivo per cui init(8)dovrebbe assolutamente avere lo slot n. 1 a meno che non ci sia una sorta di natura hard-coded che lo richiede (in cui non sarei ancora sicuro del perché ). Ovviamente, i BSD hanno jail molto più avanzate di un semplice chroot, quindi non sono nemmeno sicuro di quanto sia problematico.
Adam Katz,

4
@AdamKatz È l'opposto: pid 1 ha un ruolo speciale (deve raccogliere zombi ed è immune da SIGKILL). Il programma init è un'implementazione di quel ruolo. Il motivo per cui la mia risposta non funziona in OpenBSD non ha nulla a che fare con questo: è perché OpenBSD non ha nulla di simile a Solaris / Linux /proc. La mia risposta non voleva indirizzare nient'altro che Linux.
Gilles 'SO- smetti di essere malvagio' il

@Gilles Ho pensato che OpenBSD l'avrebbe sconfitto in un modo o nell'altro. Tuttavia, sono sorpreso che tutti quegli elementi di ruolo speciali non siano in grado di essere applicati a un PID arbitrario (senza conseguenze), che è ciò che intendevo nel mio "perché" in corsivo prima.
Adam Katz,

22

Come menzionato in Modo portatile per trovare il numero di inode e Rilevare una prigione chroot dall'interno , è possibile verificare se il numero di inode di /è 2:

$ ls -di /
2 /

Un numero di inode diverso da 2 indica che la radice apparente non è la radice effettiva di un filesystem. Ciò non rileverà i chroot che sono stati rootati su un mount point o su sistemi operativi con numeri di inode root casuali .


Su quali filesystem funziona questa euristica?
Gilles 'SO- smetti di essere malvagio' il

Testato su ext3 e hfs.
l0b0

Quindi stavo scherzando e penso di aver trovato un metodo più affidabile che non richiede permessi di root (solo Linux). Sono ancora aperto a contro-esempi o metodi più portatili.
Gilles 'SO- smetti di essere malvagio'

6
Questo è vero per ext [234], ma non per tutti i filesystem. Verifica anche che la tua radice sia la radice del filesystem, che potrebbe non essere montata come la vera radice. In altre parole, se monti un'altra partizione in / jail e chroot /jail, allora sembrerà la vera radice di questo test.
psusi

1
@AdamKatz Apparentemente no. Testato in openbsd 6.0-stable, il numero di inode è ancora 2 per il percorso root effettivo mentre è un numero casuale per il chroot.
Dmitri DB,

5

Mentre chiaramente non è portatile come molte altre opzioni elencate qui, se sei su un sistema basato su Debian, prova ischroot.

Vedi: https://manpages.debian.org/jessie/debianutils/ischroot.1.en.html

Per ottenere direttamente lo stato nella console, usando ischroot:

ischroot;echo $?

Codici di uscita:

0 if currently running in a chroot
1 if currently not running in a chroot
2 if the detection is not possible (On GNU/Linux this happens if the script is not run as root).
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.