4eecba06f4847b68b307acf232a1fc04f87b86f6
3
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
4eecba06f4 |
harkaq: Fase 1 — la cadena corre de punta a punta (Hermetico / Impuro sobre kernel real)
Tres piezas nuevas, las del §4 del SDD:
- harkaq-audit.c lector de evidencia; HOST junto a hammerd, CAP_AUDIT_READ;
espera el canario (que revela el domain=), junta las
denegaciones de ESE dominio, cruza contra el contador del
kernel al liberarse, y emite el Verdict JSON de 3 estados.
- harkaq-exec.c aplica la política y execea el builder; DENTRO de bwrap,
estático (rootfs musl). Negocia el ABI por syscall (D7:
<min rechaza, <7 avisa SIN EVIDENCIA) y pone
LOG_NEW_EXEC_ON + TSYNC.
- harkaq-run.sh encadena lector+bwrap+exec, pone el canario con nonce y
espera a que el lector confirme que escucha (--ready-fd)
antes de arrancar el build: sin esa barrera el canario se
emitiría sin nadie escuchando y daría SinEvidencia por una
carrera, no por un problema real.
El hito, con comandos sintéticos sobre el kernel real (ABI 10):
limpio {"estado":"Hermetico","canario_visto":true,"contador_kernel":1,"denials":[]}
impuro {"estado":"Impuro","canario_visto":true,"contador_kernel":2,
"denials":[{"blockers":"fs.read_file","path":"…/README.md",…}]}
Canario visto y contador coherente en ambos ⇒ los 3 estados de D9 funcionan.
Q1c contestada en la práctica: el privilegio vive en un helper chico con
`setcap cap_audit_read,cap_audit_control`, NO en hammerd entero.
Sutileza medida: lo que DAC ya bloquea es INVISIBLE para harkaq (el hook del
LSM no llega a correr). Descubierto porque el escenario "impuro" con
/root/.bashrc (drwx------) dio Hermetico: DAC lo bloqueó antes que Landlock.
No rompe D2 (si DAC lo bloqueó, el build tampoco lo usó ⇒ Hermetico es cierto)
pero acota el diagnóstico, y al escribir tests hay que elegir paths que DAC
permita o el control no controla nada.
Falta para cerrar Fase 1: harkaq-policy derivando de la clausura real + el
contraste receta-de-Alpinizada vs. receta-que-no. El rebuild del kernel
(SECURITY_LANDLOCK) NO bloquea el hito: sólo hace falta para que harkaq corra
DENTRO de hammer; el laptop ya está en ABI 10.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
6419f2a952 |
harkaq: Q1b CERRADA — la evidencia cruza el userns y el canario es la clave primaria
Banco: scripts/harkaq/q1b-attrib.c. Dos builds CONCURRENTES en bwrap --unshare-all (los ns de Sandbox::bwrap_args), sin privilegio (uid 1000), canarios con nonce distinto, lector en el host como root. (a) ✅ Los registros CRUZAN el userns/pidns/mountns (6 registros llegaron al lector del host) y cruzan con builds SIN privilegio, que es como corren de verdad. ⇒ harkaq-audit vive en el host junto a hammerd; la arquitectura del §4 se sostiene. (b) ✅ El canario con nonce ATRIBUYE: AAAA=1 BBBB=1, cero cruces con 2 builds en paralelo. ⇒ la granja puede construir en paralelo sin contaminarse la evidencia entre builds. Tres hallazgos colaterales que valen más que el veredicto: - El contador quedó VALIDADO: dos `deallocated denials=1`, uno por dominio, cuadrando con 1 ACCESS cada uno ⇒ el chequeo anti-pérdida (nº ACCESS == denials) está medido, no supuesto. - La identidad sobrevive a los ns: pid=8498 uid=1000 son del HOST (adentro del pidns la víctima es pid 1). - dev+ino identifican el OBJETO, no el BUILD: los 2 canarios dan el mismo ino=4457713 (ambos bindean /etc/hostname). Atribuir por dev/ino habría fundido dos builds leyendo el mismo fichero no declarado — el caso más común que harkaq va a ver. La clave es domain=, y el canario la revela. ⇒ D9 hace TRES trabajos con un mecanismo: honestidad (§3.4), clave primaria (§3.5) y, vía el contador, detección de pérdida. Nota de método: esta corrida también falló 2 veces más, y las 2 el banco afirmó algo falso con total confianza. (1) `cat $canario >/dev/null` — /dev no estaba en la clausura ⇒ sh fallaba en el REDIRECT y cat no corría; el rc=1 no era del canario. (2) Como root, bwrap no pudo ni ejecutar el binario y el veredicto imprimió "NADA cruzó ⇒ replantear la arquitectura" a partir de cero estímulo (causa: --unshare-all mapea sólo uid 0→0; CAP_DAC_OVERRIDE en userns sólo vale sobre uids MAPEADOS ⇒ root-en-userns no atraviesa un home drwx------). Fix: drop_privs() + gate de estímulo (exit 4 si una víctima no sale con status 0). Van 3 veces en una sesión que un cero fue el instrumento y no el kernel, con quien escribía el banco mirando de frente ese riesgo. harkaq sin canario no es un riesgo de configuración: es el comportamiento por defecto. Quedan Q1c (privilegio de harkaq-audit: mejor un helper acotado que hammerd entero) y Q1d (qué ruta reporta exe= con --bind /src). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
ad0948cfb0 |
harkaq: Q1 CERRADA — la evidencia llega; + D9 (canario deliberado) y el banco de pruebas
Q1 era el gate del proyecto (¿llegan los registros AUDIT_LANDLOCK_* a un lector?). Medido en el laptop (ABI 10) con scripts/harkaq/q1-audit.c: ✅ VIABLE. El multicast AUDIT_NLGRP_READLOG entrega blockers=fs.read_file path="/etc/passwd" dev="nvme1n1p6" ino=4458369 + exe=/comm= del que lo intentó. Es el diagnóstico de de-Alpinización que el SDD promete, saliendo del kernel sin instrumentar nada. Dos precondiciones que el Draft 2 no tenía, ambas medidas: - audit_enabled=1 NO viene de fábrica (sin audit=1 en cmdline, sin auditd) ⇒ cero registros de cualquier escenario. AUDIT_SET o audit=1 horneado. - LOG_NEW_EXEC_ON es OBLIGATORIO: same-exec=2 registros, new-exec=0, new-exec-logon=4. harkaq restringe y DESPUÉS execea el builder ⇒ sin el flag certificaría herméticos TODOS los builds, denials=[], sin un error. D9 (nueva, no negociable): el canario lo fabrica harkaq. Se investigó si el registro `deallocated denials=N` servía de verificación cruzada gratis: NO. Medido con ventana de 6s, un dominio con flags default y denegación post-exec no emite NADA (ni allocated, ni access, ni el contador); y el `allocated` es perezoso (llega pegado al primer denial logueado) ⇒ su ausencia tampoco prueba nada. Un build hermético y un lector ciego son bit-idénticos: denials=[]. El Verdict pasa a 3 estados (Hermetico / Impuro / SinEvidencia). El contador SÍ sirve para lo otro: nº ACCESS == denials caza registros perdidos por backlog (riesgo real con la granja en paralelo). Nota de método (§3.4): la 1ª corrida dio 0 en los 3 escenarios y "confirmaba" la hipótesis. Era el instrumento roto (AUDIT_GET con NLM_F_ACK: el ACK llegaba antes que la respuesta → enabled=-1 → nunca se encendía el audit). Se cazó sólo porque el CONTROL (same-exec) también dio 0, y eso era imposible. Es el modo de falla de harkaq en vivo sobre su propio banco. El test ahora aborta (exit 4) si no confirma audit_enabled=1. Nuevas Q1b (¿el lector ve a través del userns de bwrap? ¿cómo se atribuye un registro a SU build con la granja en paralelo?) y Q1c (privilegio de harkaq-audit). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |