qorpa D9: harkaq enjaula la instancia, y midiendo salieron dos conflictos
Paso 4 del ADR 0015. harkaq-exec entra como último eslabón dentro de bwrap, igual que en el sandbox del build. Cruza el borde un binario ESTÁTICO, no una librería, así que D2 sigue en pie: lo único compartido es la ABI del kernel. Honestidad primero, y está escrita en el código: en el eje del sistema de ficheros harkaq casi no agrega nada, porque el namespace de montaje de bwrap ya es una lista blanca. Escribir reglas `ro` que repiten eso sería un sello de goma, así que la política de una instancia no sellada es UNA línea (`rw /`) y no finge. Lo que sí aporta: seccomp (bwrap no instala filtro alguno — hoy una instancia podía io_uring, bpf, ptrace, userfaultfd, keyctl, perf_event_open), no_new_privs, el canal de evidencia, y `seal_image`, que congela /usr /bin /lib /opt aunque adentro seas root. Verificado contra el kernel, no contra el log: Landlock ABI 9, logging post-exec ON, NoNewPrivs 1, Seccomp 2. Y sellando, `/usr/bin` y `/bin` denegados mientras /etc y /var siguen escribibles. DOS CONFLICTOS que sólo se ven midiendo, y ninguno estaba en el ADR: 1. Landlock y los contenedores anidados son INCOMPATIBLES hoy: con un dominio activo, `mount` falla con EACCES aunque seccomp lo permita — el kernel no admite montajes nuevos bajo un dominio porque escaparían de sus reglas por-ruta. ⇒ pressure-vessel no arranca bajo Landlock. Por eso `nesting` pasa `--allow-nesting --no-landlock` y lo dice a gritos; seccomp y no_new_privs siguen puestos, que es lo que más pesa con un binario ajeno. 2. `root` adentro y anidar se pelean: con --uid 0, un userns anidado no puede escribir su uid_map. Sin remapear anida, pero el gestor de paquetes se queja. La instancia de juegos y la de paquetes quieren mapeos OPUESTOS, y ahora el manifiesto lo declara (`root`, encendido por defecto). Las dos mitades se curan con lo mismo que el impuesto de apt: un rango real de subuid con newuidmap + --userns FD. Ése es el ticket que más desbloquea. En harkaq-exec, dos flags ADITIVOS y apagados por defecto (--allow-nesting, --no-landlock): el camino del build no cambia ni un byte, que es requisito duro con 700+ artefactos sellados. La lista de syscalls del anidamiento se separó de la base y el _Static_assert del techo de salto BPF ahora suma las dos. 3 tests nuevos: que la política sin sellar no finja, que sellando el `rw /` no sobreviva (uniría derechos por ancestro y anularía el sellado), y que `root` sea lo único que nace encendido. 43/43. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5cQtQrYNjWJVXVE6aEpQ2
This commit is contained in:
@@ -285,6 +285,42 @@ máquinas, que es lo que ya hace ADR 0013 con las fuentes) hay que mirar licenci
|
||||
redistribuir un rootfs de Ubuntu o Fedora sin modificar suele estar permitido, pero la política de
|
||||
marca es cosa aparte y no es una pregunta técnica.
|
||||
|
||||
### D9 — Qué aporta harkaq a una instancia, y los dos conflictos que sólo se ven midiendo
|
||||
|
||||
**Honestidad primero: en el eje del sistema de ficheros, harkaq casi no agrega nada.** El namespace
|
||||
de montaje de bwrap ya es una lista blanca —lo que no se bindea no existe adentro, y un `--ro-bind`
|
||||
es de sólo lectura por el kernel— así que escribir reglas Landlock que repiten eso sería un sello de
|
||||
goma. Por eso la política de una instancia **no sellada** es una sola línea (`rw /`) y no finge.
|
||||
|
||||
Lo que harkaq sí aporta, y pesa mucho más con un binario ajeno y opaco que con nuestros propios
|
||||
builds:
|
||||
|
||||
| aporte | por qué importa acá |
|
||||
|---|---|
|
||||
| **seccomp** | bwrap **no instala filtro alguno**: hoy una instancia puede `io_uring`, `bpf`, `ptrace`, `process_vm_readv`, `userfaultfd`, `keyctl`, `perf_event_open`, `init_module`, `kexec`. Ésa es superficie de kernel contra un prebuilt de terceros |
|
||||
| **`no_new_privs`** | ningún setuid de la imagen ajena escala adentro |
|
||||
| **canal de evidencia** | con Landlock ABI ≥ 7 el kernel audita las denegaciones ⇒ se puede saber **qué intentó tocar** un binario cerrado. Es la única forma de auditar el montón B (leer ese canal es trabajo aparte: pide el lector con `CAP_AUDIT_READ`) |
|
||||
| **`seal_image`** | lo único del eje fs que el namespace no da: congelar `/usr`, `/bin`, `/lib`, `/opt` **aunque adentro seas root**, para que un exploit no persista en el `upper` |
|
||||
|
||||
**Conflicto 1 — Landlock y los contenedores anidados son incompatibles hoy.** Medido: con un dominio
|
||||
Landlock activo, `mount` falla con **EACCES aunque seccomp lo permita**; el kernel no admite montajes
|
||||
nuevos bajo un dominio, porque escaparían de sus reglas por-ruta. Es decir: **pressure-vessel no
|
||||
arranca bajo Landlock** (D6). Por eso `nesting = true` cuesta la política de ficheros —`harkaq-exec
|
||||
--allow-nesting --no-landlock`—, y **seccomp y `no_new_privs` siguen puestos**, que es lo que más
|
||||
pesa. Nunca por defecto y siempre dicho en la línea de arranque: harkaq no afirma una jaula que no
|
||||
puso.
|
||||
|
||||
**Conflicto 2 — `root` adentro y anidar se pelean.** Medido: con el uid remapeado a 0 (`--uid 0`), un
|
||||
userns anidado **no puede escribir su `uid_map`**. Sin remapear, anida bien pero el gestor de
|
||||
paquetes se queja. ⇒ la instancia de juegos y la de gestor de paquetes quieren mapeos **opuestos**,
|
||||
y el manifiesto lo declara (`root`, encendido por defecto). Las dos mitades se curan con lo mismo que
|
||||
el impuesto de §NO-resuelve 2: **un rango real de subuid** mapeado con `newuidmap` y pasado a bwrap
|
||||
con `--userns FD`. Ése es hoy el ticket que más desbloquea del ADR entero.
|
||||
|
||||
**Y un detalle que ordena las expectativas:** bwrap **tira todas las capabilities**, así que dentro
|
||||
de una instancia no hay `CAP_SYS_ADMIN` — el anidamiento sólo puede ser por userns sin privilegios,
|
||||
que es exactamente como lo hace pressure-vessel.
|
||||
|
||||
---
|
||||
|
||||
## Lo que este ADR admite que NO resuelve
|
||||
@@ -374,7 +410,10 @@ Se escriben acá para que no se descubran en producción.
|
||||
`recreate` / `run`. El overlay lo monta bwrap (`--overlay-src` + `--overlay`) dentro de su
|
||||
propio namespace: sin root y sin montar nada en el host. `run` entra con `--clearenv` y con
|
||||
`--unshare-net` salvo que se declare `network` — el entorno del host también es una concesión.
|
||||
4. Concesiones → `PolicySpec` de harkaq. Empezar por **nada** y abrir sólo lo declarado.
|
||||
4. ✅ **HECHO 2026-09-03.** Concesiones → política de harkaq. `harkaq-exec` entra como último
|
||||
eslabón dentro de bwrap (cruza un binario **estático**, no una librería ⇒ D2 sigue en pie), y
|
||||
aporta lo que bwrap no da: **seccomp** —hoy una instancia podría `io_uring`, `bpf`, `ptrace`,
|
||||
`userfaultfd`, `keyctl`, `perf_event_open`—, `no_new_privs`, y el canal de evidencia. Ver D9.
|
||||
5. Shims + `.desktop` generados (`export`), y clase `ajeno` en `build-state.py`.
|
||||
6. **Steam de punta a punta**, con verificación explícita del bwrap anidado.
|
||||
7. Poda (`hammer qorpa prune`) y renglón en SDD 20 sobre licencias.
|
||||
|
||||
Reference in New Issue
Block a user