El demonio registra un fallo de chroot y el perfil ya parece generoso, así que la corrección tentadora es ampliar una regla de ruta y reiniciar. Normalmente no cambia nada, porque chroot está protegido por un privilegio que el perfil nunca pudo entregar. Decidir qué capa tocar exige tres comprobaciones, y son baratas: qué puede retener el proceso, qué permite la política y qué eliminó el lanzador antes de que cualquiera de las dos cosas importara.

Dos puertas separadas, y solo una pertenece a AppArmor

chroot necesita CAP_SYS_CHROOT en el espacio de nombres de usuario en el que se ejecuta el proceso. Es un privilegio habitual de Linux, y el núcleo lo comprueba antes de que la llamada haga nada con rutas. Por separado, un perfil de AppArmor en modo de aplicación puede denegar la capacidad incluso cuando el proceso la tiene, porque la política obligatoria se consulta además de las credenciales, no en su lugar. La distinción importa en la práctica: las dos capas viven en archivos distintos y normalmente las mantienen personas distintas.

Esas dos puertas fallan con el mismo errno. Ambas producen EPERM y ambas aparecen como una queja genérica de permisos en el registro del demonio, por eso adivinar el contenido del perfil pierde tanto tiempo. La regla de ruta que iba a añadir controla el acceso a archivos después de que chroot tenga éxito; no influye en si la operación está permitida.

Una tercera puerta está por encima de las dos. Si el gestor de servicios o un envoltorio iniciaron el proceso sin la capacidad en su conjunto de límites, ningún cambio de AppArmor puede devolverla, y añadir capacidades al perfil solo documenta una intención que el núcleo no respetará.

Lea el estado de privilegios antes de editar la política

Empiece por el proceso en ejecución, no por la configuración que crea activa. El archivo de estado expone cinco máscaras de capacidad y el indicador no-new-privileges, y responden a preguntas distintas:

grep -E '^(CapInh|CapPrm|CapEff|CapBnd|CapAmb|NoNewPrivs):' /proc/$(pidof openvpn)/status
sudo aa-status | grep -i openvpn

CapEff es el conjunto que importa para la llamada: una capacidad presente en CapBnd pero ausente de CapEff está permitida por el techo y no se retiene ahora. CapAmb importa cuando el binario no es privilegiado en el sentido habitual de setuid, porque las capacidades ambientales son la forma en que un servicio conserva un privilegio a través de exec sin capacidades de archivo. CapInh guarda bits que podrían heredarse a través de exec, pero solo cuando el conjunto heredable del archivo ejecutado lo permite, así que un bit ahí no concede nada por sí solo.

Después confirme qué perfil está realmente adjunto. Un proceso puede estar confinado por un nombre de perfil que no esperaba, sobre todo cuando una distribución entrega su archivo de unidad y su perfil juntos, y leer /proc/PID/attr/current lo resuelve en una línea. Comparar su archivo editado con el perfil que informa el núcleo es la diferencia entre arreglar la causa y editar un archivo que nadie carga.

Añada la regla de capacidad solo cuando el rastro de auditoría lo diga

Los registros del núcleo y de auditoría nombran la capa que deniega. Busque una denegación que lleve la operación capable y el nombre sys_chroot, junto con el perfil que la produjo. Si ese registro existe, el proceso ya tenía la capacidad y AppArmor la denegó, y el cambio dirigido es una regla de capacidad dentro del perfil real:

capability sys_chroot,

Manténgala como fragmento en el perfil que está realmente adjunto, y compruebe la palabra clave con la referencia de perfiles apparmor.d en lugar de copiar una regla de un tutorial ajeno. Ponerla en un include compartido la concede a cada programa confinado que arrastre ese archivo, y pasar los perfiles a modo de queja oculta la siguiente denegación en vez de resolver esta. La regla del perfil elimina una denegación de política; no fabrica privilegio, así que un proceso que nunca tuvo CAP_SYS_CHROOT en su conjunto efectivo seguirá fallando con la regla puesta.

Si el registro de auditoría no muestra ninguna denegación de AppArmor, deje de editar el perfil. Está ante un problema de credenciales, y el trabajo restante está en el archivo de unidad o en el proceso padre, no en el lenguaje de política.

El gestor de servicios tiene su propio techo

systemd fija un conjunto de límites de capacidad para cada servicio, y por defecto ese conjunto es estrecho. Todo lo excluido allí está indisponible para el proceso diga lo que diga el perfil, por eso las unidades endurecidas pueden fallar en una operación que funcionaba cuando el demonio se iniciaba a mano. Las directivas relevantes son fáciles de leer en la unidad y fáciles de pasar por alto cuando la aplicación informa del error. Los drop-in que entrega un paquete de distribución son la fuente habitual de un techo que nadie recuerda haber configurado.

Subir el techo y conceder la capacidad son dos cambios, no uno. Una entrada en el conjunto de límites dice que el proceso puede retener la capacidad; no la añade al conjunto efectivo, y NoNewPrivs puede impedir que una elevación posterior tenga éxito incluso cuando todo lo demás encaja. Añada solo lo que la operación necesita, mantenga intacto el resto del endurecimiento y resista el atajo de conceder todas las capacidades para que pase una llamada.

El orden también importa aquí. Cambie primero el techo de la unidad, verifique que CapEff ya contiene el bit, y solo después decida si AppArmor sigue denegando. Hacer los dos cambios a la vez le deja adivinando otra vez si el fallo persiste.

Cuando la denegación desaparezca, compruebe la jaula misma

Un chroot exitoso mueve la raíz, así que cada ruta que el demonio toque después se resuelve dentro del árbol nuevo. Una configuración ausente, un nodo de dispositivo que falta o un directorio de certificados que no se copió aparecerán ahora como un error de archivo, y ese error es un problema de disposición, no de capacidad. Lea el siguiente evento en lugar de añadir otro permiso amplio. El movimiento también cambia qué significa una ruta relativa, por eso las guías de endurecimiento insisten en rutas absolutas en la configuración del demonio.

También ayuda recordar qué no hace chroot. Es una frontera de rutas, no una caja de arena: un proceso que conserva el privilegio puede escapar de ella, por eso la capacidad normalmente se suelta después de la llamada y por eso el confinamiento debe permanecer alrededor del demonio. Mantener el perfil de AppArmor, el conjunto de límites de capacidad y las restricciones del sistema de archivos juntos es el sentido del ejercicio, no un resto que quitar en cuanto arranca el servicio.

La regla de decisión es corta. Si el registro de auditoría nombra AppArmor, añada una regla de capacidad al perfil adjunto. Si el conjunto efectivo está vacío, corrija el techo de la unidad y el orden de soltar el privilegio. Si el perfil no es el que editó, deje de editar y encuentre el real.

Artículos relacionados