Tengo una instalación de Unix que se supone que se puede usar tanto como un chroot como un sistema independiente. Si se está ejecutando como un chroot, no quiero ejecutar ningún servicio (cron, inetd, etc.), porque entrarían en conflicto con el sistema host o serían redundantes.
¿Cómo escribo un script de shell que se comporte de manera diferente dependiendo de si se está ejecutando en un chroot? Mi necesidad inmediata es un sistema Linux moderno, con /proc
montado en el chroot, y el script se ejecuta como root, pero también son bienvenidas respuestas más portátiles. (Consulte ¿Cómo sé que estoy ejecutando en un chroot si /proc no está montado? para el caso de Linux sin /proc
.)
En términos más generales, serían interesantes las sugerencias que funcionen para otros métodos de contención. La pregunta práctica es, ¿se supone que este sistema debe ejecutar algún servicio? (La respuesta es no en un chroot y sí en máquinas virtuales completas; no conozco casos intermedios como cárceles o contenedores).
Respuesta aceptada:
Lo que he hecho aquí es probar si la raíz del init
proceso (PID 1) es el mismo que la raíz del proceso actual. Aunque /proc/1/root
siempre es un enlace a /
(a menos que init
en sí mismo está chrooteado, pero ese no es un caso que me interese), seguirlo conduce al directorio raíz "maestro". Esta técnica se usa en algunas secuencias de comandos de mantenimiento en Debian, por ejemplo, para omitir el inicio de udev después de la instalación en 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
(Por cierto, este es otro ejemplo más de por qué chroot
es inútil para la seguridad si el proceso chroot tiene acceso de root. Los procesos no root no pueden leer /proc/1/root
, pero pueden seguir /proc/1234/root
si hay un proceso en ejecución con PID 1234 ejecutándose como el mismo usuario).
Si no tiene permisos de root, puede consultar /proc/1/mountinfo
y /proc/$$/mountinfo
(brevemente documentado en filesystems/proc.txt
en la documentación del kernel de Linux). Este archivo es de lectura universal y contiene mucha información sobre cada punto de montaje en la vista del proceso del sistema de archivos. Las rutas en ese archivo están restringidas por el chroot que afecta el proceso del lector, si lo hay. Si el proceso lee /proc/1/mountinfo
está conectado a un sistema de archivos que es diferente de la raíz global (suponiendo que la raíz de pid 1 sea la raíz global), entonces no hay entrada para /
aparece en /proc/1/mountinfo
. Si el proceso lee /proc/1/mountinfo
está conectado a un directorio en el sistema de archivos raíz global, luego una entrada para /
aparece en /proc/1/mountinfo
, pero con un ID de montaje diferente. Por cierto, el campo raíz ($4
) indica dónde se encuentra el chroot en su sistema de archivos principal.
[ "$(awk '$5=="/" {print $1}' </proc/1/mountinfo)" != "$(awk '$5=="/" {print $1}' </proc/$$/mountinfo)" ]
Esta es una solución pura de Linux. Puede ser generalizable a otras variantes de Unix con un /proc
suficientemente similar (Solaris tiene un /proc/1/root
similar , creo, pero no mountinfo
).