chroot falla en OpenVPN: regra de AppArmor ou capacidade?
Engadir unha ruta a un perfil de AppArmor nunca concede CAP_SYS_CHROOT, e un chroot denegado pode vir de tres capas separadas. Avereigue cal hai que cambiar.
O demonio rexistra un fallo de chroot e o perfil xa parece xeneroso, así que a corrección tentadora é ampliar unha regra de ruta e reiniciar. Normalmente non cambia nada, porque chroot está protexido por un privilexio que o perfil nunca puido entregar. Decidir que capa tocar esixe tres comprobacións, e son baratas: que pode reter o proceso, que permite a política e que eliminou o lanzador antes de que calquera das dúas cousas importase.
Dúas portas separadas, e só unha pertence a AppArmor
chroot necesita CAP_SYS_CHROOT no espazo de nomes de usuario no que se executa o proceso. É un privilexio habitual de Linux, e o núcleo compróbao antes de que a chamada faga nada con rutas. Por separado, un perfil de AppArmor en modo de aplicación pode denegar a capacidade mesmo cando o proceso a ten, porque a política obrigatoria consúltase ademais das credenciais, non no seu lugar. A distinción importa na práctica: as dúas capas viven en ficheiros distintos e normalmente manténtenas xente distinta.
Esas dúas portas fallan co mesmo errno. Ambas producen EPERM e ambas aparecen como unha queixa xenérica de permisos no rexistro do demonio, por iso adiviñar o contido do perfil perde tanto tempo. A regra de ruta que ía engadir controla o acceso a ficheiros despois de que chroot teña éxito; non inflúe en se a operación está permitida.
Unha terceira porta está por encima das dúas. Se o xestor de servizos ou un envoltorio iniciaron o proceso sen a capacidade no seu conxunto de límites, ningún cambio de AppArmor pode devolvela, e engadir capacidades ao perfil só documenta unha intención que o núcleo non respectará.
Lea o estado dos privilexios antes de editar a política
Comece polo proceso en execución, non pola configuración que cree activa. O ficheiro de estado expón cinco máscaras de capacidade e o indicador no-new-privileges, e responden a preguntas distintas:
grep -E '^(CapInh|CapPrm|CapEff|CapBnd|CapAmb|NoNewPrivs):' /proc/$(pidof openvpn)/status
sudo aa-status | grep -i openvpnCapEff é o conxunto que importa para a chamada: unha capacidade presente en CapBnd pero ausente de CapEff está permitida polo teito e non se retén agora. CapAmb importa cando o binario non é privilexiado no sentido habitual de setuid, porque as capacidades ambientais son a forma en que un servizo conserva un privilexio a través de exec sen capacidades de ficheiro. CapInh garda bits que poderían herdarse a través de exec, pero só cando o conxunto herdable do ficheiro executado o permite, así que un bit aí non concede nada por si só.
Despois confirme que perfil está realmente adxunto. Un proceso pode estar confinado por un nome de perfil que non esperaba, sobre todo cando unha distribución entrega o seu ficheiro de unidade e o seu perfil xuntos, e ler /proc/PID/attr/current resólveo nunha liña. Comparar o seu ficheiro editado co perfil que informa o núcleo é a diferenza entre arranxar a causa e editar un ficheiro que ninguén carga.
Engada a regra de capacidade só cando o rastro de auditoría o diga
Os rexistros do núcleo e de auditoría nomean a capa que denega. Busque unha denegación que leve a operación capable e o nome sys_chroot, xunto co perfil que a produciu. Se ese rexistro existe, o proceso xa tiña a capacidade e AppArmor denegouna, e o cambio dirixido é unha regra de capacidade dentro do perfil real:
capability sys_chroot,Mantéña como fragmento no perfil que está realmente adxunto, e comprobe a palabra clave coa referencia de perfís apparmor.d en lugar de copiar unha regra dun titorial alleo. Poñela nun include compartido concédella a cada programa confinado que arrastre ese ficheiro, e pasar os perfís a modo de queixa oculta a seguinte denegación en vez de resolver esta. A regra do perfil elimina unha denegación de política; non fabrica privilexio, así que un proceso que nunca tivo CAP_SYS_CHROOT no seu conxunto efectivo seguirá fallando coa regra posta.
Se o rexistro de auditoría non mostra ningunha denegación de AppArmor, deixe de editar o perfil. Está ante un problema de credenciais, e o traballo restante está no ficheiro de unidade ou no proceso pai, non na linguaxe de política.
O xestor de servizos ten o seu propio teito
systemd fixa un conxunto de límites de capacidade para cada servizo, e por defecto ese conxunto é estreito. Todo o excluído alí está indispoñible para o proceso diga o que diga o perfil, por iso as unidades endurecidas poden fallar nunha operación que funcionaba cando o demonio se iniciaba a man. As directivas relevantes son fáciles de ler na unidade e fáciles de pasar por alto cando a aplicación informa do erro. Os drop-in que entrega un paquete de distribución son a fonte habitual dun teito que ninguén lembra ter configurado.
Subir o teito e conceder a capacidade son dous cambios, non un. Unha entrada no conxunto de límites di que o proceso pode reter a capacidade; non a engade ao conxunto efectivo, e NoNewPrivs pode impedir que unha elevación posterior teña éxito mesmo cando todo o demais encaixa. Engada só o que a operación necesita, manteña intacto o resto do endurecemento e resista o atallo de conceder todas as capacidades para que pase unha chamada.
A orde tamén importa aquí. Cambie primeiro o teito da unidade, verifique que CapEff xa contén o bit, e só despois decida se AppArmor segue denegando. Facer os dous cambios á vez déixalle adiviñando outra vez se o fallo persiste.
Cando a denegación desapareza, comprobe a gaiola mesma
Un chroot exitoso move a raíz, así que cada ruta que o demonio toque despois resólvese dentro da árbore nova. Unha configuración ausente, un nodo de dispositivo que falta ou un directorio de certificados que non se copiou aparecerán agora como un erro de ficheiro, e ese erro é un problema de disposición, non de capacidade. Lea o seguinte evento en lugar de engadir outro permiso amplo. O movemento tamén cambia que significa unha ruta relativa, por iso as guías de endurecemento insisten en rutas absolutas na configuración do demonio.
Tamén axuda lembrar que non fai chroot. É unha fronteira de rutas, non unha caixa de area: un proceso que conserva o privilexio pode escapar dela, por iso a capacidade normalmente se solta despois da chamada e por iso o confinamento debe permanecer arredor do demonio. Manter o perfil de AppArmor, o conxunto de límites de capacidade e as restricións do sistema de ficheiros xuntos é o sentido do exercicio, non un resto que quitar en canto arranca o servizo.
A regra de decisión é curta. Se o rexistro de auditoría nomea AppArmor, engada unha regra de capacidade ao perfil adxunto. Se o conxunto efectivo está baleiro, corrixa o teito da unidade e a orde de soltar o privilexio. Se o perfil non é o que editou, deixe de editar e atope o real.