# Plan: captura verificable del fallo FORTIFY > Revisión posterior: [auditoría del diagnóstico del 27/09](009-fortify-diag-review-20260927.md). > El «canal VERIFICADO» de abajo solo demuestra parte de la persistencia: > SysRq-x puede dejar la misma marca que se observa tras SysRq-c. Además, el > escritor no funciona antes de ramoops_probe. La ausencia de AXPDIAG1 tras > fortify-diag **no descarta fortify_panic**, ni demuestra watchdog. Se conserva > abajo el historial original de las pruebas. Parte de `docs/009-fortify-bounds-boot-failure-20260927.md`. Referencia LAB: combo4 `#16` (sin FORTIFY). No flashear diagnóstico hasta tener canal de captura comprobado en esa referencia. ## Hallazgos en combo4 (2026-09-27, solo lectura) | Señal | Valor | |-------|--------| | boot_completed | 1 | | pstore montado | sí, vacío | | last_kmsg / debugfs | no accesibles como shell | | Magisk / su | no activos (virgin AXP) | | cmdline | `console=null`, `androidboot.ramdump=disabled` | | config | `CONFIG_PSTORE=y`, `PSTORE_RAM`, `PSTORE_CONSOLE`, `ACCESS_RAMOOPS` | | bootreason tras recover | `reboot` / `bootloader` (no identifica el panic FORTIFY) | Conclusión: el kernel **tiene** pstore/ramoops, pero LAB no entrega traza útil tras el reboot a fastboot. Cambiar más CONFIGs sin canal de evidencia repite el bucle anterior. ## Objetivo del arranque de diagnóstico Distinguir, con registro persistente o serial: 1. `fortify_panic` (caller + backtrace) 2. fallo CFI 3. watchdog / softlockup 4. fallo de carga de módulos / ABI Sin eso, no atribuir el logo Google a audio/WLAN ni a FORTIFY genérico. ## Pasos (orden) 1. **Canal de captura en combo4 (sin FORTIFY)** - Confirmar cómo Pixel 4a/sunfish expone ramoops tras panic (`ACCESS_RAMOOPS`, partición `klog`/`logfs`, `ramdump=disabled`). - Probar un panic controlado mínimo en un boot **solo diagnóstico** (no ship) y verificar que shell/root puede leer `/sys/fs/pstore/console-ramoops*` tras el siguiente arranque bueno. - Alternativa: UART/serial o `androidboot.console` no-null si el lab lo permite. Si el canal falla, no flashear FORTIFY otra vez. 2. **Instrumentar `fortify_panic`** (solo en árbol de ensayo) - Antes del `BUG()`: `pr_emerg` con `%pS` del return address + stack. - Mantener el panic (no convertir en no-op). - Misma receta ksync (GOODMAKE + kernel FORTIFY+POS0+bounds). 3. **Marcas CFI / módulos** - Si el log muestra CFI: seguir esa vía. - Si aparece durante `insmod`/init de vendor: comparar CRC/ABI de módulos (requiere root o dump desde recovery). - Si watchdog sin fortify/CFI: otra clase de hang. 4. **Empaquetador** - Quitar el `|| true` que traga el SIGILL de `magiskboot` en VERIFY, o verificar el header en el laptop con el mismo SHA. Defecto de script, no causa del reboot (imagen unpack OK en laptop). 5. **Solo después** de una traza atribuible: cambio mínimo (call site, excepción justificada, o más port). No stubs. No ship FORTIFY. ## Estado 2026-09-27 (tras Rooted debugging) - `adb root` OK. - `vendor.ramoops.decryption.error=1` en boot normal. - Causa 1: `/vendor/bin/ramoops` hardcodea `/sys/devices/soc/.../size` pero el kernel expone `/sys/devices/platform/soc/...` (y vía `/sys/class/misc/.../size`). Binario parcheado en `/data/local/tmp/ramoops.fix` para class paths. - Causa 2: tras eso, kernel log `ramoops: Failed to set key, -22` (EINVAL) al escribir AES en sysfs. pstore sigue vacío. Remount pstore denegado por SELinux. - Claves RSA sí existen en `/data/vendor_ce/0/ramoops/{priv,pub}.pem`. - `boot_debug/crash.txt` es basura userspace antigua, no kernel FORTIFY. - Build `fortify-diag` (panic instrumentado) sigue en curso. ## Captura post fortify-diag (2026-09-27 ~01:36) Tras flash diag → fallo → recover combo4 `#16` + `adb root`: - pstore vacío; `boot_debug/kernel.txt` vacío; sin `FORTIFY_DIAG` en claro. - Dump `/dev/access-ramoops` (4 MiB): entropía alta (cifrado); 0 strings útiles. - Decrypt sigue fallando (`Failed to set key, -22`). Prueba de canal con **SysRq-c** en combo4: - Bootloader registró `androidboot.bootreason=kernel_panic` (panic real). - **Aun así** pstore vacío y alt cifrado sin plaintext. Conclusión: en este LAB un `kernel_panic` **no** produce traza legible vía pstore hasta arreglar el pipeline AES/ramoops. El síntoma FORTIFY (antes del SysRq) había dejado `bootreason=reboot`/`bootloader`, no `kernel_panic` — hipótesis abierta: reset/wdog distinto de `fortify_panic`, o el bootloader reescribe el motivo al pasar por fastboot. Siguiente trabajo de captura: diag **sin cifrado** (pstore/ramoops plaintext) o arreglo del setkey; no más flashes FORTIFY hasta tener canal verificado con SysRq → fichero legible en pstore. ## Captura plaintext (2026-09-27 ~01:45) Hallazgos en combo4 tras Rooted debugging + reboot sin unlock: | Señal | Valor | |-------|--------| | `dumpsys user` | `RUNNING_LOCKED`, Unlock time unknown | | `sys.user.0.ce_available` | vacío | | `/data/vendor_ce/0/ramoops` | `Required key not available` | | `mount \| grep pstore` | vacío tras `on boot` umount | | Remount manual `pstore` + `use_alt=0` | monta OK, **sigue sin ficheros** | | `/dev/pmsg0` + reboot | no aparece `pmsg-ramoops-*` | | SysRq-c | `bootreason=kernel_panic`, alt cifrado, primary vacío | Causa de sistema (no solo FORTIFY): 1. `init-ramoops.rc` hace `umount /sys/fs/pstore` en `on boot` y solo remonta cuando `vendor.ramoops.decrypted=true` (tras CE unlock + `ramoops -D`). 2. Binario `/vendor/bin/ramoops` usa paths sysfs pre-`platform/` → size=-1; con binario parcheado a class paths, CE locked → sin `priv.pem`. 3. Writes de pstore van al **primary**; el carveout que sobrevive/lee userspace tras decrypt es el **alt** cifrado (`/dev/access-ramoops`). 4. `ramoops_init_prz` hace `persistent_ram_zap(primary)` tras `save_old` en console/pmsg — el pipeline asume encrypt-on-shutdown a alt. Canal de evidencia (sin CE / sin AES): patch diag `ramoops_axp_plaintext_alt` — en DMESG oops/panic escribe magic `AXPDIAG1` + cuerpo en claro al **alt** (ioremap). Verificación LAB: ```text dd if=/dev/access-ramoops bs=1M count=4 | strings | grep -E 'AXPDIAG1|Kernel panic' ``` Build canal (sin FORTIFY): `scripts/009-bisect-ksync-pstore-alt-plain.sh` (`PSTORE_ALT_PLAIN=1`). Probar SysRq → magic legible **antes** de otro flash FORTIFY. ### Iteración 2 (ioremap en panic) - Alt carveout **sí** persiste: write userspace `AXPUSER1` → reboot → sigue ahí. - Build `20260927T001522Z` con mirror vía `ioremap_wc` **en** `ramoops_pstore_write` (contexto panic/atomic): SysRq → `bootreason=kernel_panic` pero **sin** `AXPDIAG1` (ioremap no es safe ahí; write silencioso no-op). - Fix: pre-map en `ramoops_probe` (`axp_alt_va`) + solo `memcpy_toio`/`wmb` en panic. Rebuild: job `009-bisect-ksync-pstore-alt-plain2`. - plain2: map OK + SysRq `kernel_panic`, sin `AXPDIAG1` (aliasing WC vs `ioremap`). - plain3: `AXPDIAG0-probe` legible tras boot (kernel→alt OK). Tras SysRq solo `AXPDIAG0` — el hook DMESG pstore no corre en este panic path. - plain4: `panic_notifier` + `AXPDIAG1-panic-notifier`, pero el boot siguiente reescribía `AXPDIAG0` encima. Fix: no clobber si head=`AXPDIAG1`. Rebuild: `pstore-alt-plain5`. ### Canal VERIFICADO (plain7, `20260927T024949Z`) | Prueba | Resultado | |--------|-----------| | `echo x > /proc/sysrq-trigger` (sin panic) | `AXPDIAG1-sysrq-fixed` en `/dev/access-ramoops` | | sysrq-x + `adb reboot` | `AXP alt keeps prior AXPDIAG1 capture` | | sysrq-x + sysrq-c → `bootreason=kernel_panic` | magic `AXPDIAG1` sobrevive (cuerpo a veces truncado por reset) | | Metadata `/dev/access-metadata` tras panic | reescrita (claves AES); no usar | Lectura post-fallo (root, no hace falta unlock CE): ```text adb root dd if=/dev/access-ramoops bs=1M count=4 | strings | grep AXPDIAG dmesg | grep AXP ``` ## v4 canal (post review v3 2026-09-27) Ver `docs/009-fortify-diag-v3-review-20260927.md`. v3 obsoleto: `ioremap` tras `paging_init` (antes de slab/vmalloc) puede tumbar el control sin FORTIFY; attrs early cached vs IO; milestones compartían slots con el fallo. `apply_fortify_diag.py` **v4**: - Early: `early_ioremap` (FIXMAP_PAGE_IO) antes de `parse_early_param`; se mantiene hasta después de `mm_init`. Permanente: `ioremap` **solo** tras `mm_init`. Handler nunca mapea. - Layout página 0: fallo @0 (+ mirrors); milestones @2048 (zonas separadas). - Adoptar fallo previo solo si registro **completo** (header + `\\n` + mirror). - Ciego residual: pre-`early_map`; ventana breve al cambiar early→perm si el VA se publica mal (v4 publica permanente antes de retirar early). Validación control (sin FORTIFY) — media/tardía; no prueba pre-`early_map`: 0. Wipe zona fallo: `dd if=/dev/zero of=/dev/access-ramoops bs=4K count=1` 1. Flash `pstore-alt-plain` v4, boot, `adb root`. 2. Milestones: `strings | grep AXPDIAG0` → `...,early_map` / `perm_map` / `mm_init` (offset distinto; pueden coexistir con un AXPDIAG1). 3. **Solo** SysRq-c (sin `x`). 4. Recover combo4 → `AXPDIAG1,C,,0x...,sysrq-c` completo. 5. Solo entonces fortify-diag v4. ### Review resultados v4 Ver `docs/009-fortify-v4-capture-results-review-20260927.md`, `docs/009-fortify-v4-clean-tests-verification-20260927.md`, y artefactos: - `.local-artifacts/009-v4-clean-c-20260927T190738Z/` - `.local-artifacts/009-v4-x-persist-20260927T191143Z/` - `.local-artifacts/009-v4-twophase-x-then-c-20260927T191809Z/` (adb readback then panic: pre-verified X lost by P3) ### LAB 2026-09-27 (plain-v4 `20260927T084531Z`) — hechos vs hipótesis **Demostrado** - Writer de first-failure en vivo: SysRq-x → `AXPDIAG1,X,20260927T084531Z,0x...,sysrq-x` @0 (+ mirrors). - Milestone slot @2048 recibe `AXPDIAG0,M,...,panic_reg` (último stage; sobrescribe stages previos en el mismo offset). - Tras SysRq-c (arranque sin `x` previo) + recover combo4: **no** hay `AXPDIAG1` en ninguno de los 8 slots de fallo; @0 es opaco. **No demostrado / correcciones** - **No** hay, en el código revisado, una rutina de *cifrado del alt al entrar en panic*. Sí hay camino de descifrado del alt. «Desactivar encrypt en el kernel» no apunta aún a una función identificada; no usar eso como siguiente paso. - Que `panic_reg` aparezca @2048 tras combo4 **no** prueba zona segura ni supervivencia al panic: combo4 no escribe `AXPDIAG*`, pero un arranque intermedio de **v4** regenera el mismo `panic_reg` con el mismo attempt id. Hace falta attempt id distinto por boot, o wipe + leer sin otro boot v4, antes de atribuir persistencia. - El latch `axp_first_latch` es **solo RAM**: un wipe del dump no lo resetea. Si en el mismo arranque se hace SysRq-x y luego SysRq-c, `c` no escribe. Las pruebas `c`-only válidas requieren wipe **y reboot** (o imagen nueva) sin `x` previo en ese boot. - Causa de @0 opaco tras `c` (sobrescritura, fallo de escritura, otro productor): **abierta**.