Namespaces: una visión distinta del árbol de directorios para cada proceso
Sigo dando la coña con los ejercicios de Linux Kernel & Hackers Hut como viene siendo habitual 😛 Esta vez le ha tocado el turno a los namespaces. Es de sobra conocido el concepto de los chroot, que se viene utilizando desde hace mucho tiempo: cambiamos el directorio raiz de nuestro proceso (y todos los hijos que cree éste) por otro distinto, restringiendo su visión del árbol de directorios.
Esto se puede hacer desde la consola con la utilidad chroot o con la propia llamada al sistema chroot. Para ejecutar algo en un chroot necesitaremos tener disponibles dentro del mismo tanto los ejecutables como las librerías de las que dependa, o bien compilarlo de forma estática. Con esto y usando los mínimos privilegios para un servicio dado podremos reducir el impacto de una posible vulnerabilidad en dicho servicio.
Pues bien, el tema de los namespaces, aunque relativamente similar, es algo distinto. El namespace es el concepto que tiene un proceso dado del árbol de directorios. En un principio, todos los procesos comparten dicho concepto, heredándolo de init. Sin embargo, desde 2.4.19 el núcleo de linux incluye la posibilidad de ejecutar nuevos procesos con una copia del namespace de su padre.
¿Y en qué influye esto? Pues en que a partir de ahora, si nuestro proceso realiza un mount sobre un directorio cualquiera, solamente él y sus hijos lo podrán ver, pues son los únicos que tienen acceso a dicho espacio de nombres. Si desde otro proceso se monta cualquier dispositivo (o directorio usando --bind
) sobre un directorio dado, nuestro proceso tampoco lo verá.
Un ejemplo de uso sería montar un /tmp diferente para cada nueva sesión de usuario (por ejemplo un bind de /tmp/uid sobre /tmp en el namespace del usuario), de forma que no puedan ver los ficheros temporales de otros usuarios.
Se pueden ver varios ejemplos en este artículo de IBM developerWorks. Los artículos muestran como aplicarlo el login usando PAM; no los he probado, quizás un día de estos que tenga menos trabajo...
Para acabar, comentar que la forma de crear un proceso con una copia del namespace de su padre es llamando a clone() [similar a fork()] con el flag NEW_NS. Está todo explicado en el man de clone ;).
October 15th, 2007 - 14:45
yo no conocía esto, mola 🙂
October 15th, 2007 - 16:49
Sí, está interesante.
Algo a tener en cuenta es que si quieres una visión completamente distinta, cambiando también el directorio raiz, entonces necesitas hacer un pivot_root para cambiar el raiz de sitio, y después ya puedes desmontar el raiz (siempre que no esté en uso… lo mejor, un umount -L y desaparece del namespace pero no se desmonta del todo, sino que espera a no estar en uso por ningún proceso 😉 ).
Hay un ejemplo en el link del artículo, usando pivot_root y umount2 que es la syscall asociada al [i]lazy umount[/i].
October 15th, 2007 - 18:06
Hola, ha sido un post muy interesante donde he aprendido algo nuevo. Te animo a que sigas contando en este blog todo lo que aprendas en esa asignatura.
Por cierto, ¿Para cuando las soluciones del juego de la campus?
October 15th, 2007 - 18:35
Uhm, cierto 😳
Me lo apunto en mi lista de cosillas por hacer esta semana, que tengo que revisar unas cuantas cosas antes… tengo algo escrito pero hubo problemas con algunas cosillas y querría poner las distintas opciones que se me ocurrían para resolverlo.
El problema será que obviamente no tengo los equipos de la campus y no podré reproducir al 100% lo que pasaba allí, pero bueno lo ejecutaré en mi PC y pondré las soluciones en cuanto pueda.
Siento la tardanza… a ver si saco algo de tiempo esta semana y lo hago, aunque primero debo terminar los assignments que tengo que entregar el viernes y el martes que viene.