capabilities - visión general del sistema de capacidades de
Linux
Con el propósito de realizar comprobaciones de permisos,
las implementaciones tradicionales de Unix distinguen dos categorías
de procesos: procesos privilegiados (cuyo identificador de usuario
efectivo es 0, refiriéndose al superusuario o root) y procesos no
privilegiados (cuyo identificador de usuario efectivo es distinto de
cero). Los procesos privilegiados evitan todas las comprobaciones de
permisos del núcleo, mientras que los procesos no privilegiados se
ven sujetos a severas comprobaciones de permisos basadas en las credenciales
del proceso (normalmente: ID de usuario efectivo, ID de grupo efectivo y
lista de grupos adicionales).
Desde la versión 2.2 del núcleo, Linux ofrece un
(hasta ahora incompleto) sistema de capacidades, que divide los
privilegios asociados tradicionalmente al superusuario en unidades distintas
que pueden ser activadas y desactivadas independientemente.
Hasta la versión 2.4.18 de Linux, las siguientes
capacidades están implementadas:
- CAP_CHOWN
- Permite cambios arbitrarios en los IDs de usuario y de grupo de los
ficheros (vea chown(2)).
- CAP_DAC_OVERRIDE
- Evita las comprobaciones de permisos sobre operaciones de lectura,
escritura y ejecución. (DAC = "control de acceso
discrecional".)
- CAP_DAC_READ_SEARCH
- Evita comprobaciones de permisos sobre operaciones de lectura de ficheros
y lectura y ejecución de directorios.
- CAP_FOWNER
- Evita comprobaciones de permisos sobre operaciones que normalmente
requieren que el ID de usuario del sistema de ficheros del proceso
coincida con el ID de usuario del fichero (p.e., utime(2)),
excluyendo aquellas operaciones cubiertas por CAP_DAC_OVERRIDE y
CAP_DAC_READ_SEARCH; ignora el bit pegajoso (sticky) en el borrado
de ficheros.
- CAP_FSETID
- No borra los bits set-user-ID y set-group-ID cuando se modifica un
fichero; permite establecer el bit set-group-ID para un fichero cuyo ID de
grupo no coincide con el del sistema de ficheros o cualquier otro ID de
grupo adicional del proceso invocador.
- CAP_IPC_LOCK
- Permite el bloqueo en memoria (mlock(2), mlockall(2),
shmctl(2)).
- CAP_IPC_OWNER
- Evita comprobaciones de permisos para las operaciones sobre objetos System
V IPC.
- CAP_KILL
- Evita comprobaciones de permisos para enviar señales (vea
kill(2)).
- CAP_LEASE
- (Linux 2.4 en adelante) Permite que se establezcan arriendos sobre
ficheros arbitrarios (vea fcntl(2)).
- CAP_LINUX_IMMUTABLE
- Permite establecer los atributos extendidos EXT2_APPEND_FL y
EXT2_IMMUTABLE_FL sobre ficheros del sistema de ficheros
ext2.
- CAP_MKNOD
- (Linux 2.4 en adelante) Permite la creación de ficheros especiales
usando mknod(2).
- CAP_NET_ADMIN
- Permite varias operaciones relacionadas con redes (p.e., establecer
opciones privilegiadas sobre conectores, habilitar la difusión de
paquetes multidestino (multicasting), configuración de
interfaces, modificar tablas de encaminamiento).
- CAP_NET_BIND_SERVICE
- Permite ligar conectores a puertos reservados del dominio de Internet
(números de puerto menores que 1024).
- CAP_NET_BROADCAST
- (No se usa) Permite la difusión universal (broadcasting) de
paquetes a través de un conector y la escucha de paquetes
multidestino.
- CAP_NET_RAW
- Permite el uso de conectores de tipo RAW y PACKET.
- CAP_SETGID
- Permite manipulaciones arbitrarias de los IDs de grupo y de la lista de
IDs de grupo adicionales de un proceso; permite el uso de IDs de grupo
falsificados cuando se pasan credenciales de conectores a través de
conectores de dominio Unix.
- CAP_SETPCAP
- Concede o elimina cualquier capacidad en el conjunto de capacidades
permitidas del invocador a o desde cualquier otro proceso.
- CAP_SETUID
- Permite manipulaciones arbitrarias de los IDs de usuario de los procesos
(setuid(2), etc.); permite el uso de IDs de usuario falsificados
cuando se pasan credenciales de conectores a través de conectores
de dominio Unix.
- CAP_SYS_ADMIN
- Permite una variedad de operaciones de administración del sistema
incluyendo: quotactl(2), mount(2), swapon(2),
sethostname(2), setdomainname(2), IPC_SET y
operaciones IPC_RMID sobre objetos arbitrarios IPC de System V;
permite el uso de IDs de usuario falsificados cuando se pasan credenciales
de conectores.
- CAP_SYS_BOOT
- Permite llamadas a reboot(2).
- CAP_SYS_CHROOT
- Permite llamadas a chroot(2).
- CAP_SYS_MODULE
- Permite cargar y eliminar módulos del núcleo.
- CAP_SYS_NICE
- Permite aumentar el valor nice del proceso invocador (nice(2),
setpriority(2)) y cambiar el valor nice de procesos arbitrarios;
permite establecer políticas de planificación de tiempo real
para el proceso invocador y establecer políticas de
planificación y prioridades para procesos arbitrarios
(sched_setscheduler(2), sched_setparam(2)).
- CAP_SYS_PACCT
- Permite llamadas a acct(2).
- CAP_SYS_PTRACE
- Permite el seguimiento detallado de procesos arbitrarios usando
ptrace(2)
- CAP_SYS_RAWIO
- Permite operaciones sobre puertos de E/S (iopl(2) y
ioperm(2)).
- CAP_SYS_RESOURCE
- Permite el uso de espacio reservado en sistemas de ficheros ext2; llamadas
ioctl(2) para controlar el registro en ext3; sobrescribir los
límites de las cuotas de disco; incrementar los límites de
recursos (vea setrlimit(2)); sobrescribir el límite del
recurso RLIMIT_NPROC; incrementar el límite
msg_qbytes para una cola de mensajes por encima del limite en
/proc/sys/kernel/msgmnb (vea msgop(2) y
msgctl(2).
- CAP_SYS_TIME
- Permite la modificación del reloj del sistema
(settimeofday(2), adjtimex(2)); permite la
modificación del reloj de tiempo real (hardware)
- CAP_SYS_TTY_CONFIG
- Permite llamadas a vhangup(2).
Cada proceso tiene tres conjuntos de capacidades conteniendo cero
o más de las capacidades citadas arriba:
- Efectivas:
- las capacidades usadas por el núcleo para llevar a cabo
comprobaciones de permisos para el proceso.
- Permitidas:
- la capacidades que el proceso puede asumir (esto es, un superconjunto
limitante para los conjuntos de efectivas y heredadas). Si un proceso
elimina una capacidad de su conjunto de permitidas, no puede volver nunca
a adquirir esa capacidad (a menos que ejecute un programa
set-UID-root).
- Heredadas:
- las capacidades que se conservan tras llamadas a execve(2).
En la implementación actual, a un proceso se le conceden
todas las capacidades permitidas y efectivas (sujetas a la operación
del conjunto limitador de capacidades descrita más abajo) cuando
ejecuta un programa set-UID-root o si un proceso con ID de usuario real cero
ejecuta un nuevo programa.
Un hijo creado con fork(2) hereda copias de los conjuntos
de capacidades del padre.
Usando capset(2), un proceso puede manipular su propio
conjunto de capacidades o, si tiene la capacidad CAP_SETPCAP, los de
otros procesos.
Cuando un programa se ejecuta mediante exec, a las
capacidades permitidas y efectivas se les aplica un AND con el valor actual
del así llamado conjunto limitador de capacidades, definido en
el fichero /proc/sys/kernel/cap-bound. Este parámetro se puede
usar para limitar de forma global las capacidades otorgadas a todos los
procesos ejecutados posteriormente. En un sistema estándar, el
conjunto limitador de capacidades siempre desactiva la capacidad
CAP_SETPCAP. Para eliminar esta restricción, modifique la
definición de CAP_INIT_EFF_SET en
include/linux/capability.h y reconstruya el núcleo.
Una implementación completa de capacidades requiere:
- 1.
- que para todas las operaciones privilegiadas, el núcleo compruebe
si el proceso tiene la capacidad requerida en su conjunto efectivo.
- 2.
- que el núcleo proporcione llamadas al sistema permitiendo modificar
y recuperar los conjuntos de capacidades de un proceso.
- 3.
- el soporte del sistema de ficheros para asociar capacidades a un fichero
ejecutable, para que un proceso obtenga esas capacidades cuando el fichero
sea ejecutado mediante exec.
Hasta la versión 2.4.18 de Linux, sólo se cumplen
los dos primeros requisitos.
Finalmente, debería ser posible asociar tres conjuntos de
capacidades a un fichero ejecutable, que en conjunción con los
conjuntos de capacidades del proceso, determinen las capacidades de un
proceso después de un exec:
- Permitidas:
- a este conjunto se le aplica la operación AND con el conjunto
heredado del proceso para determinar qué capacidades heredadas le
son permitidas al proceso después del exec.
- Forzadas:
- las capacidades permitidas automáticamente al proceso, sin importar
las capacidades heredadas del proceso.
- Efectivas:
- aquellas capacidades en el nuevo conjunto permitido del proceso son
también activadas en el nuevo conjunto efectivo. (F(efectivas)
normalmente debería ser o todo ceros o todo unos. Ver más
abajo.)
Mientras tanto, puesto que la implementación actual no
soporta conjuntos de capacidades sobre ficheros, durante un exec:
- 1.
- Se asume que inicialmente los tres conjuntos de capacidades del fichero
están vacíos.
- 2.
- Si se está ejecutando un programa set-UID-root o si el ID de
usuario real del proceso es 0 (root), entonces se considera que los
conjuntos de las capacidades permitidas y forzadas del fichero
están llenos de unos (es decir, todas las capacidades están
activas).
- 3.
- Si se está ejecutando un programa set-UID-root program, entonces se
considera que el conjunto de capacidades efectivas del fichero está
lleno de unos.
Durante un exec, el núcleo calcula las nuevas capacidades
del proceso usando el siguiente algoritmo:
P'(permitidas) = (P(heredadas) & F(permitidas)) | (F(forzadas) & cap_bset)
P'(efectivas) = P'(permitidas) & F(efectivas)
P'(heredadas) = P(heredadas) [i.e., no se modifica]
donde:
- P
- denota el valor del conjunto de capacidades de un proceso antes del
exec
- P'
- denota el valor del conjunto de capacidades de un proceso después
del exec
- F
- denota un conjunto de capacidades de fichero
- cap_bset
- es el valor del conjunto limitador de capacidades.
El paquete libcap ofrece un conjunto de rutinas para
establecer y obtener las capacidades de un proceso que resultan más
cómodas y con menos probabilidad de cambiar que la interfaz provista
por capset(2) y capget(2).
Ningún estándar determina las capacidades, aunque la
implementación de capacidades de Linux se basa en el retraído
borrador del estándar POSIX 1003.1e.
No hay hasta ahora soporte del sistema de ficheros para permitir
asociar capacidades a ficheros ejecutables.