Hace un tiempo, publiqué una entrada en la que explicaba cómo se utilizan los permisos UNIX en el sistema de archivos de cualquier distribución Linux. Ahora bien, allí explicaba que la forma de asignar los permisos usando la terminal es el comando chmod sobre los archivos cuyos permisos nos interese modificar y chown para cambiar quién es su dueño y a qué grupo se asigna. Los permisos que el sistema asigna predeterminadamente al crear un archivo o directorio son bastante aceptables para un usuario corriente, pero en caso de que estos no sean los deseados, cambiarlos cada vez que se crea un archivo puede ser, además de molesto, algo muy sencillo de olvidar. Por eso hoy os explico cómo cambiar qué permisos predeterminados asigna el sistema a los archivos, usado umask, que más que un comando es más bien un concepto básico de cualquier sistema basado o inspirado en UNIX como son los sistemas GNU/Linux.
Si creamos un archivo cualquiera en una distrubución Linux cualquiera, veremos que automáticamente se le asignarán los siguientes permisos: escritura y lectura para el dueño, lectura para el grupo al cual pertenezca el archivo (normalmente el grupo del dueño) y lectura para el resto de usuarios (644 en notación octal). A los directorios, por otra parte, se les asigna los mismos permisos añadiendo a todos el permiso de ejecución (esto es, obtienen permisos 755 en notación octal). Como ya he dicho, estos son permisos que, por ejemplo, en un sistema utilizado por un único usuario no hay absolutamente ningún problema, pero en un sistema compartido con más de un usuario puede ser interesante, por ejemplo, que se asignen permisos más restringidos a los archivos y directorios en cuanto se crean.
1. El filtro umask
Para conseguir lo que queremos usaremos un comando, umask, cuya función es filtrar los permisos que no queremos a partir de la combinación de permisos totales. Para entender esto mejor, tenéis que saber que el comportamiento predeterminado que he descrito arriba (644 para archivos y 755 para directorios) se produce porque las distribuciones Linux usan normalmente umask con el valor 022, esto es, el sistema resta 022 a 666 en archivos y a 777 en directorios para que den los resultados respectivos que he dado arriba. La idea de “filtro” procede justamente del hecho de que se resten permisos a partir de un origen que engloba todos los posibles: imaginadlo como un filtro que no permite que “pasen” ciertos permisos al resultado final. Así pues, un umask de 000 (“no filtrar”) dejaría los archivos en 666 y los directorios en 777, lo cual es una irresponsabilidad total que, como decía la Diosa en el Poema de Parménides, “no te permito ni que la digas ni que la pienses”.
Hagamos un pequeño experimento para entender mejor cómo funciona esto. En una terminal, invocad umask sin ningún valor para saber qué filtro se está aplicando en estos momentos. Lo normal, si no habéis tocado nunca umask, es que la terminal muestre lo siguiente:
$ umask 0022
Si creamos un archivo usando touch (crea un archivo de texto vacío) y un directorio con mkdir, comprobaremos que, efectivamente, son creados con los todos permisos (666 y 777) menos permisos de escritura (2) para el grupo y para el resto de usuarios; es decir 644 y 755 (Nota: el umask real es 0022 y no 022; podéis ignorar el primer cero y de hecho no es necesario escribirlo, ya que se refiere a los permisos llamados “extendidos”, que no interesan en este nivel y para los que no se suelen aplicar filtros):
$ touch test && mkdir testdir $ ls -l total 4 -rw-r--r-- 1 user user 0 feb 20 12:48 test drwxr-xr-x 2 user user 4096 feb 20 12:48 testdir
Ahora ejecutad umask con un valor de 006. De ahora en adelante, todo archivo y directorio creado hasta que se cierre la sesión se le restarán los permisos de escritura y lectura (4+2=6) al ser creado. Aquí lo veis en acción:
$ umask 006 $ touch test2 && mkdir testdir2 $ ls -l total 4 -rw-rw---- 1 user user 0 feb 20 12:54 test2 drwxrwx--x 2 user user 4096 feb 20 12:54 testdir2
Fijaos en los permisos que el sistema ha asignado a ambos elementos. En primer lugar, test2 tiene escritura y lectura tanto para el dueño como para su grupo porque el filtro se aplica siempre sobre 666; por tanto, 666 – 006 = 660. El valor que tuviera umask antes de ser cambiado no influye en absoluto. Sin embargo, es más interesante el caso del directorio, que queda con el extraño conjunto de permisos 771 (es muy extraño dar permisos de ejecución a un directorio sin dar permisos de lectura), cosa totalmente sencilla de entender si recordamos que la creación de directorios aplica el valor de umask sobre 777 (777 – 006 = 771). Así pues, si nuestro objetivo es evitar que el resto de usuarios puedan acceder a nuestros datos (ni leer ni escribir ni “recorrer” directorios), pero sin que se quede ese último permiso abierto para los directorios, lo que necesitamos es un umask 007 (para que 777 – 007 = 770).
Ahora bien, ¿qué efectos tiene un umask 007 sobre los archivos, cuyos permisos de “inicio” son 666? Es evidente que 666 – 007 daría, en principio, 66(-1), una cifra que, evidentemente, no es un conjunto válido de permisos. Recordad que estas cifras de permisos se forman de tres dígitos independientes de números octales: 666 no es “seiscientos seis menos siete”, sino “seis-seis-seis”. Por tanto, la resta demostrada arriba se obtiene de restar cada uno de los tres dígitos por separado y, por tanto, el resultado de la operación es ese extraño 6/6/(-1) y no un “599”. Sin embargo, el sistema no tiene ningún problema en restarle 7 a 6, porque en ese caso deja como resultado 0. A continuación podéis ver cómo un umask de 007 deja a los archivos en 660:
$ umask 007 $ touch test3 && mkdir testdir3 $ ls -l total 4 -rw-rw---- 1 user user 0 feb 20 16:16 test3 drwxrwx--- 2 user user 4096 feb 20 16:16 testdir3
Generalmente, si lo que queremos es restringir la lectura, lo más práctico es siempre acompañar el filtrado del permiso de lectura con el filtrado del permiso de ejecución para que tanto archivos como directorios queden con exactamente los mismos permisos. Así pues, os recomendaría no usar nunca los valores 4 o 6 en umask (lectura o lectura y escritura), salvo que encontréis una buena razón para ello (y entonces os pido que la compartáis en los comentarios), sino siempre o 5 o 7, esto es, siempre agregando el permiso de ejecución al de lectura o al de lectura y escritura. Si, en cambio, solo queréis restringir la escritura, basta con utilizar el valor 2.
2. Persistencia de umask
Como ya he dicho antes, el valor de umask solo se mantiene mientras dure la sesión, cosa que no nos interesa demasiado si queremos funcionar sistemáticamente con un determinado valor para que sea el predeterminado. Para que el valor se mantenga entre sesiones lo que haremos es un pequeño hack que consistirá en pedirle al sistema que fije el valor que queramos en el momento de iniciar sesión, cosa que se consigue modificando dos archivos que existen en nuestra home, ~/.bashrc y ~/.profile. Debemos editar ambos archivos porque el primero se encarga de las sesiones en líneas de comando (para Bash, que suele ser lo usual), mientras que el segundo se encarga de todos los demás casos, es decir, del entorno gráfico, y no tiene absolutamente ningún sentido que el umask sea diferente según el método de acceso del usuario.
En ambos archivos, simplemente donde queráis (suelo añadirlo en algún sitio visible), añadís la orden umask con su valor de la misma forma como hemos hecho en la terminal arriba. Recordad que estos archivos están en vuestra carpeta de usuario, así que no uséis privilegios de administrador para editarlos. Así pues, en ambos archivos, introducís:
umask [VALOR DESEADO]
Ahora bien, como he dicho, estos dos archivos son leídos y ejecutados al iniciar la sesión del usuario, por lo que, para que surtan efectos estos cambios, deberemos reiniciar la sesión. Una vez hayáis reiniciado la sesión, probad ejecutando umask sin argumentos para consultar el valor vigente para la sesión y veréis que es exactamente el valor que habéis configurado en ambos archivos.
3. ¡Cuidado con sudo!
Ahora entramos en terreno pedregoso. Podrá parecer que con los pasos anteriores ya habremos acabado, pero aún falta un paso muy curioso que nos ahorrará bastantes dolores de cabeza en el futuro. Resulta que el valor umask predeterminado, como ya he dicho, se carga al iniciar una sesión del usuario, por lo que, si utilizamos la cuenta de root directamente o usamos su para iniciar una shell como superusuario, el umask predeterminado del sistema se aplicará para nuestra actividad como root… excepto cuando usamos sudo.
Os muestro el siguiente experimento para que veáis el problema (que he realizado en un Ubuntu 15.10 virtualizado para no destruir accidentalmente mi configuración de sudo en Arch). Con un umask de 077 en el usuario y de 022 en el sistema (y por tanto para root), crearemos un archivo en blanco usando sudo, cuyos permisos luego revisaremos consultando el listado del directorio:
$ umask 0077 $ sudo su [sudo] password for user: # umask 0022 # exit $ sudo touch test $ ls -l total 0 -rw------- 1 root root 0 feb 21 15:38 test
Lo que se muestra arriba contradice nuestras expectativas. Si usamos sudo para crear un archivo, esperamos, en principio, que respete el umask de root, pero la razón de por qué el archivo se crea usando el umask del usuario (077) al usar sudo es porque este no abre una sesión de root, sino que utiliza la sesión del usuario que lo ha invocado (si tenéis ya más conocimientos, quizás os suene el concepto de setuid; os dejo un artículo de Linuxito sobre el tema). Esto puede traer problemas cuando es necesario crear archivos de configuración con ciertos permisos (especialmente de grupo): si el umask del usuario que ejecuta sudo es más restrictivo que el esperado (022), el archivo será creado con permisos que posiblemente producirán problemas. Ciertamente, esto no es tan grave porque no afecta, por ejemplo, a los archivos instalados por los gestores de paquetes, los cuales se encargan de asignar los permisos correctos a los archivos instalados, pero aún así puede ser un tanto incómodo. Por tanto, para que la cuenta de superusuario utilice siempre el mismo umask independientemente de cómo accedamos a ella, le exigiremos a sudo que aplique por sí mismo un umask 022.
Para ello, editaremos /etc/sudoers, pero, como ya expliqué en esta entrada Cómo configurar correctamente “sudo” (Allí también expliqué, pero menos detalladamente cómo configurar el umask), este archivo debe ser editado de una manera especial y nunca usando un editor de texto que lo abra directamente. Antes de aplicar el cambio que explicaré a continuación, os pido que reviséis esa entrada aunque no sea para novatos para entender, aunque sea superficialmente, por qué lo haremos de esta manera. Dicho esto, para editar /etc/sudoers, utilizaremos el comando visudo, pero forzando el uso del editor nano en vez de vim, porque será más sencillo:
$ sudo EDITOR=nano visudo
En /etc/sudoers, añadid donde queráis (pero hay una “sección” de “Defaults”, si queréis mantener un cierto orden) las siguientes dos opciones:
Defaults umask = 0022 Defaults umask_override
La primera fija el valor de umask que queramos, aunque recomiendo que uséis 0022 (o 022), y la segunda obliga a sudo a usar este valor por sobre cualquier otro valor de umask que pudiera recibir de otras fuentes (la cuenta del usuario que ha invocado sudo, por ejemplo).
Para guardar, usad Ctrl+X. Os preguntará si lo queréis guardar y el editor se cerrará una vez guardéis el archivo. Si queréis comprobar si ha funcionado, probad otra vez el experimento anterior y veréis que el archivo se creará usando un umask 022 aun cuando el usuario utilice uno más restrictivo.
4. Conclusión
Quizás esta sea una de las entradas para novatos más complejas que haya escrito en el blog, pero creo que es imperioso que todo aquel que se introduce en el uso de las distribuciones Linux sepa cómo gestionar los permisos de sus datos, no solo entendiendo cómo aplicarlos a cada elemento en concreto con chmod, sino entendiendo también cómo pedirle al sistema qué permisos asignar al crearlos. De esta manera solo tendremos que cambiar los permisos de aquellos archivos que se salgan de la norma que hemos impuesto. Por supuesto, si tenéis cualquier duda, no dejéis de comentar esta entrada con vuestras preguntas (¡aprovechemos que WordPress no impide comentar a nadie, a diferencia de Blogger!) e intentaré contestaros a todos los que pueda en cuanto pueda.
Extra: Corregir los permisos
Si resulta que llevábais años usando un umask permisivo y ahora, por la razón que fuera, habéis decidido utilizar uno que no lo sea tanto, podéis usar los siguientes dos comandos para adaptar con una sola línea todos los permisos de los archivos y directorios dentro de la carpeta de usuario, pero diferenciando entre ambos tipos (un simple chmod recursivo no lo haría):
find ~ -type f -exec chmod VALOR-ARCHIVOS {} \; find ~ -type d -exec chmod VALOR-DIRECTORIOS {} \;
Los comandos aprovechan una interesante función del comando find, a saber, la capacidad de ejecutar (-exec) un comando sobre todos los elementos encontrados dentro del objetivo (~, es decir, la home) según un patrón, que en este caso es el tipo (-type) de elemento, ya sea un archivo (f de file) o un directorio (d de directorio). Cuando encuentre un archivo, el primero ejecutará sobre él un chmod con los permisos (no un umask) que queramos y el segundo lo hará cuando encuentre un directorio. Así podréis modificar los archivos y los directorios antiguos sin dar rodeos extraños para que cumplan con la nueva configuración que hayáis escogido.
Imagen: Run, penguin, run!, de Andrew Davies, publicada bajo CC-BY-NC 2.0
Fuente: etccrond