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>
245 lines
11 KiB
Markdown
245 lines
11 KiB
Markdown
<!-- 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**.
|