Llevamos cinco lecciones viendo lo mismo en cada ls -l y en cada stat sin explicarlo: -rw-r-----, Uid: (990/meteora), Acceso: (0640/-rw-r-----). Hemos protegido 2026-08-31.dat del corte de luz con el diario, del fallo de un disco con RAID 1 y de un bit volteado con un CRC por registro. Pero no hemos respondido a la pregunta más básica de todas: ¿quién puede leer ese fichero, y quién puede borrarlo?
La respuesta es un modelo de doce bits diseñado en 1971 que sigue siendo, cincuenta años después, la base del control de acceso de todos los sistemas UNIX. Su virtud es la simplicidad; su peligro, que esa simplicidad esconde comportamientos que sorprenden. Que los permisos de un directorio signifiquen cosas distintas de los de un fichero. Que se pueda borrar un fichero que no se puede leer. Que el permiso se compruebe en todos los directorios de la ruta, no solo en el fichero final. Y que un programa ejecutado por un usuario normal pueda, mediante un solo bit, modificar /etc/shadow.
Esta lección explica los doce bits uno a uno, con el porqué de cada comportamiento; añade las ACL POSIX para los casos que los doce bits no cubren; presenta los atributos de fichero, que protegen incluso de root; compara el modelo con el de Windows; y termina fijando y justificando los permisos exactos de todos los ficheros de Meteora, con los comandos completos y una auditoría de lo que suele estar mal.
Contenido
- El modelo clásico: usuario, grupo y otros
- Los bits
r,wyxen ficheros y en directorios - Notación simbólica y octal:
chmod,chown,chgrp umask: cómo se calcula el permiso final- Los bits especiales: setuid, setgid y sticky
- Cómo comprueba el núcleo un acceso, paso a paso
- Listas de control de acceso POSIX
- Atributos extendidos y atributos de fichero
- Comparación con el modelo de Windows
- Los permisos de Meteora, justificados
- Errores graves y cómo auditarlos
- Cierre del módulo 4
El modelo clásico: usuario, grupo y otros
Cada fichero tiene en su inodo (04-01) dos identificadores numéricos y doce bits de modo:
- UID del propietario: quién es su dueño. En Meteora, 990 (
meteora). - GID del grupo propietario: qué grupo tiene acceso especial. También 990.
- Modo: doce bits que dicen qué puede hacer cada clase de usuario.
El inodo guarda números, no nombres. La traducción a meteora la hacen ls y stat consultando /etc/passwd y /etc/group; si borras la entrada del usuario, ls -l mostrará 990 a secas y el fichero seguirá siendo suyo.
Ante cualquier acceso, el núcleo clasifica al solicitante en exactamente una de tres clases:
| Clase | Abreviatura | Condición |
|---|---|---|
| Usuario (propietario) | u |
Su UID efectivo es el UID del fichero |
| Grupo | g |
No es el dueño, pero alguno de sus grupos es el GID del fichero |
| Otros | o |
Ni lo uno ni lo otro |
Y ahí está la primera sutileza, que produce un desconcierto clásico:
Las tres clases son excluyentes y se evalúan en ese orden. Si eres el propietario, se aplican solo los bits de usuario, aunque los de grupo sean más permisivos.
$ ls -l raro.txt ----r--r-- 1 meteora meteora 100 sep 1 15:10 raro.txt $ id uid=990(meteora) gid=990(meteora) $ cat raro.txt cat: raro.txt: Permiso denegado
El dueño no puede leer su propio fichero, mientras que cualquier otro miembro del grupo meteora sí. No es un fallo: la clase se decide primero y los permisos se aplican después. El dueño, eso sí, siempre puede ejecutar chmod sobre él y arreglarlo.
Cada clase tiene tres bits, r, w y x, lo que da los nueve bits que muestra ls -l, más tres bits especiales que veremos en el apartado 5.
Los bits r, w y x en ficheros y en directorios
Aquí está el corazón de la lección, y lo que más errores causa: los tres bits significan cosas distintas según el tipo.
| Bit | En un fichero | En un directorio |
|---|---|---|
r |
Leer el contenido | Listar los nombres que contiene |
w |
Modificar el contenido | Crear, borrar y renombrar entradas |
x |
Ejecutarlo como programa | Atravesarlo: usarlo en una ruta y acceder a lo que hay dentro |
Recuerda 04-02: un directorio es un fichero cuyo contenido es la lista de pares (nombre, inodo). Con eso, los tres significados dejan de ser arbitrarios y se vuelven inevitables:
r= leer el contenido del directorio = leer la lista de nombres. Eso es exactamente lo que hacels.w= escribir en el contenido del directorio = añadir o quitar entradas. Crear un fichero es añadir una entrada; borrarlo es quitarla. Ambas son escrituras en el directorio, no en el fichero.x= usar el directorio para llegar a algo = poder resolver un componente de la ruta (04-02) y consultar el inodo asociado a un nombre que ya conoces.
De ahí salen las cuatro consecuencias que hay que interiorizar.
1. x sin r: puedes entrar pero no mirar. Es el "directorio oscuro":
Cualquiera puede acceder a /home/analista/informe.pdf si sabe el nombre exacto, pero ls /home/analista falla con "Permiso denegado". Es la configuración clásica de los directorios personales en servidores compartidos y de la raíz de un servidor web: se sirve lo que se pide, no se enumera el contenido.
2. r sin x: puedes ver los nombres pero nada más. ls datos/ lista a.txt, pero ls -l datos/ falla en cada entrada —porque leer el inodo de cada fichero exige atravesar el directorio— y muestra una línea de interrogantes, -????????? ? ? ? ? a.txt. Esos interrogantes son la firma inconfundible de r sin x, una combinación inútil que casi siempre es un error.
3. Se puede borrar un fichero que no se puede leer ni escribir. Este es el comportamiento que más sorprende, y ahora es evidente:
$ ls -ld /tmp/pruebas ; ls -l /tmp/pruebas/secreto.txt
drwxrwxr-x 2 joan joan 4096 sep 1 15:20 /tmp/pruebas
-r-------- 1 root root 128 sep 1 15:20 /tmp/pruebas/secreto.txt
$ cat /tmp/pruebas/secreto.txt
cat: ...: Permiso denegado ← no puedo leerlo
$ rm -f /tmp/pruebas/secreto.txt ← ¡pero SÍ puedo borrarlo!Borrar no toca el fichero. unlink (04-02) elimina una entrada del directorio y decrementa el contador de enlaces del inodo. La operación es una escritura en el directorio, y por eso el permiso que se comprueba es w en el directorio, no en el fichero. Los permisos del fichero son completamente irrelevantes.
Es la razón por la que existe el bit pegajoso, y por la que un directorio escribible por todos sin ese bit es una bomba.
4. Cambiar el contenido de un fichero no requiere permiso en el directorio, y al revés. Los dos permisos son independientes y protegen cosas distintas: el del fichero protege su contenido, el del directorio protege su nombre.
| Operación | Permiso necesario en el fichero | Permiso necesario en el directorio |
|---|---|---|
| Leer el contenido | r |
x en toda la ruta |
| Modificar el contenido | w |
x en toda la ruta |
| Crear un fichero | — | w + x |
| Borrar un fichero | nada | w + x |
| Renombrar un fichero | nada | w + x en origen y destino |
| Listar el directorio | — | r |
Entrar (cd) |
— | x |
Ver metadatos (stat) |
— | x en toda la ruta |
Notación simbólica y octal: chmod, chown, chgrp
Los nueve bits se expresan de dos formas equivalentes. En octal, cada dígito codifica tres bits sumando 4 (leer) + 2 (escribir) + 1 (ejecutar/atravesar): así, 6 es rw-, 5 es r-x y 7 es rwx. Los valores más habituales, con su uso correcto:
| Octal | Simbólico | Para qué |
|---|---|---|
| 644 | rw-r--r-- |
Fichero público de solo lectura |
| 640 | rw-r----- |
Fichero de datos de un servicio (Meteora) |
| 600 | rw------- |
Secretos: claves, contraseñas |
| 755 | rwxr-xr-x |
Programa ejecutable, directorio público |
| 750 | rwxr-x--- |
Directorio de un servicio (Meteora) |
| 700 | rwx------ |
Directorio privado |
| 2770 | rwxrws--- |
Directorio compartido por un grupo (setgid) |
| 1777 | rwxrwxrwt |
/tmp: escribible por todos, con bit pegajoso |
| 777 | rwxrwxrwx |
Nunca. Jamás. Ver el apartado 11 |
Los comandos:
chmod 640 /etc/meteora/meteora.conf # octal: fija los NUEVE bits de golpe
chmod g+r,o-rwx fichero # simbólico: modifica SOLO lo indicado
chmod -R u=rwX,g=rX,o= /var/lib/meteora # la X mayúscula: ver abajo
chown meteora:meteora fichero # cambiar dueño Y grupo
chgrp analistas fichero # solo el grupoTres precisiones que evitan destrozos. El octal es absoluto y el simbólico es relativo: chmod 640 pone exactamente esos bits, mientras que chmod g+r añade uno sin tocar los demás; en un chmod -R sobre un árbol, el octal es peligroso porque aplica lo mismo a ficheros y a directorios. La X mayúscula es la solución a ese problema, porque significa "ejecutar/atravesar solo si es un directorio o si ya tenía algún x": chmod -R u=rwX,g=rX,o= deja los directorios navegables sin convertir en ejecutables los ficheros de datos. Y solo el propietario y root pueden ejecutar chmod, mientras que solo root puede ejecutar chown para regalar un fichero a otro usuario: si un usuario normal pudiera, esquivaría las cuotas de disco y podría plantar ficheros comprometedores en la cuenta de otro.
umask: cómo se calcula el permiso final
Cuando un programa crea un fichero, pasa un modo a open() (04-04) —típicamente 0666— o a mkdir —típicamente 0777—. Pero el fichero no acaba con esos permisos, porque el núcleo aplica una máscara del proceso: la umask.
Permisos finales = modo solicitado AND (NOT umask)
En la práctica, es más fácil verlo como una resta de bits: la umask dice qué permisos quitar.
$ umask
0027
Fichero: modo solicitado 666 rw- rw- rw-
umask 027 --- -w- rwx (bits a quitar)
RESULTADO 640 rw- r-- --- ✔
Directorio: modo solicitado 777 rwx rwx rwx
umask 027 --- -w- rwx
RESULTADO 750 rwx r-x --- ✔Fíjate en el detalle importante: la umask nunca añade el bit de ejecución. Los programas piden 0666 para ficheros regulares precisamente para que un fichero de datos jamás nazca ejecutable, por muy permisiva que sea la umask. El x de un programa lo pone después el compilador o el instalador con un chmod explícito.
Los valores habituales y lo que producen:
| umask | Ficheros | Directorios | Uso |
|---|---|---|---|
022 |
644 | 755 | Por defecto en la mayoría de distribuciones. Todo el mundo lee |
002 |
664 | 775 | Trabajo en grupo: el grupo también escribe |
027 |
640 | 750 | Servicios: el grupo lee, los demás nada |
077 |
600 | 700 | Máxima privacidad: solo el dueño |
Meteora usa umask 027, y eso explica todos los -rw-r----- y drwxr-x--- que llevamos viendo desde 04-01. La justificación es exacta: el ingestor crea 2026-09-01.dat y necesita que el agregador y meteo-api —miembros del grupo meteora— puedan leerlo, pero que ningún otro usuario del sistema tenga acceso. 027 da precisamente eso, sin un solo chmod posterior.
Advertencia importante: la umask por defecto es 022, que deja los ficheros legibles por todo el mundo; con ella, 2026-09-01.dat nacería 644 y cualquier usuario del servidor podría leer los datos. La umask de un servicio se fija con UMask=0027 en su unidad de systemd (módulo 7), no en el .bashrc, porque un demonio no lee perfiles de shell. Y se hereda en el fork (02-01), así que un script que la ponga a 000 "para que no haya problemas" está creando ficheros 666 y directorios 777 sin que nadie se dé cuenta.
Los bits especiales: setuid, setgid y sticky
Los doce bits de modo son nueve de permisos más tres especiales, que en octal forman un cuarto dígito delante:
| Bit | Octal | Dónde aparece en ls -l |
Valor |
|---|---|---|---|
| setuid | 4000 | s en la x del usuario |
-rwsr-xr-x |
| setgid | 2000 | s en la x del grupo |
-rwxr-sr-x |
| sticky | 1000 | t en la x de otros |
drwxrwxrwt |
Si el bit x correspondiente no está puesto, la letra aparece en mayúscula (S, T), y eso casi siempre indica un error: un setuid sin ejecución no sirve para nada.
setuid: cómo passwd escribe en /etc/shadow
El problema es concreto. Un usuario normal debe poder cambiar su contraseña, que está en /etc/shadow:
Solo root escribe ahí. ¿Cómo puede entonces un usuario cualquiera modificarlo? La respuesta es el bit setuid:
$ ls -l /usr/bin/passwd -rwsr-xr-x 1 root root 68208 mar 14 2026 /usr/bin/passwd ↑ la 's' es el bit setuid
El recorrido completo, paso a paso:
- El usuario
joan(UID 1000) ejecuta/usr/bin/passwd;forkcrea un hijo con UID real 1000 y UID efectivo 1000. execvecarga el binario y ve el bit setuid. Entonces hace lo decisivo: pone el UID efectivo al del propietario del fichero, que es root (0).- El proceso corre ahora con UID real 1000 (quién lo lanzó) y UID efectivo 0 (con qué privilegios actúa). El núcleo comprueba los permisos con el efectivo.
passwdpuede abrir/etc/shadowpara escritura. Pero antes verifica cuidadosamente la identidad: consulta el UID real para saber quién es de verdad, pide la contraseña actual, y solo permite cambiar esa línea.- Al terminar, el proceso muere y el privilegio desaparece con él.
| Concepto | Valor durante passwd |
Para qué sirve |
|---|---|---|
| UID real | 1000 (joan) |
Quién eres: contabilidad, señales, auditoría |
| UID efectivo | 0 (root) | Qué puedes hacer: es el que comprueba el núcleo |
| UID guardado | 0 | Permite bajar y recuperar el privilegio |
Por qué es peligroso. Un binario setuid root es un programa que cualquiera puede ejecutar con privilegios de root, así que cualquier fallo en él es una escalada de privilegios completa: un desbordamiento de búfer, una inyección de comandos, una variable de entorno mal validada, un fichero temporal con TOCTOU (04-04), o simplemente una opción que permita ejecutar un programa arbitrario. La historia de la seguridad en UNIX está llena de vulnerabilidades en binarios setuid, y por eso la regla es tajante:
Cuanto menos setuid, mejor. Cada binario setuid root del sistema es una superficie de ataque, y hay que poder justificar cada uno.
Dos matices que conviene conocer. El setuid se ignora en los scripts: Linux no lo respeta en ficheros con #!, porque la ventana entre abrir el script y ejecutar el intérprete permitía sustituirlo —un TOCTOU—. Y nosuid al montar (04-03) hace que el núcleo ignore el bit en todo un volumen, que es la razón de montar así los volúmenes de datos.
setgid: en ficheros y, sobre todo, en directorios
En un fichero ejecutable, setgid es el análogo de setuid con el grupo: el GID efectivo pasa a ser el del fichero. Se usa para dar acceso a un recurso de grupo sin dar root; /usr/bin/wall, por ejemplo, es setgid tty.
En un directorio hace algo completamente distinto y muy útil:
Un directorio con setgid hace que todo lo que se cree dentro herede su grupo, en lugar del grupo primario de quien lo crea. Y los subdirectorios heredan también el propio bit setgid, así que la propiedad se propaga por todo el árbol.
Sin setgid, si el usuario analista (grupo primario analista) crea un fichero en /var/lib/meteora/, ese fichero será del grupo analista y el agregador —que es del grupo meteora— no podrá leerlo. Con setgid:
sudo chgrp meteora /var/lib/meteora/lecturas
sudo chmod 2750 /var/lib/meteora/lecturas # el 2 es setgid
$ ls -ld /var/lib/meteora/lecturas
drwxr-s--- 3 meteora meteora 4096 sep 1 15:40 /var/lib/meteora/lecturas
↑ la 's' en el grupoAhora cualquier fichero creado ahí dentro pertenecerá al grupo meteora, lo cree quien lo cree. Es el mecanismo estándar para directorios compartidos por un equipo, y garantiza la coherencia de grupos sin depender de la disciplina de cada usuario.
El bit pegajoso y el caso de /tmp
Recuerda la consecuencia 3 del apartado 2: w en un directorio permite borrar cualquier entrada, sean cuales sean los permisos del fichero. Ahora aplícalo a /tmp, que por definición debe ser escribible por todos:
Sin la t, cualquier usuario podría borrar los ficheros temporales de cualquier otro, o peor: borrar el fichero de sesión de un servicio y sustituirlo por uno propio, que es una vía directa a la suplantación.
El bit pegajoso (sticky bit) añade una restricción a los directorios:
En un directorio con sticky, solo pueden borrar o renombrar una entrada: el propietario del fichero, el propietario del directorio, o root. El permiso
wdel directorio deja de bastar.
Se aplica a todo directorio escribible por varios usuarios: /tmp, /var/tmp, /dev/shm y cualquier zona de intercambio compartida. Y hay que saber una cosa más: el sticky bit en ficheros no hace nada en Linux moderno. Antiguamente indicaba "mantén este ejecutable en swap"; hoy se ignora.
Cómo comprueba el núcleo un acceso, paso a paso
Cuando meteo-api ejecuta open("/var/lib/meteora/lecturas/2026-08-31.dat", O_RDONLY), el núcleo hace esto:
graph TB
A["open() de la ruta completa"] --> B["Para CADA directorio de la ruta:<br/>/, var, lib, meteora, lecturas<br/><b>¿tengo permiso x?</b>"]
B -->|"No en alguno"| Z["EACCES: Permiso denegado"]
B -->|"Sí en todos"| C{"¿UID efectivo == 0?"}
C -->|Sí| Y["Concedido (casi siempre)"]
C -->|No| D{"¿UID efectivo ==<br/>UID del fichero?"}
D -->|Sí| E["Usar SOLO los bits de USUARIO<br/>y decidir"]
D -->|No| F{"¿GID efectivo o algún grupo<br/>suplementario == GID del fichero?"}
F -->|Sí| G["Usar SOLO los bits de GRUPO<br/>y decidir"]
F -->|No| H["Usar los bits de OTROS<br/>y decidir"]
Los cinco puntos que hay que retener de este diagrama:
1. El permiso x se comprueba en TODOS los directorios de la ruta. Es lo que hace la resolución de rutas de 04-02, componente a componente. Si a /var/lib/meteora le falta el x para tu clase, no importa que el fichero final sea rw-rw-rw-: no llegas. Es la fuente número uno de los "Permiso denegado" incomprensibles, y se diagnostica en un segundo con namei -l, que muestra los permisos de cada componente:
$ namei -l /var/lib/meteora/lecturas/2026-08-31.dat drwxr-xr-x root root / drwxr-xr-x root root var drwxr-xr-x root root lib drwxr-x--- meteora meteora meteora ← aquí se decide todo drwxr-s--- meteora meteora lecturas -rw-r----- meteora meteora 2026-08-31.dat
Cuando alguien no puede acceder a un fichero, este es el primer comando que hay que ejecutar.
2. Las clases son excluyentes y el orden es fijo. Propietario, luego grupo, luego otros: la primera coincidencia decide y no se mira más. De ahí el fichero ----r--r-- que el dueño no puede leer.
3. Cuentan todos los grupos suplementarios. Un usuario pertenece a un grupo primario y a varios secundarios (id los muestra todos), y cualquiera sirve para entrar en la clase de grupo. Aviso importante: los grupos se leen al iniciar sesión, así que un usermod -aG no afecta a las sesiones abiertas ni a los servicios ya arrancados.
4. Root se salta casi todo. El UID efectivo 0 concede casi cualquier acceso, con dos excepciones notables: no puede ejecutar un fichero sin ningún bit x, y no puede escribir en un fichero inmutable (apartado 8).
5. Se comprueba en open(), no en read(). Los permisos se verifican una sola vez, al abrir. Si después alguien ejecuta chmod 000, el proceso que ya lo tiene abierto sigue leyendo sin problemas, porque su descriptor apunta a la entrada de la tabla de ficheros abiertos (04-04) y no al nombre ni al modo. Para cortar el acceso hay que hacer que cierre el descriptor.
Listas de control de acceso POSIX
El modelo de tres clases tiene un límite estructural: solo permite expresar permisos para un usuario, un grupo y el resto. Un caso real de Meteora lo desborda enseguida: hay que dar acceso de solo lectura a /var/lib/meteora/lecturas a la usuaria nuria, del equipo de análisis, sin meterla en el grupo meteora —que le daría acceso a todo lo demás del servicio, incluida la configuración— y sin abrir los permisos de "otros".
Con los nueve bits no se puede. Con ACL POSIX, sí:
# Dar a nuria lectura y travesía en el directorio, y lectura en los ficheros
sudo setfacl -m u:nuria:rx /var/lib/meteora/lecturas
sudo setfacl -R -m u:nuria:r /var/lib/meteora/lecturas/*.dat
# Y que herede el permiso en los ficheros FUTUROS (ACL "por defecto")
sudo setfacl -d -m u:nuria:r /var/lib/meteora/lecturasEl resultado:
$ ls -ld /var/lib/meteora/lecturas
drwxr-s---+ 3 meteora meteora 4096 sep 1 15:40 /var/lib/meteora/lecturas
↑ ESTE '+' significa "hay una ACL extendida"
$ getfacl /var/lib/meteora/lecturas
# file: var/lib/meteora/lecturas
# owner: meteora
# group: meteora
# flags: -s-
user::rwx
user:nuria:r-x ← la entrada nueva
group::r-x
mask::r-x ← el TECHO de las entradas nombradas
other::---
default:user:nuria:r-- ← herencia para lo que se cree despuésLos elementos: user::rwx y group::r-x son el propietario y el grupo propietario, equivalentes a los bits u y g de siempre; user:nuria:r-x y group:analistas:r-- son entradas nombradas, que dan permisos a un usuario o grupo concreto; other::--- son los demás; default:... es lo que heredarán los ficheros creados aquí; y mask::r-x es la máscara, el máximo efectivo de todas las entradas nombradas y del grupo.
La máscara es la parte que confunde a todo el mundo, y merece una explicación clara. Los permisos efectivos de cualquier entrada nombrada son la intersección de esa entrada con la máscara. Si la máscara es r-- y la entrada de nuria es rwx, nuria obtiene solo r--, y getfacl lo señala explícitamente:
Existe porque ls -l solo tiene nueve bits que mostrar. Cuando hay una ACL, los bits de grupo que muestra ls -l son en realidad la máscara, no los permisos del grupo propietario. Es un compromiso deliberado para que las herramientas antiguas vean algo razonable, y de ahí sale la trampa práctica:
Un
chmod g-wsobre un fichero con ACL modifica la MÁSCARA, y por tanto recorta de golpe los permisos efectivos de todas las entradas nombradas. Es la forma más habitual de romper una ACL sin querer.
La regla es: cuando un fichero tiene + en ls -l, gestiona sus permisos con setfacl, no con chmod.
Comandos esenciales:
getfacl fichero # ver la ACL completa
setfacl -m u:nuria:r fichero # añadir o modificar una entrada
setfacl -x u:nuria fichero # eliminar una entrada
setfacl -b fichero # eliminar TODA la ACL
setfacl -d -m u:nuria:r directorio # ACL por defecto (herencia)
setfacl -R -m u:nuria:rX directorio # recursivo, con X mayúsculaDos advertencias operativas: las ACL requieren que el sistema de archivos las soporte —ext4 y XFS sí, y en las distribuciones actuales están activadas por defecto—; y hay que verificar que las herramientas de copia las preserven, porque cp -a, rsync -A y tar --acls sí lo hacen pero un cp normal las pierde en silencio, lo que produce fallos de permisos misteriosos tras una restauración.
Atributos extendidos y atributos de fichero
Además de los permisos, un inodo puede llevar dos cosas más.
Atributos extendidos (xattr): pares clave-valor arbitrarios organizados en cuatro espacios de nombres —system.* para las ACL y el uso interno del núcleo, security.* para las etiquetas de SELinux y las capabilities, trusted.* para uso privilegiado, y user.* para metadatos de aplicación, escribible por cualquiera con permiso w—. Se manipulan con setfattr -n user.origen -v "estacion-42" fichero y getfattr -d fichero. Las ACL del apartado anterior son atributos extendidos (system.posix_acl_access), igual que las etiquetas de SELinux y AppArmor del módulo 5.
Atributos de fichero (chattr): banderas en el inodo que modifican el comportamiento del sistema de archivos. Son mucho más potentes de lo que parecen, porque algunos vinculan incluso a root:
| Atributo | Efecto |
|---|---|
i (immutable) |
Nadie, ni root, puede modificar, borrar, renombrar ni enlazar el fichero |
a (append-only) |
Solo se puede añadir al final: no se puede modificar ni truncar |
A (no atime) |
No actualizar el atime de este fichero (04-01) |
C (no CoW) |
Desactiva la copia al escribir en Btrfs (04-05) |
j (data journalling) |
Este fichero usa data=journal aunque el volumen no (04-05) |
Los dos primeros son los interesantes:
# La configuración con secretos: que nadie la toque por accidente
sudo chattr +i /etc/meteora/meteora.conf
sudo lsattr /etc/meteora/meteora.conf
----i---------e------- /etc/meteora/meteora.conf
$ sudo rm /etc/meteora/meteora.conf
rm: no se puede borrar '...': Operación no permitida ← ¡ni siquiera root!
# Log a prueba de manipulación: solo se puede añadir
sudo chattr +a /var/log/meteora/meteo-api.log
$ sudo truncate -s 0 /var/log/meteora/meteo-api.log
truncate: no se puede abrir ... : Operación no permitida
$ echo "linea" | sudo tee -a /var/log/meteora/meteo-api.log ← añadir SÍ funciona+a es especialmente valioso para los registros de seguridad, porque un atacante que consiga root no puede borrar sus huellas del log: solo puede seguir añadiendo. Es un complemento natural del O_APPEND de 04-04, con la diferencia de que aquel es un acuerdo del programa y este lo impone el sistema de archivos.
Ahora la letra pequeña, para no crear falsa seguridad. Quitar el atributo requiere la capacidad CAP_LINUX_IMMUTABLE, que root tiene: chattr -i lo desactiva en un segundo, y un atacante con root puede hacerlo. Su valor real es doble: evita errores propios —un rm -rf mal escrito, un script de despliegue defectuoso— y obliga a un paso deliberado y auditable antes de tocar algo crítico. No es una barrera contra un atacante decidido; es un seguro contra accidentes y una traza en los registros, porque el aislamiento fuerte frente a root es cosa de capabilities, SELinux y AppArmor, que se ven en el módulo 5. Y una consecuencia práctica que muerde a todo el mundo: un fichero con +i rompe las actualizaciones automáticas del gestor de paquetes, de forma confusa. Documenta siempre qué has marcado.
Comparación con el modelo de Windows
Conviene conocer el otro modelo, porque los conceptos se cruzan constantemente en entornos mixtos:
| UNIX / Linux | Windows (NTFS) | |
|---|---|---|
| Unidad de permiso | 9 bits + 3 especiales | Lista de ACE (entradas de control de acceso) |
| Identidad | UID y GID numéricos | SID (identificador de seguridad) |
| Destinatarios | Un usuario, un grupo, el resto | Cualquier número de usuarios y grupos |
| Granularidad | 3 permisos (r, w, x) |
13 permisos (leer datos, escribir atributos, borrar, tomar posesión...) |
| Denegación explícita | No existe | Sí, y tiene prioridad sobre cualquier permiso |
| Herencia | Solo default de las ACL y setgid |
Nativa y automática, con propagación |
| Borrar un fichero | w en el directorio |
Permiso Delete en el fichero o Delete child en la carpeta |
| Permisos efectivos | Se deducen a ojo | Herramienta específica para calcularlos |
| Administrador se salta todo | Sí (root) | No del todo: puede tomar posesión y luego darse permisos |
| Complejidad | Baja | Alta |
La diferencia más importante para quien viene de Windows es la semántica del borrado: allí se controla con un permiso del fichero, aquí con el permiso w del directorio. Es la causa de la mayoría de las sorpresas al migrar, y explica por qué el bit pegajoso es necesario en UNIX y no tiene equivalente directo en Windows. La otra es la denegación explícita: en Windows puedes decir "todos los del grupo Ventas pueden leer, excepto Juan", mientras que en UNIX solo se conceden permisos y la única forma de excluir a alguien es no incluirlo en ninguna clase que los tenga.
El juicio equilibrado: el modelo de Windows es más expresivo y el de UNIX más comprensible. Y en seguridad, lo comprensible tiene un valor propio: una ACL de Windows con veinte entradas heredadas, denegaciones y grupos anidados puede ser tan difícil de auditar que nadie sepa realmente quién tiene acceso. Los nueve bits de UNIX se leen de un vistazo.
Los permisos de Meteora, justificados
Ahora, la aplicación completa. Estos son los permisos exactos de todo lo que compone el servicio, con el porqué de cada decisión.
| Ruta | Dueño:grupo | Modo | Justificación |
|---|---|---|---|
/var/lib/meteora/ |
meteora:meteora |
2750 | El servicio lo controla; el grupo entra pero no escribe; setgid para heredar el grupo; nadie más entra |
/var/lib/meteora/lecturas/ |
meteora:meteora |
2750 | Igual: el ingestor (dueño) escribe, el agregador (grupo) lee |
.../lecturas/*.dat |
meteora:meteora |
0640 | El ingestor escribe, el grupo lee, nadie más. Los crea la umask 027 |
/etc/meteora/ |
root:meteora |
0750 | De root: el servicio no debe poder modificar su propia configuración |
/etc/meteora/meteora.conf |
root:meteora |
0640 | Root la edita; el servicio la lee por el grupo. Sin secretos dentro |
/etc/meteora/secrets.conf |
root:meteora |
0640 | Claves de API y de base de datos, en un fichero aparte |
/var/log/meteora/ |
meteora:adm |
2750 | El servicio escribe; el grupo adm lee los logs sin ser del servicio |
/var/log/meteora/*.log |
meteora:adm |
0640 | Lo mismo, y +a en los de auditoría |
/usr/bin/meteo-api |
root:root |
0755 | De root, no del servicio: el servicio no puede modificar su binario |
/run/meteora/ |
meteora:meteora |
0750 | Sockets y FIFO. En tmpfs, se recrea al arrancar (04-02) |
/run/meteora/api.sock |
meteora:www-data |
0660 | El servidor web se conecta por el grupo |
Los comandos completos:
# --- Datos ---
sudo chown -R meteora:meteora /var/lib/meteora
sudo find /var/lib/meteora -type d -exec chmod 2750 {} + # setgid en directorios
sudo find /var/lib/meteora -type f -exec chmod 0640 {} + # 640 en ficheros
# --- Configuración y binario: de ROOT, no del servicio ---
sudo chown root:meteora /etc/meteora /etc/meteora/*.conf
sudo chmod 0750 /etc/meteora
sudo chmod 0640 /etc/meteora/meteora.conf /etc/meteora/secrets.conf
sudo chattr +i /etc/meteora/secrets.conf # inmutable: cambio deliberado
sudo chown root:root /usr/bin/meteo-api && sudo chmod 0755 /usr/bin/meteo-api
# --- Registros: grupo adm, y auditoría solo-añadir ---
sudo chown -R meteora:adm /var/log/meteora
sudo chmod 2750 /var/log/meteora && sudo chmod 0640 /var/log/meteora/*.log
sudo chattr +a /var/log/meteora/auditoria.log
# --- Acceso de solo lectura para el equipo de análisis ---
sudo setfacl -m u:nuria:rx /var/lib/meteora /var/lib/meteora/lecturas
sudo setfacl -R -m u:nuria:r /var/lib/meteora/lecturas
sudo setfacl -d -m u:nuria:r /var/lib/meteora/lecturas # herenciaLas cuatro decisiones que de verdad importan aquí, porque son las que la gente hace mal:
1. La configuración pertenece a root, no al servicio. Es la aplicación directa del principio de mínimo privilegio: si meteora fuera el dueño de meteora.conf, un atacante que comprometiera meteo-api podría reescribir la configuración —cambiar rutas, desactivar la validación, apuntar a otro servidor— y esperar al reinicio. Siendo de root con grupo meteora y modo 640, el servicio lee pero no escribe. Lo mismo con el binario: meteora no puede sustituir /usr/bin/meteo-api por un troyano.
2. Los secretos van en un fichero aparte. No porque 640 no baste, sino porque separa dos ciclos de vida: meteora.conf se puede versionar en Git, compartir en una incidencia y copiar entre entornos; secrets.conf no. Mezclarlos garantiza que las claves acabarán en un repositorio o en un ticket. Se usa 0640 con grupo meteora —y no 0600— porque el servicio necesita leerlo al arrancar.
3. Los logs tienen grupo adm, no meteora. Así los administradores y la monitorización leen los registros sin pertenecer al grupo del servicio, que les daría acceso también a los datos y a la configuración. Es separación de privilegios, no burocracia.
4. Ningún binario setuid. meteo-api escucha en el puerto 8080 y no en el 80, precisamente para no necesitar privilegios. Si tuviera que usar un puerto por debajo de 1024, la solución correcta no es setuid root, sino AmbientCapabilities=CAP_NET_BIND_SERVICE en la unidad de systemd, o un proxy inverso delante. Volveremos sobre las capabilities en el módulo 5.
Errores graves y cómo auditarlos
Los cuatro errores que más daño hacen, y el comando que los encuentra.
chmod 777. Es el error emblemático. Significa "cualquier usuario del sistema puede leer, modificar y borrar esto", y además marca los ficheros como ejecutables. Se pone casi siempre para salir del paso ante un "permiso denegado" que no se ha entendido, y deja el agujero abierto para siempre.
# Ficheros y directorios escribibles por CUALQUIERA
sudo find / -xdev \( -type f -o -type d \) -perm -0002 \
! -path '/proc/*' ! -path '/sys/*' -ls 2>/dev/null-perm -0002 busca el bit de escritura para "otros". Los únicos resultados legítimos son directorios con sticky bit (/tmp, /var/tmp, /dev/shm); todo lo demás hay que revisarlo. Ante un "permiso denegado", el reflejo correcto es namei -l, no chmod 777.
Secretos legibles por todos. Una clave privada con permiso de lectura para "otros" es una clave comprometida; de hecho, ssh se niega a usar una clave demasiado abierta, precisamente por esto.
sudo find /etc -type f \( -name '*secret*' -o -name '*.key' -o -name '*.pem' \
-o -name '*credential*' -o -name '*password*' \) -perm -0004 -lschmod -R sobre un árbol mixto. Este merece explicación porque parece inofensivo:
El segundo es el caso instructivo. Aplica 644 a todo, incluidos los directorios, que se quedan sin el bit x: nadie puede atravesarlos, y todo el árbol se vuelve inaccesible —el efecto "interrogantes" del apartado 2—. La forma correcta usa la X mayúscula o separa por tipo:
chmod -R u=rwX,g=rX,o= /var/lib/meteora # opción 1: X mayúscula
find /var/lib/meteora -type d -exec chmod 2750 {} + # opción 2: por tipo
find /var/lib/meteora -type f -exec chmod 0640 {} +Binarios setuid innecesarios. El inventario hay que revisarlo y justificarlo entrada por entrada. Una lista saneada tiene entre 10 y 20: passwd, su, sudo, mount, umount, ping, chsh, newgrp... Cualquier binario setuid en /home, /tmp, /var o en un directorio de aplicación es una alarma roja, y probablemente una puerta trasera. Guardar una lista de referencia y compararla es una detección barata y eficaz:
sudo find / -xdev \( -perm -4000 -o -perm -2000 \) -type f 2>/dev/null | sort \
> /root/setuid.actual
diff /root/setuid.referencia /root/setuid.actual # ¿ha aparecido alguno nuevo?Otras dos comprobaciones que conviene automatizar son find / -xdev \\( -nouser -o -nogroup \\) y find / -xdev -type f -perm -0002 -perm -0111. Los ficheros huérfanos —cuyo UID no corresponde a ningún usuario— aparecen tras borrar una cuenta y son peligrosos porque el siguiente usuario que reciba ese UID heredará su propiedad. Y un fichero a la vez escribible por todos y ejecutable es un vector de ataque de manual: cualquiera sustituye su contenido y espera a que alguien lo ejecute.
Errores Comunes y Consejos
Responder a un "permiso denegado" con chmod 777. Casi siempre el problema es un x que falta en un directorio de la ruta. Ejecuta namei -l primero: te dirá en qué componente exacto se rompe.
Aplicar chmod -R con un valor octal. Trata igual a ficheros y directorios, y deja los directorios sin x o los ficheros con x. Usa u=rwX,g=rX,o= o separa con find -type d y find -type f.
Creer que quitar r y w a un fichero impide borrarlo. Borrar depende del permiso w en el directorio. Si quieres proteger un fichero de verdad, protege el directorio o usa chattr +i.
Olvidar que los grupos se leen al iniciar sesión. Tras un usermod -aG, ni tu sesión abierta ni los servicios en marcha ven el grupo nuevo. Reinicia la sesión o el servicio.
Usar chmod sobre un fichero con ACL. Modifica la máscara y recorta los permisos efectivos de todas las entradas nombradas: si ves un + en ls -l, usa setfacl. Y al copiar, preserva las ACL con cp -a, rsync -A o tar --acls, porque un cp a secas las pierde en silencio.
Dejar que un servicio sea dueño de su configuración y de su binario. Si lo comprometen, puede reescribir ambos y persistir. Configuración y binario, de root; el servicio solo lee.
Poner setuid a un programa propio "para que funcione". Un binario setuid root es una escalada de privilegios esperando a un fallo. Casi siempre hay una alternativa: una capability concreta, un grupo, un socket con permisos, o un servicio separado.
Consejo: namei -l y getfacl son tus dos herramientas de diagnóstico —la primera recorre la ruta componente a componente, la segunda revela las ACL que ls -l solo insinúa con un +— y audita periódicamente contra una línea base: la lista de setuid, los escribibles por todos y los huérfanos detectan tanto errores propios como intrusiones.
Ejercicios
Ejercicio 1: los permisos de directorio, demostrados
Crea una estructura de pruebas y demuestra empíricamente, mostrando la salida de cada comando: (a) que con x pero sin r en un directorio puedes leer un fichero cuyo nombre conoces pero no listarlo; (b) que con r pero sin x obtienes los interrogantes de ls -l; (c) que puedes borrar un fichero de otro usuario, sin permiso de lectura sobre él, si tienes w en el directorio; (d) que al activar el bit pegajoso ya no puedes. Explica en cada caso qué permiso se comprueba y sobre qué objeto.
Ejercicio 2: acceso de solo lectura sin tocar el grupo
La usuaria nuria necesita leer todos los ficheros de /var/lib/meteora/lecturas, incluidos los que se creen en el futuro, sin pertenecer al grupo meteora y sin que los permisos de "otros" cambien. Implementa la solución completa con ACL, verifica que funciona, comprueba qué ocurre después con un chmod g-w sobre el directorio y explica por qué. Compara con las dos alternativas malas —meterla en el grupo meteora, o poner o+r— indicando exactamente a qué tendría acceso de más en cada caso.
Ejercicio 3: auditoría de permisos de un servidor
Escribe un script de auditoría que revise: binarios setuid y setgid comparados con una lista de referencia; ficheros y directorios escribibles por todos que no tengan sticky bit; secretos en /etc legibles por otros; ficheros huérfanos; y ficheros simultáneamente escribibles por todos y ejecutables. Para cada hallazgo debe indicar el riesgo concreto y la corrección propuesta. Ejecútalo en tu máquina e interpreta los resultados: di cuáles son legítimos y por qué.
Soluciones
Solución 1
mkdir -p /tmp/lab && cd /tmp/lab
mkdir prueba && echo "contenido secreto" > prueba/dato.txt
chmod 0644 prueba/dato.txt(a) x sin r — el directorio oscuro:
chmod 0711 prueba # rwx dueño, --x otros
sudo -u nobody ls prueba # ls: no se puede abrir: Permiso denegado
sudo -u nobody cat prueba/dato.txt # contenido secreto ← ¡SÍ funciona!ls necesita r para leer la lista de nombres del directorio, y no lo tiene. cat solo necesita x para atravesarlo hasta el inodo de un nombre que ya conoce. Se comprueba r sobre el directorio en el primer caso y x sobre el directorio más r sobre el fichero en el segundo.
(b) r sin x:
chmod 0644 prueba
sudo -u nobody ls prueba # dato.txt ← ve el nombre
sudo -u nobody ls -l prueba # -????????? ? ? ? ← no puede leer el inodo
sudo -u nobody cat prueba/dato.txt # Permiso denegadols lee la lista y funciona. ls -l necesita atravesar el directorio para leer el inodo de cada entrada, y sin x no puede: de ahí los interrogantes. cat falla por la misma razón.
(c) Borrar sin poder leer, y (d) con sticky bit:
chmod 0777 prueba # w para todos, SIN sticky
sudo chown root:root prueba/dato.txt && sudo chmod 0600 prueba/dato.txt
sudo -u nobody cat prueba/dato.txt # Permiso denegado
sudo -u nobody rm -f prueba/dato.txt # ¡SIN ERROR! (c)
echo x | sudo tee prueba/dato.txt >/dev/null && sudo chmod 0600 prueba/dato.txt
chmod 1777 prueba # ← el 1 es el sticky
sudo -u nobody rm -f prueba/dato.txt # Operación no permitida (d)En (c), nobody no puede leer un fichero de root con modo 600 pero sí puede borrarlo, porque unlink es una escritura en el directorio y tiene w ahí: los permisos y el propietario del fichero no intervienen en absoluto.
En (d), con sticky, solo el dueño del fichero (root), el dueño del directorio o root pueden borrar. Fíjate en el detalle: el error ya no es EACCES ("Permiso denegado") sino EPERM ("Operación no permitida"), porque la comprobación que falla no es la del bit w sino la regla adicional del sticky. Es exactamente el mecanismo que protege /tmp.
Solución 2
# 1. Acceso al directorio (r para listar + x para atravesar)
sudo setfacl -m u:nuria:rx /var/lib/meteora
sudo setfacl -m u:nuria:rx /var/lib/meteora/lecturas
# 2. Lectura de los ficheros existentes
sudo setfacl -R -m u:nuria:r /var/lib/meteora/lecturas
# 3. Herencia para los FUTUROS ficheros que cree el ingestor
sudo setfacl -d -m u:nuria:r /var/lib/meteora/lecturas
# 4. Verificación
sudo -u nuria cat /var/lib/meteora/lecturas/2026-08-31.dat > /dev/null && echo OK
sudo -u nuria ls /var/lib/meteora/lecturas
sudo -u nuria cat /etc/meteora/secrets.conf # debe seguir fallando ✔
getfacl /var/lib/meteora/lecturasEl paso 3 es el que más se olvida: sin la ACL por defecto, nuria leería los ficheros de hoy pero no los de mañana, y el fallo aparecería una semana después sin causa aparente.
Qué ocurre con chmod g-w:
sudo chmod g-w /var/lib/meteora/lecturas
getfacl /var/lib/meteora/lecturas
# user:nuria:r-x #effective:r-x ← si la máscara conserva r y xchmod sobre un fichero con ACL modifica la máscara. Si el chmod recortara los bits r o x de la clase de grupo, la máscara bajaría y los permisos efectivos de nuria se recortarían con ella, aunque su entrada siga diciendo r-x. Se restaura con setfacl -m m::rx. La regla operativa: cuando ls -l muestra +, gestiona los permisos con setfacl.
Las dos alternativas malas:
| Alternativa | A qué daría acceso de más |
|---|---|
usermod -aG meteora nuria |
A todo lo del grupo meteora: /etc/meteora/meteora.conf, /etc/meteora/secrets.conf con las claves de API, /run/meteora/api.sock y cualquier fichero futuro del servicio. Y de forma permanente y transitiva: cualquier cosa que se cree con grupo meteora |
chmod o+r en los .dat |
A todos los usuarios del sistema, incluidas las cuentas de servicio de otras aplicaciones y cualquier proceso comprometido. Convierte un acceso nominal y auditable en uno universal |
La ACL da exactamente el acceso pedido, a la persona pedida, sobre los ficheros pedidos, y queda documentado en getfacl: es el principio de mínimo privilegio aplicado con la herramienta adecuada.
Solución 3
#!/bin/bash
# auditoria-permisos.sh — ejecutar como root
REF=/root/setuid.referencia
echo "=== AUDITORÍA DE PERMISOS — $(hostname) — $(date +%F) ==="
echo -e "\n[1] Binarios setuid/setgid nuevos respecto a la referencia"
find / -xdev \( -perm -4000 -o -perm -2000 \) -type f 2>/dev/null | sort > /tmp/su.now
if [ -f "$REF" ]; then
diff "$REF" /tmp/su.now | grep '^>' && \
echo " RIESGO: binario privilegiado NUEVO. Verificar origen; si no se justifica," \
"chmod u-s y analizar el sistema en busca de compromiso."
else
cp /tmp/su.now "$REF"; echo " Referencia creada con $(wc -l < "$REF") entradas."
fi
echo -e "\n[2] Escribibles por TODOS sin sticky bit"
find / -xdev \( -type f -o \( -type d ! -perm -1000 \) \) -perm -0002 \
! -path '/proc/*' ! -path '/sys/*' -ls 2>/dev/null
echo " RIESGO: cualquier usuario puede modificar o borrar. Corregir con chmod o-w."
echo -e "\n[3] Posibles secretos legibles por otros en /etc"
find /etc -type f \( -name '*.key' -o -name '*.pem' -o -name '*secret*' \
-o -name '*credential*' \) -perm -0004 -ls 2>/dev/null
echo " RIESGO: credencial expuesta. Corregir con chmod 600 y ROTAR la clave."
echo -e "\n[4] Ficheros huérfanos (UID/GID sin usuario)"
find / -xdev \( -nouser -o -nogroup \) ! -path '/proc/*' -ls 2>/dev/null
echo " RIESGO: el próximo usuario que reciba ese UID heredará su propiedad."
echo -e "\n[5] Escribibles por todos Y ejecutables"
find / -xdev -type f -perm -0002 -perm -0111 ! -path '/proc/*' -ls 2>/dev/null
echo " RIESGO CRÍTICO: cualquiera sustituye el contenido y espera a que se ejecute."Interpretación de los resultados en una máquina sana. En [1] aparecen entre 10 y 20 binarios, todos en /usr/bin, /usr/sbin, /usr/lib o /bin —passwd, su, sudo, mount, umount, chsh, newgrp, pkexec, ping, y setgid crontab, wall, write—, y todos son legítimos porque necesitan privilegios que un usuario normal no tiene: modificar /etc/shadow, montar sistemas de archivos, abrir sockets ICMP. Un setuid fuera de esos directorios —en /home, /tmp, /opt o /var— es una alarma roja.
En [2] lo esperable es ningún resultado, porque /tmp, /var/tmp y /dev/shm quedan excluidos por el filtro ! -perm -1000; si aparece algo, casi siempre es un chmod 777 histórico. En [3] debe estar vacío, y cualquier resultado exige dos acciones y no una: corregir el permiso y rotar la credencial, porque hay que asumir que ha sido leída. En [4] suele haber alguno tras desinstalar software o borrar cuentas, y se corrige con chown o borrando el fichero. Y [5] debe estar vacío siempre: es la combinación más peligrosa de todas.
Lo que convierte esto en una herramienta útil es ejecutarlo periódicamente y comparar con la ejecución anterior: los hallazgos nuevos, y no la lista completa, son lo que hay que mirar. Automatizar estas comprobaciones e integrarlas con la auditoría del sistema es el tema de Auditoría, Registros y Respuesta a Incidentes.
Conclusión
El modelo de permisos de UNIX son doce bits y dos números en el inodo, con tres clases —usuario, grupo y otros— que son excluyentes y se evalúan en ese orden, de ahí que un fichero ----r--r-- no lo pueda leer su propio dueño. Los bits r, w y x significan cosas distintas en ficheros y en directorios, y esa diferencia deja de ser arbitraria en cuanto recuerdas que un directorio es un fichero con una lista de pares (nombre, inodo): r es leer esa lista, w es añadir o quitar entradas y x es atravesar. De ahí las cuatro consecuencias: el directorio oscuro 0711, los interrogantes de r sin x, y sobre todo que se puede borrar un fichero que no se puede leer, porque unlink escribe en el directorio y no toca el fichero. Esa última es la razón de que exista el bit pegajoso, sin el cual /tmp sería inutilizable.
Los permisos se expresan en octal o simbólico, y la diferencia importa: el octal es absoluto y el simbólico relativo, así que un chmod -R 644 deja los directorios sin x y rompe el árbol entero. La forma correcta de recorrer un árbol mixto es la X mayúscula o separar con find -type d y -type f. La umask decide con qué permisos nacen los ficheros restando bits del modo solicitado —666 para ficheros, 777 para directorios—, y nunca añade el x: la 027 de Meteora es exactamente lo que produce los 0640 y 0750 que llevamos viendo todo el módulo, frente a la 022 por defecto que los dejaría legibles por todo el sistema.
Los tres bits especiales resuelven tres problemas concretos. setuid explica cómo passwd escribe en /etc/shadow: execve pone el UID efectivo al del propietario del binario, dejando el UID real para saber quién es de verdad; es potentísimo y por eso peligroso, y nosuid al montar (04-03) lo desactiva por volumen. setgid en un directorio hace que todo lo que se cree dentro herede su grupo y propaga el propio bit a los subdirectorios, que es lo que garantiza la coherencia de grupo en /var/lib/meteora. Y el sticky limita el borrado al dueño del fichero.
La comprobación del núcleo tiene cinco propiedades que hay que recordar: el x se exige en todos los directorios de la ruta —namei -l es el diagnóstico—, las clases son excluyentes, cuentan todos los grupos suplementarios pero solo los que había al iniciar sesión, root se salta casi todo salvo la ejecución sin ningún x y el atributo inmutable, y se comprueba en open(), de modo que un chmod 000 no corta a quien ya tiene el fichero abierto. Cuando las tres clases no bastan, las ACL POSIX dan permisos a usuarios y grupos concretos, con ACL por defecto para la herencia y una máscara que actúa de techo —y que un chmod descuidado recorta, rompiendo la ACL sin avisar—. Los atributos chattr +i y +a añaden una capa que vincula incluso a root: la primera evita accidentes sobre ficheros críticos y la segunda hace un log al que solo se puede añadir. Frente al modelo de Windows, más expresivo con sus ACE, su herencia nativa y sus denegaciones explícitas, el de UNIX gana en algo que en seguridad vale mucho: se lee de un vistazo.
Aplicado a Meteora, todo se reduce a cuatro decisiones: datos 2750/0640 con meteora:meteora; configuración y binario de root, para que un servicio comprometido no pueda reescribirse a sí mismo; secretos en fichero aparte con +i; logs con grupo adm para separar quien administra de quien ejecuta; y ningún binario setuid. Y las auditorías con find —setuid contra una lista de referencia, escribibles por todos sin sticky, secretos legibles, huérfanos y escribibles-y-ejecutables— convierten esas decisiones en algo verificable en lugar de en una intención.
Cierre del módulo 4
Merece la pena mirar el recorrido completo, porque el módulo ha tenido un hilo muy claro.
Empezamos con la abstracción (04-01): un fichero es una secuencia de bytes con nombre, tamaño y dueño que el sistema coloca donde quiere, y esa idea resuelve de golpe los siete problemas que tendría cualquier aplicación sobre el vector de bloques crudo del módulo 2, con la misma estrategia que la memoria virtual. Vimos los siete tipos de UNIX, diseccionamos el inodo —y su ausencia más importante, el nombre—, recorrimos la disposición física con superbloque, mapas de bits y tabla de inodos, calculamos el compromiso del tamaño de bloque y elegimos ext4 para /var/lib/meteora con argumentos y no por costumbre.
El nombre, que faltaba, llegó en 04-02: un directorio es un fichero con pares (nombre, inodo), la organización en grafo acíclico explica por qué no se permiten enlaces duros a directorios, la resolución de rutas cuesta once accesos en frío y casi ninguno con la caché de dentries, y unlink quita un nombre en lugar de borrar un fichero, de donde salen los enlaces duros, el fichero borrado que sigue ocupando 17 GB y el truncate -s 0 /proc/<pid>/fd/N que lo cura.
Después ensamblamos el árbol (04-03): particiones GPT, LVM con sus instantáneas para copiar en caliente, y el montaje paso a paso, con UUID= en un fstab validado y las opciones nosuid,nodev,noexec que cierran tres vectores por el precio de tres palabras. Y debajo de todo, el VFS con sus cuatro objetos, que es lo que permite que el mismo open() funcione sobre ext4, sobre tmpfs, sobre /proc —que inventa sus ficheros al leerlos— y sobre NFS.
Con el mapa completo pasamos a usarlo (04-04): cinco llamadas al sistema, las tres tablas que explican fork, dup y 2>&1, las dos capas de búfer que hay que distinguir para no perder datos, y los dos patrones que más vas a escribir —la publicación atómica con temporal y rename(), y O_APPEND para los logs— más flock para que no haya dos agregador. Luego bajamos al disco (04-05): las cuatro estrategias de asignación hasta los extents, los tres mecanismos que hacen que un fichero escrito 24 bytes cada 125 ms acabe contiguo, el diario con su bloque de commit atómico, los tres modos de ext4 con ordered como elección razonada, y la distinción que cierra el asunto: coherencia de metadatos no es integridad de datos, RAID 1 detecta discrepancias pero no sabe cuál copia es la buena, y a veces la garantía tiene que ponerla la aplicación.
Y esta última lección ha respondido a quién puede hacer qué.
Si el módulo 2 respondía a cómo se reparte un recurso escaso y el módulo 3 a cómo se coordinan varios flujos sobre un dato compartido, el módulo 4 ha respondido a cómo se guarda algo para que siga estando mañana. Y la respuesta ha tenido siempre la misma forma: una estructura en el disco, una capa de indirección que la hace manejable, y una disciplina —de formato, de sincronización o de permisos— que el programador debe respetar.
Pero fíjate en dónde nos deja el último apartado. Hemos cerrado el acceso a /var/lib/meteora con nueve bits y una ACL, y hemos supuesto todo el tiempo que el UID 990 es meteora, que quien inicia sesión es quien dice ser, y que un proceso que corre como meteora hace lo que meteora haría. Ninguna de esas tres suposiciones es gratis. ¿Cómo demuestra alguien que es quien dice ser? ¿Por qué root puede saltarse todos los permisos, y hay alguna forma de que no pueda? ¿Qué impide que un meteo-api comprometido, con sus permisos perfectamente configurados, haga cosas que nadie previó? ¿Y cómo se detecta que algo así ha ocurrido, cuando el atacante controla el sistema que escribe los registros?
Los permisos de fichero son solo una pieza de un modelo de protección mucho más amplio, que abarca sujetos, objetos, dominios de protección, autenticación, privilegios mínimos, control de acceso obligatorio y auditoría. Es el Módulo 5: Protección y Seguridad del Sistema, y empieza en Principios de Protección y Control de Acceso.
Fundamentos de Sistemas Operativos
Módulo 1: Introducción a los Sistemas Operativos
- Conceptos Básicos de Sistemas Operativos
- Historia y Evolución de los Sistemas Operativos
- Tipos de Sistemas Operativos
- Funciones Principales de un Sistema Operativo
- Arquitectura del Núcleo: Monolítico, Microkernel e Híbrido
- Modo Usuario, Modo Núcleo y Llamadas al Sistema
Módulo 2: Gestión de Recursos
- Gestión de Procesos
- Planificación de la CPU
- Gestión de Memoria
- Memoria Virtual y Paginación
- Gestión de Almacenamiento
- Gestión de Dispositivos
- Controladores, Interrupciones y Operaciones de E/S
Módulo 3: Concurrencia
- Conceptos de Concurrencia
- Hilos y Procesos
- Comunicación entre Procesos (IPC)
- Sincronización y Exclusión Mutua
- Problemas Clásicos de Concurrencia
- Interbloqueos: Prevención, Detección y Recuperación
Módulo 4: Estructuras de Archivos
- Sistemas de Archivos
- Estructuras de Directorios
- Particiones, Montaje y Sistema de Archivos Virtual
- Gestión de Archivos
- Asignación de Espacio, Journaling e Integridad
- Seguridad y Permisos de Archivos
Módulo 5: Protección y Seguridad del Sistema
- Principios de Protección y Control de Acceso
- Usuarios, Autenticación y Escalada de Privilegios
- Amenazas Comunes y Endurecimiento del Sistema
- Auditoría, Registros y Respuesta a Incidentes
Módulo 6: Virtualización y Contenedores
- Virtualización: Hipervisores y Máquinas Virtuales
- Contenedores: Namespaces y cgroups
- El Sistema Operativo en la Nube
- Sistemas Operativos Móviles y de Tiempo Real
