Files
AXP-Resurection/docs/009-fortify-diag-capture-plan.md
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

245 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- Status: historical — Magisk 009 ship resume: docs/009-handoff-20261008.md -->
> **Status: historical.** Do not use as execution order. Resume: [`009-handoff-20261008.md`](009-handoff-20261008.md).
# 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,<attempt>,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**.