Files
AXP-Resurection/docs/009-kernel-boot-audit-20260926.md
T
sunfish-adminandCursor 2d145c2878 009: Polish bacon fixes, OTA host scripts, and migration docs.
Restore disable_configstore, EuiccDisabler and thermal CDEV guards, branding
and rebuild/sync helpers; document device roles, laptop migration, and Gitea.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-16 21:06:45 +02:00

13 KiB

Status: historical. Do not use as execution order. Resume: 009-handoff-20261008.md.

Auditoría de los fallos de arranque del kernel — 2026-09-26

Revisión de documentación local, scripts, fuentes y artefactos de rom-dev01. No se ha compilado, flasheado, reiniciado ni modificado el servidor o los teléfonos. Este documento registra evidencias y un punto de reanudación; no cambia requisitos.

Conclusión

Hallazgo prioritario posterior: los bisect cambian TARGET_RELEASE de bp4a a bp2a. La comparación binaria y el log demuestran que no se está aislando el hardening. Ver la sección siguiente antes de construir o probar más boots.

Hay errores verificables en la preparación de los experimentos y en su trazabilidad. Todavía no hay una traza que identifique la causa exacta del fallo de arranque. El siguiente paso debe recuperar un experimento controlado, no volver a aplicar todo el hardening/CVE/deblob desde cero.

Hallazgo principal: cambio accidental de release Android en los bisect

Tras confirmar el dueño que GOODMAKE también arranca, se han desempaquetado GOODMAKE y el boot mild y extraído sus configuraciones IKCONFIG y ramdisks. Evidencia y diff de configuración.

  • GOODMAKE: cabecera con parche 2026-09; ramdisk declara ro.build.version.security_patch=2026-09-01, SDK completo 36.1.
  • MILD: cabecera con parche 2025-08; ramdisk declara ro.build.version.security_patch=2025-08-05, SDK completo 36.0.
  • DTB idéntico. Ramdisk diferente, incluyendo bibliotecas y propiedades.
  • Configuración del kernel: además de DMESG/SLAB cambian VT/fbcon, watchdog y PANIC_TIMEOUT (de 0 a 5), entre otros cambios derivados. La base buena conservaba configuración de depuración y el bloque Kconfig de KernelSU, aunque CONFIG_KSU estaba desactivado.

Origen confirmado en el servidor:

  • scripts/009-bacon-axp.sh:87 usa breakfast sunfish userdebug.
  • vendor/lineage/build/envsetup.sh hace que breakfast lea vendor/lineage/vars/aosp_target_release, cuyo valor actual es bp4a.
  • Los bisect fuerzan lunch lineage_sunfish-bp2a-userdebug.
  • El log detach-009-bisect-dc-20260921T180802Z.log:53 registra literalmente TARGET_RELEASE ("bp4a" -> "bp2a").
  • build/release/flag_values/bp2a/RELEASE_PLATFORM_SECURITY_PATCH.textproto contiene 2025-08-05.
  • Los dos scripts nuevos del 26 de septiembre, 009-bisect-dmesg-only.sh y 009-bisect-slab-only.sh, también fuerzan bp2a en la línea 32. No se han detenido ni modificado sus procesos desde esta auditoría.

Defecto demostrado: los experimentos denominados «solo una/dos opciones» cambian también la release Android y metadatos de seguridad del boot. Que GOODMAKE arranque no valida la equivalencia del entorno que los recompila.

Hipótesis causal prioritaria, aún no confirmada en LAB: el retroceso del nivel de parche o su inconsistencia con el sistema instalado puede interferir con Keymaster y las claves necesarias para montar datos. AOSP documenta version binding: las claves están vinculadas a versiones/niveles de parche y no se pueden degradar libremente. Los flags AVB que desactivan verificación no constituyen una prueba de compatibilidad de esas claves. Falta traza o prueba controlada; no afirmar que esto explique también todos los OTA Stage1 anteriores.

Corrección del experimento: recuperar la release y metadatos efectivos del build bueno; verificar cabecera, propiedades y AVB del resultado antes de flashear. Cambiar simplemente a bp4a no basta como verificación: el archivo bp4a actual declara 2025-12-05, mientras GOODMAKE declara 2026-09-01, por lo que hay que localizar/reproducir sus overrides y no inventar una fecha. Usar salida aislada y empezar con un control recompilado sin hardening nuevo. No hacer factory reset como método de validación. Después aislar kernel y módulos sin variar simultáneamente ramdisk, release o metadatos.

Historial aportado por el dueño después de la revisión

El 26 de septiembre el dueño aporta una conversación previa:

  • «Tanto con uno como el otro» el teléfono reinicia en recovery y muestra «Try again / Factory data reset». El fragmento no identifica inequívocamente los dos archivos por nombre/hash; no asignar este resultado a mild.
  • Tras restaurar el boot GOOD de 20260918T143547Z, confirma «estoy en el sistema». No se relata un borrado de datos. Es evidencia de recuperación con el boot conocido, no una prueba de corrupción permanente de /data.
  • El agente anterior informa ADB unauthorized en recovery; después, ya en sistema, informa ausencia de su, depuración root desactivada y ningún log útil obtenido. No hay salidas originales que permitan verificar qué rutas pudo leer: «no pude obtener evidencia» no equivale a «no se generó evidencia».
  • La conversación termina proponiendo mild como prueba pendiente. No aporta una respuesta posterior que confirme su ejecución ni su resultado.

Este historial matiza el registro «nunca recovery/Android»: al menos en los intentos relatados sí se llega a recovery tras el fallo. No demuestra que el kernel del arranque normal alcanzara una fase concreta, porque recovery es un arranque posterior. Preparar acceso diagnóstico en el sistema GOOD antes de otro ensayo, sin completar Magisk únicamente para obtener logs ni mezclar su activación con el cambio de kernel. No interpretar el menú de recovery como una indicación de que sea necesario hacer factory reset.

1. Imagen antigua dentro del ensayo nuevo (confirmado por SHA-256)

Raíz de artefactos remota: /srv/rom/artifacts/009-axp-los23-port/.

Estos dos archivos tienen el mismo SHA-256, recalculado el 26 de septiembre:

  • 20260921T185024Z-bisect-defconfig-only/boot.img
  • 20260918T231654Z-axp-kh-full/boot.img

SHA-256: 3715f9f20c8823e5a23323792600b5d76d9f25e73eed3492c28f457a751d3c51.

El script remoto scripts/009-bisect-defconfig-only.sh ejecuta mka bootimage y luego busca el primer target_files_intermediates/.../IMAGES/boot.img. Ese segundo archivo pertenece al empaquetado anterior: el ensayo termina conteniendo dos imágenes con kernels distintos.

El boot-make.img del ensayo tiene SHA-256 registrado f52405c6b39a14d3357efd59441c9a28128bbce982186b1d86c71b01da8846b1. El README sí indica usar ese archivo. No he encontrado en lo revisado un registro de flasheo con hash que permita confirmar cuál se probó. Por tanto, la identidad equivocada está demostrada; que se flashease la imagen equivocada, no. El script posterior 009-bisect-defconfig-mild.sh ya evita esta copia.

2. «Solo defconfig» también cambia código de FORTIFY (confirmado)

El mismo script añade a lib/string.c definiciones exportadas de __read_overflow, __read_overflow2, __read_overflow3 y __write_overflow, todas con cuerpo BUG(). El log /srv/rom/artifacts/detach-009-bisect-dc-20260921T180802Z.log confirma added fortify stubs.

En las fuentes LOS inspeccionadas, include/linux/string.h:241 y siguientes declaran los helpers de lectura con __compiletime_error. Proporcionarles un cuerpo permite resolver símbolos que impedían enlazar, pero no demuestra que las llamadas sean correctas ni que no se ejecuten. Si se alcanza uno de esos cuerpos se ejecuta BUG(). Falta investigar los sitios de llamada y su relación con Clang/LTO; no atribuir el bootloop a ellos sin traza.

La conclusión previa «defconfig extras alone are enough to kill boot» es demasiado fuerte: el ensayo incluye cambios C, varias opciones simultáneas y la ambigüedad de imágenes anterior. Además cambia SLAB_HARDENED de Stage1 por SLAB_FREELIST_HARDENED, por lo que tampoco reproduce exactamente su config.

3. Se avanzó de etapa sin validar arranque (confirmado documentalmente)

docs/009-kernel-hardening-map.md ordena diferir los CVE hasta que Stage1 arranque, pero registra tres builds el 18 de septiembre: Stage1, Stage1 con unos 500 CVE, y hardening ampliado. Los tres fallaron en LAB según el registro del 21. Compilar correctamente no cumplía esa condición.

Stage1 ya agrupaba 30 parches y varias opciones; también se documentan restos de modificaciones SusFS en el árbol inicial. El script de bisect posterior sí limpia las fuentes hasta 28f9290ae067; no confundir ambos estados.

4. Aplicación de parches y reparaciones no reproducibles

El apply_stage1.sh local usa patch --batch sin exigir fuzz cero. Ya existe un caso documentado de aplicación en la función equivocada: slab/0014 entró en is_root_cache en vez de slab_equal_or_root.

El listado sigue incluyendo ese parche. Las correcciones de slab y FORTIFY se describen en BUILD-FIXES.md, pero no están implementadas por el aplicador local. Ejecutar la receta publicada no reproduce por sí solo el árbol corregido.

Otros defectos visibles del aplicador:

  • Si falta un archivo, incrementa fail y continúa; al acabar puede devolver éxito porque el último comando es echo.
  • Ante fallo elimina .rej y .orig, perdiendo evidencia; no revierte los hunks que se hayan aplicado antes del fallo.
  • --dry-run prueba cada parche sobre el mismo árbol sin aplicar sus predecesores: no valida fielmente una serie con dependencias.

En el servidor, scripts/009-cve-compile-fix.sh intenta seleccionar parches para excluir por tokens extraídos del mensaje del compilador y registra el código de salida de su reversión sin exigir que sea cero. Esto no verifica dependencias ni garantiza que el árbol coincida con la denylist. Son defectos del método; esta revisión no establece qué rondas concretas los ejercitaron.

5. Kernel y módulos: compatibilidad pendiente de demostrar

Los dos scripts de bisect generan y guardan únicamente imágenes de arranque; sus instrucciones reutilizan la ROM 20260918T143547Z-axp-full instalada. No guardan ni indican desplegar un conjunto correspondiente de módulos vendor.

El código actual include/linux/slub_def.h:120 añade el campo random a struct kmem_cache bajo CONFIG_SLAB_FREELIST_HARDENED. La .config generada actual contiene esa opción y CONFIG_MODVERSIONS=y.

Esto justifica comprobar ABI/CRC de los módulos realmente cargados y los que van en el ramdisk/vendor antes de interpretar un ensayo de solo boot. No prueba por sí solo incompatibilidad ni explica necesariamente los primeros tres OTA. La misma precaución ya consta en docs/007-susfs-source-audit.md.

6. Faltan observabilidad y continuidad entre sesiones

El logo de Google no identifica por sí solo la fase exacta del bloqueo. El pstore vacío tampoco demuestra que no hubiera traza: la auditoría de 007 documenta un error de descifrado de ramoops en LAB. Es evidencia histórica; no se ha vuelto a medir el estado actual del teléfono en esta revisión.

El mapa local acaba proponiendo el ensayo mild, pero este ya fue compilado:

  • Artefacto: 20260921T192533Z-bisect-defconfig-mild/boot-make.img.
  • SHA-256 registrado en su log: 6ed0351edb762bdf4bfe2dd96d7e4e2fa43ccf0ad497d7fce35ab88cd722f4f2.
  • Estado del proceso: exit=0, finalizado el 21 a las 19:25:33 UTC.
  • Resultado de arranque: no encontrado en los registros revisados.
  • Árbol remoto actual: HEAD 28f9290ae067d3e7857126eb6312720dbe9c7c80; único archivo modificado según Git: sunfish_defconfig, con KSU desactivado, SECURITY_DMESG_RESTRICT=y y SLAB_FREELIST_HARDENED=y.
  • .config actual: FORTIFY e INIT_ON_ALLOC/FREE desactivados. No sustituye a una configuración archivada de cada build anterior.

Punto de reanudación propuesto

  1. Conservar como referencia el build 20260918T143547Z-axp-full, cuyo arranque está confirmado por el dueño en el mapa. Identificar por hash el boot realmente probado en cada bisect y aclarar el resultado de mild.
  2. Reproducir un control sin hardening nuevo con fuentes, herramienta de compilación, salida aislada y módulos identificados. Validar arranque en LAB.
  3. Separar las variables: una opción por ensayo. Tratar FORTIFY más sus modificaciones C como una investigación propia; no ocultar errores de enlace bajo la etiqueta «solo config».
  4. Para cambios que afecten ABI, comprobar o desplegar un conjunto compatible de kernel y módulos. Registrar slot, particiones, hashes y resultado.
  5. Recuperar diagnóstico del fallo antes de atribuirlo a un subsistema. No borrar datos, alternar slots o añadir parches como sustituto de evidencia.
  6. Congelar cada estado probado: revisión y diff de fuentes, parches y sus hashes, .config efectiva, compilador, imágenes/módulos, log y resultado. No avanzar a CVE ni deblob hasta aceptar la etapa anterior.

Deblob no es una causa demostrada en estos ensayos: el registro de 009 lo declara pendiente, y la retirada de IPA se omitió expresamente. No se ha realizado aquí una auditoría exhaustiva del contenido de todos los payloads.