From deaaf42caaa2610d9e3ca7edc5fad0bee9017b2c Mon Sep 17 00:00:00 2001 From: sunfish-admin Date: Mon, 5 Oct 2026 10:42:00 +0200 Subject: [PATCH] 009: Magisk ship pack through US-S5-1 + US-S4 OpenSSH/Jelly/Gallery2. Release-keys/AVB, CVE clean+hi batches, Yama/slabrand, Pro branding, bundled apps, and AXP-class product surface docs/scripts. --- .gitignore | 4 + AGENTS.md | 22 + docs/002-golden-inventory.md | 22 +- docs/009-axp-graphene-remaining.md | 66 ++ docs/009-axp-pro-product-apps-20260324.md | 54 ++ docs/009-capability-matrix.md | 58 ++ docs/009-cve-bisect-plan.md | 171 +++++ docs/009-cve-high-offset-triage-20261001.txt | 83 +++ docs/009-fortify-boot-audit-20260926.md | 123 ++++ ...09-fortify-bounds-boot-failure-20260927.md | 87 +++ docs/009-fortify-clang-port.md | 98 +++ docs/009-fortify-diag-capture-plan.md | 240 +++++++ docs/009-fortify-diag-review-20260927.md | 119 ++++ docs/009-fortify-diag-v2-review-20260927.md | 60 ++ docs/009-fortify-diag-v3-review-20260927.md | 68 ++ .../009-fortify-driver-bounds-candidate.patch | 27 + docs/009-fortify-family-bisect-20260927.md | 127 ++++ docs/009-fortify-port-review-20260926.md | 89 +++ .../009-fortify-pos0-link-failure-20260927.md | 103 +++ ...tify-v4-capture-results-review-20260927.md | 99 +++ ...fy-v4-clean-tests-verification-20260927.md | 50 ++ docs/009-gate-g-kernel-attribution.md | 135 ++++ docs/009-hardening-signing-checklist.md | 248 ++++++++ ...009-internet-connectivity-axp-providers.md | 64 ++ docs/009-kernel-boot-audit-20260926.md | 229 +++++++ ...-kernel-boot-image-comparison-20260926.txt | 125 ++++ docs/009-kernel-hardening-map.md | 267 ++++++++ docs/009-lab-acceptance-20261002-avb.md | 22 + docs/009-lab-acceptance-20261002-uss4.md | 27 + docs/009-lab-acceptance-20261002-uss5.md | 27 + docs/009-localization-axp-vs-los.md | 22 + docs/009-magisk-preinstall-runbook.md | 111 ++++ docs/009-private-dns-axp-providers.md | 34 + docs/009-sideload-system-updates.md | 30 + docs/009-us-s4-userspace-hardening.md | 52 ++ docs/009-version-pins.md | 24 + docs/axp-pro-parity.md | 2 +- docs/hardening-backlog.md | 37 +- scripts/009-bacon-axp-combo4-fortify.sh | 152 +++++ .../009-bacon-axp-stage1-combo4-cve-bisect.sh | 142 +++++ .../009-bacon-axp-stage1-combo4-cve-clean.sh | 142 +++++ ...9-bacon-axp-stage1-combo4-cve-hi-batch1.sh | 155 +++++ ...9-bacon-axp-stage1-combo4-cve-hi-batch2.sh | 160 +++++ ...9-bacon-axp-stage1-combo4-cve-hi-batch3.sh | 162 +++++ ...on-axp-stage1-combo4-cve-hi-releasekeys.sh | 380 +++++++++++ scripts/009-bacon-axp-stage1-combo4-cve.sh | 164 +++++ scripts/009-bacon-axp-stage1-combo4.sh | 176 ++++++ scripts/009-bisect-ksync-one.sh | 113 ++++ scripts/009-bisect-ksync-pstore-alt-plain.sh | 13 + scripts/009-build-fortify-family-isolated.sh | 76 +++ scripts/009-chain-hi3-to-releasekeys.sh | 41 ++ scripts/009-fortify-select-family.py | 78 +++ scripts/009-generate-release-keys.sh | 101 +++ scripts/009-wait-flash-cve-clean.sh | 73 +++ scripts/009-wait-flash-cve-hi-batch1.sh | 77 +++ scripts/009-wait-flash-cve-hi-batch2.sh | 81 +++ scripts/009-wait-flash-cve-hi-batch3.sh | 76 +++ scripts/009-watch-then-cve-bacon.sh | 54 ++ .../contracts/flag-secure-surface.md | 2 +- specs/008-call-rec-flag-secure/research.md | 8 +- .../contracts/acceptance-gates.md | 30 +- specs/009-axp-los23-port/plan.md | 18 +- specs/009-axp-los23-port/quickstart.md | 23 +- specs/009-axp-los23-port/research.md | 139 +++- specs/009-axp-los23-port/spec.md | 232 +++++-- specs/009-axp-los23-port/tasks.md | 339 ++++++++++ vendor/sunfish-a16/.gitignore | 1 + vendor/sunfish-a16/Android.mk | 48 ++ vendor/sunfish-a16/BoardConfig.mk | 19 + vendor/sunfish-a16/apps.mk | 8 + vendor/sunfish-a16/branding.mk | 13 + vendor/sunfish-a16/extra-product.mk | 5 + vendor/sunfish-a16/hardening.mk | 29 + vendor/sunfish-a16/magisk.mk | 15 + vendor/sunfish-a16/magisk/README.md | 26 + .../magisk/apply_releasetools_hook.py | 149 +++++ vendor/sunfish-a16/magisk/patch.sh | 122 ++++ vendor/sunfish-a16/magisk/prepare_magisk.sh | 55 ++ .../008-call-rec-flag-secure/README.md | 18 +- .../apply_008_call_rec_flag_secure.py | 31 +- ...pply_wms_disable_secure_debuggable_gate.py | 81 +++ ...ConnectivityCheckPreferenceController.java | 222 +++++++ .../patches/009-axp-los23-port/README.md | 58 ++ .../apply_009_connectivity_check.py | 114 ++++ .../apply_009_disable_user_apps.py | 52 ++ .../apply_009_drop_jelly_gallery2.py | 161 +++++ .../apply_009_drop_openssh_packages.py | 99 +++ .../apply_009_private_dns_providers.py | 498 +++++++++++++++ .../apply_009_unofficial_build_id.py | 41 ++ .../009-axp-los23-port/hardening/README.md | 67 ++ .../009-axp-los23-port/signing/README.md | 89 +++ .../009-kernel-hardening/BUILD-FIXES.md | 22 + .../patches/009-kernel-hardening/README.md | 83 +++ .../apply_combo4_fortify.sh | 51 ++ .../009-kernel-hardening/apply_cve_strict.sh | 164 +++++ .../009-kernel-hardening/apply_stage1.sh | 49 ++ .../apply_stage1_combo4.sh | 47 ++ .../apply_stage1_combo4_cve.sh | 12 + .../apply_uss5_1_defconfig.sh | 31 + .../cve-bisect-49980-only.list | 1 + .../009-kernel-hardening/cve-bisect-h1.list | 215 +++++++ .../009-kernel-hardening/cve-bisect-h1a.list | 108 ++++ .../009-kernel-hardening/cve-bisect-h1a1.list | 54 ++ .../009-kernel-hardening/cve-bisect-h1a2.list | 54 ++ .../cve-bisect-h1a2a.list | 27 + .../cve-bisect-h1a2b.list | 27 + .../cve-bisect-h1a2b1.list | 14 + .../cve-bisect-h1a2b1a.list | 7 + .../cve-bisect-h1a2b1b-no49980.list | 6 + .../cve-bisect-h1a2b1b.list | 7 + .../cve-bisect-h1a2b2.list | 13 + .../009-kernel-hardening/cve-bisect-h1b.list | 107 ++++ .../009-kernel-hardening/cve-bisect-h2.list | 215 +++++++ .../cve-clean-offset.list | 429 +++++++++++++ .../009-kernel-hardening/cve-denylist.txt | 38 ++ .../cve-high-offset-batch1.list | 9 + .../cve-high-offset-batch2.list | 10 + .../cve-high-offset-batch3.list | 11 + .../cve-high-offset-ge200.txt | 73 +++ .../cve-high-offset-sunfish-candidate.list | 26 + .../cve-high-offset-sunfish-skip.list | 47 ++ .../009-kernel-hardening/cve-strict.list | 503 +++++++++++++++ .../0001-driver-bounds-rtac-fils.patch | 27 + .../fortify-clang/README.md | 36 ++ .../fortify-clang/apply_fortify_clang.py | 244 +++++++ .../fortify-clang/apply_fortify_diag.py | 597 ++++++++++++++++++ .../patches/009-kernel-hardening/stage1.list | 33 + .../009-kernel-hardening/uss5-1-README.md | 42 ++ vendor/sunfish-a16/signing.mk | 17 + 129 files changed, 11769 insertions(+), 141 deletions(-) create mode 100644 docs/009-axp-graphene-remaining.md create mode 100644 docs/009-axp-pro-product-apps-20260324.md create mode 100644 docs/009-capability-matrix.md create mode 100644 docs/009-cve-bisect-plan.md create mode 100644 docs/009-cve-high-offset-triage-20261001.txt create mode 100644 docs/009-fortify-boot-audit-20260926.md create mode 100644 docs/009-fortify-bounds-boot-failure-20260927.md create mode 100644 docs/009-fortify-clang-port.md create mode 100644 docs/009-fortify-diag-capture-plan.md create mode 100644 docs/009-fortify-diag-review-20260927.md create mode 100644 docs/009-fortify-diag-v2-review-20260927.md create mode 100644 docs/009-fortify-diag-v3-review-20260927.md create mode 100644 docs/009-fortify-driver-bounds-candidate.patch create mode 100644 docs/009-fortify-family-bisect-20260927.md create mode 100644 docs/009-fortify-port-review-20260926.md create mode 100644 docs/009-fortify-pos0-link-failure-20260927.md create mode 100644 docs/009-fortify-v4-capture-results-review-20260927.md create mode 100644 docs/009-fortify-v4-clean-tests-verification-20260927.md create mode 100644 docs/009-gate-g-kernel-attribution.md create mode 100644 docs/009-hardening-signing-checklist.md create mode 100644 docs/009-internet-connectivity-axp-providers.md create mode 100644 docs/009-kernel-boot-audit-20260926.md create mode 100644 docs/009-kernel-boot-image-comparison-20260926.txt create mode 100644 docs/009-kernel-hardening-map.md create mode 100644 docs/009-lab-acceptance-20261002-avb.md create mode 100644 docs/009-lab-acceptance-20261002-uss4.md create mode 100644 docs/009-lab-acceptance-20261002-uss5.md create mode 100644 docs/009-localization-axp-vs-los.md create mode 100644 docs/009-magisk-preinstall-runbook.md create mode 100644 docs/009-private-dns-axp-providers.md create mode 100644 docs/009-sideload-system-updates.md create mode 100644 docs/009-us-s4-userspace-hardening.md create mode 100644 docs/009-version-pins.md create mode 100755 scripts/009-bacon-axp-combo4-fortify.sh create mode 100644 scripts/009-bacon-axp-stage1-combo4-cve-bisect.sh create mode 100644 scripts/009-bacon-axp-stage1-combo4-cve-clean.sh create mode 100644 scripts/009-bacon-axp-stage1-combo4-cve-hi-batch1.sh create mode 100755 scripts/009-bacon-axp-stage1-combo4-cve-hi-batch2.sh create mode 100755 scripts/009-bacon-axp-stage1-combo4-cve-hi-batch3.sh create mode 100755 scripts/009-bacon-axp-stage1-combo4-cve-hi-releasekeys.sh create mode 100644 scripts/009-bacon-axp-stage1-combo4-cve.sh create mode 100755 scripts/009-bacon-axp-stage1-combo4.sh create mode 100755 scripts/009-bisect-ksync-one.sh create mode 100755 scripts/009-bisect-ksync-pstore-alt-plain.sh create mode 100644 scripts/009-build-fortify-family-isolated.sh create mode 100755 scripts/009-chain-hi3-to-releasekeys.sh create mode 100644 scripts/009-fortify-select-family.py create mode 100755 scripts/009-generate-release-keys.sh create mode 100755 scripts/009-wait-flash-cve-clean.sh create mode 100755 scripts/009-wait-flash-cve-hi-batch1.sh create mode 100755 scripts/009-wait-flash-cve-hi-batch2.sh create mode 100755 scripts/009-wait-flash-cve-hi-batch3.sh create mode 100644 scripts/009-watch-then-cve-bacon.sh create mode 100644 specs/009-axp-los23-port/tasks.md create mode 100644 vendor/sunfish-a16/.gitignore create mode 100644 vendor/sunfish-a16/apps.mk create mode 100644 vendor/sunfish-a16/branding.mk create mode 100644 vendor/sunfish-a16/extra-product.mk create mode 100644 vendor/sunfish-a16/hardening.mk create mode 100644 vendor/sunfish-a16/magisk.mk create mode 100644 vendor/sunfish-a16/magisk/README.md create mode 100755 vendor/sunfish-a16/magisk/apply_releasetools_hook.py create mode 100755 vendor/sunfish-a16/magisk/patch.sh create mode 100755 vendor/sunfish-a16/magisk/prepare_magisk.sh create mode 100644 vendor/sunfish-a16/patches/008-call-rec-flag-secure/apply_wms_disable_secure_debuggable_gate.py create mode 100644 vendor/sunfish-a16/patches/009-axp-los23-port/ConnectivityCheckPreferenceController.java create mode 100644 vendor/sunfish-a16/patches/009-axp-los23-port/README.md create mode 100644 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_connectivity_check.py create mode 100644 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_disable_user_apps.py create mode 100644 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_drop_jelly_gallery2.py create mode 100644 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_drop_openssh_packages.py create mode 100644 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_private_dns_providers.py create mode 100644 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_unofficial_build_id.py create mode 100644 vendor/sunfish-a16/patches/009-axp-los23-port/hardening/README.md create mode 100644 vendor/sunfish-a16/patches/009-axp-los23-port/signing/README.md create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/BUILD-FIXES.md create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/README.md create mode 100755 vendor/sunfish-a16/patches/009-kernel-hardening/apply_combo4_fortify.sh create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/apply_cve_strict.sh create mode 100755 vendor/sunfish-a16/patches/009-kernel-hardening/apply_stage1.sh create mode 100755 vendor/sunfish-a16/patches/009-kernel-hardening/apply_stage1_combo4.sh create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/apply_stage1_combo4_cve.sh create mode 100755 vendor/sunfish-a16/patches/009-kernel-hardening/apply_uss5_1_defconfig.sh create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-49980-only.list create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1.list create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a.list create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a1.list create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2.list create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2a.list create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2b.list create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2b1.list create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2b1a.list create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2b1b-no49980.list create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2b1b.list create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2b2.list create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1b.list create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h2.list create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/cve-clean-offset.list create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/cve-denylist.txt create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/cve-high-offset-batch1.list create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/cve-high-offset-batch2.list create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/cve-high-offset-batch3.list create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/cve-high-offset-ge200.txt create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/cve-high-offset-sunfish-candidate.list create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/cve-high-offset-sunfish-skip.list create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/cve-strict.list create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/fortify-clang/0001-driver-bounds-rtac-fils.patch create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/fortify-clang/README.md create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/fortify-clang/apply_fortify_clang.py create mode 100755 vendor/sunfish-a16/patches/009-kernel-hardening/fortify-clang/apply_fortify_diag.py create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/stage1.list create mode 100644 vendor/sunfish-a16/patches/009-kernel-hardening/uss5-1-README.md create mode 100644 vendor/sunfish-a16/signing.mk diff --git a/.gitignore b/.gitignore index 821b8cf..7da737f 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,7 @@ aosp-webview*.apk # 004 proprietary / large prebuilts (host-only) vendor/sunfish-a16/prebuilt/ *.apk + +# Local AXP OTA extracts (payload.bin ~1GB+) +AXP.OS-*/ +*.bin diff --git a/AGENTS.md b/AGENTS.md index abe5b93..9e70354 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -25,6 +25,28 @@ unless the owner explicitly asks. Magisk, microG, and related projects — prefer these over secondary blogs or guesses. KernelSU docs are reference-only here (optional recycle). +## Clone AXP first (mandatory) + +This track is an **AXP.OS → LOS23/A16** resurrection (~clone). Default method: + +1. Find how AXP / EXTENDROM / GOLDEN did it **before inventing a local policy**: + shipped PRO/GOLDEN zips (`payload.bin` → partition images), + `/srv/rom/references/axp/` + EXTENDROM on `rom-dev01`, GOLDEN `adb` + oracle, and real AXP product trees — **not** only Lineage-looking + `upstream_*` mirrors on disroot. +2. **Copy that method** into this tree (same flags, same packaging shape, same + virgin/activation UX where applicable). +3. Only invent or diverge when LOS 23.2, Android 16, or a newer dependency + **breaks** the AXP path — then document why and the minimal fix. + +Do **not** redesign Magisk, microG, Phonesky, DNS, connectivity, hardening +package sets, or other AXP-class features “our way” for convenience. +KernelSU/SusFS (`007`) stays **standby** — never mix into Magisk ship boots. + +Magisk specifically: EXTENDROM `EXTENDROM_PREROOT_BOOT` (boot patch, Magisk +**not** a `PRODUCT_PACKAGE`, dormant until Additional Setup). See +`docs/009-magisk-preinstall-runbook.md`. + ## Working rules - Do not invent unresolved technical decisions; investigate them in the relevant diff --git a/docs/002-golden-inventory.md b/docs/002-golden-inventory.md index 6283c2a..109d70f 100644 --- a/docs/002-golden-inventory.md +++ b/docs/002-golden-inventory.md @@ -66,8 +66,13 @@ Checked packages (package-level; process expand not fully visible in shots): Visible unchecked (partial): Aegis, Amarok, Amaze, Aosmium. -Owner notes: most DenyList banking apps still pass; **Yuh fails** for ~weeks. -Extra Magia DenyList/host checks + Island uninstall/reclone did **not** fix Yuh. +Owner notes (2026-09-13): most DenyList banking apps still pass; **Yuh failed** +for ~weeks. Extra Magia DenyList/host checks + Island uninstall/reclone did +**not** fix Yuh at that time. + +**Owner update 2026-10-02:** Yuh works again on GOLDEN after enabling Vector’s +**bootloader spoofer** module (`zygisk_vector` / Vector manager). DenyList alone +was never enough for that HA path. ## Compatibility / attestation (observational) @@ -75,14 +80,15 @@ Extra Magia DenyList/host checks + Island uninstall/reclone did **not** fix Yuh. |-------|--------|----------| | Swissquote | **PASS** (owner report) | Still used; on DenyList | | Other DenyList banks (N26, DKB, …) | **PASS** (owner: “casi todos”) | UI DenyList | -| Yuh | **FAIL** — hardware attestation / “certificate is invalid” | Owner UI + logcat ~21:51–21:52 | +| Yuh | **PASS again** (owner 2026-10-02) via Vector bootloader spoofer | Was **FAIL** 2026-09-13 (HA / “certificate is invalid”) | | Play Integrity token path | Client path still runs | `Finsky requestIntegrityToken() finished for com.yuh`; DroidGuard `pia_attest_e1` for `com.yuh` | -| KeyMint / TEE | Errors concurrent with Yuh attempt | `keystore2`: `HARDWARE_TYPE_UNAVAILABLE` (IRPC / `TRUSTED_ENVIRONMENT`); `addRngEntropy` → `DEAD_OBJECT` / KeyMint `-1000` | +| KeyMint / TEE | Errors concurrent with 2026-09-13 Yuh FAIL | `keystore2`: `HARDWARE_TYPE_UNAVAILABLE` (IRPC / `TRUSTED_ENVIRONMENT`); `addRngEntropy` → `DEAD_OBJECT` / KeyMint `-1000` | -Interpretation for later `006`/`007` (not a GOLDEN fix): DenyList alone is -insufficient for Yuh’s hardware-attestation path; KeyMint/TEE remote-provisioning -errors correlate with the failure window. Project production root path remains -**KernelSU-Next (+ SusFS) or ReSukiSU evaluation** — Magisk/Magia is oracle-only. +Interpretation for Gate E / LAB: GOLDEN banking stack = Magisk DenyList + +`playintegrityfix` + `teesim` + **Vector bootloader spoofer** (owner-proven for +Yuh). Ship ROM still does **not** bake those modules (`009-magisk-preinstall-runbook`); +owner installs post-flash. Wrong PIF prints (e.g. `comet` CANARY on sunfish LAB) +break the same surface. Magisk/Magia remains the AXP oracle path for `009`. Call recording: GOLDEN Secure dump shows native EXTENDROM `extendrom_call_recording=1` (see `008` — port `er.sh` F_CALLREC, not Magisk diff --git a/docs/009-axp-graphene-remaining.md b/docs/009-axp-graphene-remaining.md new file mode 100644 index 0000000..4e20c43 --- /dev/null +++ b/docs/009-axp-graphene-remaining.md @@ -0,0 +1,66 @@ +# 009 — Remaining path to AXP / Graphene-class ship (post clean-429) + +Non-normative roadmap after LAB **BOOT_OK** on Stage1+combo4+FORTIFY+Magisk+ +**CVE clean-offset 429** (denylist `CVE-2022-49980`), kernel `#47` +(`20261001T180955Z-axp-stage1-combo4-cve-clean`). Authoritative requirements +remain `specs/009-axp-los23-port/spec.md` + constitution. + +Goal (owner): **almost all** applicable AXP.OS / Graphene-class behaviour on +LOS 23.2 sunfish Magisk track — not a blind dump, not bootloader lock. + +## Already landed (kernel / Magisk core) + +| Layer | Status | +|-------|--------| +| Stage1 Graphene/AH | Ship | +| Combo4 + Clang FORTIFY | Ship | +| Magisk preroot EXTENDROM-class | Ship | +| CVE clean-offset 429 | Ship (LAB OK) | +| `CVE-2022-49980` | Denylist until lock-scope port | +| High-offset CVE (~73) | Quarantine — triage started | + +Recover/bisect baseline: `20260929T123401Z-axp-stage1-combo4` (`#32`). + +## Kernel remaining (toward “AXP CVE / Graphene depth”) + +1. **High-offset quarantine** — KEEP batches 1–3 **shipped** (`151944Z`). + nf_tables leftovers still skipped. Next kernel depth: **US-S5-1** defconfig + (Yama + `SLAB_FREELIST_RANDOM`), not more bulk CVE. +2. **`CVE-2022-49980` proper port** — keep UAF fix without recursive + `udc_lock` (mainline lock-scope series). Optional; denylist is safe. +3. Failed Stage1 probes (allocsize/ro/slab) — low priority vs high-offset. +4. Graphene modern techniques / `hardened_malloc` — backlog (`docs/hardening-backlog.md`); + evaluate after CVE depth is stable. + +## Userspace / product remaining (AXP surface) + +From `docs/009-capability-matrix.md` / Gate G (still open or partial): + +| Item | Notes | +|------|--------| +| Release keys + AVB (unlocked) | US-S2/S3 — leave test-keys | +| Private DNS / connectivity check | Patches exist; keep AXP-class, no axp.os endpoints | +| Call-rec / FLAG_SECURE | `008` — selectable unlock | +| Bundled apps (Aurora, Droidify, gallery, …) | Packaging | +| Disable-app UX on A16 | Restore classic Disable | +| Hosts / DNS privacy helpers | Magisk module vs ROM-native TBD | +| WebView | LOS default (Aosmium exception) | +| Banking / Island | Deferred | +| Bootloader lock | Wont | +| KernelSU swap | Optional later; do not mix Magisk ship boots | + +## Suggested execution order (default if owner has no preference) + +1. Finish high-offset **relevance filter** → small apply batches (≤10) with + strict applicator + LAB boot each batch. +2. Wire **release keys** bacon of current ship pack; keep Magisk/preroot OK. +3. Land remaining **Settings/UX** AXP clones (DNS, connectivity, disable-app) + if not already on LAB zip. +4. Optional: 49980 lock-scope port; Graphene userspace / hardened_malloc spikes. + +## Do-not + +- Reflash full-503 / old kh-cve zips. +- Bulk-apply high-offset without manual review. +- Mix KernelSU into Magisk ship boots. +- Treat “almost AXP/Graphene” as requiring locked bootloader. diff --git a/docs/009-axp-pro-product-apps-20260324.md b/docs/009-axp-pro-product-apps-20260324.md new file mode 100644 index 0000000..42f4737 --- /dev/null +++ b/docs/009-axp-pro-product-apps-20260324.md @@ -0,0 +1,54 @@ +# AXP.OS PRO sunfish product/app surface — 20260324 zip + +Oracle: `AXP.OS-22.2-20260324-PRO-sunfish.zip` (`payload.bin` → partitions). +Extracted 2026-10-02 (local `payload-dumper-go`). Authoritative for **debloat** +vs Lineage product defaults — not the disroot `upstream_*` lineage mirror. + +## `product/app` (present) + +Aperture, ApertureLensLauncher, Backgrounds, Camelot, DeskClock, +ExactCalculator, LatinIME, LocalContactsBackup, ModuleMetadata, PhotoTable, +Recorder, ThemesStub, Twelve, messaging, uimremoteclient, uimremoteserver + +## `product/app` (absent vs typical LOS product) + +| LOS / our prior ship | AXP PRO | +|----------------------|---------| +| Jelly | **absent** (browser stub on system_ext) | +| Gallery2 | **absent** (Fossify only) | +| Etar | **absent** (uses `Etar_ER` on system_ext) | +| AuroraStore / Droidify / Fossify | not on product — on **system_ext** | +| VZWAPNLib / PixelCameraServices* | absent here (device packs may differ) | + +## `product/priv-app` + +Contacts, Dialer, SettingsIntelligence + +## `product/bin` + +**No** `/bin` tree (no sshd/ssh/rsync). `etc/init/init.openssh.rc` **present**. + +## `system_ext/app` (bundled AXP extras) + +AuroraStore, Etar_ER, F-Droid, FossifyGallery_FD, GsfProxy_GH, +MicrogGmsCore_GH_presigned, Profiles, AccessibilityMenu, +QtiTelephonyService, SimpleSettingsConfig, +`noDefaultBrowserWebView`, `noeSpeakNG` + +## `system_ext/priv-app` (selected) + +AOSLauncher (NeoLauncher — **wont** for 009), AOSmium_webview64 +(**exception** — we ship LOS WebView), OpenEUICC_AXP-OS, Seedvault, +TrebuchetQuickStep, Updater, Lineage*, Settings, SystemUI, ims, … + +## 009 mapping + +| AXP | Our ship policy | +|-----|-----------------| +| AuroraStore | product `AuroraStore` (already) | +| F-Droid | **Droidify** substitute (owner) | +| FossifyGallery_FD | product `FossifyGallery` + override Gallery2 | +| noDefaultBrowserWebView | **US-S4-2**: drop Jelly | +| Gallery2 absent | **US-S4-2**: ensure Gallery2 gone (override alone left dir) | +| NeoLauncher / Aosmium | wont / exception — keep Launcher3 + LOS WebView | +| OpenSSH bins | US-S4-1 done | diff --git a/docs/009-capability-matrix.md b/docs/009-capability-matrix.md new file mode 100644 index 0000000..30593b6 --- /dev/null +++ b/docs/009-capability-matrix.md @@ -0,0 +1,58 @@ +# 009 AXP capability matrix (resurrection track) + +Maps GOLDEN/`002` + `docs/axp-pro-parity.md` → ship status for **Magisk AXP +clone on LOS23**. Authoritative requirements remain `specs/009-axp-los23-port/spec.md`. + +Status: `required` | `exception` | `deferred` | `impossible` + +| category | golden_ref | status | notes | +|----------|------------|--------|-------| +| Base LOS 23.2 sunfish | `003` | required | Vanilla baseline before AXP integrate | +| microG + GSF | `002` / `004` | required | Newest stable | +| Phonesky (project patched) | `002` / `004` | required | Host artifact; FakeStore forbidden | +| Selectable signature spoofing | `005` / GOLDEN `allow_signature_fake` | required | Restricted; DO toggle | +| Selectable call-recording unlock | `008` / GOLDEN `extendrom_call_recording` | required | EXTENDROM key | +| Magisk preroot + DenyList-class | GOLDEN Magisk 29.0 / Magia | required | Newest Magisk; EXTENDROM-class boot patch | +| Bundled usability apps (Aurora, Droidify, gallery, …) | `002` / parity | required | Newest workable; **Droidify** (light + many default repos); **no NeoLauncher** | +| Private DNS presets (AXP-class provider list) | AXP Settings | required | Clone AXP private-DNS entries; no AXP OTA/repos | +| Internet connectivity / INTERNET special permission UX | AXP/Graphene-class | required | Keep behaviour; **do not** integrate `axp.os` endpoints/branding | +| Disable app (classic) vs Archive | AOSP/LOS A16 Archive | required | Restore usable **Disable** on A16; Archive alone disliked by owner | +| DNS/hosts privacy helpers | parity / GOLDEN modules `hosts` | required | If in AXP surface; Magisk module vs ROM-native TBD | +| Userspace hardening / AVB (unlocked) | parity `011`–`012` pulled into `009` | required | Staged; gaps documented; no bootloader lock | +| Release / definitive signing keys | GOLDEN / plan `/srv/rom/secrets` | required | Ship off test-keys; Phonesky same identity | +| Bootloader lock / relock | IOdes-class | wont | AXP/LOS unlocked norm; Magisk preroot assumes unlocked | +| Kernel update + hardening | parity / FR-017 | required | LOS23 sunfish kernel + attributable patches | +| WebView | GOLDEN Aosmium | exception | LOS23 WebView default; chooser unlocked; no Aosmium | +| Banking / Island / Swissquote / Yuh | `002` Gate E | deferred | Owner future (2026-09-17); not MVP | +| Localization / location hardening AXP vs LOS | owner complaint | deferred | FR-018 — **do not extra-cap** vs LOS for ship (2026-09-18); no MVP toggle; compare doc later only | +| NeoLauncher | AXP default | wont | Owner: do not integrate; LOS Launcher3 | +| F-Droid client (`org.fdroid.fdroid`) | GOLDEN | substitute | Prefer **Droidify** | +| AXP external market repos / AXP OTA servers | AXP EOL infra | wont | Servers down / EOL — do not wire | +| Sideloadable system package refresh (microG, Magisk, Phonesky, …) | owner cadence ~2–3 mo | required | FR-019 — same-signer / PRESIGNED / Magisk update path; no OTA | +| KernelSU / SusFS | `007` | deferred | Out of ship; optional recycle FR-016 | +| AXP backup ROM feature | parity | impossible / wont | External NeoBackup only | +| FLAG_SECURE global override | project `008` | deferred | Nice-to-have; not AXP hard gate | + +## Bundled packages observed on GOLDEN (2026-09-17 `pm list packages -s`) + +| package | role | matrix | +|---------|------|--------| +| `com.aurora.store` | Aurora | required (pin newest) | +| `com.looker.droidify` | Droidify (F-Droid client) | required — preferred over `org.fdroid.fdroid` | +| `org.fdroid.fdroid` | F-Droid | substitute / skip unless packaging forces it | +| `org.fossify.gallery` | Fossify Gallery | required | +| `com.stevesoltys.seedvault` | Seedvault | often los-provides | +| `com.android.launcher3` | Launcher | los-provides — **no NeoLauncher** | +| `org.axpos.aosmium` / `_wv` | Aosmium | exception — do not ship; LOS WebView | +| `com.google.android.gsf` | GSF | required | +| `com.android.vending` | Phonesky | required (project artifact) | + +User-installed (not system): Island, banks, Magisk manager (hidden pkg), etc. + +## Build oracle note + +Prefer AXP **build tree + docs** on `rom-dev01` (see axpos.org developer +building / EXTENDROM preroot) to learn Magisk/product packaging. GOLDEN `adb` +is for runtime behaviour, not the first compile reference. Host currently has +rendered docs under `/srv/rom/references/axp/archive/…`; full AXP `build` +checkout still to stage. diff --git a/docs/009-cve-bisect-plan.md b/docs/009-cve-bisect-plan.md new file mode 100644 index 0000000..2adec63 --- /dev/null +++ b/docs/009-cve-bisect-plan.md @@ -0,0 +1,171 @@ +# 009 CVE bisect plan (after full CVE Google-logo hang) + +**Baseline GOOD:** Stage1 + combo4 + Clang FORTIFY +Artifact: `20260929T123401Z-axp-stage1-combo4` (LAB recovered 2026-09-29 via +`fastboot flash boot` of that pack’s Magisk `boot.img`). + +**BAD:** Stage1+combo4+FORTIFY + full `cve-strict.list` (503) +Artifact: `20260929T181525Z-axp-stage1-combo4-cve` — compiles, wlan CRC OK, +**hangs at Google logo**. **Do not** re-flash the full 503 set. + +## Audit before more flashes (2026-09-29 evening) + +Owner review correctly flagged the applicator and asked for reject/partial +review **before** bisect flashes. + +| Check | Result | +|-------|--------| +| Patch `FAIL` count on BAD build | **0** (`OK=503`) — no `.rej` from that run | +| Continue-on-fail + delete `.rej` | **Procedural defect** (fixed in `apply_cve_strict.sh`) — would hide incomplete applies on future drift | +| GNU patch “Succeeded with fuzz≥2” | **0** | +| Hunks with **\|offset\| ≥ 200 lines** | **168** of 503 — strong mis-apply risk even when `patch` exits 0 | +| \|offset\| ≥ 200 list | `cve-high-offset-ge200.txt` (**73 unique** paths in report extract; full 168 in host fuzz report) | +| Host report | `/srv/rom/artifacts/009-axp-los23-port/cve-stage/apply-cve-strict-20260929T173037Z-fuzz-report.txt` | + +Logo hang alone does **not** identify a CVE id; “Additional Setup” is unrelated. +USB loss after sideload does **not** mean the zip was not installed. + +### Applicator fix (`apply_cve_strict.sh`) + +- Default: **abort** on first FAIL (no partial tree). +- Keep `*.rej` / `*.orig` under `CVE_REJECT_DIR` (no silent delete). +- **QUALITY_FAIL** if fuzz ≥ `CVE_MAX_FUZZ` (default 1) or + \|offset\| ≥ `CVE_MAX_ABS_OFFSET` (default **200**). +- Forensic only: `CVE_STRICT_CONTINUE=1`. + +H1 bacon (`009-bacon-cve-h1`) **stopped** — do not flash that half until a +strict re-apply (offsets gated) produces a clean tree. + +## Next method (revised) + +1. Build allowlist = `cve-strict.list` **minus** high-offset (≥200) suspects + (and existing denylist). +2. Re-apply with new applicator (must finish with QUALITY_FAIL=0 / abort). +3. Bacon that “clean-offset” set → LAB boot test (**fastboot flash boot** only; + recover with Stage1 boot if needed). +4. If still BAD → classic binary bisect on the **clean** list only. +5. Separately, quarantine high-offset patches for manual review / port + (do not bulk-apply with huge offsets). + +## Flash rules (LAB) + +1. sunfish recovery is in `boot` — bad kernel ⇒ Recovery looks like logo loop. +2. Unbrick: `fastboot -s 11231JEC207477 flash boot ` → reboot. + **Always** pin LAB serial. Never flash “any” fastboot device (GOLDEN risk). +3. No reboot-loop automation. No unscoped recover watchers. +4. One reboot after a deliberate flash. + +## Diagnostic limits (owner review 2026-09-30) + +- A BAD half **reproduces** the hang; it does **not** prove a single CVE is the + root cause (interactions / order / mis-apply semantics still possible). +- Applicator had **0 FAIL** on the original full set; abort/offset gates were + still required, but they did **not** clear this logo hang. +- Bisect flashes are **`boot.img` only** on `boot_a` (serial-pinned). No slot / + download / flash miss seen on H1a2: hang tracks what H1a2 changes vs Stage1 + base. **No** demonstrated need to re-sideload full zip or wipe data for this + bisect. +- “CRC wlan OK” so far = host-side `kmalloc_caches` only (kernel + `Module.symvers` vs pack `wlan.ko`). Does **not** check all symbols nor the + on-device installed module (adb pull denied without root). Narrows one + suspicion; does **not** rule out module ABI skew. +- Next interpretation: if H1a2a boots, still test H1a2b. If **both** boot alone + but H1a2 fails → interaction/dependency, not a single-patch proof. +- **Applicability (owner 2026-10-01):** AXP A15 success ≠ correct port to + LOS23/A16 sunfish. Per [kernel CVE process](https://cdn.kernel.org/doc/html/latest/process/cve.html), + each CVE must be judged for *this* tree/config/modules — not bulk-trusted. + H1a2b includes useful fixes (USB gadget UAF, QC audio DSP bounds, F2FS + state, QRTR) but also arch/drivers off in our defconfig (x86/AMD, s390, + CAN/ATA/SAS/kprobes/brcmfmac, …). These are mostly **bugfixes**, not + transversal hardening like FORTIFY/allocator. Concrete hypothesis (unproven): + `CVE-2022-49980` (`udc_lock` on gadget events) — check whether this tree + already holds that lock on the same paths (possible deadlock). Also re-audit + F2FS patches vs exact sunfish F2FS version/deps. **In H1a2b1b list** + (not H1a2b1a). + +### Code review: CVE-2022-49980 vs msm-4.14 (2026-10-01) + +Patch only wraps `udc->driver` read in `usb_udc_uevent()` with +`mutex_lock(&udc_lock)`. On **our** `msm-4.14` `udc/core.c` (base +`28f9290ae067`, pre-CVE apply), `kobject_uevent()` is still invoked **while +holding `udc_lock`**: + +- `usb_gadget_remove_driver()` → `KOBJ_CHANGE` (called from + `usb_del_gadget_udc` / `usb_gadget_unregister_driver` under lock) +- `udc_bind_to_driver()` → `KOBJ_CHANGE` (called from + `usb_gadget_probe_driver` under lock) + +`dev_uevent` / `class->dev_uevent` run **synchronously** inside +`kobject_uevent`. `udc_lock` is a non-recursive `mutex`. Applying 49980 alone +⇒ same thread: lock → uevent → `usb_udc_uevent` → lock again ⇒ **deadlock**. + +This matches community reports that backporting CVE-2022-49980 to older trees +(e.g. 5.10.y) introduces deadlock; mainline later needed **lock-scope** +changes (unbind/bind outside `udc_lock`), not the one-liner alone. + +sunfish_defconfig: `CONFIG_USB_GADGET=y`, rich `CONFIG_USB_CONFIGFS_*` (ADB / +MTP / etc.) — gadget bind/unbind at boot is plausible. Still **hypothesis** +until H1a2b1b (or a 49980-only build) is LAB-tested; do **not** ship 49980 +without the companion lock-order fix (or omit it from the allowlist). + +**2026-10-01 evening:** 49980-only LAB = BAD (logo). Deadlock paths on this +tree include both (a) `device_add` / uevent under `udc_lock` at UDC register +and (b) `kobject_uevent` from remove/bind while lock held. Serial console / +pstore stack not captured yet — would confirm hang site; denylist stands. + +## GPS + +FR-018: no location lockdown. + +## Status + +- [x] Full CVE = BAD (logo); documented do-not-reflash +- [x] Audit apply log (0 FAIL, many huge offsets) +- [x] Fix applicator abort + keep rejects + offset/fuzz gate +- [x] Stop premature H1 bacon (full-503 halves archived `*.full503.bak`) +- [x] Clean-offset allowlist bacon + LAB boot + Artifact `20260929T203844Z-axp-stage1-combo4-cve-clean` (430 patches, + QUALITY_FAIL=0) — **BAD** 2026-09-29T20:42Z: `fastboot flash boot` + OK on `boot_a`, then Google-logo hang / USB dark (~4+ min). Recover = + Stage1 `20260929T123401Z-axp-stage1-combo4` boot only. +- [x] Clean H1 (215) bacon + LAB boot — artifact + `20260929T213532Z-axp-stage1-combo4-cve-h1` — **BAD** 2026-09-30 + (logo). H1 **reproduces**; H2 untested; not a single-CVE ID yet. +- [x] H1a (108) — `20260930T075006Z-…-cve-h1a` **BAD** (logo). H1a + **reproduces**; interaction possible; module coherence not yet checked + for CVE boots. +- [x] H1a1 (54) — `20260930T084048Z-…-cve-h1a1` **BOOT_OK** 2026-09-30T19:21Z + (kernel `#38`, slot `_a`). Build-tree `wlan`/`kmalloc_caches` CRC + `0xe7ccd971` matches Stage1 Gate G (device pull of `wlan.ko` denied + without root; intra-pack CRC OK). H1a1 set alone does **not** reproduce + the hang. +- [x] H1a2 (54) — `20260930T200752Z-…-cve-h1a2` **BAD** (owner: Google logo + after flash; reproduces). H1a1 GOOD + H1a2 BAD ⇒ hang associated with + H1a2 set (still not a single id; module CRC intra-pack was Stage1-class + on prior boots). +- [x] H1a2a (27) — `20260930T213106Z-…-cve-h1a2a` **BOOT_OK** 2026-09-30T21:36Z + (kernel `#40`). Host `kmalloc_caches` match. Alone does **not** reproduce. +- [x] H1a2b (27) — `20260930T222148Z-…-cve-h1a2b` **BAD** (logo alone). + H1a2a GOOD + H1a2b BAD ⇒ hang associated with H1a2b set (not proven + single patch). Note: owner phrasing “combi” = this half failed on LAB; + interaction check already satisfied by testing halves separately. +- [x] H1a2b1 (14) — `20260930T231324Z-…-cve-h1a2b1` **BAD** (logo). Includes + `CVE-2022-49980` (udc_lock hypothesis). Set of 14 reproduces. +- [x] H1a2b1a (7) — `20261001T001808Z-…-cve-h1a2b1a` **BOOT_OK** 2026-10-01 + (kernel `#43`). No `CVE-2022-49980` in this half. +- [x] H1a2b1b (7, includes `CVE-2022-49980`) — + `20261001T010705Z-…-cve-h1a2b1b` **BAD** 2026-10-01 (logo). H1a2b1a + GOOD + H1a2b1b BAD ⇒ hang associated with this 7-set (49980 still + unproven alone). +- [x] **49980-only** — `20261001T160836Z-…-cve-49980-only` **BAD** 2026-10-01 + (logo). Single-patch reproduce on LAB. Added to `cve-denylist.txt`. + Do not re-apply without lock-scope companion fix. +- [x] H1a2b1b **without** 49980 (6) — + `20261001T170442Z-…-cve-h1a2b1b-no49980` **BOOT_OK** 2026-10-01 + (kernel `#46`, LAB `11231JEC207477`). Confirms 49980 was the **sole** + hang trigger in the H1a2b→…→H1a2b1b BAD lineage (other six alone OK). +- [x] Clean-offset **minus 49980** (429) — + `20261001T180955Z-axp-stage1-combo4-cve-clean` **BOOT_OK** 2026-10-01 + (kernel `#47`). List md5 `e05056f6…`; apply OK=429. Prior BAD 430 pack + `20260929T203844Z-…` kept. **49980 was the only logo hang** found in the + clean-offset set so far. 15m poll loop stopped after flash. diff --git a/docs/009-cve-high-offset-triage-20261001.txt b/docs/009-cve-high-offset-triage-20261001.txt new file mode 100644 index 0000000..3fdc61c --- /dev/null +++ b/docs/009-cve-high-offset-triage-20261001.txt @@ -0,0 +1,83 @@ +# high-offset triage 2026-10-01T18:18:58+00:00 +# list=/srv/rom/src/lineage/vendor/sunfish-a16/patches/009-kernel-hardening/cve-high-offset-ge200.txt count=73 +mmfs, CVE-2020-29372/^5.7/0001.patch mm: check that mm is still valid in madvise() mm/madvise.c, +other, CVE-2021-47209/^5.15/0001.patch sched/fair: Prevent dead task groups from regaining cfs_rq's kernel/sched/autogroup.c,kernel/sched/core.c,kernel/sched/fair.c,kernel/sched/rt.c,kernel/sched/sched.h, +net, CVE-2021-47299/^5.13/0001.patch xdp, net: Fix use-after-free in bpf_xdp_link_release net/core/dev.c, +offarch, CVE-2022-48825/^5.17/0001.patch scsi: qedf: Add stag_work to all the vports drivers/scsi/qedf/qedf_main.c, +net, CVE-2022-48969/^6.1/0001.patch xen-netfront: Fix NULL sring after live migration drivers/net/xen-netfront.c, +net, CVE-2022-49086/ANY/0001.patch net: openvswitch: fix leak of nested actions net/openvswitch/flow_netlink.c, +net, CVE-2022-49341/ANY/0001.patch bpf, arm64: Clear prog->jited_len along prog->jited arch/arm64/net/bpf_jit_comp.c, +mmfs, CVE-2022-49412/ANY/0001.patch bfq: Avoid merging queues with different parents block/bfq-iosched.c, +other, CVE-2022-49641/ANY/0001.patch sysctl: Fix data races in proc_douintvec(). kernel/sysctl.c, +net, CVE-2022-49687/ANY/0001.patch virtio_net: fix xdp_rxq_info bug after suspend/resume drivers/net/virtio_net.c, +net, CVE-2022-49695/ANY/0001.patch igb: fix a use-after-free issue in igb_clean_tx_ring drivers/net/ethernet/intel/igb/igb_main.c, +other, CVE-2022-49715/ANY/0001.patch irqchip/gic-v3: Fix refcount leak in gic_populate_ppi_partitions drivers/irqchip/irq-gic-v3.c, +usb, CVE-2022-50246/ANY/0001.patch usb: typec: tcpci: fix of node refcount leak in tcpci_register_port() drivers/usb/typec/tcpm/tcpci.c, +other, CVE-2022-50304/ANY/0001.patch mtd: core: fix possible resource leak in init_mtd() drivers/mtd/mtdcore.c, +net, CVE-2023-3777/^6.5/0001.patch netfilter: nf_tables: skip bound chain on rule flush net/netfilter/nf_tables_api.c, +other, CVE-2023-52486/^6.7/0001.patch drm: Don't unref the same fb many times by mistake due to deadlock drivers/gpu/drm/drm_plane.c, +other, CVE-2023-52676/^6.7/0001.patch bpf: Guard stack limits against 32bit overflow kernel/bpf/verifier.c, +other, CVE-2023-52707/^6.2/0001.patch sched/psi: Fix use-after-free in ep_remove_wait_queue() kernel/sched/psi.c, +other, CVE-2023-52847/^6.6/0001.patch media: bttv: fix use after free error due to btv->timeout timer drivers/media/pci/bt8xx/bttv-driver.c, +other, CVE-2023-53594/ANY/0001.patch driver core: fix resource leak in device_add() drivers/base/core.c, +net, CVE-2023-53669/ANY/0001.patch tcp: fix skb_copy_ubufs() vs BIG TCP net/core/skbuff.c, +other, CVE-2023-53709/ANY/0001.patch ring-buffer: Handle race between rb_move_tail and rb_check_pages kernel/trace/ring_buffer.c, +offarch, CVE-2024-2201/^6.9/0001.patch x86/bugs: Change commas to semicolons in 'spectre_v2' sysfs file arch/x86/kernel/cpu/bugs.c, +offarch, CVE-2024-24855/^6.4/0001.patch scsi: lpfc: Fix a possible data race in lpfc_unregister_fcf_rescan() drivers/scsi/lpfc/lpfc_hbadisc.c, +net, CVE-2024-26643/^6.8/0001.patch netfilter: nf_tables: mark set as dead when unbinding anonymous set net/netfilter/nf_tables_api.c, +other, CVE-2024-26900/^6.8/0001.patch md: fix kmemleak of rdev->serial drivers/md/md.c, +net, CVE-2024-39296/^6.9/0001.patch bonding: fix oops during rmmod drivers/net/bonding/bond_main.c, +mmfs, CVE-2024-40917/^6.10/0001.patch memblock: make memblock_set_node() also warn about use of mm/memblock.c, +net, CVE-2024-40923/^6.10/0001.patch vmxnet3: disable rx data ring on dma allocation failure drivers/net/vmxnet3/vmxnet3_drv.c, +net, CVE-2024-40954/^6.10/0001.patch net: do not leave a dangling sk pointer, when socket creation fails net/core/sock.c, +mmfs, CVE-2024-41014/^6.10/0001.patch xfs: add bounds checking to xlog_recover_process_data fs/xfs/xfs_log_recover.c, +net, CVE-2024-43879/^6.10/0001.patch wifi: cfg80211: handle 2x996 RU allocation in net/wireless/util.c, +net, CVE-2024-46754/^6.10/0001.patch bpf: Remove tst_run from lwt_seg6local_prog_ops. net/core/filter.c, +offarch, CVE-2024-46830/^6.11/0001.patch KVM: x86: Acquire kvm->srcu when handling KVM_SET_VCPU_EVENTS arch/x86/kvm/x86.c, +net, CVE-2024-50186/^6.12/0001.patch net: explicitly clear the sk pointer, when pf->create fails net/socket.c, +mmfs, CVE-2024-50273/^6.11/0001.patch btrfs: reinitialize delayed ref list after deleting it from the list fs/btrfs/delayed-ref.c, +mmfs, CVE-2024-53066/^6.12/0001.patch nfs: Fix KMSAN warning in decode_getfattr_attrs() fs/nfs/inode.c, +mmfs, CVE-2024-53173/ANY/0002.patch NFSv4.0: Fix a use-after-free problem in the asynchronous open() fs/nfs/nfs4proc.c, +mmfs, CVE-2024-53217/ANY/0002.patch NFSD: Prevent NULL dereference in nfsd4_process_cb_update() fs/nfsd/nfs4callback.c, +net, CVE-2024-53240/ANY/0001.patch xen/netfront: fix crash when removing device drivers/net/xen-netfront.c, +mmfs, CVE-2024-56558/ANY/0001.patch nfsd: make sure exp active before svc_export_show fs/nfsd/export.c, +other, CVE-2024-56569/ANY/0001.patch ftrace: Fix regression with module command in stack_trace_filter kernel/trace/ftrace.c, +mmfs, CVE-2024-56596/ANY/0002.patch jfs: fix array-index-out-of-bounds in jfs_readdir fs/jfs/jfs_dtree.c, +mmfs, CVE-2024-56598/ANY/0002.patch jfs: array-index-out-of-bounds fix in dtReadFirst fs/jfs/jfs_dtree.c, +net, CVE-2024-56605/ANY/0002.patch Bluetooth: L2CAP: do not leave dangling sk pointer on error in net/bluetooth/l2cap_sock.c, +mmfs, CVE-2024-56779/ANY/0002.patch nfsd: fix nfs4_openowner leak when concurrent nfsd4_open occur fs/nfsd/nfs4state.c, +offarch, CVE-2024-57849/ANY/0002.patch s390/cpum_sf: Handle CPU hotplug remove during sampling arch/s390/kernel/perf_cpum_sf.c, +net, CVE-2024-58009/ANY/0001.patch Bluetooth: L2CAP: handle NULL sock pointer in l2cap_sock_alloc net/bluetooth/l2cap_sock.c, +other, CVE-2024-58083/ANY/0001.patch KVM: Explicitly verify target vCPU is online in kvm_get_vcpu() include/linux/kvm_host.h, +mmfs, CVE-2025-21671/ANY/0001.patch zram: fix potential UAF of zram table drivers/block/zram/zram_drv.c, +net, CVE-2025-21909/ANY/0001.patch wifi: nl80211: reject cooked mode if it is set along with other flags net/wireless/nl80211.c, +net, CVE-2025-37789/ANY/0001.patch net: openvswitch: fix nested key length validation in the set() net/openvswitch/flow_netlink.c, +net, CVE-2025-37795/ANY/0001.patch wifi: mac80211: Update skb's control block key in net/mac80211/tx.c, +mmfs, CVE-2025-37839/ANY/0001.patch jbd2: remove wrong sb->s_sequence check fs/jbd2/journal.c, +other, CVE-2025-37923/ANY/0001.patch tracing: Fix oob write in trace_seq_to_buffer() kernel/trace/trace.c, +net, CVE-2025-37932/ANY/0001.patch sch_htb: make htb_qlen_notify() idempotent net/sched/sch_htb.c, +other, CVE-2025-38034/ANY/0001.patch btrfs: correct the order of prelim_ref arguments in btrfs__prelim_ref include/trace/events/btrfs.h, +other, CVE-2025-38044/ANY/0001.patch media: cx231xx: set device_caps for 417 drivers/media/usb/cx231xx/cx231xx-417.c, +net, CVE-2025-38200/ANY/0001.patch i40e: fix MMIO write access to an invalid page in i40e_clear_hw drivers/net/ethernet/intel/i40e/i40e_common.c, +mmfs, CVE-2025-38204/ANY/0001.patch jfs: fix array-index-out-of-bounds read in add_missing_indices fs/jfs/jfs_dtree.c, +mmfs, CVE-2025-38218/ANY/0001.patch f2fs: fix to do sanity check on sit_bitmap_size fs/f2fs/super.c, +other, CVE-2025-38285/ANY/0001.patch bpf: Fix WARN() in get_bpf_raw_tp_regs kernel/trace/bpf_trace.c, +net, CVE-2025-38473/ANY/0001.patch Bluetooth: Fix null-ptr-deref in l2cap_sock_resume_cb() net/bluetooth/l2cap_sock.c, +other, CVE-2025-38495/ANY/0001.patch HID: core: ensure the allocated report buffer can contain the drivers/hid/hid-core.c, +mmfs, CVE-2025-38498/ANY/0002.patch do_change_type(): refuse to operate on unmounted/not ours mounts fs/namespace.c, +other, CVE-2025-39742/ANY/0001.patch RDMA: hfi1: fix possible divide-by-zero in find_hw_thread_mask() drivers/infiniband/hw/hfi1/affinity.c, +audio, CVE-2025-39751/ANY/0001.patch ALSA: hda/ca0132: Fix buffer overflow in add_tuning_control sound/pci/hda/patch_ca0132.c, +other, CVE-2025-39824/ANY/0001.patch HID: asus: fix UAF via HID_CLAIMED_INPUT validation drivers/hid/hid-asus.c, +net, CVE-2025-39847/ANY/0001.patch ppp: fix memory leak in pad_compress_skb drivers/net/ppp/ppp_generic.c, +net, CVE-2025-39874/ANY/0001.patch macsec: sync features on RTM_NEWLINK drivers/net/macsec.c, +other, CVE-2025-39998/ANY/0001.patch scsi: target: target_core_configfs: Add length check to avoid buffer drivers/target/target_core_configfs.c, +net, CVE-2025-40078/ANY/0001.patch bpf: Explicitly check accesses to bpf_sock_addr net/core/filter.c, +mmfs, CVE-2025-40080/ANY/0001.patch nbd: restrict sockets to TCP and UDP drivers/block/nbd.c, +--- counts --- + 27 net, + 21 other, + 18 mmfs, + 5 offarch, + 1 usb, + 1 audio, + 1 --- counts --- diff --git a/docs/009-fortify-boot-audit-20260926.md b/docs/009-fortify-boot-audit-20260926.md new file mode 100644 index 0000000..12ca4f9 --- /dev/null +++ b/docs/009-fortify-boot-audit-20260926.md @@ -0,0 +1,123 @@ +# FORTIFY: auditoría del build 20260926T183144Z + +Revisión de solo lectura en rom-dev01. Sin compilaciones ni flasheos nuevos. +El dueño confirma arranque de ksync-slab y fallo del último FORTIFY. + +## Artefactos y empaquetado + +Raíz remota: `/srv/rom/artifacts/009-axp-los23-port/`. + +- Referencia: `20260926T171215Z-bisect-ksync-slab-only`. +- Fallido: `20260926T183144Z-bisect-ksync-fortify-only/boot-make.img`. +- SHA-256 registrado del fallido: + `89734e6a34f99bfdc2d334e06e1ff49da46dac311139b7dc54f25ae7af0f0641`. +- Ambos ramdisks desempaquetados tienen SHA-256 + `c9ebabdcec875c896530214c5f2988e30a6bc37754855e4cba4863692d7db519`. +- Ambos DTB tienen SHA-256 + `2fca15709ff6d9f48fea938952439e8d00c2b998c73e7a216172ae3965b07566`. +- El header del FORTIFY conserva Android 16 y parche `2026-09`. +- El script usa breakfast y exige TARGET_RELEASE=bp4a. + +El problema anterior de cambiar la release/ramdisk no aparece en esta comparación. +La config embebida del fallido tiene FORTIFY=y, SLAB_FREELIST_HARDENED=n; +la referencia slab tiene las dos opciones al revés. Ambos conservan LTO y CFI. + +## Hallazgo principal: la exclusión de Clang es ineficaz + +En `/srv/rom/src/lineage/kernel/google/msm-4.14/security/Kconfig:190-195`: + +```text +config FORTIFY_SOURCE + bool "Harden common str/mem functions against buffer overflows" + depends on ARCH_HAS_FORTIFY_SOURCE + # https://bugs.llvm.org/show_bug.cgi?id=50322 + # https://bugs.llvm.org/show_bug.cgi?id=41459 + depends on !CC_IS_CLANG +``` + +`git grep` no encuentra una definición de `CC_IS_CLANG` en ese árbol. +La config generada tampoco contiene CONFIG_CC_IS_CLANG. La restricción usa +un símbolo no definido y por ello no detecta el compilador real. + +`obj/KERNEL_OBJ/include/generated/compile.h` identifica **Clang 21.0.0, +r563880c, LLD 21**, no GCC. El commit que introdujo la restricción es +`eb4c4383950d`, «fortify: Explicitly disable Clang support». + +Esto demuestra un defecto de integración/configuración. No demuestra por sí +solo la instrucción concreta que provoca el fallo de arranque. Un Clang más +nuevo no sustituye automáticamente las adaptaciones del código FORTIFY. + +Referencia primaria de las adaptaciones upstream: Kees Cook, +[fortify: Add Clang support, v7 8/8](https://lists.openwall.net/linux-kernel/2022/02/08/1547). +La serie adapta wrappers y atributos de tamaño de objeto; no consiste en +añadir cuerpos BUG a símbolos sin resolver. El parche AXP +`0008-Graphene-Kernel_Hardening-fortify/4.14/0004.patch`, inspeccionado, añade +comprobaciones intra-object; no aporta por sí solo ese soporte Clang. + +## Segundo defecto: el error de enlace se convirtió en código ejecutable + +Primer intento, log remoto +`/srv/rom/artifacts/detach-009-bisect-ksync-fortify-20260926T172516Z.log`: + +```text +ERROR: "__read_overflow2" [techpack/audio/dsp/q6_dlkm.lto.ko] undefined! +ERROR: "__read_overflow" [drivers/staging/qcacld-3.0/wlan.lto.ko] undefined! +``` + +El script `scripts/009-bisect-ksync-one.sh` añade después a `lib/string.c` +cuatro funciones exportadas (`__read_overflow`, `__read_overflow2`, +`__read_overflow3`, `__write_overflow`) con cuerpo `BUG()`. +Así consigue enlazar, pero no resuelve por qué el compilador emite llamadas +a esos helpers, declarados para diagnóstico en `include/linux/string.h:241`. + +El objeto generado `techpack/audio/dsp/q6_dlkm.ko`, desensamblado, contiene: + +```text +rtac_remove_voice + 0x1d0, offset 0x673ec: +R_AARCH64_CALL26 __read_overflow2 +``` + +El código asociado incluye la copia de elementos en `shift_voice_devices` +(`techpack/audio/dsp/rtac.c:638-644`). Falta resolver si el diagnóstico indica +un acceso real fuera de límites o un problema de los wrappers/compilador. +No convertirlo en un no-op ni aceptar BUG como solución. + +**Límite importante:** el ensayo despliega solo boot y conserva los módulos +vendor previos. Esta llamada existe en el módulo recién compilado, pero no +se ha demostrado que ese módulo se cargue en LAB. Tampoco se encontraron +llamadas directas desde funciones ordinarias de vmlinux a los cuatro stubs +en la búsqueda realizada (sí sus entradas CFI y sus bucles internos). +Por tanto, no se atribuye el fallo de arranque específicamente a ese stub. +Las llamadas normales a `fortify_panic` son parte de FORTIFY y su presencia +no prueba que ninguna se ejecute durante el arranque fallido. + +## Siguiente paso justificado + +1. Conservar ksync-slab como referencia que arranca. No encadenar más opciones + sobre el build FORTIFY fallido. +2. Tratar FORTIFY como un port con dependencias: estudiar la implementación + AXP y adaptar soporte Clang al kernel 4.14, incluyendo detección de compilador + y pruebas de los wrappers. Corregir la detección sola bloquearía esta + opción; no equivaldría a implementar FORTIFY. +3. Retirar los stubs BUG de la receta candidata y resolver los diagnósticos + de audio/WLAN, validando la causa de cada llamada. Mantener LTO/CFI como + referencia; desactivarlos globalmente introduce otra variable y pierde + protecciones ya funcionales. +4. Archivar .config, diff, vmlinux y Module.symvers por build. Comprobar + compatibilidad con los módulos realmente desplegados, no solo uname. +5. Obtener una traza del intento fallido que distinga FORTIFY, CFI, carga de + módulos y montaje de datos. En esta revisión ADB no detecta teléfonos, + por lo que no se han leído registros actuales de LAB. + +Conclusión: hay un defecto concreto de habilitación y un arreglo de enlace +inadecuado. La causa exacta en ejecución sigue pendiente; no anunciar otro +boot como reparado únicamente porque vuelva a compilar. + +Plan de port (siguiente documento): `docs/009-fortify-clang-port.md`. + +## Logs LAB post-fallo (2026-09-26, Cursor) + +Teléfono en fastboot tras FORTIFY. Reflasheo slab-only (`boot_a`/`boot_b`) y reboot. +`/sys/fs/pstore/` vacío (0 ficheros); sin `console-ramoops` ni `last_kmsg`. +Misma ausencia de traza que en hangs Stage1/CVE previos. No hay dmesg del intento fallido. +Artefacto local vacío: `.local-artifacts/009-fortify-crash-20260926/`. diff --git a/docs/009-fortify-bounds-boot-failure-20260927.md b/docs/009-fortify-bounds-boot-failure-20260927.md new file mode 100644 index 0000000..1937256 --- /dev/null +++ b/docs/009-fortify-bounds-boot-failure-20260927.md @@ -0,0 +1,87 @@ +# FORTIFY bounds: enlace correcto, arranque fallido + +Artefacto remoto: `20260926T223246Z-bisect-ksync-fortify-bounds` bajo +`/srv/rom/artifacts/009-axp-los23-port/`. +El dueño informa logo Google, reinicios y finalmente fastboot. El proceso +de build terminó exit=0 a las 22:32:52 UTC del 26 de septiembre. + +## Verificaciones realizadas + +- Los dos parches de límites están en las fuentes actuales. Audio/WLAN + ya no tienen los símbolos sin resolver `__read_overflow*` en sus objetos + LTO. Sí usan `fortify_panic`, que el kernel define y exporta normalmente. +- `lib/string.c` no tiene modificaciones/stubs; `vmlinux` no contiene los + cuatro helpers artificiales de overflow de los intentos anteriores. +- El boot descargado tiene SHA-256 + `ba5ac99eb2873dac4c3c8b108753bb89e5aa7a7d71972361e32b39f6ed9ef136`, + igual al registro remoto. +- Desempaquetado local correcto: Android 16, parche 2026-09, header v2. + El kernel extraído tiene SHA-256 + `99348e4f21a46c3bf95dde3a97995cd97375a6792427c5d497b3296fa0c0a906`, + idéntico al kernel nuevo y al kernel verificado en el servidor. +- Los ramdisks en los directorios remotos work/check del fallido y combo4 + tienen el mismo SHA-256. Se conserva el método ksync. + +## Error ignorado por el empaquetador + +El log muestra que el último `magiskboot unpack` (línea 91 del script) +terminó con `Illegal instruction (core dumped)`. El `|| true` permitió +continuar y declarar DONE. Es un defecto de verificación que debe corregirse. +No demuestra que la imagen sea inválida: la copia con el mismo hash se ha +desempaquetado correctamente en el portátil y contiene el kernel esperado. +No confundir el fallo de la herramienta host con una traza del teléfono. + +## Estado de LAB durante esta revisión + +ADB disponible como usuario shell, sin privilegios root. LAB ya ejecuta +combo4, kernel #16, `sys.boot_completed=1`. Pstore vacío. Propiedades de +motivo de arranque: ro.boot.bootreason=reboot, sys.boot.reason=bootloader. +No identifican el fallo previo. El tramo de logcat consultado no contiene +una traza FORTIFY/CFI del intento fallido. + +Intentos de leer módulos instalados en vendor devolvieron Permission denied. +Por tanto, no se ha podido comparar su ABI/CRC con el kernel fallido. +No se ha ejecutado adb root, cambiado Magisk, reiniciado ni flasheado LAB. + +## Prueba adicional de eficacia de wrappers + +Se extrajo el bloque FORTIFY del string.h actual a un harness temporal, +con sus wrappers y macros, tipos auxiliares y libc host. Clang r563880c, +`-O2 -flto -fuse-ld=lld`. No se añadieron stubs overflow. El handler de +fortify del harness termina con código 77 para observar el rechazo. + +Directorio remoto: `/tmp/axp-fortify-runtime-9t4hrer_`. + +13 casos dieron el resultado esperado: + +- strlen/strnlen sobre una cadena válida, strcpy válido; +- memcpy, memmove, memset, memcmp y strncpy: tamaño 8 sobre buffers de 8 + aceptado, tamaño dinámico 9 rechazado por fortify_panic. + +**Límites:** ejecución host x86_64, no kernel ARM64; no prueba CFI del kernel, +wrappers restantes, todos los call sites, módulos ni arranque. El caso memcmp +usa el mismo buffer a ambos lados; no es una prueba exhaustiva de comparación. +Estas pruebas muestran protección efectiva en los casos probados, no que el +port completo sea correcto. + +## Lo que falta para atribuir el fallo + +La corrección de límites resolvió el enlace, que era su alcance probado. +No se ha identificado la instrucción que detiene el arranque. Encontrar +llamadas a fortify_panic en el binario (incluso en funciones de inicio) es +normal y no demuestra que se ejecuten durante el fallo. + +Prioridad: preparar una captura de fallo utilizable antes del próximo ensayo. +Comprobar en la referencia funcional el acceso y funcionamiento de pstore/ +ramoops, incluido el mecanismo del dispositivo que procesa sus registros. +Un arranque de diagnóstico puede instrumentar fortify_panic para registrar +caller/backtrace conservando su comportamiento de fallo; también debe poder +distinguir una caída CFI, un watchdog y un fallo de módulos. Esa instrumentación +sin un canal persistente/serial verificado no garantiza obtener evidencia. + +Conservar combo4 como referencia aceptada. No habilitar FORTIFY para ship, +ni atribuir el fallo a un controlador concreto, ni reintroducir stubs/no-ops +a partir del solo síntoma del logo. Revisar después compatibilidad de módulos +y los call sites identificados por una traza real. + +Plan de captura (siguiente documento): `docs/009-fortify-diag-capture-plan.md`. diff --git a/docs/009-fortify-clang-port.md b/docs/009-fortify-clang-port.md new file mode 100644 index 0000000..b9e5bd9 --- /dev/null +++ b/docs/009-fortify-clang-port.md @@ -0,0 +1,98 @@ +# FORTIFY + Clang en msm-4.14 (plan de port) + +Documento de preparación. No es un parche listo. Relacionado: +`docs/009-fortify-boot-audit-20260926.md` (diagnóstico del fallo LAB). + +## Hechos ya cerrados + +| Hecho | Evidencia | +|-------|-----------| +| Packaging ksync OK | Ramdisk/DTB idénticos a slab; patch `2026-09` | +| FORTIFY one-CONFIG tumba arranque | LAB → reinicios → fastboot; pstore vacío | +| DMESG / SLAB / INIT_ON_ALLOC / INIT_ON_FREE solos OK | Bisect ksync 2026-09-26 | +| `depends on !CC_IS_CLANG` es inútil aquí | `CC_IS_CLANG` **no existe** en msm-4.14; el build usa Clang 21 + LTO/CFI | +| Stubs `__read_overflow*` + `BUG()` | Anti-patrón: enlazan pero dejan llamadas reales (p.ej. `q6_dlkm` → `__read_overflow2`). **No reutilizar** | +| AXP `fortify/4.14/0004.patch` | Solo intra-object (`FORTIFY_SOURCE_STRICT_STRING` / Micay). **No** aporta soporte Clang | + +## Qué hace falta (upstream, no inventado) + +Serie Kees Cook *fortify: Add Clang support* (v7, 2022-02), mergeada en kernels +modernos. Idea central: + +1. Atributos Clang: `__pass_object_size`, `__overloadable`, `__diagnose_as` + (en `compiler_attributes.h`). +2. Wrappers FORTIFY adaptados para que `__builtin_object_size(p, 1)` funcione + desde inlines (en kernels nuevos: `include/linux/fortify-string.h`). +3. Kconfig: `depends on !CC_IS_CLANG || CLANG_VERSION >= 120001` (y exclusiones + arch específicas). Clang 21 cumple la versión; falta el código. + +Referencias: + +- Cover: +- Commit ilustrativo: `281d0c962752` (*fortify: Add Clang support*) +- Antecedente del disable: `a52f8a59aef4` / bugs LLVM 41459, 50322 + +En **4.14** el FORTIFY vive todavía dentro de `include/linux/string.h` (no hay +`fortify-string.h`). El backport no es un cherry-pick limpio: hay que adaptar +los wrappers al layout 4.14 o traer la separación de headers con cuidado. + +## Detección de compilador (paso previo pequeño) + +Sin `CC_IS_CLANG` / `CLANG_VERSION` en Kconfig, cualquier `depends on !CC_IS_CLANG` +es no-op. Antes o junto al port de wrappers: + +1. Backport mínimo de los símbolos Kconfig que usan árboles Android/comunes + modernos (`CC_IS_CLANG`, `CLANG_VERSION`) **o** equivalencia documentada + vía `scripts/Kconfig.include` / Makefile del árbol. +2. Con eso solo + `depends on !CC_IS_CLANG`: FORTIFY queda **apagado** con + Clang — correcto, pero no da hardening. Sirve como red de seguridad para + no volver a activarlo “por accidente”. + +## Camino de implementación propuesto (orden) + +1. **Quitar stubs** de `009-bisect-ksync-one.sh` (o dejarlos detrás de un + flag explícito `ALLOW_FORTIFY_BUG_STUBS=1` no usado por defecto). Un + FORTIFY que no enlace sin stubs = señal de que el port está incompleto. +2. **Introducir detección Clang** en Kconfig (paso pequeño, testeable). +3. **Port wrappers Clang** al `string.h` 4.14 (o split a `fortify-string.h` + si el diff queda más limpio), tomando la serie Kees como fuente, no stubs. +4. **Build ksync** solo `CONFIG_FORTIFY_SOURCE=y` (sin STRICT_STRING al + principio). Criterio de éxito: modpost **sin** undefined + `__read_overflow*` y sin exportar cuerpos `BUG()`. +5. Si aparecen llamadas residuales en audio/WLAN: tratar cada una como bug + de tamaño/objeto o fallo del wrapper — no enmascarar. +6. Flash LAB (mismo método ksync / GOODMAKE). Solo entonces valorar + `FORTIFY_SOURCE_STRICT_STRING` (AXP 0004) encima. +7. Reintroducir FORTIFY en el combo defconfig OK (DMESG+SLAB+INIT_ON_*). + +Fuera de alcance de este port: desactivar LTO/CFI globales “para que compile” +(introduce otra variable y pierde protecciones ya validadas). + +## Qué no es “clonar AXP” aquí + +AXP aporta el parche Graphene de **strict string** sobre un FORTIFY que ya +debe ser válido con el toolchain del producto. En LOS23/sunfish el toolchain +es Clang+LTO; el vacío es el **soporte Clang de FORTIFY**, no el 0004. +Hasta tener (3)+(4), no marcar FR-017 FORTIFY como listo. + +Nota (búsqueda host): el `0008-…-fortify/5.15/0006.patch` AXP (*rewrite +fortify source for 5.15 gki*) también es strict-string sobre +`fortify-string.h` ya existente — no sustituye la serie Kees de Clang. + +## Estado + +- **LAB combo4 OK** (2026-09-26): `#16`, DMESG+SLAB+INIT_ON_ALLOC+INIT_ON_FREE, sin FORTIFY. +- Stubs BUG gated off en ksync (`ALLOW_FORTIFY_BUG_STUBS`). +- Port en curso: `vendor/.../fortify-clang/apply_fortify_clang.py`. +- **fortify-pos0 FAIL 2026-09-26T21:54Z:** modpost + `__read_overflow*` undefined en `q6_dlkm.lto.ko` / `wlan.lto.ko`. + **vmlinux/Image.lz4 sí generaron** (sin esos U en el núcleo). El port POS0 + no basta aún para módulos LTO; no reintroducir stubs. + Siguiente: localizar call sites (p.ej. rtac) o `__NO_FORTIFY` puntual / + más del port Kees — no ACCEPT hasta harness + link limpio. +- **Ensayo 2026-09-26T22:06Z:** POS0 + bounds (`rtac`/`lim_process_fils`) en + job `009-bisect-ksync-fortify-bounds`. Log: + `detach-009-bisect-ksync-fortify-bounds-20260926T220634Z.log`. + **Build OK / LAB FAIL:** logo Google → reboot. Reflasheo a combo4. + Bounds resolvieron el link; no bastan para arrancar. FORTIFY sigue + aparcado para ship hasta traza o port más completo + harness. diff --git a/docs/009-fortify-diag-capture-plan.md b/docs/009-fortify-diag-capture-plan.md new file mode 100644 index 0000000..12693b2 --- /dev/null +++ b/docs/009-fortify-diag-capture-plan.md @@ -0,0 +1,240 @@ +# 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**. diff --git a/docs/009-fortify-diag-review-20260927.md b/docs/009-fortify-diag-review-20260927.md new file mode 100644 index 0000000..929c317 --- /dev/null +++ b/docs/009-fortify-diag-review-20260927.md @@ -0,0 +1,119 @@ +# FORTIFY diagnostic review — 2026-09-27 + +## Conclusion + +The boot failure remains unresolved. The latest capture does **not** exclude +`fortify_panic`, and does not establish a watchdog reset. The diagnostic channel +has an early-boot blind spot and its documented panic validation admits a stale +marker. Fix these experimental controls before interpreting another empty dump. + +Review covered the Cursor transcript, local patch scripts and capture plan, +remote kernel sources/build artifacts, saved diag2 dump and installed LAB +modules. No flashing, rebooting, live source changes or new builds were performed +in this review. + +## Experiment history and what it establishes + +1. Original defconfig bisects also changed bp4a to bp2a (security patch and + platform version regression). Those experiments did not isolate hardening. +2. Corrected ksync packaging retained GOODMAKE's boot environment. Combo4 boots + with DMESG restriction, slab freelist hardening and allocation/free clearing. +3. FORTIFY required a Clang port. Exported overflow BUG stubs were removed; + pass_object_size was aligned to the wrappers' object-size mode 0. +4. The audio/WLAN overflow-helper link failures were localized to specific + functions. Explicit array-capacity guards resolved the targeted compilation + failures. Successful linking does not establish runtime correctness of the + port, or prove those drivers caused the subsequent boot failure. +5. Bounds FORTIFY boots still failed. Diagnostics then added caller printing, + stack dumping and a plaintext marker in the alternate ramoops region. +6. Plain-channel iterations tested mapping, probe overwriting, a panic notifier + and SysRq writes. These are useful channel experiments, but the recorded + plain7 result is insufficient to validate fresh panic-time writes. +7. Latest diag2 (`20260927T032419Z-bisect-ksync-fortify-diag`) failed to boot; + recovery used combo4. No readable failure record has been obtained. + +## Confirmed diagnostic defects + +### 1. Capture starts too late to exclude an early FORTIFY failure + +`apply_fortify_diag.py` maps the alternate region only at the successful end of +`ramoops_probe`. Remote `fs/pstore/ram.c:1270` performs the mapping; +`ramoops_init` is a `postcore_initcall` at line 1365. The writer immediately +returns if `axp_alt_va` is null (patch script lines 105–106). + +Remote `init/main.c` calls `setup_arch` at 565 and `parse_early_param` at 579, +before `rest_init` at 738 and the later `do_basic_setup` / `do_initcalls` path. +Disassembly of the current FORTIFY vmlinux contains branches to fortify_panic: + +```text +parse_early_param: ffffff8012290974 -> ffffff8011ac186c +start_kernel: ffffff8012290fb8 -> ffffff8011ac186c +setup_arch: ffffff8012296750 -> ffffff8011ac186c +``` + +These are possible failure paths, **not evidence that any executed**. They +demonstrate that an instrumented FORTIFY failure can occur while the persistent +writer is unavailable. A SysRq test from a fully booted system cannot validate +that interval. + +### 2. Plain7's positive control can accept an old marker + +The capture plan records `sysrq-x + sysrq-c` followed by survival of the magic +`AXPDIAG1`, sometimes without the complete body. SysRq-x already writes that +magic. The next probe explicitly preserves it. Therefore magic survival alone +does not prove that SysRq-c or the panic notifier wrote anything new. + +Require a distinct per-attempt identifier and a complete panic-specific record, +different from the pre-panic marker. Validate the exact failed-boot → fastboot +→ rescue-image → dump sequence, not just a normal reboot into plain7. + +### 3. The durable record follows operations that may fail + +The injected `fortify_panic` first calls `pr_emerg` and `dump_stack`, then writes +the persistent mark (patch script lines 36–39). A failure or recursion in those +operations could prevent the mark. The durable body contains only the helper +name, not the caller address printed to the unavailable console. Subsequent +panic-notifier and pstore writes also target the same slots and can overwrite +the first record. + +Record the first failure before formatted output; include a raw caller address, +event type and attempt identifier. Preserve the first record. Use a minimal +writer independent of the fortified helpers under investigation. This still +requires a correctly reserved/mapped region available at the tested boot stage; +moving the call alone does not fix defect 1. + +## Additional checks + +- Latest local boot SHA-256 matches the remote published boot: + `a5be43617770205bb9a2d2ad5989ca566ad9713134e7210c585f02fd7bdea554`. +- Current build configuration enables FORTIFY, Clang LTO, Clang CFI and + MODVERSIONS. +- Read-only comparison of all 41 installed vendor `.ko` files against current + remote `Module.symvers`: **3,182 version entries, zero CRC mismatches, zero + missing symbols**. This checks symbol version compatibility only; it does not + prove all runtime ABI/CFI behavior is correct or identify the crashing code. +- LAB was recovered and running combo4 kernel #16 with `sys.boot_completed=1`. +- Saved diag2 `access-ramoops.bin` is 4 MiB and contains none of `AXPDIAG0`, + `AXPDIAG1`, `FORTIFY`, `DBGC` or `Oops`. Measured byte entropy is approximately + 7.99996 bits/byte. This does not uniquely distinguish encryption, overwritten + contents or other high-entropy data, nor prove no panic occurred. +- `bootreason=reboot` observed after rescue is not a preserved trace of the + original failure and cannot exclude a panic in the earlier attempt. + +## Next experiment requirements + +1. Preserve combo4 and archive each diagnostic patch, config, vmlinux and hashes. +2. Validate fresh, distinguishable failure records with an otherwise booting + control. Test persistence across the same recovery sequence used in practice. +3. Cover the early interval explicitly: use a board-supported early output or + correctly reserved early persistent writer, with initialization milestones. + Do not insert ordinary ioremap calls into arbitrary early/panic context. +4. Validate an intentionally triggered diagnostic event at the boot stage being + tested. A late SysRq control alone is insufficient. +5. Only then repeat FORTIFY with a first-failure record containing a caller and + symbolize it using the exact vmlinux. If no reliable early channel is + achievable, use controlled localization experiments and label them as such; + do not promote them to a working or complete hardening port. + +Do not add overflow stubs, suppress fortify_panic or declare watchdog/CFI the +cause solely because the current capture is empty. diff --git a/docs/009-fortify-diag-v2-review-20260927.md b/docs/009-fortify-diag-v2-review-20260927.md new file mode 100644 index 0000000..d86039e --- /dev/null +++ b/docs/009-fortify-diag-v2-review-20260927.md @@ -0,0 +1,60 @@ +# Diagnostic v2 review — 2026-09-27 + +Reviewed local `apply_fortify_diag.py` and generated remote +`kernel/axp_diag_capture.c` with attempt `20260927T083401Z`, while the plain-v2 +control build was running. No live sources or build jobs were changed. + +The direction is useful: record before printing, include event/caller/build +identifier, and validate SysRq-c without first writing SysRq-x. However, this +implementation is not yet a validated early-boot recorder. + +## Required corrections + +1. **Do not map from the failure handler.** `axp_diag_mark_event` calls + `axp_diag_map`, which calls ordinary `ioremap` if no mapping exists. This + reintroduces mapping in panic/early context. In this tree ARM64 ioremap uses + `get_vm_area_caller` and `ioremap_page_range`; mm_init initializes the slab + allocator and vmalloc. Mapping after successful mm_init is a reasonable + later-stage control, but the failure handler must not try to compensate for + an earlier failure with that same ordinary mapping path. + +2. **The previously identified early interval is still uncovered.** Remote + `init/main.c` calls setup_arch at 565 and parse_early_param at 579; mm_init + and the new hook are at 600–604. A successful late SysRq test does not + validate a failure in either earlier function or inside mm_init itself. + +3. **First-failure retention is not guaranteed.** `axp_first_done` is a plain + integer tested before recording and set only after the writes. Concurrent + CPUs or recursion can both pass the test. The event writer does not inspect + an existing persistent record, despite the stated promise to preserve one; + only the milestone writer does. Use a deliberate atomic/reentrancy protocol + and an explicit policy for records from previous boots. A build timestamp + distinguishes builds, not repeated attempts with the same image. + +4. **Milestone format contains an embedded NUL.** The literal `AXPDIAG0,M,` + is 10 characters, but memcpy copies 11 and advances by 11. This copies the + string terminator before the attempt identifier. Consequently `strings | + grep AXPDIAG0` loses the attempt/stage from the same line. Use the literal's + length excluding its terminator (for example sizeof(literal)-1). + +## Validation scope + +A complete new `C` record surviving the actual combo4 recovery sequence would +be useful evidence for late panic capture. It would not establish early-boot +coverage. Require the exact expected identifier and complete record; define +how previous records are archived/cleared before repeating the same image. +Keep the first failure separate from milestones and subsequent notifier events. + +The capture implementation still includes linux/string.h and memcpy calls; +verify the final ARM64/LTO generated writer does not depend on the FORTIFY +failure path under test. `no_sanitize("cfi")` alone does not disable FORTIFY. + +Do not interpret an empty capture from this v2 as proof against fortify_panic. + +## Status + +Local `apply_fortify_diag.py` updated to **v3** addressing items 1–4 +(no map-from-handler; early+perm maps in `setup_arch`; atomic latch + durable +head check; milestone `sizeof(lit)-1`). Residual pre-`early_map` blind spot +remains documented in the capture plan. plain-v2 build is obsolete — rebuild +control as plain-v3 before flash. diff --git a/docs/009-fortify-diag-v3-review-20260927.md b/docs/009-fortify-diag-v3-review-20260927.md new file mode 100644 index 0000000..f935818 --- /dev/null +++ b/docs/009-fortify-diag-v3-review-20260927.md @@ -0,0 +1,68 @@ +# Diagnostic v3 review — 2026-09-27 + +Checked the local generator and remote generated kernel/axp_diag_capture.c, +attempt 20260927T084106Z, while plain-v3 was building. No build cancellation, +source modification on the server, or device operations were performed. + +## Corrected + +- Failure handler no longer maps memory. +- Event claim uses atomic_cmpxchg before composing the record. +- Event path checks a previous persistent AXPDIAG1 header. +- Milestone prefix length excludes the terminating NUL. +- Explicit byte I/O replaces memcpy on the MMIO writer path. +- Early mapping now precedes parse_early_param in ARM64 setup_arch. + +## Blocking issue: permanent mapping before allocators exist + +The new setup.c hook at lines 398–402 calls axp_diag_map_permanent immediately +after paging_init. This is still inside setup_arch, before start_kernel calls +mm_init. It even precedes bootmem_init in setup_arch. + +axp_diag_map_permanent releases the early map and calls ordinary ioremap. +In this tree, arch/arm64/mm/ioremap.c calls get_vm_area_caller, which reaches +mm/vmalloc.c:1405 __get_vm_area_node and kzalloc_node at line 1421, followed by +alloc_vmap_area. The allocator initialization (mem_init, kmem_cache_init, +vmalloc_init) occurs later in init/main.c:mm_init. + +Thus paging_init is NOT the readiness gate for ordinary ioremap. This diagnostic +can introduce its own boot failure in the no-FORTIFY control. Do not use a +failure of this control to draw conclusions about FORTIFY. + +The transition needs a deliberate lifetime plan: ordinary mapping only after +its allocators are ready, and safe retirement of the early mapping respecting +early_ioremap_reset. Simply relocating one call without checking that lifetime +is insufficient. If a temporary uncovered interval is chosen, document it and +ensure failure writers cannot dereference a stale early mapping. + +## Mapping attributes and persistence + +early_memremap uses FIXMAP_PAGE_NORMAL, whereas the permanent ioremap and +access-ramoops use PROT_DEVICE_nGnRE. This changes memory attributes. The writer +only uses wmb and a readback; it has no explicit cache maintenance for a cached +early mapping. These operations alone do not establish that early cached writes +reach reset-surviving memory. Review compatible early I/O mapping attributes +(early_ioremap uses FIXMAP_PAGE_IO in this tree) and verify on hardware. + +## Remaining first-record limitations + +- Milestones check the latch but do not participate in its atomic claim. A + milestone interrupted by a failure writer can resume and overwrite the same + slots. Separate milestone storage from first-failure storage, or use a + protocol that also covers milestones and reentrancy. +- A bare eight-byte header is treated as a complete prior failure. An interrupted + write that persisted only that header can suppress later captures. Validate a + complete record/commit indication and inspect mirrors. +- The identifier remains per build, not per boot; archive/clear old captures + under an explicit test procedure before repeating the same image. + +The improvements are real, but v3 is not yet ready to be described as a +validated early-capture channel. These findings concern instrumentation, not an +identified cause of the original FORTIFY boot failure. + +## Status + +Local generator updated to **v4**: no `ioremap` until after `mm_init`; early +map uses `early_ioremap` (IO attrs) and is kept until then; failure @0 vs +milestones @2048; adopt only complete records. plain-v3 must not be flashed — +rebuild control as plain-v4. diff --git a/docs/009-fortify-driver-bounds-candidate.patch b/docs/009-fortify-driver-bounds-candidate.patch new file mode 100644 index 0000000..f8bebe5 --- /dev/null +++ b/docs/009-fortify-driver-bounds-candidate.patch @@ -0,0 +1,27 @@ +--- a/techpack/audio/dsp/rtac.c ++++ b/techpack/audio/dsp/rtac.c +@@ -652,6 +652,12 @@ + pr_debug("%s\n", __func__); + + mutex_lock(&rtac_voice_mutex); ++ if (rtac_voice_data.num_of_voice_combos > ARRAY_SIZE(rtac_voice_data.voice)) { ++ pr_err("%s: invalid voice count %u\n", __func__, ++ rtac_voice_data.num_of_voice_combos); ++ mutex_unlock(&rtac_voice_mutex); ++ return; ++ } + /* look for device */ + for (i = 0; i < rtac_voice_data.num_of_voice_combos; i++) { + if (rtac_voice_data.voice[i].cvs_handle == cvs_handle) { +--- a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_fils.c ++++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_fils.c +@@ -1092,6 +1092,9 @@ + return false; + } + ++ if (dot11f_ie_rsn.pmkid_count > ARRAY_SIZE(dot11f_ie_rsn.pmkid)) ++ return false; ++ + for (i = 0; i < dot11f_ie_rsn.pmkid_count; i++) { + if (qdf_mem_cmp(dot11f_ie_rsn.pmkid[i], + pe_session->fils_info->fils_pmkid, diff --git a/docs/009-fortify-family-bisect-20260927.md b/docs/009-fortify-family-bisect-20260927.md new file mode 100644 index 0000000..0796dd5 --- /dev/null +++ b/docs/009-fortify-family-bisect-20260927.md @@ -0,0 +1,127 @@ +# FORTIFY family bisection — 2026-09-27 + +## Why this experiment + +The two-phase X-then-C experiment establishes loss of an adb-verified record +somewhere in the panic/reboot sequence. Further recovery-channel engineering +has not identified the original FORTIFY boot failure. This experiment instead +isolates the protection families while leaving panic behavior intact. + +This is diagnostic-only: a boot with one family is not a completed FORTIFY port +and must not be promoted into the shipping hardening configuration. + +## Independent analysis before build + +- Reconstructed symbols from the saved failed bounds kernel #19, rather than + inspecting the live output overwritten by later no-FORTIFY diagnostic builds. +- Found 372 direct branches to fortify_panic, including its CFI jump-table + entry. Their presence alone does not prove execution. Inspected early + start_kernel/setup_arch checks; no demonstrated unconditional failure found. +- Recompiled init/main.c, arch/arm64/kernel/setup.c and lib/string.c in scratch + space with the actual Clang 21 flags and the ported header; this is not a + replacement for whole-kernel LTO or a device boot. +- The selector's full, memory and strings variants compile for init/main.c and + lib/string.c with those flags. No overflow stubs are added. + +## Source and build isolation + +`scripts/009-fortify-select-family.py` selects complete wrapper functions from +the existing port and verifies the expected inventory of 15 wrappers. Memory +keeps memset, memcpy, memmove, memscan, memcmp, memchr, memchr_inv and kmemdup. +Strings keeps strncpy, strcat, strlen, strnlen, strlcpy, strncat and strcpy. +Disabled wrappers use the existing raw declarations, not a returning panic stub. + +`scripts/009-build-fortify-family-isolated.sh` archives kernel commit +28f9290ae067d3e7857126eb6312720dbe9c7c80 to its own source directory. It applies +the existing Clang port and the already-tested audio/WLAN bounds patch, then +selects a family. It never resets Cursor's live source or writes its output. + +The input .config is extracted from the saved failing bounds kernel. olddefconfig +must leave it byte-identical or the job aborts. Clang r563880c, LLVM tools and +Android host build flags are reused. Kernel release suffix is preserved for +installed modules. Full module linking is required even though only boot will +be packaged. The raw new Image is injected into GOODMAKE; ramdisk and DTB stay +from GOODMAKE. Local unpack, metadata, payload and module-version checks remain +required before device use. + +## First run + +Remote root: `/srv/rom/artifacts/009-fortify-family-20260927/`. + +Detached session: `009-codex-fortify-memory-20260927`. + +Log: `/srv/rom/artifacts/detach-009-codex-fortify-memory-20260927-20260927T193643Z.log`. + +Status: `/srv/rom/artifacts/detach-009-codex-fortify-memory-20260927.status`. + +The memory-only build started at 19:36:43 UTC. Configuration drift check passed +(empty memory/config.diff). Build finished exit=0 at 19:58:48 UTC +(`memory/boot-make.img`). + +**LAB boot (2026-09-27 ~22:00 local):** flashed both slots → `sys.boot_completed=1` +on kernel `#1` `Sun Sep 27 19:45:25 UTC 2026`. Memory-only family **boots**. + +**Strings-only build:** session `009-codex-fortify-strings-20260927`, finished +exit=0 at 20:51:38 UTC (`strings/boot-make.img`). + +**LAB boot (strings):** flashed both slots → returned to **fastboot** (~100s, +no `boot_completed`). Recovered combo4. Strings-only family **fails to boot**. + +**Family result:** memory boots, strings does not → narrow toward string +wrappers (`strncpy`/`strcpy`/`strlen`/…), not the memcpy family. Still +diagnostic-only; not a shippable FORTIFY subset. + +**Strings split (LAB):** +- `strings-copy` → **boots** +- `strings-len` (strlen, strnlen) → **boots** +- full `strings` (copy+len together) → **fails** + +Implication: neither half alone is sufficient to reproduce; failure is in the +**interaction** of fortified copy + fortified len (or LTO/CFI coupling of +both). Next: smaller cross products (e.g. strcpy+strlen only), same baseline. + +**Cross products (LAB):** +- `strings-strcpy-strlen` → **boots** +- `strings-copy-strlen` (5 copy + strlen) → **fails** +- `strings-copy-strnlen` → **boots** (strlen is the critical len partner) +- `strings-strlen-restcopy` (strlen+strncpy/strlcpy/strcat/strncat) → **fails** +- `strings-strlen-ncopy` (strlen+strncpy+strlcpy) → **fails** +- `strings-strlen-cat` (strlen+strcat+strncat) → **boots** +- `strings-strlen-strncpy` → **boots** +- `strings-strlen-strlcpy` → **fails** +- **Smoking gun:** fortified `strlcpy` + fortified `strlen` together. +- **Root cause:** 4.14 `strlcpy` does `ret = strlen(q)`. With Clang + `__pass_object_size`, nested fortified `strlen` panics on known-size + sources; GCC usually saw bos==-1 and skipped. Fix in + `apply_fortify_clang.py`: `strlcpy`/`strcpy` use `__underlying_strlen`. + +**Fix verification (LAB 2026-09-28):** +- Rebuilt `strings-strlen-strlcpy` + full `strings` with fixed apply → both + `exit=0` (~18:24 / 18:26 UTC). +- Flashed both slots: `strlen+strlcpy` → `boot_completed=1`; full `strings` + → `boot_completed=1` (`CONFIG_FORTIFY_SOURCE=y`, kernels `#1` 18:06 / 18:10 UTC). +- Pre-fix pair archived as `strings-strlen-strlcpy-broken/` on the host. + +**Full family (LAB 2026-09-28):** rebuilt `full` (15 wrappers) with nested-strlen +fix → `exit=0` 19:31 UTC → flashed both slots → **`boot_completed=1`** +(`CONFIG_FORTIFY_SOURCE=y`, kernel `#1` 19:18 UTC). Port wrappers alone are +no longer the brick. + +**combo4+FORTIFY (LAB 2026-09-28):** ksync +`20260928T201655Z-bisect-ksync-combo4-fortify-fix` → flashed both slots → +**`boot_completed=1`** with `FORTIFY` + `INIT_ON_*` + `DMESG` + +`SLAB_FREELIST_HARDENED`. Nested-strlen fix unblocked the previous ship +candidate pack. + +## Interpretation + +- A memory-only boot would narrow investigation toward the string wrappers or + their interaction with memory wrappers. It would not prove a specific string + operation or driver is faulty. +- A memory-only failure would keep the memory family, common port machinery and + build/runtime interactions in scope; it would not clear the string family. +- Complementary/control builds should follow the observation, changing only the + selector. If behavior is deterministic, continue by splitting the implicated + group, then its caller set. Do not restart from an unrelated build baseline. +- Preserve vmlinux, source, effective config, command, compiler version, hashes + and the exact boot result for each variant. diff --git a/docs/009-fortify-port-review-20260926.md b/docs/009-fortify-port-review-20260926.md new file mode 100644 index 0000000..e630dc2 --- /dev/null +++ b/docs/009-fortify-port-review-20260926.md @@ -0,0 +1,89 @@ +# Revisión del port FORTIFY en curso — 2026-09-26, 21:25 UTC + +Revisión de solo lectura del servidor; no se han editado scripts en ejecución. +El dueño confirma combo4 arrancado. Cursor registra kernel #16, DMESG, +SLAB_FREELIST_HARDENED, INIT_ON_ALLOC y INIT_ON_FREE activos, FORTIFY apagado. +No se ha repetido aquí la inspección de LAB. + +## Estado real + +Job: `009-bisect-ksync-fortify-clang`, iniciado a las 21:15:03 UTC. +Log: `/srv/rom/artifacts/detach-009-bisect-ksync-fortify-clang-20260926T211503Z.log`. +A las 21:25 UTC seguía activo, con procesos clang consumiendo CPU. El log +principal no se actualizaba desde las 21:18:39; eso no implicaba bloqueo. +No había resultado final ni nuevo artefacto FORTIFY validado. + +El script recibe **solo CONFIG_FORTIFY_SOURCE**. Es un ensayo aislado, no +combo4+FORTIFY; coincide con el plan local. Preserva breakfast/bp4a y el +empaquetado sobre GOODMAKE. El diff actual no modifica lib/string.c ni añade +los stubs BUG. Mantener deshabilitado ALLOW_FORTIFY_BUG_STUBS. + +## Hallazgo que revisar antes de aceptar el port + +El script `apply_fortify_clang.py` adapta atributos y prototipos, pero deja +consultas de tamaño incoherentes con algunos atributos: + +- POS equivale a `pass_object_size(1)`. +- `strlen` y `strnlen` reciben p con POS y consultan + `__builtin_object_size(p, 0)`. +- `strlcpy`, `strncat` y `strcpy` reciben q con POS y consultan su tamaño + con tipo 0. En otros wrappers, POS0 sí coincide con las consultas tipo 0. + +Esto no es un detalle estético. La información de tamaño implícita depende +del tipo. Se compiló por stdin una prueba pequeña con el mismo Clang +r563880c, también para AArch64 freestanding, sin escribir en el servidor: + +```c +typedef __SIZE_TYPE__ size_t; +__attribute__((noinline)) +size_t mismatch(const char *const p __attribute__((pass_object_size(1)))) { + return __builtin_object_size(p, 0); +} +__attribute__((noinline)) +size_t matched(const char *const p __attribute__((pass_object_size(0)))) { + return __builtin_object_size(p, 0); +} +``` + +El IR optimizado de mismatch devuelve -1 (tamaño desconocido); matched +devuelve el argumento implícito de tamaño. **Límite:** es una prueba aislada +noinline del mecanismo, no una demostración de que todas las llamadas a los +wrappers always_inline reales pierdan protección. Es necesario probar los +wrappers reales con optimización/LTO, tamaños conocidos y desconocidos. + +Referencia primaria: +[Clang: pass_object_size](https://clang.llvm.org/docs/AttributeReference.html#pass-object-size-pass-dynamic-object-size). + +Adaptar coherentemente los atributos y la semántica de tamaño del 4.14; +no sustituir todas las consultas por tipo 1 a ciegas, porque cambia la +política whole-object/subobject y puede alterar accesos válidos del árbol. + +## Otros puntos de aceptación pendientes + +- El port elimina `depends on !CC_IS_CLANG` sin implementar la detección y + los límites de versión/capacidades que propone su propio plan. Los macros + de atributos tienen fallback vacío: un compilador no compatible puede + volver a habilitar un FORTIFY sin soporte. No es prueba de fallo de Clang 21, + pero la configuración aún no tiene una protección adecuada. +- `__diagnose_as` está definido pero no utilizado en los wrappers revisados. + Documentar si se omite intencionadamente y validar diagnósticos reales; + declarar el atributo no implementa su efecto. +- El empaquetador imprime propiedades/config pero varias comprobaciones + terminan en `|| true`. Mostrar el valor no garantiza que coincida con el + esperado. Antes de entregar: comparar hashes de ramdisk/DTB, metadatos, + kernel inyectado y opciones de la config embebida, fallando si difieren. +- No editar el script activo. Congelar copia, hash, argumentos, diff y + configuración por experimento para evitar repetir el incidente combo4. + +## Qué debe probarse además de compilar y arrancar + +Sin stubs es necesario, pero no suficiente: quitar accidentalmente una +comprobación también puede hacer desaparecer símbolos de overflow. +Usar casos válidos y desbordamientos intencionados en un harness aislado +de los wrappers reales (no provocar corrupción en LAB), comprobando el +diagnóstico o camino de fallo esperado con Clang/LTO. Verificar también +ausencia de stubs en binarios/módulos, .config efectiva y hardware básico. +Después del ensayo aislado, validar combo4+FORTIFY como artefacto distinto. + +Conclusión: el enfoque mejora y el build está activo; aún hay detalles del +port y pruebas de eficacia pendientes. No equivale a un port ya aceptado. diff --git a/docs/009-fortify-pos0-link-failure-20260927.md b/docs/009-fortify-pos0-link-failure-20260927.md new file mode 100644 index 0000000..5f4fffa --- /dev/null +++ b/docs/009-fortify-pos0-link-failure-20260927.md @@ -0,0 +1,103 @@ +# FORTIFY POS0: dos errores localizados y corrección candidata + +Revisión del job `009-bisect-ksync-fortify-pos0`, que terminó con exit=1 +el 2026-09-26 a las 21:54:28 UTC. Se leyó el log del servidor, el fragmento +aportado y la conversación reciente de Cursor de este proyecto. + +## Resultado + +Se reprodujeron los dos símbolos sin resolver en compilaciones aisladas de +los archivos responsables, usando los argumentos del build fallido y su +Clang 21. Añadiendo validaciones explícitas de capacidad, desaparecen ambos +en los objetos tras LTO, **sin stubs y sin desactivar FORTIFY**. + +[Parche candidato](009-fortify-driver-bounds-candidate.patch). +Es un cambio local propuesto en esta revisión, no un parche upstream. +No se ha aplicado al árbol de compilación de Cursor. `git apply --check` +contra el árbol remoto actual terminó correctamente. + +## Localización en los objetos reales del build fallido + +Raíz: `/srv/rom/src/lineage/out/target/product/sunfish/obj/KERNEL_OBJ`. + +- `techpack/audio/dsp/q6_dlkm.lto.o`: `rtac_remove_voice+0x1d0`, + relocación `R_AARCH64_CALL26 __read_overflow2`. +- `drivers/staging/qcacld-3.0/wlan.lto.o`: + `lim_process_fils_auth_frame2+0xe48`, + relocación `R_AARCH64_CALL26 __read_overflow`. + +Importante: modpost etiqueta el error con `.lto.ko`, pero los objetos +intermedios disponibles son `.lto.o`. Los `.ko` antiguos que quedan en out +no deben confundirse con módulos del intento fallido. + +### Audio + +`techpack/audio/dsp/rtac.c` tiene capacidad para dos entradas de voz. +`rtac_remove_voice` usa un contador global para recorrer el array y llama a +`shift_voice_devices`, que copia del elemento `idx+1`. El código de alta +ya limita el número de entradas, pero ese invariante no basta para eliminar +la rama de diagnóstico en esta compilación. + +El candidato valida el contador bajo `rtac_voice_mutex`, antes del recorrido. +Si supera ARRAY_SIZE(voice), registra el error, libera el mutex y retorna. +Esto evita aceptar el estado inválido; no altera el recorrido válido ni +desactiva las comprobaciones de memoria. + +### Wi-Fi + +`lim_process_fils.c:1095` recorre `dot11f_ie_rsn.pmkid_count` y compara +PMKID de 16 bytes. El array declarado en `dot11f.h:6725` es `pmkid[4][16]`. +El objeto LTO conserva una rama al helper de overflow cuando el contador +alcanza cinco o más sin haberse encontrado una coincidencia. + +El parser `dot11f.c:6703` ya rechaza contadores mayores de cuatro. Por tanto, +esta revisión **no demuestra que exista una entrada explotable ni una lectura +real fuera de límites**. El compilador no elimina todas las ramas inválidas +en el consumidor. El candidato comprueba ARRAY_SIZE(pmkid) justo antes del +bucle y devuelve false ante un contador inválido. + +## Validación realizada + +Se trabajó en directorios temporales de rom-dev01, sin cambiar las fuentes +ni los objetos de salida usados por Cursor: + +- `/tmp/axp-fortify-probe-bl9zsxpt`: reproducción de ambos archivos y + prueba Wi-Fi; contiene también una variante preliminar de audio no elegida. +- `/tmp/axp-fortify-probe-kkcpn4o9`: reproducción y candidato final de audio. + +Método: leer la orden original de `.rtac.o.cmd` / `.lim_process_fils.o.cmd`, +conservar sus opciones de Clang/LTO/CFI e includes; cambiar únicamente la +fuente/output a copias temporales, evitar generar dependencias en out y +añadir el directorio original para resolver includes locales. Ejecutar +`ld.lld -m aarch64linux -O2 -r` sobre cada objeto bitcode y consultar +símbolos sin resolver con llvm-nm. + +Resultados: + +```text +audio baseline: U __read_overflow2 +audio con validación del contador: ningún símbolo overflow sin resolver +wifi baseline: U __read_overflow +wifi con validación del contador: ningún símbolo overflow sin resolver +``` + +**Alcance:** son dos unidades de compilación y su enlace LTO aislado. No se +ha repetido el enlace completo de q6_dlkm/wlan, modpost global, ROM o boot. +No se han probado arranque, llamadas de voz, audio ni Wi-Fi en LAB. Tampoco +se sustituye con esto el harness pendiente de eficacia de los wrappers. + +## Reanudación para Cursor + +1. Conservar la evidencia del intento fallido y revisar/aplicar el candidato + después del reset y del port FORTIFY en la receta reproducible. El script + ksync resetea las fuentes: una edición manual previa se perdería. +2. Validar módulos completos/modpost sin `__read_overflow*`, sin nuevos + stubs, sin `__NO_FORTIFY` en estos controladores y sin apagar LTO/CFI. +3. Validar el harness de FORTIFY, la config efectiva y el empaquetado antes + de entregar un nuevo boot. Mantener combo4 como referencia que arranca. +4. Tras aceptar FORTIFY aislado, probar combo4+FORTIFY y funciones de hardware. + +La conversación de Cursor proponía mirar los call sites o una exclusión +puntual con `__NO_FORTIFY`. Ya hay evidencia para intentar primero estas +validaciones de límites. Las advertencias de versionado de símbolos WLAN +son un asunto adicional; esta corrección no afirma resolverlas. diff --git a/docs/009-fortify-v4-capture-results-review-20260927.md b/docs/009-fortify-v4-capture-results-review-20260927.md new file mode 100644 index 0000000..ebc8fcf --- /dev/null +++ b/docs/009-fortify-v4-capture-results-review-20260927.md @@ -0,0 +1,99 @@ +# v4 capture results review — 2026-09-27 + +## Result + +The capture channel still has no validated panic-survival result. Do not infer +that AES selectively overwrites offset 0 while sparing offset 2048, and do not +choose a high offset as a safe region without establishing its ownership and +observed persistence. No FORTIFY-specific failure has been captured yet. + +Reviewed Cursor's recorded experiment summaries, v4 generated source, the kernel +ramoops implementation, sunfish DT and init.ramoops.sh. Read the current LAB alt +region while LAB was running combo4 #16; no device writes, flashes or reboots. + +Current 4 MiB capture SHA-256: +`24bbccbf4ed1271bc0950167f4a7921e2a79c534ad735d506ebb504a0353f310`. +It contains `AXPDIAG0,M,20260927T084531Z,panic_reg` at 2048, and no AXPDIAG +marker at the eight expected failure offsets 0,128,256,384,512,640,768,896. + +## Unsupported steps in the current explanation + +1. Random-looking bytes are not proof that the current test caused encryption. + Without a before/after snapshot from the same attempt, they can be old data, + overwritten data or ciphertext. The stored old captures are from different + experiments and cannot establish this particular transition. +2. The milestone is written again on every v4 boot, with a build-time identifier + shared by every boot of that image. Cursor reports that the first SysRq-c + returned with kernel_panic, followed by further live v4 tests. A regenerated + milestone is therefore an alternative to survival across panic. Final + recovery to combo4 does not resolve its age across the preceding boots. +3. The v4 latch is in ordinary kernel RAM. SysRq-x sets it. Clearing the alt + region with dd does not clear the latch in the running kernel. A subsequent + SysRq-c in that same boot will skip recording, even if the region looks + empty. Cursor's summary says a clean retry occurred but does not establish + the full clear/reboot/no-X sequence; this remains a confounder, not a proven + mistake in the executed sequence. +4. Current fs/pstore/ram.c exposes ramoops_decrypt_alt: it reads cxt->size, + decrypts with crypto_aead_decrypt, and copies the whole buffer back only on + success. This is not a panic-time encrypt routine. The inspected sunfish + init script invokes ramoops -D and then ramoops -g -l -c. No kernel panic + encrypt implementation was identified by these searches. Firmware ownership + remains possible, but unproven. Disabling kernel decryption would not by + itself demonstrate that an external encryption path was disabled. +5. The DT declares a 4 MiB alt ramoops reservation, not a separately reserved + diagnostic high-offset region. No offset within it is currently shown safe. + +## Next useful test: preserve attribution before another rebuild + +Use the existing no-FORTIFY control to establish a documented timeline. Keep +SysRq-x and SysRq-c experiments in separate boots, and archive full dumps, +kernel identity, and boot reason at each available observation point. + +- Archive and clear the diagnostic region BEFORE booting the control; then + verify the region contains no complete old failure record. Do not clear only + the persistent bytes after X and assume the in-memory latch has reset. +- Run a fresh boot with no X. Archive the pre-C contents; execute only C. + Recover directly to combo4 when possible, recording any intermediate v4 + boot or forced hardware reset. A forced reset is a separate experimental + condition from the automatic panic reboot. +- Compare the full before/after bytes, including mirrors and milestone area. + Do not use the same-build milestone alone as evidence of survival. +- Independently test X persistence through the SAME recovery sequence. This + distinguishes a writer that works in a live kernel from storage that survives + the recovery path. It does not replace the fresh-C test. + +If fresh C still leaves no attributable record, a control-only diagnostic can +read back/validate the exact committed C record immediately before panic and +report or expose that result while observable. This separates failure to write +from later loss. It must remain a diagnostic experiment, not a swallowed panic +or a production hardening change. + +Only after identifying which transition loses a verified record should the +next patch change its storage or intercept an identified writer. A separately +reserved region needs a board/firmware-compatible design; an arbitrary high +offset is not a substitute for that evidence. + +## Remaining source limitation + +v4 composes up to 128 bytes but caps persistence at 120; long tokens can lose +the terminating newline required by adoption. This does not explain the short +sysrq-c/sysrq-x records, but must be fixed for general panic messages. + +The original FORTIFY cause remains open. Diagnostics v2/v3 had concrete +implementation defects; v4 fixes those major defects and boots, but its test +results still do not establish a working early-panic channel. + +## Follow-up LAB (same evening, documented) + +Clean C-only: +`.local-artifacts/009-v4-clean-c-20260927T190738Z/` — clear → v4 boot (no X) +→ C → **intermediate auto v4 reboot** (`kernel_panic`) → combo4. No +`AXPDIAG1` at T3 or T4. Fail zone 0:1024 went from all-zero (T2) to opaque +non-`AXPDIAG1` bytes (T3=T4). Latch/X confounder ruled out for this run. + +X persistence (no panic): +`.local-artifacts/009-v4-x-persist-20260927T191143Z/` — `AXPDIAG1,X,...` +survives combo4 recover; fail[0:128] identical before/after. + +Next: distinguish “C never committed” vs “lost across panic” with a +control-only pre-panic readback of the committed C record (see above). diff --git a/docs/009-fortify-v4-clean-tests-verification-20260927.md b/docs/009-fortify-v4-clean-tests-verification-20260927.md new file mode 100644 index 0000000..6272541 --- /dev/null +++ b/docs/009-fortify-v4-clean-tests-verification-20260927.md @@ -0,0 +1,50 @@ +# Verification of clean C and X experiments — 2026-09-27 + +Independently parsed the binary dumps and recorded kernel/boot properties in: + +- `.local-artifacts/009-v4-clean-c-20260927T190738Z/` +- `.local-artifacts/009-v4-x-persist-20260927T191143Z/` + +The clean C test removes the earlier X/latch confounder: T2 has a zero failure +zone and a fresh v4 #29 boot; T3 reports kernel_panic on an intermediate v4 boot; +T4 is combo4 #16. No complete failure record is present after C. The intermediate +boot prevents localization of loss to the panic itself versus later boot stages. + +The X test demonstrates that all eight complete 55-byte X records survive the +normal recovery to combo4 unchanged. It does not include the panic transition +of the C test, so it is a recovery control rather than the same full sequence. + +Precision correction: T3 and T4 are NOT identical binary dumps. Their first 128 +bytes match, but 7,213 bytes differ across 4 MiB, including six bytes in the first +1 KiB. Likewise X2 and X3 have 79 differing bytes, despite their complete X +records surviving intact. These differences do not negate X persistence, but +avoid describing entire zones or dumps as identical. Their cause is not yet +established. + +Next diagnostic should check a full C record (primary and mirrors, expected +event/id/caller/terminator) immediately after its writer and before panic. +The success/failure result must be observable independently of the storage +whose survival is under test. A print to a console that cannot be retrieved, or +another flag only in the same alt region, would repeat the observability problem. +A control-only two-phase arm/readback/trigger protocol can expose the record +and status through adb before deliberately entering panic; document the changed +timing and validate the actual immediate path subsequently. Keep normal FORTIFY +failure behavior intact. + +This establishes a narrower investigation: the writer plus normal recovery can +work; a clean panic experiment still loses or fails to produce the record. +Selective AES overwrite and a safe alternative offset remain unproven. + +## Follow-up: two-phase arm/readback/panic (same evening) + +Artifact: +`.local-artifacts/009-v4-twophase-x-then-c-20260927T191809Z/` + +Using existing v4 (no rebuild): SysRq-x → **adb dump confirms** eight +complete `AXPDIAG1,X` records → SysRq-c (latch no-ops C write; panic runs) +→ intermediate v4 (`kernel_panic`) → combo4. + +Result: pre-verified X is **absent at P3 and P4**. Independent channel was +adb, not alt-only flags. Timing caveat: adb RTT between arm and panic; type +X not C. Narrow reading: fail-zone content verified before panic does not +survive this panic/reboot path; soft recover without panic still preserves X. diff --git a/docs/009-gate-g-kernel-attribution.md b/docs/009-gate-g-kernel-attribution.md new file mode 100644 index 0000000..cbe0952 --- /dev/null +++ b/docs/009-gate-g-kernel-attribution.md @@ -0,0 +1,135 @@ +# Gate G / FR-017 — kernel hardening attribution (ship candidate) + +**What “Gate G doc” means:** the acceptance contract asks for a written list of +**what kernel hardening we applied, what we skipped and why**, plus userspace +AVB/signing gaps (or “impossible on this stack”). This file is that list for the +**kernel** half. Userspace AVB is tracked separately below as still open. + +**LAB device:** `11231JEC207477` only. +**Accepted kernel ship pack (LAB 2026-10-01):** Stage1 Graphene/AH + combo4 + +Clang FORTIFY + Magisk preroot + **CVE clean-offset 429** + **hi-batch1+2 (15)** +with `CVE-2022-49980` denylisted. Clean-only `#47` / hi-batch1 `#48` remain bisect GOODs. + +Prior Stage1-only pack `20260929T123401Z-axp-stage1-combo4` remains the +**recover / bisect GOOD** baseline (kernel `#32`). + +## Current accepted artifact + +| Field | Value | +|--------|--------| +| Artifact | `/srv/rom/artifacts/009-axp-los23-port/20261001T201836Z-axp-stage1-combo4-cve-hi-batch2/` | +| Local flash copy | `.local-artifacts/009-flash-cve-hi-batch2/` | +| Prior hi-batch1 GOOD | `20261001T192418Z-…-cve-hi-batch1/` (`#48`) | +| Prior clean GOOD | `20261001T180955Z-…-cve-clean/` (`#47`) | +| Kernel base | LOS `msm-4.14` `@ 28f9290ae067` (`4.14.357-openela`) | +| Running LAB (boot flash) | slot `_a`, kernel `#49` `Thu Oct 1 19:49:54 UTC 2026` | +| CVE list | clean **429** + hi-batch1 (**7**) + hi-batch2 (**8**) | +| Apply quality | clean OK=429; hi OK=15 fuzz≤1 (elevated abs-offset) | +| Note | host detach `exit=141` after `bacon_exit=0` = tee SIGPIPE, not a real fail | +| Magisk | EXTENDROM-class preroot v30.7 (virgin until Additional Setup; `magiskd` OK) | +| KernelSU | absent (Magisk track) | + +**Flash procedure that works:** recovery → (optional wipe) → sideload zip → +**Reboot system**. Bisect/CVE boots may use `fastboot -s 11231JEC207477 flash boot` +only when CRC/modules match the installed vendor. Do **not** flash Magisk +`boot.img` onto the other slot alone (new kernel + old vendor ⇒ `wlan` CRC mismatch). + +**Build entrypoints:** + +- Apply: `apply_stage1_combo4.sh` then `apply_cve_strict.sh` with + `CVE_STRICT_LIST=…/cve-clean-offset.list` (denylist includes 49980) +- Bacon: `scripts/009-bacon-axp-stage1-combo4-cve-clean.sh` (or + `009-bacon-cve-clean-post49980` host wrapper) +- Baseline-only: `scripts/009-bacon-axp-stage1-combo4.sh` + +## Applied (attributable) + +### A. Combo4 defconfig + Clang FORTIFY port + +| Item | Source / notes | +|------|----------------| +| `CONFIG_FORTIFY_SOURCE=y` | Ship; Clang port required on this toolchain | +| `CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y` | Combo4 | +| `CONFIG_INIT_ON_FREE_DEFAULT_ON=y` | Combo4 | +| `CONFIG_SECURITY_DMESG_RESTRICT=y` | Combo4 | +| `CONFIG_SLAB_FREELIST_HARDENED=y` | Combo4 (not `SLAB_HARDENED` alone) | +| Clang FORTIFY / `__pass_object_size` | `fortify-clang/apply_fortify_clang.py` (Kees-class port adapted to 4.14 `string.h`) | +| Nested strlen fix | `strlcpy`/`strcpy` use `__underlying_strlen(q)` — LAB smoking gun 2026-09-28 | +| Driver bounds | `fortify-clang/0001-driver-bounds-rtac-fils.patch` (link/false-path) | +| `# CONFIG_KSU is not set` | Magisk track | + +### B. Stage1 Graphene / AndroidHardening (30 patches) + +Source tree: AXP `kernel_patches` (host `/srv/rom/references/axp/kernel_patches`). +List: `vendor/sunfish-a16/patches/009-kernel-hardening/stage1.list` via +`apply_stage1.sh`. + +Includes (series names): Deny_USB, allocsize (partial), bugon, fortify +strict-string patch (AXP `0004` — **not** a substitute for the Clang port), +misc, random, ro, sanitize, slab, unused, etc. Full paths in `stage1.list`. + +**LAB marker:** `/proc/sys/kernel/deny_new_usb` present (Graphene Deny USB). + +**Build fix retained:** Stage1 `slab/0014` misfuzz into `is_root_cache` → +reverted in `apply_stage1_combo4.sh` when detected (`BUILD-FIXES.md`). + +## Explicitly NOT in this ship pack + +| Item | Why | +|------|-----| +| Full `cve-strict.list` (~503) | Logo hang; includes high-offset (≥200) and `CVE-2022-49980`. Do not reflash `20260929T181525Z-…-cve` / old `*-kh-cve`. | +| `CVE-2022-49980` (USB gadget UAF) | **Denylist.** Alone reproduces Google-logo hang on LAB (2026-10-01). One-liner takes `udc_lock` in `usb_udc_uevent` while this 4.14 tree still fires uevents under the same lock (`device_add` / bind / unbind). Needs lock-scope companion port, not bulk apply. See `docs/009-cve-bisect-plan.md`. | +| High-offset CVE set (`cve-high-offset-ge200.txt`, ~73) | Quarantine + sunfish filter (26 KEEP). **hi-batch1+2 (15) LAB BOOT_OK `#49`**. Remaining KEEP ~10 (skip `3777`/`26643` nf_tables-class). | +| LinuxIncrementals | Skipped (policy / scope) | +| Failed Stage1 probes | allocsize/0007, ro/0007+0034, slab/0010+0018 — port later | +| Location lockdown | FR-018 — **skip forever on this track**; keep GPS precise/fast (LOS defaults) | +| FORTIFY `BUG()` overflow stubs | Invalid ship fix; never reuse | +| KernelSU / SusFS | Out of Magisk ship track (optional later recycle) | +| Userspace Deblob (Widevine/IMS/CNE) | Deferred (mobile data / Widevine) | +| Bootloader lock | Wont (AXP/LOS unlocked norm) | + +## Historical note (why this pack exists) + +1. Stage1 / CVE / kh-full bacons of 2026-09-18 **compiled** but **did not boot** on LAB (logo hang). +2. Bisect found Clang FORTIFY + nested `strlen` inside `strlcpy` as a hard brick; combo4 without broken FORTIFY booted. +3. Fixed FORTIFY → combo4+FORTIFY Magisk bacon OK → Stage1 **re-tried on that baseline** → LAB OK 2026-09-29. + +## Userspace Gate G (still open) + +Kernel attribution above satisfies the **FR-017 / SC-010 kernel** bullet. +Userspace / signing work is **not** done by this kernel bacon. + +### In scope (do) + +| Item | Intent | +|------|--------| +| **Release / definitive signing keys** | Ship OTAs and images signed with project release keys (not AOSP test-keys). Phonesky and update identity stay on that key across releases. Secrets stay on `rom-dev01` under `/srv/rom/secrets/` — never in Git. | +| **AVB as applicable on unlocked sunfish** | Match GOLDEN/AXP-class AVB *build* posture where LOS 23.2 allows; document any gap that is impossible without locked bootloader or vendor glue we do not have. | +| **Userspace hardening** | Staged Graphene/AXP-class patches (and CVE mega on the boot-OK kernel pack) — attributable, bisectable. | +| **CVE mega (kernel)** | **Partial ship:** clean-offset 429 on Stage1+combo4+FORTIFY (LAB OK). Remaining: high-offset quarantine + proper 49980 port. Never flash `20260918*-kh-cve/full` or full-503 BAD packs. | + +### Out of scope (explicit skip) + +| Item | Why | +|------|-----| +| **Bootloader relock / locked-device ship** | Neither **AXP.OS** nor **LineageOS** ship a locked-bootloader product as the normal path. **IOdes** does; we are not cloning that model. LAB and end-user sunfish remain **unlocked** for Magisk preroot / sideload workflow. Do **not** treat “cannot lock bootloader” as a Gate G failure. | + +Gap rule unchanged: anything still missing from the **in-scope** rows must be present **or** written down as impossible on this stack — no silent omit. + +**Checklist + measured GOLDEN vs LAB:** `docs/009-hardening-signing-checklist.md` +(T040). LAB 2026-09-29 is still `userdebug`/`test-keys`/`orange`; GOLDEN is +`user`/`release-keys`/`orange` unlocked — same unlock class, missing project +keys. + +## Prior known-good (fallback) + +| Artifact | Role | +|----------|------| +| `20260929T033128Z-axp-combo4-fortify` | Magisk + combo4+FORTIFY **without** Stage1 | +| `20260918T143547Z-axp-full` | Pre-KH Magisk baseline (bisect GOODMAKE source) | + +## Owner LAB smoke (2026-09-29) + +Owner reported Magisk, microG, and related checks OK on Stage1 pack after +sideload to slot `_b`. Optional: second sideload to refresh leftover slot `_a` +(not required for daily use). diff --git a/docs/009-hardening-signing-checklist.md b/docs/009-hardening-signing-checklist.md new file mode 100644 index 0000000..531286b --- /dev/null +++ b/docs/009-hardening-signing-checklist.md @@ -0,0 +1,248 @@ +# 009 — Userspace hardening / signing / AVB checklist (Gate G) + +**Task:** T040. +**Companion:** kernel half = `docs/009-gate-g-kernel-attribution.md`. +**Policy (2026-09-29):** project **release keys yes**; **bootloader relock no** +(AXP/LOS unlocked norm; IOdes-class lock = non-goal). See +`specs/009-axp-los23-port/research.md`. + +Secrets never enter Git. Host material lives under `/srv/rom/secrets/` on +`rom-dev01` only. + +--- + +## Measured baseline (2026-09-29) + +| Prop / fact | GOLDEN (AXP Pro) | LAB (Stage1 pack) | Target | +|-------------|------------------|-------------------|--------| +| `ro.build.type` | `user` | `userdebug` | `user` for ship; `userdebug` OK while developing | +| `ro.build.tags` | `release-keys` | `test-keys` | `release-keys` | +| `ro.build.flavor` | `lineage_sunfish-user` | `lineage_sunfish-userdebug` | `…-user` at ship | +| `ro.debuggable` | `0` | `0` on LAB measure wait — typically `1` on userdebug | `0` on ship | +| `ro.secure` | `1` | (LOS default) | `1` | +| `ro.boot.flash.locked` | `0` | `0` | `0` (unlocked — intentional) | +| `ro.boot.verifiedbootstate` | `orange` | `orange` | `orange` while unlocked | +| `ro.boot.vbmeta.device_state` | `unlocked` | (same class) | unlocked | +| `ro.boot.veritymode` | `enforcing` | expect enforcing | keep | +| SELinux | Enforcing (expect) | **Enforcing** | keep | +| OTA zip cert | AXP releasekey | **AOSP `testkey.x509.pem`** (byte-match on stage1 zip) | project releasekey | +| AVB signing key in tree | AXP custom | `external/avb/test/data/testkey_rsa2048.pem` | project AVB key | +| `BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS --flags 3` | AXP sets real AVB when enabled | LOS sunfish adds `--flags 3` unless `WITH_AVB=true` | keep flags 3 (signing infra only; not runtime harden) | + +LAB adb sample (device `11231JEC207477`, Stage1 sideload): +`test-keys` / `userdebug` / `orange` / `flash.locked=0` / `getenforce=Enforcing`. + +GOLDEN source: `/srv/rom/references/axp/golden/2026-09-13/getprop.txt`. + +--- + +## What “done” means for Gate G userspace + +1. Ship images/OTAs verify as **`release-keys`** (not AOSP test-keys). +2. Phonesky / microG keep **their** project JKS identities under + `/srv/rom/secrets/{phonesky,microg}-signing/` (already exist). +3. AVB *build* uses project keys where LOS23/sunfish allows; device stays + **unlocked** (`orange`). Relock is **out of scope**. +4. Userspace hardening stages are attributable (patch dir + map) or explicitly + deferred/skipped with reason. +5. Gaps written down — no silent omit. + +--- + +## Stages (do in order) + +### US-S0 — Inventory (this doc) — **done 2026-09-29** + +- [x] Compare GOLDEN vs LAB signing/AVB props. +- [x] Confirm stage1 zip OTA cert == AOSP testkey. +- [x] Confirm no `~/.android-certs` / platform release keys on host yet + (only Phonesky + microG JKS). +- [x] Record bootloader-lock = wont. + +### US-S1 — Generate project Android signing keys — **done 2026-09-29 (host)** + +Host-only. Never commit `.pk8` / private PEM. + +| Key | Role | +|-----|------| +| `releasekey` | Default APK/OTA (`PRODUCT_DEFAULT_DEV_CERTIFICATE`) | +| `platform` | `platform`-signed priv-apps | +| `shared` / `media` / `networkstack` / `sdk_sandbox` / `bluetooth` / `nfc` | AOSP partition signing set | + +Procedure: `scripts/009-generate-release-keys.sh` on `rom-dev01` +→ prefers `/srv/rom/secrets/android-certs/` if writable, else +`$HOME/.android-certs` (Lineage default; used 2026-09-29 because secrets/ +is root-owned 750 without group write). + +**Mandatory before first signed ship bacon:** encrypted/offline backup of that +directory (constitution). Public `*.x509.pem` may later be copied into Git for +docs; private material must not. + +Acceptance: + +- [x] `$HOME/.android-certs/{releasekey,platform,…}.{pk8,x509.pem}` + `avb.pem` + exist on `rom-dev01` (2026-09-29T16:37Z) +- [x] Host tar backup: `/home/android-build/backups/android-certs-20260929T1637Z.tar.gz` + (mode 600; SHA256 in `.sha256`) — **still copy offline/encrypted** +- [x] `releasekey` DN = `O=AXP-Resurection, OU=sunfish-a16, CN=release` + (not AOSP testkey) +- [ ] Root later: `install -d` `/srv/rom/secrets/android-certs` and move keys there +- [ ] Owner offline encrypted copy confirmed + +### US-S2 — Wire release keys into bacon — **in progress** + +Lineage convention: `PRODUCT_DEFAULT_DEV_CERTIFICATE` → path without suffix +(e.g. `…/releasekey`). On LOS 23 / soong, **env export alone is ignored** — +must be a product makefile `PRODUCT_` (see `vendor/sunfish-a16/signing.mk`, +inherited via `magisk.mk`). Verified `get_build_var` → project releasekey. + +Keys **present** on rom-dev01 (`$HOME/.android-certs/releasekey.pk8`, 2026-09-29). +First artifact `20261001T221102Z-…-cve-hi-releasekeys` was **still AOSP testkey** +(env-only wire). Rebacon after `signing.mk` (2026-10-01T22:12Z). +CVE LAB bacons keep test-keys. First real signed bacon stays **`userdebug`**. + +**LAB 2026-10-02:** first signed sideload booted Wi‑Fi OK but Bluetooth +crash-looped — zygote `selinux_android_setcontext` failed with +`seinfo=default` for `com.android.bluetooth`. Cause: APK signed with project +`certs/bluetooth.pk8` while `MAINLINE_BLUETOOTH_SEPOLICY_DEV_CERTIFICATES` +stayed on AOSP `build/make/target/product/security/` (non-`com.google.android.bt` +default in `config.mk`). Fix: `PRODUCT_MAINLINE_BLUETOOTH_SEPOLICY_DEV_CERTIFICATES` +in `signing.mk` (rebacon required; boot-only flash insufficient). + +Acceptance: + +- [ ] Zip `META-INF/com/android/otacert` ≠ AOSP testkey +- [ ] `ro.build.tags=release-keys` on LAB after **sideload** (boot-only flash insufficient) + (note: first RK sideload still showed `dev-keys` on userdebug — recheck after BT fix) +- [x] Magisk preroot + microG + Wi‑Fi **and Bluetooth** OK on Stage1+combo4+CVE-hi ship pack + (`20261002T085915Z-…-cve-hi-releasekeys`, LAB 2026-10-02: BT ON, crashed 0) +- [x] `plat_mac_permissions.xml` embeds project `bluetooth.x509.pem` (`seinfo=bluetooth`) +- [ ] Minor: LOS SetupWizard after Wi‑Fi connect can bounce to language step + (Wi‑Fi stays connected; non-blocking; note only) +- [ ] Prior test-keys image retained for bisect + (`20261001T201836Z-…-cve-hi-batch2` / `#49`, or hi-batch3 when OK) + +Script: `scripts/009-bacon-axp-stage1-combo4-cve-hi-releasekeys.sh` + +`vendor/sunfish-a16/signing.mk` → `vendor/sunfish-a16/certs/releasekey` +(in-tree copy of `$HOME/.android-certs`; **gitignored** — soong rejects paths +outside `ANDROID_BUILD_TOP`). + +### US-S3 — Project AVB key (unlocked device) + +Today sunfish often signs with AOSP `testkey_rsa4096` (or rsa2048) and adds +`--flags 3` unless `WITH_AVB=true` (`BoardConfigLineage.mk` / +`BoardConfig-common.mk`). LAB `20261002T085915Z` vbmeta = AOSP testkey_rsa4096 ++ flags 3 (not project `avb.pem`). + +AXP ships custom AVB keys and documents AVB2; GOLDEN stays **unlocked/orange**. +Clone that *signing* posture, not IOdes lock. + +**Bootloader / OEM unlocking (2026-10-02):** relock remains **wont** for this +Magisk track (orange + preroot). Locking with Magisk-patched boot is a brick +risk on Pixel unless the full AVB chain is enforced end-to-end — out of scope. +Keep `flash.locked=0` / `verifiedbootstate=orange`. Prefer leaving **OEM +unlocking** enabled in Developer options as a *best-effort* escape hatch for +future unlock attempts — it is **not** a guarantee of recovery, data +preservation, or rescue from every failure mode (AOSP: unlock ability is +conditional). Do **not** turn it off casually. + +Wire: `vendor/sunfish-a16/BoardConfig.mk` overrides `BOARD_AVB_*` → +`vendor/sunfish-a16/certs/avb.pem` + `SHA256_RSA4096`. Leave `WITH_AVB` +unset so `--flags 3` stays (Magisk-friendly). + +**What flags 3 means (libavb):** `HASHTREE_DISABLED (1) | VERIFICATION_DISABLED (2)`. +Descriptors are not enforced at boot; this is **AVB signing infrastructure**, +not “AVB-hardened verified boot”. Do not call US-S3 “AVB endurecido” while +flags stay 3. A later stage may measure `WITH_AVB=true` (flags 0) + Magisk +resign — separate acceptance. + +Acceptance: + +- [x] `BOARD_AVB_KEY_PATH` → project `vendor/sunfish-a16/certs/avb.pem` +- [x] Artifact gates **fail closed** on **target_files/IMAGES** (not OUT make + images): pubkey sha1 == `avb_pkmd.bin` (≠ AOSP `2597c218…`); Flags `3`; + `verify_image --key` vbmeta + `--expected_chain_partition` vbmeta_system; + Magisk boot hash matches vbmeta; `magiskboot cpio test` ≠ 0 +- [x] Document clearly: runtime AVB enforce = **off** (flags 3) — not “AVB endurecido” +- [x] Device still boots unlocked; Magisk preroot intact (LAB 2026-10-02 sideload + + boot/vbmeta reinforce; `magiskd`, `flash.locked=0`, orange) +- [x] No bootloader relock; OEM unlocking left enabled (escape hatch, not guarantee) + +### Branding (no rebacon-only) + +- [x] Wire `vendor/sunfish-a16/branding.mk` → + `TARGET_UNOFFICIAL_BUILD_ID=AXP-Resurection-Pro` (full Magisk track, not slim; + next bacon embeds it in `ro.lineage.version`) +- [x] Ship script publishes sibling `AXP-Resurection-Pro-*-sunfish.zip` + (hardlink/copy of Lineage bacon zip). Current artifact renamed the same way + without rebuild. + +### US-S4 — Userspace hardening (first attributable pack) + +See `docs/009-us-s4-userspace-hardening.md`. + +- [x] Stage 0 LAB measure (Enforcing + FBE) +- [x] US-S4-1: strip Openssh/rsync/procmem packages from Lineage `common.mk` + (`apply_009_drop_openssh_packages.py`); keep `init.openssh.rc` (AXP PRO) +- [x] LAB 2026-10-02: ship `20261002T151944Z` sideloaded + reinforced; + see `docs/009-lab-acceptance-20261002-uss4.md` +- [ ] **US-S4-2** (wired, pending bacon): drop Jelly + Gallery2 (AXP PRO + product oracle — Fossify stays); `apply_009_drop_jelly_gallery2.py` + + `NoLineageJelly`; see `docs/009-axp-pro-product-apps-20260324.md` + +| Candidate | Priority | Notes | +|-----------|----------|-------| +| Confirm SELinux Enforcing + encryption | **done** | LAB Enforcing + FBE | +| ptrace/Yama | **done US-S5-1** | LAB `162840Z` `CONFIG_SECURITY_YAMA=y` | +| Debug/bugreport surface trim | **done US-S4-1** | AXP PRO product oracle | +| Jelly + Gallery2 debloat | **US-S4-2 wired** | AXP PRO product; Fossify kept | +| mount flags / noexec where stock allows | early | don't break HW | +| hardened_malloc | later | Graphene/AXP; portability cost | +| Broad Graphene framework (scopes, etc.) | later / deferred | high UX cost; not Magisk-clone MVP | + +Ship patches under `vendor/sunfish-a16/patches/009-axp-los23-port/hardening/` with README +attribution. One stage per bacon when risk is unclear. + +### US-S5 — Kernel CVE mega / more Graphene (on boot-OK pack) + +**Do not** flash old `20260918*-axp-kh-cve` / `kh-full` (logo hang). + +- [x] CVE clean-offset 429 + hi-batch1–3 on Magisk ship (`151944Z` LAB OK) +- [x] **US-S5-1** LAB OK (`162840Z`): `CONFIG_SECURITY_YAMA=y` + + `CONFIG_SLAB_FREELIST_RANDOM=y` — see + `docs/009-lab-acceptance-20261002-uss5.md` +- [ ] Optional later: `CVE-2022-49980` lock-scope port; Stage1 slab FAIL + retries; `hardened_malloc` + +Map updates: `docs/009-kernel-hardening-map.md` + Gate G attribution. + +### US-S6 — Optional later + +- [ ] Switch default lunch to `lineage_sunfish-user` for ship +- [ ] GPG-sign published SHA sums (AXP does; nice-to-have) +- [ ] LOS23 nightly rebase (vanilla + re-apply Magisk/stage1/keys) +- [ ] Bootloader lock — **wont** + +--- + +## Host paths + +| What | Path | +|------|------| +| Platform / OTA / AVB secrets | `$HOME/.android-certs/` on rom-dev01 (2026-09-29); prefer `/srv/rom/secrets/android-certs/` after root relocate | +| Certs tar backup | `/home/android-build/backups/android-certs-20260929T1637Z.tar.gz` | +| Phonesky JKS | `/srv/rom/secrets/phonesky-signing/` | +| microG JKS | `/srv/rom/secrets/microg-signing/` | +| Keygen script (repo) | `scripts/009-generate-release-keys.sh` | +| Signing README (vendor) | `vendor/sunfish-a16/patches/009-axp-los23-port/signing/README.md` | +| GOLDEN props | `/srv/rom/references/axp/golden/2026-09-13/` | +| AXP docs (mirror) | `…/axpos.org/docs/knowledge/{signatures,verifiedboot}/` | + +--- + +## Explicit non-goals + +- Bootloader relock / green verified-boot for end users. +- Replacing Phonesky/microG keys with platform keys. +- Committing private keys or passphrases to Git. +- Treating missing lock as Gate G failure. diff --git a/docs/009-internet-connectivity-axp-providers.md b/docs/009-internet-connectivity-axp-providers.md new file mode 100644 index 0000000..9884841 --- /dev/null +++ b/docs/009-internet-connectivity-axp-providers.md @@ -0,0 +1,64 @@ +# AXP Internet connectivity check providers (from GOLDEN Settings) + +Source: `Settings.apk` on GOLDEN `11071JEC203839` +(`ConnectivityCheckPreferenceController` + `connectivity_check_*` arrays), +pulled 2026-09-18. +Artifact: `.local-artifacts/002-golden/20260918-connectivity/` + +Preference: **Internet connectivity check** +(`connectivity_check_settings`) — sets global +`captive_portal_{http,https,fallback,other_fallback}_url` and +`captive_portal_mode`. + +## GOLDEN UI list (as shipped) + +| value | UI label | HTTP check URL | +|------:|----------|----------------| +| 0 | Disabled | *(mode=0; stock Google URLs cleared/disabled)* | +| 1 | Amazon Fire OS (US) | `http://fireoscaptiveportal.com/generate_204` | +| 2 | Cloudflare (US) | `http://cp.cloudflare.com` | +| 3 | **AXP.OS (DE)** | `http://captiveportal.axpos.org/generate_204` | +| 4 | Google (US) [default] | `http://connectivitycheck.gstatic.com/generate_204` | +| 5 | Huawei (CN) | `http://connectivitycheck.platform.hicloud.com/generate_204` | +| 6 | Kuketz (DE) | `http://captiveportal.kuketz.de` | +| 7 | Microsoft Edge (US) | `http://edge-http.microsoft.com/captiveportal/generate_204` | +| 8 | openSUSE (DE) | `http://conncheck.opensuse.org` | +| 9 | Ubuntu (UK) | `http://connectivity-check.ubuntu.com` | + +Code also implements (not in GOLDEN `connectivity_check_entries`): + +| value | internal name | HTTP check URL | +|------:|---------------|----------------| +| 10 | Xiaomi / MIUI | `http://connect.rom.miui.com/generate_204` | +| 11 | GrapheneOS | `http://connectivitycheck.grapheneos.network/generate_204` | + +Note: value `3` constants are named `DIVESTOS_*` in smali but point at +`captiveportal.axpos.org` and are labeled **AXP.OS (DE)** in the UI. + +## Clone target for LOS 23.2 (sans axp.os) + +**Drop** value 3 / AXP.OS / `*.axpos.org` entirely (spec: no axp.os endpoints). + +Ship UI (renumber values contiguously after drop): + +| UI label | HTTP | HTTPS | +|----------|------|-------| +| Disabled | — | — | +| Amazon Fire OS (US) | `http://fireoscaptiveportal.com/generate_204` | `https://fireoscaptiveportal.com/generate_204` | +| Cloudflare (US) | `http://cp.cloudflare.com` | `https://cp.cloudflare.com` | +| Google (US) [default] | `http://connectivitycheck.gstatic.com/generate_204` | `https://www.google.com/generate_204` | +| Huawei (CN) | `http://connectivitycheck.platform.hicloud.com/generate_204` | `https://connectivitycheck.platform.hicloud.com/generate_204` | +| Kuketz (DE) | `http://captiveportal.kuketz.de` | `https://captiveportal.kuketz.de` | +| Microsoft Edge (US) | `http://edge-http.microsoft.com/captiveportal/generate_204` | same (AXP uses HTTP URL for https slot) | +| openSUSE (DE) | `http://conncheck.opensuse.org` | `https://conncheck.opensuse.org` | +| Ubuntu (UK) | `http://connectivity-check.ubuntu.com` | `https://connectivity-check.ubuntu.com` | + +Optional extras already in GOLDEN controller (owner choice later): Xiaomi, GrapheneOS. + +Google default also sets: +- fallback: `http://www.google.com/gen_204` +- other fallback: `http://play.googleapis.com/generate_204` + +GrapheneOS (if enabled later) also sets: +- fallback: `http://grapheneos.online/gen_204` +- other: `http://grapheneos.online/generate_204` diff --git a/docs/009-kernel-boot-audit-20260926.md b/docs/009-kernel-boot-audit-20260926.md new file mode 100644 index 0000000..d83672b --- /dev/null +++ b/docs/009-kernel-boot-audit-20260926.md @@ -0,0 +1,229 @@ +# 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](009-kernel-boot-image-comparison-20260926.txt). + +- 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](https://source.android.com/docs/security/features/keystore/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. diff --git a/docs/009-kernel-boot-image-comparison-20260926.txt b/docs/009-kernel-boot-image-comparison-20260926.txt new file mode 100644 index 0000000..faa3a09 --- /dev/null +++ b/docs/009-kernel-boot-image-comparison-20260926.txt @@ -0,0 +1,125 @@ +Comparación directa de imágenes — 2026-09-26 +GOODMAKE: .local-artifacts/009-flash-20260918T143547Z/boot-make.img +MILD: rom-dev01:/srv/rom/artifacts/009-axp-los23-port/20260921T192533Z-bisect-defconfig-mild/boot-make.img + +good: SHA256=fcc52ec5c7c077def20ce9d9b9ac3782475e0834817f453e845eb2c1e66d1255 +header patch level: 2026-09 +ro.build.version.sdk_full=36.1 +ro.build.version.security_patch=2026-09-01 +ro.build.version.sdk_full=36.1 +ro.build.version.security_patch=2026-09-01 +kernel: SHA256=5db3af0d7eb76dcd26d7fdbe7dad554d7493073bfa3495f1b49c1aa323ad6b4f +ramdisk.cpio: SHA256=a2e412792fa236a1db3416b6bf7ed374e606f88c714339319759b04f84d90067 +dtb: SHA256=2fca15709ff6d9f48fea938952439e8d00c2b998c73e7a216172ae3965b07566 + +mild: SHA256=6ed0351edb762bdf4bfe2dd96d7e4e2fa43ccf0ad497d7fce35ab88cd722f4f2 +header patch level: 2025-08 +ro.build.version.sdk_full=36.0 +ro.build.version.security_patch=2025-08-05 +ro.build.version.sdk_full=36.0 +ro.build.version.security_patch=2025-08-05 +kernel: SHA256=c7829fa4751643067da5ca6e726d402771c781cfc10771201ab989d73a10cdf8 +ramdisk.cpio: SHA256=17d51096168cffb1bb0d93682045203d50e3fc00783f4339e4b79adf0785b3eb +dtb: SHA256=2fca15709ff6d9f48fea938952439e8d00c2b998c73e7a216172ae3965b07566 + +Configuración extraída de IKCONFIG de cada kernel: +--- GOODMAKE.config ++++ MILD.config +@@ -243,7 +243,7 @@ + # CONFIG_SLOB is not set + CONFIG_SLAB_MERGE_DEFAULT=y + # CONFIG_SLAB_FREELIST_RANDOM is not set +-# CONFIG_SLAB_FREELIST_HARDENED is not set ++CONFIG_SLAB_FREELIST_HARDENED=y + CONFIG_SLUB_CPU_PARTIAL=y + CONFIG_SYSTEM_DATA_VERIFICATION=y + CONFIG_PROFILING=y +@@ -2282,12 +2282,7 @@ + # Character devices + # + CONFIG_TTY=y +-CONFIG_VT=y +-CONFIG_CONSOLE_TRANSLATIONS=y +-CONFIG_VT_CONSOLE=y +-CONFIG_VT_CONSOLE_SLEEP=y +-CONFIG_HW_CONSOLE=y +-CONFIG_VT_HW_CONSOLE_BINDING=y ++# CONFIG_VT is not set + CONFIG_UNIX98_PTYS=y + # CONFIG_LEGACY_PTYS is not set + # CONFIG_SERIAL_NONSTANDARD is not set +@@ -3564,16 +3559,6 @@ + # CONFIG_BACKLIGHT_ARCXCNN is not set + # CONFIG_VGASTATE is not set + CONFIG_HDMI=y +- +-# +-# Console display driver support +-# +-CONFIG_DUMMY_CONSOLE=y +-CONFIG_DUMMY_CONSOLE_COLUMNS=80 +-CONFIG_DUMMY_CONSOLE_ROWS=25 +-CONFIG_FRAMEBUFFER_CONSOLE=y +-CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +-CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y + CONFIG_LOGO=y + # CONFIG_LOGO_LINUX_MONO is not set + # CONFIG_LOGO_LINUX_VGA16 is not set +@@ -4493,7 +4478,6 @@ + # + # Speakup console speech + # +-# CONFIG_SPEAKUP is not set + # CONFIG_STAGING_MEDIA is not set + + # +@@ -4780,7 +4764,7 @@ + CONFIG_QCOM_MEMORY_DUMP_V2=y + # CONFIG_MSM_DEBUG_LAR_UNLOCK is not set + CONFIG_QCOM_WATCHDOG_V2=y +-# CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC is not set ++CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y + CONFIG_QCOM_WDOG_IPI_ENABLE=y + CONFIG_QCOM_SMEM_STATE=y + CONFIG_QCOM_SMP2P=y +@@ -5331,11 +5315,6 @@ + CONFIG_ESOC_MDM_DRV=y + CONFIG_ESOC_MDM_DBG_ENG=y + # CONFIG_MDM_DBG_REQ_ENG is not set +- +-# +-# KernelSU +-# +-# CONFIG_KSU is not set + + # + # Firmware Drivers +@@ -5651,7 +5630,7 @@ + # CONFIG_PANIC_ON_OOPS is not set + CONFIG_PANIC_ON_OOPS_VALUE=0 + # CONFIG_PANIC_ON_WARN_DEFAULT_ENABLE is not set +-CONFIG_PANIC_TIMEOUT=0 ++CONFIG_PANIC_TIMEOUT=5 + CONFIG_SCHED_DEBUG=y + CONFIG_SCHED_INFO=y + # CONFIG_PANIC_ON_SCHED_BUG is not set +@@ -5830,7 +5809,7 @@ + # CONFIG_PFT is not set + CONFIG_PFK=y + # CONFIG_PFK_WRAPPED_KEY_SUPPORTED is not set +-# CONFIG_SECURITY_DMESG_RESTRICT is not set ++CONFIG_SECURITY_DMESG_RESTRICT=y + CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y + CONFIG_SECURITY=y + # CONFIG_SECURITY_WRITABLE_HOOKS is not set +@@ -6139,10 +6118,6 @@ + CONFIG_MPILIB=y + CONFIG_LIBFDT=y + CONFIG_OID_REGISTRY=y +-CONFIG_FONT_SUPPORT=y +-# CONFIG_FONTS is not set +-CONFIG_FONT_8x8=y +-CONFIG_FONT_8x16=y + # CONFIG_SG_SPLIT is not set + CONFIG_SG_POOL=y + CONFIG_ARCH_HAS_SG_CHAIN=y diff --git a/docs/009-kernel-hardening-map.md b/docs/009-kernel-hardening-map.md new file mode 100644 index 0000000..62ccccb --- /dev/null +++ b/docs/009-kernel-hardening-map.md @@ -0,0 +1,267 @@ +# 009 kernel hardening map (FR-017) + +> **Priority finding, 2026-09-26:** Bisect scripts (including the new dmesg-only +> and slab-only scripts) force **bp2a**, whereas the GOOD build used **bp4a**. +> Direct image comparison finds GOODMAKE security patch 2026-09 / SDK 36.1 +> versus mild 2025-08 / SDK 36.0. GOODMAKE boots according to the owner. +> These are not isolated defconfig trials; see the audit below before testing. + +> **Audit 2026-09-26:** Before resuming builds, read +> [the boot investigation](009-kernel-boot-audit-20260926.md). +> The defconfig-only experiment also added FORTIFY C stubs and its `boot.img` +> is byte-identical to the older full-hardening image; only `boot-make.img` +> represents the new build. Its reported boot failure does not yet isolate +> configuration alone. The later mild build already exists; its LAB boot +> result was not found in the reviewed records. +> Subsequent owner-provided history reports failed attempts rebooting into +> recovery (Try again / Factory data reset), followed by successful system +> boot after restoring GOOD. Thus "never recovery" below is not a universal +> description. That history still presents mild as pending; see the audit. + +**Base**: LineageOS 23.2 `sunfish` / `kernel/google/msm-4.14` (non-GKI). +**Not base**: GrapheneOS A13 sunfish tree, random prebuilts, KernelSU. + +## Inventory (2026-09-18, `rom-dev01`) + +| Item | Value | +|------|--------| +| LOS tree | `/srv/rom/src/lineage/kernel/google/msm-4.14` | +| LOS rev | `28f9290ae067` — *Revert "BACKPORT: module: Do not offer sha224…"* | +| Version | `4.14.357-openela` | +| AXP stack | `/srv/rom/references/axp/kernel_patches` @ `df3cab2155b3` (codeberg mirror) | +| Dry-run worktree | `/srv/rom/artifacts/009-axp-los23-port/kernel-harden-dryrun/` | +| Iodé manifest | `/srv/rom/references/iode/android-manifest` (`v5-staging`) | + +### LOS `sunfish_defconfig` already on + +`CFI_CLANG`, `SHADOW_CALL_STACK`, `CC_STACKPROTECTOR_STRONG`, `RANDOMIZE_BASE`, +`ARM64_SW_TTBR0_PAN`, `SECURITY_PERF_EVENTS_RESTRICT`, `HARDENED_USERCOPY`(+PAGESPAN), +`BUG_ON_DATA_CORRUPTION`, `SCHED_STACK_END_CHECK`, `# CONFIG_DEVMEM is not set`, +`BPF_JIT_ALWAYS_ON`. +`# CONFIG_UNMAP_KERNEL_AT_EL0 is not set` (kept as LOS). + +### LOS defconfig gaps (vs typical Graphene/AH) + +Not set in `sunfish_defconfig` (may need Kconfig + patches first): +`FORTIFY_SOURCE`, `INIT_ON_ALLOC_DEFAULT_ON`, `INIT_ON_FREE_DEFAULT_ON`, +`SLAB_FREELIST_RANDOM`, `SLAB_FREELIST_HARDENED`, `SHUFFLE_PAGE_ALLOCATOR`, +`PAGE_POISONING`, `SECURITY_DMESG_RESTRICT`, `DEBUG_LIST`, `REFCOUNT_FULL`. + +### AXP `kernel_patches` shape + +| Series | 4.14 patches | Role | +|--------|-------------:|------| +| `0001-LinuxIncrementals` | 335 | Version bumps — **skip** (tree already 4.14.357-openela) | +| `0004`–`0006`, `0008-*`, `0009` | ~40 Graphene/AH | Stage-1 candidates (below) | +| `CVE-*` dirs | ~2301 with 4.14 | Mega CVE stage — **later**, after Stage 1 boots | +| Location-related | — | **Skip** (FR-018 policy) | + +### IodéOS + +`v5-staging` manifest cloned; **no** `sunfish` / `msm-4.14` kernel project in +snippets. Public gitlab device/kernel repos need auth. Treat Iodé as +**userspace privacy** for this device; no extra 4.14 kernel delta found. + +## Source priority (owner 2026-09-18) + +| Priority | Source | Role | +|----------|--------|------| +| 1 | **AXP** sunfish kernel / build patches | Clone first (max) | +| 2 | **LOS 23.2** msm-4.14 as shipped | Inventory; skip dupes | +| 3 | **IodéOS** (LOS fork) | Diff for extra 4.14-safe hardening/deblob | +| 4 | **GrapheneOS** | Optional: modern techniques / docs; A13 sunfish only if clearly useful | +| — | **DivestOS** standalone | **Do not hunt** (EOL). AXP-inherited commits OK via AXP clone | + +## Location policy + +**Do not** extra-cap location vs LOS defaults (FR-018). Skip AXP location +lockdown patches; document as skipped. Goal: **precise, fast GPS** like +stock LOS 23.2 — not AXP privacy lockdown. Deblob/CVE stages must not +reintroduce location hardening by accident. + +## Sequential apply probe (Graphene/AH only) + +Clean worktree @ `28f9290ae067`, patches from AXP `kernel_patches` in Divest-like +order (`4.14` then `ANY`). Result: **OK=30, SKIP_ALREADY=4, FAIL=12**. + +Full machine log: +`/srv/rom/artifacts/009-axp-los23-port/kernel-harden-dryrun/apply-sequential-summary.txt` + +## Patch ledger + +| id | title | source | AXP? | 4.14-safe? | decision | notes | +|----|-------|--------|------|------------|----------|-------| +| KH-INC | LinuxIncrementals 4.14 (335) | AXP `0001` @ df3cab215 | Y | n/a | **skip** | Already 4.14.357-openela | +| KH-004 | Perf events restrict | AXP `0004` ANY/0001 | Y | Y | **skip** | Already in LOS (`SKIP_ALREADY` + defconfig) | +| KH-005 | Deny USB (toggle) | AXP `0005-Graphene-Deny_USB` 4.14/0003 | Y | Y | **stage1 apply** | Clean apply | +| KH-006 | wcnss buffer fixes | AXP `0006` ANY/0001–0003 | Y | ? | **skip/port later** | Wrong path on this tree (`can't find file`) | +| KH-008-as | alloc_size attrs | AXP `0008-…-allocsize` | Y | Y | **stage1 apply** | OK: 0002,0011,0016,0021; FAIL: 0007 (vmalloc.h hunk) | +| KH-008-bug | ksize BUG_ON | AXP `0008-…-bugon` 0010 | Y | Y | **stage1 apply** | OK | +| KH-008-fort | FORTIFY intra-object | AXP `0008-…-fortify` 0004 | Y | Y | **stage1 apply** | OK; then enable `CONFIG_FORTIFY_SOURCE` | +| KH-008-misc | misc Graphene | AXP `0008-…-misc` | Y | Y | **stage1 apply** | OK 0001,0005,0010,0018; SKIP 0021 + ANY/0015 | +| KH-008-rnd | brk/arg randomize | AXP `0008-…-random` | Y | Y | **stage1 apply** | All 4 OK when sequential | +| KH-008-ro | __ro_after_init / sysctl RO | AXP `0008-…-ro` | Y | partial | **stage1 apply** | OK most; FAIL 0007, 0034 (sysctl drift) | +| KH-008-san | page/slab sanitize | AXP `0008-…-sanitize` | Y | Y | **stage1 apply** | All 4 OK sequential | +| KH-008-slab | SLAB_HARDENED | AXP `0008-…-slab` | Y | partial | **stage1 apply** | OK 0006,0014; FAIL 0010,0018 | +| KH-008-un | unused-fn noise | AXP `0008-…-unused` | Y | Y | **stage1 apply** | OK (build hygiene) | +| KH-009 | rfc4941bis IPv6 | AXP `0009` | Y | partial | **skip** | 4.14/0003 already present; ANY/* fail | +| KH-CVE | CVE clean-offset 429 + denylist | AXP `CVE-*` | Y | LAB OK `#47` | **ship partial** | `cve-clean-offset.list` (ex-430−49980); high-offset ≥200 quarantined; `CVE-2022-49980` denylist (udc_lock); see `009-cve-bisect-plan.md` / `009-axp-graphene-remaining.md` | +| KH-LOC | AXP location lockdown | AXP | Y | — | **skip** | FR-018 | +| KH-IODE | Iodé kernel delta | Iodé | — | — | **skip** | No sunfish 4.14 fork found | +| KH-CFG | Hardening defconfig | LOS+AXP | — | Y | **stage1 after patches** | Flip gaps that Kconfig allows post-patch | +| KH-US-S5-1 | Yama + SLAB_FREELIST_RANDOM | Graphene/AXP class | Y | Y | **apply** | `apply_uss5_1_defconfig.sh`; LSM already listed yama | + +### Stage 1 apply list (exact files) + +From host `$KP=/srv/rom/references/axp/kernel_patches` — **only** these (order +matters): + +``` +0005-Graphene-Deny_USB/4.14/0003.patch +0008-Graphene-Kernel_Hardening-allocsize/4.14/0002.patch +0008-Graphene-Kernel_Hardening-allocsize/4.14/0011.patch +0008-Graphene-Kernel_Hardening-allocsize/4.14/0016.patch +0008-Graphene-Kernel_Hardening-allocsize/4.14/0021.patch +0008-Graphene-Kernel_Hardening-bugon/4.14/0010.patch +0008-Graphene-Kernel_Hardening-fortify/4.14/0004.patch +0008-Graphene-Kernel_Hardening-misc/4.14/0001.patch +0008-Graphene-Kernel_Hardening-misc/4.14/0005.patch +0008-Graphene-Kernel_Hardening-misc/4.14/0010.patch +0008-Graphene-Kernel_Hardening-misc/4.14/0018.patch +0008-Graphene-Kernel_Hardening-random/4.14/0002.patch +0008-Graphene-Kernel_Hardening-random/4.14/0007.patch +0008-Graphene-Kernel_Hardening-random/4.14/0012.patch +0008-Graphene-Kernel_Hardening-random/4.14/0017.patch +0008-Graphene-Kernel_Hardening-ro/4.14/0002.patch +0008-Graphene-Kernel_Hardening-ro/4.14/0012.patch +0008-Graphene-Kernel_Hardening-ro/4.14/0017.patch +0008-Graphene-Kernel_Hardening-ro/4.14/0028.patch +0008-Graphene-Kernel_Hardening-ro/4.14/0030.patch +0008-Graphene-Kernel_Hardening-ro/4.14/0032.patch +0008-Graphene-Kernel_Hardening-ro/4.14/0038.patch +0008-Graphene-Kernel_Hardening-sanitize/4.14/0005.patch +0008-Graphene-Kernel_Hardening-sanitize/4.14/0009.patch +0008-Graphene-Kernel_Hardening-sanitize/4.14/0015.patch +0008-Graphene-Kernel_Hardening-sanitize/4.14/0017.patch +0008-Graphene-Kernel_Hardening-slab/4.14/0006.patch +0008-Graphene-Kernel_Hardening-slab/4.14/0014.patch +0008-Graphene-Kernel_Hardening-unused/4.14/0001.patch +0008-Graphene-Kernel_Hardening-unused/4.14/0002.patch +``` + +Then defconfig (only options that exist after patches): at least +`CONFIG_FORTIFY_SOURCE=y`; evaluate `INIT_ON_*` / slab freelist / dmesg restrict +against Kconfig `depends on` before flipping. + +## Applied / skipped summary + +- **Applied (2026-09-18, live tree):** Stage 1 — 30 AXP Graphene/AH patches via + `vendor/sunfish-a16/patches/009-kernel-hardening/apply_stage1.sh` onto + `/srv/rom/src/lineage/kernel/google/msm-4.14` (Stage1 alone ~28 paths; + tree also had prior Magisk-track dirt: KSU/SusFS `# CONFIG_* is not set` + stubs + residual SusFS-touched fs/overlayfs etc. — not Stage1). +- **Defconfig (same day):** `CONFIG_FORTIFY_SOURCE=y`, + `CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y`, `CONFIG_INIT_ON_FREE_DEFAULT_ON=y`, + `CONFIG_SECURITY_DMESG_RESTRICT=y`, `CONFIG_SLAB_HARDENED=y`. +- Skipped: location lockdown (policy); Divest-as-hunt (policy); LinuxIncrementals; + KH-004 (already present); KH-006 wcnss (path miss); KH-009 ANY; Iodé kernel + (none found); CVE mega (in progress via `cve_checker`) +- Failed probe (port later): allocsize/0007, ro/0007+0034, slab/0010+0018 +- **Build fix 2026-09-18:** Stage1 `slab/0014` misfuzzed into `is_root_cache` + (`return p == s` with no `p`) — reverted that stub. Intent was + `slab_equal_or_root`; LOS already has `return s == p` there. +- **Build fix 2026-09-18b:** `CONFIG_FORTIFY_SOURCE=y` + Clang LTO left + `__read_overflow*` undefined in modules (qcacld/techpack) — added `BUG()` + stubs + `EXPORT_SYMBOL` in `lib/string.c`. +- **Bacon OK (Stage1 only):** + `/srv/rom/artifacts/009-axp-los23-port/20260918T180359Z-axp-kh-stage1/` +- **CVE bacon OK:** + `/srv/rom/artifacts/009-axp-los23-port/20260918T215034Z-axp-kh-cve/` + Stage1 + ~500 CVE patches that compile. ~34 incomplete series on denylist + (`cve-stage/denylist.txt`) — skipped, not silently dropped without a log. + Magisk preroot present; KernelSU absent. +- **More complete bacon OK:** + `/srv/rom/artifacts/009-axp-los23-port/20260918T231654Z-axp-kh-full/` + AXP `hardenDefconfig` on the CVE tree (only options this Kconfig has). + Left on: `IO_URING`, `USERFAULTFD`, WireGuard, IPA. Magisk preroot OK. +- **Not done:** userspace Deblob.sh (Widevine/IMS/CNE). Kernel deblob in AXP + is mostly IPA removal — skipped so mobile data keeps working. +- **Flash target (LAB 2026-09-21):** back on + `20260918T143547Z-axp-full` (pre-kernel-hardening). Owner confirmed boot OK. +- **Boot-fail (LAB 2026-09-21):** all three KH artifacts hang at Google logo + (bootloader splash, never recovery/Android): + - `231654Z-axp-kh-full`, `215034Z-axp-kh-cve`, `180359Z-axp-kh-stage1` + - Stage1 **`boot-make.img` (no Magisk)** also hangs → kernel Stage1 (+ + Stage1 defconfig extras), not Magisk packaging. + - OTA `payload` boot == Magisk artifact boot; OTA `dtbo` identical across + good vs Stage1. Loose `dtbo.img`/`vbmeta.img` in artifact dirs ≠ payload + (do not flash those sueltos). Embedded boot `dtb` identical all four. + - `/sys/fs/pstore` empty after failed boots (no ramoops). +- **Bisect 2026-09-21:** `20260921T185024Z-bisect-defconfig-only` + (clean LOS + FORTIFY/INIT_ON_*/DMESG/SLAB_FREELIST_HARDENED, no Graphene + patches) → LAB **bootloop** / try-again recovery. +- **LAB 2026-09-28:** Clang FORTIFY nested-`strlen` fix (`strlcpy`/`strcpy` → + `__underlying_strlen`). Family `full` + **combo4+FORTIFY** boot. Magisk bacon: + `apply_combo4_fortify.sh` / `009-bacon-axp-combo4-fortify.sh`. +- **LAB 2026-09-29 (ship kernel pack):** Stage1 (30) + combo4 + Clang FORTIFY + Magisk bacon `20260929T123401Z-axp-stage1-combo4` — boots, Wi‑Fi CRC OK, + Deny USB sysctl present. Attribution: `docs/009-gate-g-kernel-attribution.md`. + Apply: `apply_stage1_combo4.sh`. Bacon: `009-bacon-axp-stage1-combo4.sh`. +- **CVE re-try 2026-09-29:** full `cve-strict` (503) = LAB Google logo hang. + Bisect: `docs/009-cve-bisect-plan.md` (`cve-bisect-h1/h2.list`). +- **Bisect 2026-09-21 mild:** `DMESG_RESTRICT` + `SLAB_FREELIST_HARDENED` + only → same failure. +- **Control 2026-09-26:** `20260918T143547Z` **boot-make.img** (no Magisk, + no extra CONFIG) flashed onto Magisk system → **boots OK**. +- **Audit 2026-09-26 (owner second opinion):** bisect scripts wrongly used + `lunch …-bp2a-userdebug` while good bacon uses `breakfast` → `bp4a`. + Mild/defconfig-only boots carry `security_patch=2025-08-05` / SDK 36.0 vs + GOODMAKE `2026-09-01` / 36.1; ramdisk and other kernel options also differ. + **Invalidates** “DMESG/SLAB alone kill boot”. bp2a one-config builds aborted. + See `docs/009-kernel-boot-audit-20260926.md`. +- **Control ksync 2026-09-26:** new breakfast/bp4a kernel (no Stage1 CONFIG) + injected into GOODMAKE ramdisk → LAB **boots OK** (`20260926T161646Z-bisect-ksync-control`). + Method validated. Next: same inject path, one CONFIG at a time (DMESG then SLAB). + **Future tests:** always `breakfast`/bp4a + inject kernel into GOODMAKE ramdisk; + never bp2a-only bootimage as a “config” experiment. Lessons also in agent + personal store `009-kernel-bisect-lessons.md`. + Deblob still deferred (GPS: no AXP location lockdown). + +## CVE / hardening / deblob policy (owner 2026-09-18 evening) + +- **Source of truth**: AXP method (`kernel_patches` + `cve_checker`), applied onto + LOS23 `msm-4.14` — not inventing our own CVE hunt. +- **Skip if already fixed** in LOS tree (patcher “already applied” / reverse + hunks). LOS23 is newer than AXP22; many CVEs may already be present via + `4.14.357-openela`. Hardening/deblob are where AXP usually still wins. +- **Loose 4.19**: when enabled, the patcher may also try patches filed under + `4.19/` (and with extreme matching, even `^5.x`/`^6.x`) on a `4.14` tree. + First pass with loose ON applied ~185 non-4.14 patches and **broke the + build** (incomplete binder/bpf/f2fs series). **OFF for CVE apply** (exact + `4.14` + `ANY` only). Re-evaluate later if needed. +- **On failure**: do not silent-drop — attempt fix / adapt / re-apply; only + then document skip with reason (AXP `Fix_CVE_Patchers` style). +- **Deblob**: AXP deblob pass after CVE/hardening inventory (separate from CVE + IDs); Lineage rarely matches AXP here. +- **Flash**: owner on return; agent does not need to flash for this phase. + +## 2026 catalog refresh (started 2026-09-19) + +CIP `kernel-sec` cloned at `/srv/rom/references/cip-kernel-sec` @ `025be706` +(2026-09-19). Scrape vs AXP catalog `df3cab215` (2025-10-30): **7086** CVEs +not in that list (6317× CVE-2026, 769× CVE-2025). **None** have a `4.14` +backport link; one has `4.19`. The rest are mainline / 5.10+. + +kernel.org `linux-stable` `v4.14.*` stops at **4.14.336**. Nothing newer to +incremental-apply; the LOS tree is already `4.14.357-openela`. + +Android bulletins (new URL `/docs/security/bulletin/YYYY/YYYY-MM-01`, which +the jar scraper does not accept) have **no** `git.kernel.org` links. Kernel +rows point at `android.googlesource.com/kernel/common`: 2025-12 (44), +2026-03 (36), 2026-06 (2), 2026-09 (10). Links saved in +`/srv/rom/artifacts/009-axp-los23-port/cve-2026/asb-links.txt`. + +Download + checker (read-only on the live tree; does not reset the flashed +kernel) is detached as tmux `009-cve-2026`. One mainline patch per new CVE +lands in `/srv/rom/references/axp/kernel_patches_2026/`. Apply is **not** +started: 2026 patches are 6.x and the last loose pass broke 4.14. diff --git a/docs/009-lab-acceptance-20261002-avb.md b/docs/009-lab-acceptance-20261002-avb.md new file mode 100644 index 0000000..48fa627 --- /dev/null +++ b/docs/009-lab-acceptance-20261002-avb.md @@ -0,0 +1,22 @@ +# LAB acceptance note — 20261002T103558Z (AVB infra ship) + +Device: `11231JEC207477` +Artifact: `20261002T103558Z-axp-stage1-combo4-cve-hi-releasekeys` +Ship zip twin: `AXP-Resurection-Pro-23.2-20261002-sunfish.zip` (= lineage zip bytes) + + +Owner smoke 2026-10-02: no errors reported after sideload + boot/vbmeta reinforce. + +| Gate | Status | Notes | +|------|--------|-------| +| A Boot/HW | pass (owner) | Boots home; Wi‑Fi/BT/call smoke OK per owner | +| B Google stack | pass (prior+owner) | microG/Phonesky path unchanged this bacon | +| C Toggles | pass (prior) | Spoof / call-rec not regressed this bacon | +| D Magisk | pass | `magiskd` present; preroot; unlocked orange | +| E Banking | deferred | Not MVP | +| F Usability | pass (prior) | Bundled apps / WebView LOS | +| G Hardening | partial | Release-keys + AVB **signing** infra (flags 3); US-S4 stage0 measure done; US-S4-1 code pending next content bacon | + +`ro.lineage.version` on this flash is still `23.2-20261002-UNOFFICIAL-sunfish` +(pre-branding.mk). Next content bacon picks up +`…-UNOFFICIAL-AXP-Resurection-Pro-…`. diff --git a/docs/009-lab-acceptance-20261002-uss4.md b/docs/009-lab-acceptance-20261002-uss4.md new file mode 100644 index 0000000..e9e2b90 --- /dev/null +++ b/docs/009-lab-acceptance-20261002-uss4.md @@ -0,0 +1,27 @@ +# LAB acceptance — 20261002T151944Z (US-S4-1 + Pro branding) + +Device: `11231JEC207477` +Artifact: `20261002T151944Z-axp-stage1-combo4-cve-hi-releasekeys` +Ship: `AXP-Resurection-Pro-23.2-20261002-sunfish.zip` + +Sideload + boot/vbmeta/dtbo reinforce 2026-10-02 evening. Owner/ChatGPT artifact +gates + LAB post-boot checks below. + +| Gate | Status | Notes | +|------|--------|-------| +| A Boot/HW | pass | `sys.boot_completed=1`, slot `_a` | +| B Google stack | pass (prior) | microG/Phonesky unchanged this bacon | +| C Toggles | pass (prior) | Not regressed | +| D Magisk | pass | `magiskd` pid present; TF Magisk boot reinforced | +| E Banking | deferred | | +| F Usability | pass (prior) | | +| G Hardening | pass (this pack) | AVB **signing** infra flags=3; US-S4-1 OpenSSH/rsync/procmem absent; `init.openssh.rc` present (AXP) | + +Props: +- `ro.lineage.version=23.2-20261002-UNOFFICIAL-AXP-Resurection-Pro-sunfish` +- `ro.axp.resurection.track=pro` +- `ro.boot.flash.locked=0` +- no `/product/bin/sshd`, no `/product/bin/rsync` +- `/product/etc/init/init.openssh.rc` present + +Prior AVB-only ship note: `docs/009-lab-acceptance-20261002-avb.md` (`103558Z`). diff --git a/docs/009-lab-acceptance-20261002-uss5.md b/docs/009-lab-acceptance-20261002-uss5.md new file mode 100644 index 0000000..c7436c0 --- /dev/null +++ b/docs/009-lab-acceptance-20261002-uss5.md @@ -0,0 +1,27 @@ +# LAB acceptance — 20261002T162840Z (US-S5-1 Yama + SLAB_FREELIST_RANDOM) + +Device: `11231JEC207477` +Artifact: `20261002T162840Z-axp-stage1-combo4-cve-hi-releasekeys` +Ship: `AXP-Resurection-Pro-23.2-20261002-sunfish.zip` + +Sideload Pro zip + reinforce Magisk `boot`/`dtbo`/`vbmeta`/`vbmeta_system` on +active slot `_b` (2026-10-02 evening). + +| Gate | Status | Notes | +|------|--------|-------| +| A Boot/HW | pass | `sys.boot_completed=1`, slot `_b` | +| B Google stack | pass (prior) | microG/Phonesky unchanged this bacon | +| C Toggles | pass (prior) | Not regressed | +| D Magisk | pass | `magiskd` present; TF Magisk boot reinforced | +| E Banking | deferred | PIF/Vector BL spoof — owner config, not this pack | +| F Usability | pass (prior) | | +| G Hardening | pass (this pack) | US-S5-1: `CONFIG_SECURITY_YAMA=y`, `CONFIG_SLAB_FREELIST_RANDOM=y`, LSM lists `yama`; US-S4-1 OpenSSH still absent; `init.openssh.rc` present | + +Props: +- `ro.lineage.version=23.2-20261002-UNOFFICIAL-AXP-Resurection-Pro-sunfish` +- `ro.axp.resurection.track=pro` +- `ro.boot.flash.locked=0`, `verifiedbootstate=orange` +- `/proc/config.gz`: YAMA + SLAB_FREELIST_RANDOM + `LSM=…,yama,…` + +Recover baseline: `20261002T085915Z-axp-stage1-combo4-cve-hi-releasekeys` (README). +Prior US-S4 LAB: `docs/009-lab-acceptance-20261002-uss4.md` (`151944Z`). diff --git a/docs/009-localization-axp-vs-los.md b/docs/009-localization-axp-vs-los.md new file mode 100644 index 0000000..cf7dd22 --- /dev/null +++ b/docs/009-localization-axp-vs-los.md @@ -0,0 +1,22 @@ +# 009 localization / location: AXP vs LOS (deferred — FR-018) + +**Status**: Look later — **not** an MVP acceptance gate. + +Owner note (2026-09-17): AXP has historically felt aggressive on localization / +location; want a deliberate compare vs stock LineageOS before cloning that +policy blindly. + +## What to compare later + +| Area | AXP / GOLDEN | Stock LOS 23 | Decision TBD | +|------|--------------|--------------|--------------| +| Network location / NLP backends | microG BeaconDB path (see `004`/`005` docs) | LOS + microG defaults | | +| Location permission defaults | | | | +| Privacy toggles / sensors | | | | +| Extra lockdown patches | | | | +| UX: “how much it capea” | Owner complaint baseline | | | + +## Until then + +Do **not** invent extra location lockdown beyond what the rest of the AXP clone +already implies. Matrix row = `deferred`. diff --git a/docs/009-magisk-preinstall-runbook.md b/docs/009-magisk-preinstall-runbook.md new file mode 100644 index 0000000..6512c6d --- /dev/null +++ b/docs/009-magisk-preinstall-runbook.md @@ -0,0 +1,111 @@ +# 009 Magisk preinstall runbook (AXP / GOLDEN class) + +**Device roles**: GOLDEN `11071JEC203839` = `adb` **read-only** oracle. +LAB `11231JEC207477` = flash/test only. **Never** flash or Magisk-change GOLDEN. + +**Evidence**: `/srv/rom/artifacts/009-axp-los23-port/` +**Contract**: `specs/009-axp-los23-port/contracts/magisk-preinstall.md` + +## Ship policy (owner 2026-09-17) + +- **Clone AXP first (mandatory):** Magisk packaging = EXTENDROM + `EXTENDROM_PREROOT_BOOT` method. Copy that flow; do **not** invent alternate + Magisk install paths. Only diverge if LOS23 / Magisk version breaks the + AXP/EXTENDROM path, and document why. +- **Magisk clean**: ship Magisk preroot only — **do not** bake GOLDEN modules + (`playintegrityfix`, `teesim`, `hosts`, `flag-secure-disabler`, + `zygisk_vector`, …). Owner installs modules later if wanted. +- **Manager UI**: stock **Magisk** upstream (not Magia branding). +- **Dormant until activation (AXP Pro):** after flash, Magisk is pre-rooted in + boot but root must stay inactive until the user opens Magisk and completes + Additional Setup. Skipping setup ⇒ no `su` / no Magisk binaries in the OS + (undetectable). Do **not** bake Magisk as `PRODUCT_PACKAGE`; do **not** + sideload the full Magisk APK before measuring virgin LAB state. +- **Build host**: LAB/GOLDEN USB **not required** to compile. Phones only for + measurement (GOLDEN `adb`) or flash validation (LAB). + +## GOLDEN measurement (2026-09-17, live `adb`) + +| Item | Value | +|------|--------| +| Build | `22.2-2026.003-sunfish-pro` / `BP1A.250505.005` | +| Magisk binary | **29.0:MAGISK:R** (`29000`) at `/system_ext/bin/magisk` | +| Also present | `/system_ext/bin/magiskpolicy` | +| Runtime | `/data/adb/magisk/` full toolkit + `stub.apk`; `magisk.db` | +| Settings (sqlite via `magisk --sqlite`) | `zygisk=1`, `denylist=1`, `mnt_ns=2`, `bootloop=0` | +| Manager UI | Magisk app **hidden/renamed** (random pkg `oq.aq.cjn`, `versionName=1.0`) — AXP brands this UI as **Magia** in docs/screenshots; package name is not stable after “Hide the Magisk app” | +| Modules seen | `flag-secure-disabler`, `hosts`, `playintegrityfix`, `teesim`, `zygisk_vector` | +| Secure toggles | `allow_signature_fake=1`, `extendrom_call_recording=1` | + +**Important:** GOLDEN is already **fully activated**. The virgin +“preinstalled but not fully activated” UX is the **first-boot / additional +setup** Magisk flow after an AXP-style preroot image (see AXP setup guide + +EXTENDROM FAQ: “Requires Additional Setup”). Measure that class from AXP docs + +EXTENDROM `PREINITDEVICE=userdata` behaviour — do not wipe GOLDEN to re-see it. + +## How AXP / EXTENDROM builds Magisk into the ROM + +Attribute: **sfX-android `android_vendor_extendrom`** + Magisk APK. + +1. `EXTENDROM_PREROOT_BOOT=true` — Magisk is **not** a normal PRODUCT_PACKAGE; + it patches **boot / init_boot** at image build time. +2. Magisk APK (v22+) is unzipped under `out/.magisk/`; `boot_patch.sh` runs via + `vendor/extendrom/config/magisk/patch.sh`. +3. Releasetools inject: patch under + `config/magisk/{lineage|axp}/A{version}/0001-build_make_tools_releasetools_common.py` + hooks `common.py` `_BuildBootableImage` / prebuilt boot. +4. Patcher env of note: `KEEPVERITY=true`, `KEEPFORCEENCRYPT=true`, + `PREINITDEVICE=userdata`, `BOOTMODE=false`. +5. Post-flash **virgin**: stub may appear; `/system_ext/bin/magisk` and `su` + appear only **after** user activation (AXP FAQ “Revert Magisk activation”). + Measure virgin before opening Magisk. GOLDEN already activated is not virgin. + +Host reference tree: `/srv/rom/references/extendrom/` on `rom-dev01`. + +## Enable Magisk on next bacon (009) + +```bash +export ANDROID_BUILD_TOP=/srv/rom/src/lineage +export OUT_DIR=/srv/rom/src/lineage/out # or /srv/rom/out-009 for parallel +export SUNFISH_A16_MAGISK_PREROOT=1 +# Copy staged runtime into OUT (or re-run prepare): +# rsync -a /srv/rom/prebuilts/magisk/runtime/ "$OUT_DIR/.magisk/" +# or: MAGISK_STAGE_DIR=$OUT_DIR/.magisk vendor/sunfish-a16/magisk/prepare_magisk.sh +``` + +Hook is already in `build/make/tools/releasetools/common.py` but **no-ops** unless +`SUNFISH_A16_MAGISK_PREROOT=1` (008 in-flight stays safe). + +1. Clean-flash LAB with Magisk-preroot `009` images (wipe `/data` if LAB had + Magisk activated before). +2. **Virgin check (before opening Magisk):** + `adb shell 'which su; which magisk; ps -A | grep magiskd'` — expect no `su`, + no Magisk binaries (AXP dormant). Record under `…/magisk/pre-activation.md`. +3. Open Magisk stub → download/install full Magisk if prompted → complete + **Additional setup** → reboot (AXP setup guide). +4. Confirm `magisk -v` matches pin (target: newest workable stable; host aims + at **v30.7** unless regression). +5. Enable Zygisk + DenyList as needed. +6. For DenyList smoke (MVP): hide a **non-bank test package** before first open. +7. Banking DenyList workflow = **deferred** (US3 / Gate E). + +## Optional KernelSU recycle (FR-016) + +Paths under `/srv/rom/artifacts/007-*/` — debug/reference only. **Not ship.** +Never gate Magisk acceptance on KSU. + +**Hard rule for Magisk LAB:** `sunfish_defconfig` must keep `# CONFIG_KSU is not +set` (and SusFS off). Magisk + in-kernel ReSukiSU/KSU on the same boot causes +app `failed to attach` / `start timeout` and hung `su`. + +**Full AXP-clone bacon (detached):** +`/srv/rom/artifacts/009-axp-los23-port/scripts/009-bacon-axp.sh` +session `009-bacon-axp` — Magisk preroot + noksu + Phonesky exact-alarm + +WMS FLAG_SECURE (no `ro.debuggable` gate). After zip sideload, flash +artifact `boot.img` (TF IMAGES) to both slots. + +## Staged known-good images (FR-013) + +Keep prior LAB flashables + SHA-256 under +`/srv/rom/artifacts/009-axp-los23-port//` before each risky Magisk or +hardening stage. diff --git a/docs/009-private-dns-axp-providers.md b/docs/009-private-dns-axp-providers.md new file mode 100644 index 0000000..04920f5 --- /dev/null +++ b/docs/009-private-dns-axp-providers.md @@ -0,0 +1,34 @@ +# AXP Private DNS providers (from GOLDEN Settings) + +Source: `Settings.apk` on GOLDEN `11071JEC203839` +(`22.2-2026.003-sunfish-pro`), pulled 2026-09-18. +Artifact: `.local-artifacts/002-golden/20260918-private-dns/Settings.apk` + +Stock AOSP/LOS radios: Off / Automatic / Provider hostname. +AXP adds the following preset radios (hostname → DoT provider): + +| key (resource) | UI label (en) | hostname | +|----------------|---------------|----------| +| `adguard` | AdGuard (CT) | `dns.adguard.com` | +| `appliedprivacy` | AppliedPrivacy (AT) | `dot1.applied-privacy.net` | +| `cira` | CIRA (CA) | `protected.canadianshield.cira.ca` | +| `cleanbrowsing` | CleanBrowsing (US) | `security-filter-dns.cleanbrowsing.org` | +| `cloudflare` | Cloudflare (US) | `security.cloudflare-dns.com` | +| `controld` | Control D (CA) | `p2.freedns.controld.com` | +| `cznic` | CZ.NIC (CZ) | `odvr.nic.cz` | +| `dnssb` | DNS.SB (DE) | `dot.sb` | +| `dnszero` | DNS0 (FR) | `zero.dns0.eu` | +| `google` | Google (US) | `dns.google` | +| `mullvad` | Mullvad (SE) | `base.dns.mullvad.net` | +| `quadnine` | Quad9 (CH) | `dns.quad9.net` | +| `restena` | Restena (LU) | `kaitain.restena.lu` | +| `switch` | SWITCH (CH) | `dns.switch.ch` | +| `uncensoreddns` | UncensoredDNS (DK) | `anycast.censurfridns.dk` | + +Plus stock: Off, Opportunistic (Automatic), custom Provider hostname. + +AXP setup docs recommend Quad9 (`dns.quad9.net`) and DNS0 (`zero.dns0.eu`). + +Clone target for LOS 23.2: extend `PrivateDnsModeDialogPreference` + +`private_dns_mode_dialog.xml` + strings to match this set (no `axp.os` +branding). diff --git a/docs/009-sideload-system-updates.md b/docs/009-sideload-system-updates.md new file mode 100644 index 0000000..4683b57 --- /dev/null +++ b/docs/009-sideload-system-updates.md @@ -0,0 +1,30 @@ +# 009 — Sideload system package updates (FR-019) + +Owner cadence: refresh bundled **system / privileged** packages about every +**2–3 months** without a full ROM reflash. **No** AXP OTA / external repos. + +Status: **stub** — fill before final ship (task T046a). Packaging of the +shipping image MUST already preserve update eligibility. + +## In scope + +| Component | Intended update path | Signing constraint | +|-----------|----------------------|--------------------| +| microG GmsCore / companions | `adb install -r` / recovery sideload of upstream APK | **PRESIGNED** / same signer as shipped | +| Magisk | Magisk app self-update and/or documented boot re-patch | Manager + boot image must stay matched | +| Project Phonesky | Sideload project-signed APK | **Same project key** across releases | +| Other bundled system apps | Sideload matching-signer APK (or recovery zip if priv-app needs it) | Same identity as image | + +## Out of scope + +- Network OTA / AXP update servers +- Full `bacon` + clean flash for routine APK bumps (still OK for kernel / + framework / Magisk boot changes when required) + +## Checklist before claiming FR-019 done + +- [ ] Each row above has a concrete command/runbook step +- [ ] `pm install` / PackageManager does not reject for signature mismatch +- [ ] Privileged permissions still grant after update (or re-flash privapp XML noted) +- [ ] Magisk version after update matches kernel/boot expectation +- [ ] Record new versions in `docs/009-version-pins.md` diff --git a/docs/009-us-s4-userspace-hardening.md b/docs/009-us-s4-userspace-hardening.md new file mode 100644 index 0000000..ef021d6 --- /dev/null +++ b/docs/009-us-s4-userspace-hardening.md @@ -0,0 +1,52 @@ +# US-S4 — Userspace hardening (first stage) + +Status 2026-10-02. No bacon solely for this doc. + +## Stage 0 — LAB baseline (measure, closed) + +On LAB `11231JEC207477` after AVB ship `20261002T103558Z` (+ boot/vbmeta reinforce): + +| Check | Result | +|-------|--------| +| SELinux | Enforcing | +| Encryption | `ro.crypto.state=encrypted`, `ro.crypto.type=file` | +| Verified boot | orange / `flash.locked=0` (unlocked Magisk track) | +| `security.perf_harden` | 1 (already) | +| Yama / `ptrace_scope` | **done** (US-S5-1 `162840Z`) — `CONFIG_SECURITY_YAMA=y` | + +## Stage 1 — US-S4-1 drop product OpenSSH / rsync / procmem + +**Oracle**: `AXP.OS-22.2-20260324-PRO-sunfish.zip` product (+ system) images — +no `sshd`/`ssh`/`rsync`/`procmem` binaries; orphan `init.openssh.rc` only. + +**Shipped in tree**: `vendor/sunfish-a16/hardening.mk` + +`patches/009-axp-los23-port/hardening/README.md`. + +Removes Lineage product OpenSSH binaries + `rsync`, `procmem` (DEBUG). +**Keeps** `init.openssh.rc` (AXP PRO still has it). Admin path: adb + Magisk. + +LAB verify after flash: no `/product/bin/sshd`, no `/product/bin/rsync`, +`/product/etc/init/init.openssh.rc` present, Magisk still up. + +## Stage 2 — US-S4-2 drop Jelly + Gallery2 + +**Oracle**: AXP PRO product has neither; Fossify on system_ext. See +`docs/009-axp-pro-product-apps-20260324.md`. + +Wired: `apply_009_drop_jelly_gallery2.py`, `NoLineageJelly` phony override, +hardening.mk filter, bacon gate. Pending next bacon + LAB. + +## Later candidates (one per bacon when risk unclear) + +1. Mount / noexec where stock sunfish already allows (verify HW first) +2. Package-visibility / query hardening (high app-compat risk → later) +3. Further debug-tool trim (`adb_root` only if LAB proves unused) + +Promote from `docs/hardening-backlog.md` only with upstream attribution. + +## Out of scope here + +- `WITH_AVB=true` / flags 0 +- Bootloader relock +- `lineage_sunfish-user` default lunch (US-S6) +- Kernel Yama / more CVE (US-S5) diff --git a/docs/009-version-pins.md b/docs/009-version-pins.md new file mode 100644 index 0000000..0fe1710 --- /dev/null +++ b/docs/009-version-pins.md @@ -0,0 +1,24 @@ +# 009 version pins + +Policy: newest stable (or newest tagged pre-release upstream ships) that works +on sunfish / LOS 23.2 — except Phonesky = project artifact, WebView = LOS +default. Refresh with `git fetch --tags` / release APIs before long builds. +Never ship from stale laptop caches. + +| component | version_name | version_code | upstream_ref | policy | verified_on | notes | +|-----------|--------------|--------------|--------------|--------|-------------|-------| +| VanillaBaseline | lineage-23.2 sunfish | | `/srv/rom/artifacts/003-vanilla/20260914-lineage-23.2-sunfish` | los_default | 2026-09-14 | Known-good vanilla artifact on host | +| microG GmsCore | v0.3.16.252432 | | microG official (matches GitHub latest 2026-09-17) | newest_stable | 2026-09-16 staged | `/srv/rom/prebuilts/microg/` | +| GSF Proxy | v0.1.0 | | microG official | newest_stable | 2026-09-16 staged | | +| Phonesky | 52.9.22-24 | | project patched host artifact | project_phonesky | 2026-09-14 | `/srv/rom/prebuilts/phonesky/`; never Git | +| Magisk | v30.7 | | https://github.com/topjohnwu/Magisk/releases/tag/v30.7 | newest_stable | 2026-09-17 | Staged APK; GOLDEN oracle **29.0** layout only | +| Kernel sunfish | 4.14.357-openela | | `kernel/google/msm-4.14` @ `28f9290ae067` | los_default + FR-017 stage1 | 2026-09-18 | AXP `kernel_patches` @ `df3cab2155b3`; see `docs/009-kernel-hardening-map.md` | +| Aurora Store | present on GOLDEN | | `com.aurora.store` | newest_stable | 2026-09-17 seen | Stage APK later | +| F-Droid | present on GOLDEN | | `org.fdroid.fdroid` | newest_stable | 2026-09-17 seen | | +| Fossify Gallery | present on GOLDEN | | `org.fossify.gallery` | newest_stable | 2026-09-17 seen | | +| Seedvault | present on GOLDEN | | `com.stevesoltys.seedvault` | los_default / newest | 2026-09-17 seen | Often LOS-provides | +| Island | deferred | | `com.oasisfeng.island.fdroid` | | | US3 deferred | + +## Host artifact hashes (copy from host VERSIONS when refreshed) + +See `/srv/rom/prebuilts/*/VERSIONS.txt` on `rom-dev01`. diff --git a/docs/axp-pro-parity.md b/docs/axp-pro-parity.md index 4011fa7..205b96e 100644 --- a/docs/axp-pro-parity.md +++ b/docs/axp-pro-parity.md @@ -39,7 +39,7 @@ feature. Signing/AVB, userspace hardening, and kernel hardening remain `011`– | Magisk / preroot | Magisk (**Magia** UI on GOLDEN, 29.0) | **Substitute:** KernelSU-Next (+ SusFS) / evaluate ReSukiSU | substitute | Captured in `002`; do **not** fix GOLDEN; project root = `007` on LAB | | DenyList / umount for banks | Magia DenyList (pkg list in `docs/002-golden-inventory.md`) | KernelSU app profiles + verified umount | todo | `007` re-runs `006`; GOLDEN DenyList captured `002` | | Insular work profile | AXP docs say Insular; **GOLDEN measures Island** (`com.oasisfeng.island.fdroid` 6.4.2) | Banking workflow parity (Island or equivalent) | todo | `006`; capture in `002` | -| Yuh in Insular/Island | Historically worked; **FAIL since ~weeks** (HA / “certificate invalid”; KeyMint/TEE errors in `002` logs) | Hard-gate Compatibility MVP (rootless in `006`); **Revolut not a hard-gate** | partial | `002` evidence; LAB may need SusFS+TrickyStore-class stack (`reference-sources.md` §8); never GOLDEN | +| Yuh in Insular/Island | Was FAIL ~weeks (HA); **PASS again 2026-10-02 on GOLDEN** with Vector **bootloader spoofer** (`002`) | Hard-gate Compatibility MVP (rootless in `006`); **Revolut not a hard-gate** | partial | `002`; Gate E on LAB = DenyList + PIF/teesim + Vector BL spoof (sunfish-coherent); never flash GOLDEN | | Swissquote in Insular/Island | **PASS** on GOLDEN (owner report, DenyList) | Hard-gate Compatibility MVP (rootless in `006`) | partial | `002`; re-test in `006`/`007`/`011` | | Unrestricted call recording | Yes | Yes — native ROM on Android 16 | todo | AXP/EXTENDROM/iodé as references only; re-validate on LOS 23.2; `008` | | DNS blocker / privacy DNS | Yes | Wanted; exact UX TBD | decide | `010` | diff --git a/docs/hardening-backlog.md b/docs/hardening-backlog.md index 89bcb14..0f1352d 100644 --- a/docs/hardening-backlog.md +++ b/docs/hardening-backlog.md @@ -55,31 +55,32 @@ Status: `candidate` | `investigate` | `accepted→spec` | `rejected` | `los-prov The kernel base remains the LineageOS 23.2-compatible sunfish kernel. +**Priority (009 / owner 2026-09-18):** AXP clone first → LOS inventory → +IodéOS diff → optional Graphene (modern techniques / selective A13). +**Do not** separately mine DivestOS EOL. See `docs/009-kernel-hardening-map.md`. + ```text - ┌─ historical GOS sunfish + ┌─ AXP sunfish (max priority clone) │ -LOS23/A16 sunfish 4.14 ←─┼─ AXP own + DivestOS +LOS23/A16 sunfish 4.14 ←─┼─ LOS23 already-present OUR BASE │ - ├─ modern GOS techniques + ├─ IodéOS (LOS fork, hardened/deblobbed) │ - └─ original upstream fixes + └─ Graphene optional (modern / selective A13) ``` **Not:** GrapheneOS Android 13 (or any old GrapheneOS) kernel tree as our base. +**Not:** DivestOS as a hunt target (EOL). -Candidate hardening comes from four classes: +Candidate hardening comes from: -1. **Historical GrapheneOS sunfish** — device-specific patches/configuration known - to have run on sunfish (real commits, not only `.config`). -2. **AXP.OS / DivestOS sunfish** — audit the actual patch stack; distinguish - AXP-owned changes from inherited changes. -3. **Modern GrapheneOS** — use current kernel hardening as a source of - techniques/security properties; adapt/backport only where feasible on - non-GKI Linux 4.14; do not assume current Pixel kernel patches cherry-pick - cleanly. -4. **Original upstream** — where a GrapheneOS/AXP/Divest patch derives from AOSP, - Android common, Linux stable, or another upstream source, prefer the - appropriate original upstream fix when practical. +1. **AXP.OS sunfish** — primary; audit actual patch stack on `rom-dev01`. +2. **LineageOS 23.2 msm-4.14** — what is already applied. +3. **IodéOS** — diff vs LOS for extra hardening/deblob worth porting. +4. **GrapheneOS** — optional: modern Pixel techniques adaptable to 4.14; + historical sunfish A13 only if clearly still valuable. +5. **Original upstream** — when a patch derives from Linux/AOSP common, + prefer upstream form when practical. For each candidate record: @@ -96,6 +97,10 @@ For each candidate record: - test result; - final decision. +**Location:** do not extra-cap vs LOS (owner GPS UX); skip AXP location +lockdown in this track unless revisited later. + + ## Much later / evaluate | Idea | Notes | Status | diff --git a/scripts/009-bacon-axp-combo4-fortify.sh b/scripts/009-bacon-axp-combo4-fortify.sh new file mode 100755 index 0000000..1ae8046 --- /dev/null +++ b/scripts/009-bacon-axp-combo4-fortify.sh @@ -0,0 +1,152 @@ +#!/bin/bash +# 009 bacon — AXP Magisk preroot + combo4+Clang-FORTIFY kernel (LAB-verified pack). +# Does NOT apply Graphene Stage1 mega-pack (not boot-OK yet on LOS23/Clang). +set -e +cd /srv/rom/src/lineage +export HOME=/home/android-build +export CCACHE_DIR=/srv/rom/ccache +export USE_CCACHE=1 +export PATH=/home/android-build/bin:/usr/local/bin:/usr/bin:/bin:$PATH +export ANDROID_BUILD_TOP=/srv/rom/src/lineage +unset OUT_DIR || true +export SUNFISH_A16_MAGISK_PREROOT=1 +export MAGISK_APK=/srv/rom/prebuilts/magisk/Magisk-v30.7.apk + +LOGDIR=/srv/rom/logs/009-build +mkdir -p "$LOGDIR" +LOG=$LOGDIR/bacon-axp-combo4-fortify.log +exec > >(tee -a "$LOG") 2>&1 + +echo "=== START 009-bacon-axp-combo4-fortify $(date -Is) ===" + +LIVE=kernel/google/msm-4.14 +BASE=28f9290ae067 +test -d "$LIVE" + +echo "=== reset kernel @ $BASE ===" +git -C "$LIVE" reset --hard "$BASE" +git -C "$LIVE" clean -fdq + +APPLY=vendor/sunfish-a16/patches/009-kernel-hardening/apply_combo4_fortify.sh +test -x "$APPLY" || chmod +x "$APPLY" +bash "$APPLY" "$LIVE" + +DEF=$LIVE/arch/arm64/configs/sunfish_defconfig +if grep -qE "^CONFIG_KSU.*=y" "$DEF"; then + echo "FAIL: $DEF still enables KernelSU" >&2 + exit 1 +fi +for k in FORTIFY_SOURCE INIT_ON_ALLOC_DEFAULT_ON INIT_ON_FREE_DEFAULT_ON \ + SECURITY_DMESG_RESTRICT SLAB_FREELIST_HARDENED; do + if ! grep -q "^CONFIG_${k}=y" "$DEF"; then + echo "FAIL: missing CONFIG_${k}=y" >&2 + exit 1 + fi +done +grep -q "ret = __underlying_strlen(q);" "$LIVE/include/linux/string.h" +echo "OK: combo4+FORTIFY markers + nested-strlen fix present" + +rm -f out/target/product/sunfish/obj/KERNEL_OBJ/arch/arm64/boot/Image.lz4 \ + out/target/product/sunfish/obj/KERNEL_OBJ/arch/arm64/boot/Image \ + out/target/product/sunfish/kernel +echo "OK: cleared prior Image for kernel rebuild" + +# FLAG_SECURE + Settings UX (idempotent) +python3 vendor/sunfish-a16/patches/008-call-rec-flag-secure/apply_wms_disable_secure_debuggable_gate.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_disable_user_apps.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_private_dns_providers.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_connectivity_check.py + +PH=/srv/rom/src/lineage/vendor/sunfish-a16/prebuilt/Phonesky.apk +test -e "$PH" +AAPT=/srv/rom/src/lineage/prebuilts/sdk/tools/linux/bin/aapt +if ! "$AAPT" dump permissions "$PH" 2>/dev/null | grep -q USE_EXACT_ALARM; then + echo "FAIL: Phonesky missing USE_EXACT_ALARM" >&2 + exit 1 +fi +echo "OK: Phonesky has USE_EXACT_ALARM" + +MAGISK_STAGE_DIR=/srv/rom/src/lineage/out/.magisk \ + vendor/sunfish-a16/magisk/prepare_magisk.sh +python3 vendor/sunfish-a16/magisk/apply_releasetools_hook.py --top "$ANDROID_BUILD_TOP" --force +test -f out/.magisk/READY + +rm -rf out/soong/.intermediates/build/make/tools/releasetools/releasetools_common +rm -rf out/soong/.intermediates/build/make/tools/releasetools/add_img_to_target_files +rm -rf out/target/product/sunfish/obj/PACKAGING/target_files_intermediates +rm -f out/target/product/sunfish/lineage-*.zip \ + out/target/product/sunfish/boot.img \ + out/target/product/sunfish/system/priv-app/Phonesky/Phonesky.apk +touch frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java + +set +u +# shellcheck disable=SC1091 +source build/envsetup.sh +set -e +breakfast sunfish userdebug +test "${TARGET_RELEASE:-}" = "bp4a" + +echo "=== mka bacon $(date -Is) ===" +set -o pipefail +mka bacon -j8 +ec=${PIPESTATUS[0]} +echo "bacon_exit=$ec $(date -Is)" +[ "$ec" -eq 0 ] || exit "$ec" + +PROD=out/target/product/sunfish +BID=$(date -u +%Y%m%dT%H%M%SZ) +DEST=/srv/rom/artifacts/009-axp-los23-port/${BID}-axp-combo4-fortify +mkdir -p "$DEST" + +TF_BOOT=$(find "$PROD/obj/PACKAGING/target_files_intermediates" -path "*/IMAGES/boot.img" 2>/dev/null | head -1) +MAKE_BOOT=$PROD/boot.img +if [ -n "${TF_BOOT:-}" ] && [ -f "$TF_BOOT" ]; then + cp -v "$TF_BOOT" "$DEST/boot.img" + cp -v "$MAKE_BOOT" "$DEST/boot-make.img" 2>/dev/null || true + echo "boot_source=target_files_IMAGES" +else + cp -v "$MAKE_BOOT" "$DEST/boot.img" + echo "WARN: no TF IMAGES/boot.img — using Make boot" +fi + +cp -v "$PROD"/lineage-*-UNOFFICIAL-sunfish.zip "$DEST/" 2>/dev/null || true +for f in vbmeta.img dtbo.img; do + [ -f "$PROD/$f" ] && cp -v "$PROD/$f" "$DEST/" +done + +# Magisk present, KernelSU absent +MB=out/.magisk/magiskboot +if [ -x "$MB" ]; then + rm -rf "$DEST/boot-check" && mkdir -p "$DEST/boot-check" + if "$MB" unpack "$DEST/boot.img" "$DEST/boot-check" >/dev/null 2>&1; then + if [ -f "$DEST/boot-check/ramdisk.cpio" ]; then + if "$MB" cpio "$DEST/boot-check/ramdisk.cpio" "exists overlay.d/sbin/magisk64.xz" \ + || "$MB" cpio "$DEST/boot-check/ramdisk.cpio" "exists overlay.d/sbin/magisk.xz"; then + echo "OK: Magisk overlay in boot.img" + else + echo "WARN: Magisk overlay not detected in boot.img ramdisk" + fi + fi + else + echo "WARN: magiskboot unpack failed (host SIGILL flake possible); skip TF check" + fi +fi +if strings "$DEST/boot.img" | grep -qiE 'KernelSU|CONFIG_KSU_SUSFS'; then + echo "FAIL: KernelSU strings in boot.img" >&2 + exit 1 +fi +echo "OK: no KernelSU strings in boot.img" + +{ + echo "artifact=$DEST" + echo "kernel_base=$BASE" + echo "hardening=combo4+clang-fortify (nested __underlying_strlen)" + echo "magisk=preroot EXTENDROM-class v30.7" + echo "stage1_graphene=NOT_INCLUDED (not boot-OK on LOS23 yet)" + date -u +"built=%Y-%m-%dT%H:%M:%SZ" +} | tee "$DEST/README.txt" + +(cd "$DEST" && sha256sum boot.img boot-make.img lineage-*-UNOFFICIAL-sunfish.zip 2>/dev/null || true) \ + | tee "$DEST/SHA256SUMS" + +echo "=== DONE $DEST $(date -Is) ===" diff --git a/scripts/009-bacon-axp-stage1-combo4-cve-bisect.sh b/scripts/009-bacon-axp-stage1-combo4-cve-bisect.sh new file mode 100644 index 0000000..c234905 --- /dev/null +++ b/scripts/009-bacon-axp-stage1-combo4-cve-bisect.sh @@ -0,0 +1,142 @@ +#!/bin/bash +# 009 bacon — Stage1+combo4+FORTIFY + CVE bisect half (h1|h2). +# Usage on rom-dev01: CVE_BISECT=h1 bash scripts/009-bacon-axp-stage1-combo4-cve-bisect.sh +set -e +BISECT="${CVE_BISECT:?set CVE_BISECT=h1 or h2}" +case "$BISECT" in h1|h2) ;; *) echo "CVE_BISECT must be h1 or h2" >&2; exit 2 ;; esac + +cd /srv/rom/src/lineage +export HOME=/home/android-build +export CCACHE_DIR=/srv/rom/ccache +export USE_CCACHE=1 +export PATH=/home/android-build/bin:/usr/local/bin:/usr/bin:/bin:$PATH +export ANDROID_BUILD_TOP=/srv/rom/src/lineage +unset OUT_DIR || true +export SUNFISH_A16_MAGISK_PREROOT=1 +export MAGISK_APK=/srv/rom/prebuilts/magisk/Magisk-v30.7.apk +unset PRODUCT_DEFAULT_DEV_CERTIFICATE || true + +LOGDIR=/srv/rom/logs/009-build +mkdir -p "$LOGDIR" +LOG=$LOGDIR/bacon-axp-stage1-combo4-cve-${BISECT}.log +exec > >(tee -a "$LOG") 2>&1 + +echo "=== START 009-bacon-axp-stage1-combo4-cve-${BISECT} $(date -Is) ===" + +LIVE=kernel/google/msm-4.14 +BASE=28f9290ae067 +KH=vendor/sunfish-a16/patches/009-kernel-hardening +LIST="$KH/cve-bisect-${BISECT}.list" +test -f "$LIST" +test -d "$LIVE" + +echo "=== reset kernel @ $BASE ===" +git -C "$LIVE" reset --hard "$BASE" +git -C "$LIVE" clean -fdq + +chmod +x "$KH"/apply_stage1_combo4.sh "$KH"/apply_cve_strict.sh \ + "$KH"/apply_stage1.sh "$KH"/apply_combo4_fortify.sh 2>/dev/null || true + +bash "$KH/apply_stage1_combo4.sh" "$LIVE" +export CVE_STRICT_LIST="$LIST" +bash "$KH/apply_cve_strict.sh" "$LIVE" + +DEF=$LIVE/arch/arm64/configs/sunfish_defconfig +if grep -qE "^CONFIG_KSU.*=y" "$DEF"; then + echo "FAIL: KernelSU in defconfig" >&2 + exit 1 +fi +for k in FORTIFY_SOURCE INIT_ON_ALLOC_DEFAULT_ON INIT_ON_FREE_DEFAULT_ON \ + SECURITY_DMESG_RESTRICT SLAB_FREELIST_HARDENED; do + grep -q "^CONFIG_${k}=y" "$DEF" || { echo "FAIL missing $k" >&2; exit 1; } +done +grep -q "ret = __underlying_strlen(q);" "$LIVE/include/linux/string.h" +echo "OK: Stage1+combo4+FORTIFY + CVE-${BISECT} markers present" + +rm -f out/target/product/sunfish/obj/KERNEL_OBJ/arch/arm64/boot/Image.lz4 \ + out/target/product/sunfish/obj/KERNEL_OBJ/arch/arm64/boot/Image \ + out/target/product/sunfish/kernel + +python3 vendor/sunfish-a16/patches/008-call-rec-flag-secure/apply_wms_disable_secure_debuggable_gate.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_disable_user_apps.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_private_dns_providers.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_connectivity_check.py + +PH=/srv/rom/src/lineage/vendor/sunfish-a16/prebuilt/Phonesky.apk +test -e "$PH" +AAPT=/srv/rom/src/lineage/prebuilts/sdk/tools/linux/bin/aapt +"$AAPT" dump permissions "$PH" 2>/dev/null | grep -q USE_EXACT_ALARM + +MAGISK_STAGE_DIR=/srv/rom/src/lineage/out/.magisk \ + vendor/sunfish-a16/magisk/prepare_magisk.sh +python3 vendor/sunfish-a16/magisk/apply_releasetools_hook.py --top "$ANDROID_BUILD_TOP" --force +test -f out/.magisk/READY + +rm -rf out/soong/.intermediates/build/make/tools/releasetools/releasetools_common +rm -rf out/soong/.intermediates/build/make/tools/releasetools/add_img_to_target_files +rm -rf out/target/product/sunfish/obj/PACKAGING/target_files_intermediates +rm -f out/target/product/sunfish/lineage-*.zip \ + out/target/product/sunfish/boot.img \ + out/target/product/sunfish/system/priv-app/Phonesky/Phonesky.apk +touch frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java + +set +u +# shellcheck disable=SC1091 +source build/envsetup.sh +set -e +unset PRODUCT_DEFAULT_DEV_CERTIFICATE || true +breakfast sunfish userdebug +test "${TARGET_RELEASE:-}" = "bp4a" + +echo "=== mka bacon $(date -Is) ===" +set -o pipefail +mka bacon -j8 +ec=${PIPESTATUS[0]} +echo "bacon_exit=$ec $(date -Is)" +[ "$ec" -eq 0 ] || exit "$ec" + +PROD=out/target/product/sunfish +BID=$(date -u +%Y%m%dT%H%M%SZ) +DEST=/srv/rom/artifacts/009-axp-los23-port/${BID}-axp-stage1-combo4-cve-${BISECT} +mkdir -p "$DEST" + +TF_BOOT=$(find "$PROD/obj/PACKAGING/target_files_intermediates" -path "*/IMAGES/boot.img" 2>/dev/null | head -1) +MAKE_BOOT=$PROD/boot.img +if [ -n "${TF_BOOT:-}" ] && [ -f "$TF_BOOT" ]; then + cp -v "$TF_BOOT" "$DEST/boot.img" + cp -v "$MAKE_BOOT" "$DEST/boot-make.img" 2>/dev/null || true +else + cp -v "$MAKE_BOOT" "$DEST/boot.img" +fi +cp -v "$PROD"/lineage-*-UNOFFICIAL-sunfish.zip "$DEST/" 2>/dev/null || true +for f in vbmeta.img dtbo.img; do + [ -f "$PROD/$f" ] && cp -v "$PROD/$f" "$DEST/" +done + +WLAN=$PROD/vendor/lib/modules/wlan.ko +if [ -f "$WLAN" ] && [ -f "$PROD/obj/KERNEL_OBJ/Module.symvers" ]; then + KCRC=$(awk '$2=="kmalloc_caches"{print $1; exit}' "$PROD/obj/KERNEL_OBJ/Module.symvers") + MCRC=$(/sbin/modprobe --dump-modversions "$WLAN" 2>/dev/null | awk '$2=="kmalloc_caches"{print $1; exit}') + echo "wlan kmalloc_caches kernel=$KCRC module=$MCRC" +fi + +if strings "$DEST/boot.img" | grep -qiE 'KernelSU|CONFIG_KSU_SUSFS'; then + echo "FAIL: KernelSU in boot" >&2 + exit 1 +fi + +{ + echo "artifact=$DEST" + echo "bisect=$BISECT" + echo "list=$LIST" + echo "hardening=Stage1+combo4+FORTIFY + CVE-${BISECT}" + echo "signing=test-keys" + echo "flash=fastboot flash boot boot.img (preferred for bisect); sideload zip if Wi-Fi breaks" + echo "recover=fastboot flash boot from 20260929T123401Z-axp-stage1-combo4" + date -u +"built=%Y-%m-%dT%H:%M:%SZ" +} | tee "$DEST/README.txt" + +(cd "$DEST" && sha256sum boot.img boot-make.img lineage-*-UNOFFICIAL-sunfish.zip 2>/dev/null || true) \ + | tee "$DEST/SHA256SUMS" + +echo "=== DONE $DEST $(date -Is) ===" diff --git a/scripts/009-bacon-axp-stage1-combo4-cve-clean.sh b/scripts/009-bacon-axp-stage1-combo4-cve-clean.sh new file mode 100644 index 0000000..25fde17 --- /dev/null +++ b/scripts/009-bacon-axp-stage1-combo4-cve-clean.sh @@ -0,0 +1,142 @@ +#!/bin/bash +# 009 bacon — Stage1+combo4+FORTIFY + CVE clean-offset allowlist (no huge patch offsets). +# Does not include cve-high-offset-ge200.txt. test-keys. Do not flash until boot-tested. +set -e +cd /srv/rom/src/lineage +export HOME=/home/android-build +export CCACHE_DIR=/srv/rom/ccache +export USE_CCACHE=1 +export PATH=/home/android-build/bin:/usr/local/bin:/usr/bin:/bin:$PATH +export ANDROID_BUILD_TOP=/srv/rom/src/lineage +unset OUT_DIR || true +export SUNFISH_A16_MAGISK_PREROOT=1 +export MAGISK_APK=/srv/rom/prebuilts/magisk/Magisk-v30.7.apk +unset PRODUCT_DEFAULT_DEV_CERTIFICATE || true + +LOGDIR=/srv/rom/logs/009-build +mkdir -p "$LOGDIR" +LOG=$LOGDIR/bacon-axp-stage1-combo4-cve-clean.log +exec > >(tee -a "$LOG") 2>&1 + +echo "=== START 009-bacon-axp-stage1-combo4-cve-clean $(date -Is) ===" + +LIVE=kernel/google/msm-4.14 +BASE=28f9290ae067 +KH=vendor/sunfish-a16/patches/009-kernel-hardening +LIST="$KH/cve-clean-offset.list" +test -f "$LIST" +test -d "$LIVE" + +echo "=== reset kernel @ $BASE ===" +git -C "$LIVE" reset --hard "$BASE" +git -C "$LIVE" clean -fdq + +chmod +x "$KH"/apply_stage1_combo4.sh "$KH"/apply_cve_strict.sh \ + "$KH"/apply_stage1.sh "$KH"/apply_combo4_fortify.sh 2>/dev/null || true + +bash "$KH/apply_stage1_combo4.sh" "$LIVE" +export CVE_STRICT_LIST="$LIST" +# Strict quality gates (defaults in apply_cve_strict.sh) +unset CVE_STRICT_CONTINUE || true +export CVE_MAX_FUZZ=1 +export CVE_MAX_ABS_OFFSET=200 +bash "$KH/apply_cve_strict.sh" "$LIVE" + +DEF=$LIVE/arch/arm64/configs/sunfish_defconfig +if grep -qE "^CONFIG_KSU.*=y" "$DEF"; then + echo "FAIL: KernelSU in defconfig" >&2 + exit 1 +fi +for k in FORTIFY_SOURCE INIT_ON_ALLOC_DEFAULT_ON INIT_ON_FREE_DEFAULT_ON \ + SECURITY_DMESG_RESTRICT SLAB_FREELIST_HARDENED; do + grep -q "^CONFIG_${k}=y" "$DEF" || { echo "FAIL missing $k" >&2; exit 1; } +done +grep -q "ret = __underlying_strlen(q);" "$LIVE/include/linux/string.h" +echo "OK: Stage1+combo4+FORTIFY + CVE-clean-offset markers present" + +rm -f out/target/product/sunfish/obj/KERNEL_OBJ/arch/arm64/boot/Image.lz4 \ + out/target/product/sunfish/obj/KERNEL_OBJ/arch/arm64/boot/Image \ + out/target/product/sunfish/kernel + +python3 vendor/sunfish-a16/patches/008-call-rec-flag-secure/apply_wms_disable_secure_debuggable_gate.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_disable_user_apps.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_private_dns_providers.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_connectivity_check.py + +PH=/srv/rom/src/lineage/vendor/sunfish-a16/prebuilt/Phonesky.apk +test -e "$PH" +AAPT=/srv/rom/src/lineage/prebuilts/sdk/tools/linux/bin/aapt +"$AAPT" dump permissions "$PH" 2>/dev/null | grep -q USE_EXACT_ALARM + +MAGISK_STAGE_DIR=/srv/rom/src/lineage/out/.magisk \ + vendor/sunfish-a16/magisk/prepare_magisk.sh +python3 vendor/sunfish-a16/magisk/apply_releasetools_hook.py --top "$ANDROID_BUILD_TOP" --force +test -f out/.magisk/READY + +rm -rf out/soong/.intermediates/build/make/tools/releasetools/releasetools_common +rm -rf out/soong/.intermediates/build/make/tools/releasetools/add_img_to_target_files +rm -rf out/target/product/sunfish/obj/PACKAGING/target_files_intermediates +rm -f out/target/product/sunfish/lineage-*.zip \ + out/target/product/sunfish/boot.img \ + out/target/product/sunfish/system/priv-app/Phonesky/Phonesky.apk +touch frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java + +set +u +# shellcheck disable=SC1091 +source build/envsetup.sh +set -e +unset PRODUCT_DEFAULT_DEV_CERTIFICATE || true +breakfast sunfish userdebug +test "${TARGET_RELEASE:-}" = "bp4a" + +echo "=== mka bacon $(date -Is) ===" +set -o pipefail +mka bacon -j8 +ec=${PIPESTATUS[0]} +echo "bacon_exit=$ec $(date -Is)" +[ "$ec" -eq 0 ] || exit "$ec" + +PROD=out/target/product/sunfish +BID=$(date -u +%Y%m%dT%H%M%SZ) +DEST=/srv/rom/artifacts/009-axp-los23-port/${BID}-axp-stage1-combo4-cve-clean +mkdir -p "$DEST" + +TF_BOOT=$(find "$PROD/obj/PACKAGING/target_files_intermediates" -path "*/IMAGES/boot.img" 2>/dev/null | head -1) +MAKE_BOOT=$PROD/boot.img +if [ -n "${TF_BOOT:-}" ] && [ -f "$TF_BOOT" ]; then + cp -v "$TF_BOOT" "$DEST/boot.img" + cp -v "$MAKE_BOOT" "$DEST/boot-make.img" 2>/dev/null || true +else + cp -v "$MAKE_BOOT" "$DEST/boot.img" +fi +cp -v "$PROD"/lineage-*-UNOFFICIAL-sunfish.zip "$DEST/" 2>/dev/null || true +for f in vbmeta.img dtbo.img; do + [ -f "$PROD/$f" ] && cp -v "$PROD/$f" "$DEST/" +done + +WLAN=$PROD/vendor/lib/modules/wlan.ko +if [ -f "$WLAN" ] && [ -f "$PROD/obj/KERNEL_OBJ/Module.symvers" ]; then + KCRC=$(awk '$2=="kmalloc_caches"{print $1; exit}' "$PROD/obj/KERNEL_OBJ/Module.symvers") + MCRC=$(/sbin/modprobe --dump-modversions "$WLAN" 2>/dev/null | awk '$2=="kmalloc_caches"{print $1; exit}') + echo "wlan kmalloc_caches kernel=$KCRC module=$MCRC" +fi + +if strings "$DEST/boot.img" | grep -qiE 'KernelSU|CONFIG_KSU_SUSFS'; then + echo "FAIL: KernelSU in boot" >&2 + exit 1 +fi + +{ + echo "artifact=$DEST" + echo "list=$LIST (cve-strict minus high-offset>=200 minus denylist)" + echo "hardening=Stage1+combo4+FORTIFY + CVE-clean-offset" + echo "signing=test-keys" + echo "flash=fastboot flash boot ONLY after owner OK; recover=Stage1 boot.img" + echo "note=do not flash full 503 CVE zip" + date -u +"built=%Y-%m-%dT%H:%M:%SZ" +} | tee "$DEST/README.txt" + +(cd "$DEST" && sha256sum boot.img boot-make.img lineage-*-UNOFFICIAL-sunfish.zip 2>/dev/null || true) \ + | tee "$DEST/SHA256SUMS" + +echo "=== DONE $DEST $(date -Is) ===" diff --git a/scripts/009-bacon-axp-stage1-combo4-cve-hi-batch1.sh b/scripts/009-bacon-axp-stage1-combo4-cve-hi-batch1.sh new file mode 100644 index 0000000..24f4fc9 --- /dev/null +++ b/scripts/009-bacon-axp-stage1-combo4-cve-hi-batch1.sh @@ -0,0 +1,155 @@ +#!/bin/bash +# 009 bacon — Stage1+combo4+FORTIFY + CVE clean-offset + high-offset batch1 (≤10). +# Batch1: intentional CVE_MAX_ABS_OFFSET=9999 after spot-check (fuzz=0). test-keys. +# Do not flash until boot-tested. Recover = last clean BOOT_OK boot.img. +set -e +cd /srv/rom/src/lineage +export HOME=/home/android-build +export CCACHE_DIR=/srv/rom/ccache +export USE_CCACHE=1 +export PATH=/home/android-build/bin:/usr/local/bin:/usr/bin:/bin:$PATH +export ANDROID_BUILD_TOP=/srv/rom/src/lineage +unset OUT_DIR || true +export SUNFISH_A16_MAGISK_PREROOT=1 +export MAGISK_APK=/srv/rom/prebuilts/magisk/Magisk-v30.7.apk +unset PRODUCT_DEFAULT_DEV_CERTIFICATE || true + +LOGDIR=/srv/rom/logs/009-build +mkdir -p "$LOGDIR" +LOG=$LOGDIR/bacon-axp-stage1-combo4-cve-hi-batch1.log +exec > >(tee -a "$LOG") 2>&1 + +echo "=== START 009-bacon-axp-stage1-combo4-cve-hi-batch1 $(date -Is) ===" + +LIVE=kernel/google/msm-4.14 +BASE=28f9290ae067 +KH=vendor/sunfish-a16/patches/009-kernel-hardening +LIST_CLEAN="$KH/cve-clean-offset.list" +LIST_HI="$KH/cve-high-offset-batch1.list" +test -f "$LIST_CLEAN" +test -f "$LIST_HI" +test -d "$LIVE" + +echo "=== reset kernel @ $BASE ===" +git -C "$LIVE" reset --hard "$BASE" +git -C "$LIVE" clean -fdq + +chmod +x "$KH"/apply_stage1_combo4.sh "$KH"/apply_cve_strict.sh \ + "$KH"/apply_stage1.sh "$KH"/apply_combo4_fortify.sh 2>/dev/null || true + +bash "$KH/apply_stage1_combo4.sh" "$LIVE" + +export CVE_STRICT_LIST="$LIST_CLEAN" +unset CVE_STRICT_CONTINUE || true +export CVE_MAX_FUZZ=1 +export CVE_MAX_ABS_OFFSET=200 +bash "$KH/apply_cve_strict.sh" "$LIVE" + +echo "=== high-offset batch1 (elevated abs-offset gate; fuzz still ≤1) ===" +export CVE_STRICT_LIST="$LIST_HI" +export CVE_MAX_ABS_OFFSET=9999 +bash "$KH/apply_cve_strict.sh" "$LIVE" + +DEF=$LIVE/arch/arm64/configs/sunfish_defconfig +if grep -qE "^CONFIG_KSU.*=y" "$DEF"; then + echo "FAIL: KernelSU in defconfig" >&2 + exit 1 +fi +for k in FORTIFY_SOURCE INIT_ON_ALLOC_DEFAULT_ON INIT_ON_FREE_DEFAULT_ON \ + SECURITY_DMESG_RESTRICT SLAB_FREELIST_HARDENED; do + grep -q "^CONFIG_${k}=y" "$DEF" || { echo "FAIL missing $k" >&2; exit 1; } +done +grep -q "ret = __underlying_strlen(q);" "$LIVE/include/linux/string.h" +# batch1 markers (spot-checked) +grep -q "mmget_still_valid" "$LIVE/mm/madvise.c" +grep -q "sched_release_group" "$LIVE/kernel/sched/core.c" +grep -q "fwnode_handle_put(tcpci->tcpc.fwnode)" "$LIVE/drivers/usb/typec/tcpm/tcpci.c" +echo "OK: Stage1+combo4+FORTIFY + CVE-clean + hi-batch1 markers present" + +rm -f out/target/product/sunfish/obj/KERNEL_OBJ/arch/arm64/boot/Image.lz4 \ + out/target/product/sunfish/obj/KERNEL_OBJ/arch/arm64/boot/Image \ + out/target/product/sunfish/kernel + +python3 vendor/sunfish-a16/patches/008-call-rec-flag-secure/apply_wms_disable_secure_debuggable_gate.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_disable_user_apps.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_private_dns_providers.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_connectivity_check.py + +PH=/srv/rom/src/lineage/vendor/sunfish-a16/prebuilt/Phonesky.apk +test -e "$PH" +AAPT=/srv/rom/src/lineage/prebuilts/sdk/tools/linux/bin/aapt +"$AAPT" dump permissions "$PH" 2>/dev/null | grep -q USE_EXACT_ALARM + +MAGISK_STAGE_DIR=/srv/rom/src/lineage/out/.magisk \ + vendor/sunfish-a16/magisk/prepare_magisk.sh +python3 vendor/sunfish-a16/magisk/apply_releasetools_hook.py --top "$ANDROID_BUILD_TOP" --force +test -f out/.magisk/READY + +rm -rf out/soong/.intermediates/build/make/tools/releasetools/releasetools_common +rm -rf out/soong/.intermediates/build/make/tools/releasetools/add_img_to_target_files +rm -rf out/target/product/sunfish/obj/PACKAGING/target_files_intermediates +rm -f out/target/product/sunfish/lineage-*.zip \ + out/target/product/sunfish/boot.img \ + out/target/product/sunfish/system/priv-app/Phonesky/Phonesky.apk +touch frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java + +set +u +# shellcheck disable=SC1091 +source build/envsetup.sh +set -e +unset PRODUCT_DEFAULT_DEV_CERTIFICATE || true +breakfast sunfish userdebug +test "${TARGET_RELEASE:-}" = "bp4a" + +echo "=== mka bacon $(date -Is) ===" +set -o pipefail +mka bacon -j8 +ec=${PIPESTATUS[0]} +echo "bacon_exit=$ec $(date -Is)" +[ "$ec" -eq 0 ] || exit "$ec" + +PROD=out/target/product/sunfish +BID=$(date -u +%Y%m%dT%H%M%SZ) +DEST=/srv/rom/artifacts/009-axp-los23-port/${BID}-axp-stage1-combo4-cve-hi-batch1 +mkdir -p "$DEST" + +TF_BOOT=$(find "$PROD/obj/PACKAGING/target_files_intermediates" -path "*/IMAGES/boot.img" 2>/dev/null | head -1) +MAKE_BOOT=$PROD/boot.img +if [ -n "${TF_BOOT:-}" ] && [ -f "$TF_BOOT" ]; then + cp -v "$TF_BOOT" "$DEST/boot.img" + cp -v "$MAKE_BOOT" "$DEST/boot-make.img" 2>/dev/null || true +else + cp -v "$MAKE_BOOT" "$DEST/boot.img" +fi +cp -v "$PROD"/lineage-*-UNOFFICIAL-sunfish.zip "$DEST/" 2>/dev/null || true +for f in vbmeta.img dtbo.img; do + [ -f "$PROD/$f" ] && cp -v "$PROD/$f" "$DEST/" +done + +WLAN=$PROD/vendor/lib/modules/wlan.ko +if [ -f "$WLAN" ] && [ -f "$PROD/obj/KERNEL_OBJ/Module.symvers" ]; then + KCRC=$(awk '$2=="kmalloc_caches"{print $1; exit}' "$PROD/obj/KERNEL_OBJ/Module.symvers") + MCRC=$(/sbin/modprobe --dump-modversions "$WLAN" 2>/dev/null | awk '$2=="kmalloc_caches"{print $1; exit}') + echo "wlan kmalloc_caches kernel=$KCRC module=$MCRC" +fi + +if strings "$DEST/boot.img" | grep -qiE 'KernelSU|CONFIG_KSU_SUSFS'; then + echo "FAIL: KernelSU in boot" >&2 + exit 1 +fi + +{ + echo "artifact=$DEST" + echo "list_clean=$LIST_CLEAN (429)" + echo "list_hi=$LIST_HI (7; dropped CVE-2023-3777 missing nft_chain_is_bound)" + echo "hardening=Stage1+combo4+FORTIFY + CVE-clean + hi-batch1" + echo "cve_max_abs_offset_hi=9999" + echo "signing=test-keys" + echo "flash=fastboot flash boot ONLY after owner OK; recover=cve-clean BOOT_OK" + date -u +"built=%Y-%m-%dT%H:%M:%SZ" +} | tee "$DEST/README.txt" + +(cd "$DEST" && sha256sum boot.img boot-make.img lineage-*-UNOFFICIAL-sunfish.zip 2>/dev/null || true) \ + | tee "$DEST/SHA256SUMS" + +echo "=== DONE $DEST $(date -Is) ===" diff --git a/scripts/009-bacon-axp-stage1-combo4-cve-hi-batch2.sh b/scripts/009-bacon-axp-stage1-combo4-cve-hi-batch2.sh new file mode 100755 index 0000000..5c88b9b --- /dev/null +++ b/scripts/009-bacon-axp-stage1-combo4-cve-hi-batch2.sh @@ -0,0 +1,160 @@ +#!/bin/bash +# 009 bacon — Stage1+combo4+FORTIFY + CVE clean + hi-batch1 + hi-batch2. +# Elevated CVE_MAX_ABS_OFFSET=9999 for high-offset lists. test-keys. +# Recover = hi-batch1 BOOT_OK boot.img (or cve-clean). +set -e +cd /srv/rom/src/lineage +export HOME=/home/android-build +export CCACHE_DIR=/srv/rom/ccache +export USE_CCACHE=1 +export PATH=/home/android-build/bin:/usr/local/bin:/usr/bin:/bin:$PATH +export ANDROID_BUILD_TOP=/srv/rom/src/lineage +unset OUT_DIR || true +export SUNFISH_A16_MAGISK_PREROOT=1 +export MAGISK_APK=/srv/rom/prebuilts/magisk/Magisk-v30.7.apk +unset PRODUCT_DEFAULT_DEV_CERTIFICATE || true + +LOGDIR=/srv/rom/logs/009-build +mkdir -p "$LOGDIR" +LOG=$LOGDIR/bacon-axp-stage1-combo4-cve-hi-batch2.log +exec > >(tee -a "$LOG") 2>&1 + +echo "=== START 009-bacon-axp-stage1-combo4-cve-hi-batch2 $(date -Is) ===" + +LIVE=kernel/google/msm-4.14 +BASE=28f9290ae067 +KH=vendor/sunfish-a16/patches/009-kernel-hardening +LIST_CLEAN="$KH/cve-clean-offset.list" +LIST_HI1="$KH/cve-high-offset-batch1.list" +LIST_HI2="$KH/cve-high-offset-batch2.list" +test -f "$LIST_CLEAN" +test -f "$LIST_HI1" +test -f "$LIST_HI2" +test -d "$LIVE" + +echo "=== reset kernel @ $BASE ===" +git -C "$LIVE" reset --hard "$BASE" +git -C "$LIVE" clean -fdq + +chmod +x "$KH"/apply_stage1_combo4.sh "$KH"/apply_cve_strict.sh \ + "$KH"/apply_stage1.sh "$KH"/apply_combo4_fortify.sh 2>/dev/null || true + +bash "$KH/apply_stage1_combo4.sh" "$LIVE" + +export CVE_STRICT_LIST="$LIST_CLEAN" +unset CVE_STRICT_CONTINUE || true +export CVE_MAX_FUZZ=1 +export CVE_MAX_ABS_OFFSET=200 +bash "$KH/apply_cve_strict.sh" "$LIVE" + +echo "=== high-offset batch1 (prior LAB OK) ===" +export CVE_STRICT_LIST="$LIST_HI1" +export CVE_MAX_ABS_OFFSET=9999 +bash "$KH/apply_cve_strict.sh" "$LIVE" + +echo "=== high-offset batch2 ===" +export CVE_STRICT_LIST="$LIST_HI2" +export CVE_MAX_ABS_OFFSET=9999 +bash "$KH/apply_cve_strict.sh" "$LIVE" + +DEF=$LIVE/arch/arm64/configs/sunfish_defconfig +if grep -qE "^CONFIG_KSU.*=y" "$DEF"; then + echo "FAIL: KernelSU in defconfig" >&2 + exit 1 +fi +for k in FORTIFY_SOURCE INIT_ON_ALLOC_DEFAULT_ON INIT_ON_FREE_DEFAULT_ON \ + SECURITY_DMESG_RESTRICT SLAB_FREELIST_HARDENED; do + grep -q "^CONFIG_${k}=y" "$DEF" || { echo "FAIL missing $k" >&2; exit 1; } +done +grep -q "ret = __underlying_strlen(q);" "$LIVE/include/linux/string.h" +grep -q "mmget_still_valid" "$LIVE/mm/madvise.c" +echo "OK: Stage1+combo4+FORTIFY + CVE-clean + hi-batch1+2 markers present" + +rm -f out/target/product/sunfish/obj/KERNEL_OBJ/arch/arm64/boot/Image.lz4 \ + out/target/product/sunfish/obj/KERNEL_OBJ/arch/arm64/boot/Image \ + out/target/product/sunfish/kernel + +python3 vendor/sunfish-a16/patches/008-call-rec-flag-secure/apply_wms_disable_secure_debuggable_gate.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_disable_user_apps.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_private_dns_providers.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_connectivity_check.py + +PH=/srv/rom/src/lineage/vendor/sunfish-a16/prebuilt/Phonesky.apk +test -e "$PH" +AAPT=/srv/rom/src/lineage/prebuilts/sdk/tools/linux/bin/aapt +"$AAPT" dump permissions "$PH" 2>/dev/null | grep -q USE_EXACT_ALARM + +MAGISK_STAGE_DIR=/srv/rom/src/lineage/out/.magisk \ + vendor/sunfish-a16/magisk/prepare_magisk.sh +python3 vendor/sunfish-a16/magisk/apply_releasetools_hook.py --top "$ANDROID_BUILD_TOP" --force +test -f out/.magisk/READY + +rm -rf out/soong/.intermediates/build/make/tools/releasetools/releasetools_common +rm -rf out/soong/.intermediates/build/make/tools/releasetools/add_img_to_target_files +rm -rf out/target/product/sunfish/obj/PACKAGING/target_files_intermediates +rm -f out/target/product/sunfish/lineage-*.zip \ + out/target/product/sunfish/boot.img \ + out/target/product/sunfish/system/priv-app/Phonesky/Phonesky.apk +touch frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java + +set +u +# shellcheck disable=SC1091 +source build/envsetup.sh +set -e +unset PRODUCT_DEFAULT_DEV_CERTIFICATE || true +breakfast sunfish userdebug +test "${TARGET_RELEASE:-}" = "bp4a" + +echo "=== mka bacon $(date -Is) ===" +set -o pipefail +mka bacon -j8 +ec=${PIPESTATUS[0]} +echo "bacon_exit=$ec $(date -Is)" +[ "$ec" -eq 0 ] || exit "$ec" + +PROD=out/target/product/sunfish +BID=$(date -u +%Y%m%dT%H%M%SZ) +DEST=/srv/rom/artifacts/009-axp-los23-port/${BID}-axp-stage1-combo4-cve-hi-batch2 +mkdir -p "$DEST" + +TF_BOOT=$(find "$PROD/obj/PACKAGING/target_files_intermediates" -path "*/IMAGES/boot.img" 2>/dev/null | head -1) +MAKE_BOOT=$PROD/boot.img +if [ -n "${TF_BOOT:-}" ] && [ -f "$TF_BOOT" ]; then + cp -v "$TF_BOOT" "$DEST/boot.img" + cp -v "$MAKE_BOOT" "$DEST/boot-make.img" 2>/dev/null || true +else + cp -v "$MAKE_BOOT" "$DEST/boot.img" +fi +cp -v "$PROD"/lineage-*-UNOFFICIAL-sunfish.zip "$DEST/" 2>/dev/null || true +for f in vbmeta.img dtbo.img; do + [ -f "$PROD/$f" ] && cp -v "$PROD/$f" "$DEST/" +done + +WLAN=$PROD/vendor/lib/modules/wlan.ko +if [ -f "$WLAN" ] && [ -f "$PROD/obj/KERNEL_OBJ/Module.symvers" ]; then + KCRC=$(awk '$2=="kmalloc_caches"{print $1; exit}' "$PROD/obj/KERNEL_OBJ/Module.symvers") + MCRC=$(/sbin/modprobe --dump-modversions "$WLAN" 2>/dev/null | awk '$2=="kmalloc_caches"{print $1; exit}') + echo "wlan kmalloc_caches kernel=$KCRC module=$MCRC" +fi + +if strings "$DEST/boot.img" | grep -qiE 'KernelSU|CONFIG_KSU_SUSFS'; then + echo "FAIL: KernelSU in boot" >&2 + exit 1 +fi + +{ + echo "artifact=$DEST" + echo "list_clean=$LIST_CLEAN (429)" + echo "list_hi1=$LIST_HI1" + echo "list_hi2=$LIST_HI2" + echo "hardening=Stage1+combo4+FORTIFY + CVE-clean + hi-batch1+2" + echo "cve_max_abs_offset_hi=9999" + echo "signing=test-keys" + echo "flash=fastboot flash boot; recover=hi-batch1 BOOT_OK" + date -u +"built=%Y-%m-%dT%H:%M:%SZ" +} | tee "$DEST/README.txt" + +(cd "$DEST" && sha256sum boot.img boot-make.img lineage-*-UNOFFICIAL-sunfish.zip 2>/dev/null || true) \ + | tee "$DEST/SHA256SUMS" + +echo "=== DONE $DEST $(date -Is) ===" diff --git a/scripts/009-bacon-axp-stage1-combo4-cve-hi-batch3.sh b/scripts/009-bacon-axp-stage1-combo4-cve-hi-batch3.sh new file mode 100755 index 0000000..047a435 --- /dev/null +++ b/scripts/009-bacon-axp-stage1-combo4-cve-hi-batch3.sh @@ -0,0 +1,162 @@ +#!/bin/bash +# 009 bacon — Stage1+combo4+FORTIFY + CVE clean + hi-batch1+2+3. +# Elevated CVE_MAX_ABS_OFFSET=9999 for high-offset lists. test-keys. +# Recover = hi-batch2 BOOT_OK boot.img. +set -e +cd /srv/rom/src/lineage +export HOME=/home/android-build +export CCACHE_DIR=/srv/rom/ccache +export USE_CCACHE=1 +export PATH=/home/android-build/bin:/usr/local/bin:/usr/bin:/bin:$PATH +export ANDROID_BUILD_TOP=/srv/rom/src/lineage +unset OUT_DIR || true +export SUNFISH_A16_MAGISK_PREROOT=1 +export MAGISK_APK=/srv/rom/prebuilts/magisk/Magisk-v30.7.apk +unset PRODUCT_DEFAULT_DEV_CERTIFICATE || true + +LOGDIR=/srv/rom/logs/009-build +mkdir -p "$LOGDIR" +LOG=$LOGDIR/bacon-axp-stage1-combo4-cve-hi-batch3.log +exec > >(tee -a "$LOG") 2>&1 + +echo "=== START 009-bacon-axp-stage1-combo4-cve-hi-batch3 $(date -Is) ===" + +LIVE=kernel/google/msm-4.14 +BASE=28f9290ae067 +KH=vendor/sunfish-a16/patches/009-kernel-hardening +LIST_CLEAN="$KH/cve-clean-offset.list" +LIST_HI1="$KH/cve-high-offset-batch1.list" +LIST_HI2="$KH/cve-high-offset-batch2.list" +LIST_HI3="$KH/cve-high-offset-batch3.list" +test -f "$LIST_CLEAN" +test -f "$LIST_HI1" +test -f "$LIST_HI2" +test -f "$LIST_HI3" +test -d "$LIVE" + +echo "=== reset kernel @ $BASE ===" +git -C "$LIVE" reset --hard "$BASE" +git -C "$LIVE" clean -fdq + +chmod +x "$KH"/apply_stage1_combo4.sh "$KH"/apply_cve_strict.sh \ + "$KH"/apply_stage1.sh "$KH"/apply_combo4_fortify.sh 2>/dev/null || true + +bash "$KH/apply_stage1_combo4.sh" "$LIVE" + +export CVE_STRICT_LIST="$LIST_CLEAN" +unset CVE_STRICT_CONTINUE || true +export CVE_MAX_FUZZ=1 +export CVE_MAX_ABS_OFFSET=200 +bash "$KH/apply_cve_strict.sh" "$LIVE" + +export CVE_MAX_ABS_OFFSET=9999 +for L in "$LIST_HI1" "$LIST_HI2" "$LIST_HI3"; do + echo "=== high-offset $(basename "$L") ===" + export CVE_STRICT_LIST="$L" + bash "$KH/apply_cve_strict.sh" "$LIVE" +done + +DEF=$LIVE/arch/arm64/configs/sunfish_defconfig +if grep -qE "^CONFIG_KSU.*=y" "$DEF"; then + echo "FAIL: KernelSU in defconfig" >&2 + exit 1 +fi +for k in FORTIFY_SOURCE INIT_ON_ALLOC_DEFAULT_ON INIT_ON_FREE_DEFAULT_ON \ + SECURITY_DMESG_RESTRICT SLAB_FREELIST_HARDENED; do + grep -q "^CONFIG_${k}=y" "$DEF" || { echo "FAIL missing $k" >&2; exit 1; } +done +grep -q "ret = __underlying_strlen(q);" "$LIVE/include/linux/string.h" +grep -q "mmget_still_valid" "$LIVE/mm/madvise.c" +echo "OK: Stage1+combo4+FORTIFY + CVE-clean + hi-batch1+2+3 markers present" + +rm -f out/target/product/sunfish/obj/KERNEL_OBJ/arch/arm64/boot/Image.lz4 \ + out/target/product/sunfish/obj/KERNEL_OBJ/arch/arm64/boot/Image \ + out/target/product/sunfish/kernel + +python3 vendor/sunfish-a16/patches/008-call-rec-flag-secure/apply_wms_disable_secure_debuggable_gate.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_disable_user_apps.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_private_dns_providers.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_connectivity_check.py + +PH=/srv/rom/src/lineage/vendor/sunfish-a16/prebuilt/Phonesky.apk +test -e "$PH" +AAPT=/srv/rom/src/lineage/prebuilts/sdk/tools/linux/bin/aapt +"$AAPT" dump permissions "$PH" 2>/dev/null | grep -q USE_EXACT_ALARM + +MAGISK_STAGE_DIR=/srv/rom/src/lineage/out/.magisk \ + vendor/sunfish-a16/magisk/prepare_magisk.sh +python3 vendor/sunfish-a16/magisk/apply_releasetools_hook.py --top "$ANDROID_BUILD_TOP" --force +test -f out/.magisk/READY + +rm -rf out/soong/.intermediates/build/make/tools/releasetools/releasetools_common +rm -rf out/soong/.intermediates/build/make/tools/releasetools/add_img_to_target_files +rm -rf out/target/product/sunfish/obj/PACKAGING/target_files_intermediates +rm -f out/target/product/sunfish/lineage-*.zip \ + out/target/product/sunfish/boot.img \ + out/target/product/sunfish/system/priv-app/Phonesky/Phonesky.apk +touch frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java + +set +u +# shellcheck disable=SC1091 +source build/envsetup.sh +set -e +unset PRODUCT_DEFAULT_DEV_CERTIFICATE || true +breakfast sunfish userdebug +test "${TARGET_RELEASE:-}" = "bp4a" + +echo "=== mka bacon $(date -Is) ===" +set -o pipefail +mka bacon -j8 +ec=${PIPESTATUS[0]} +echo "bacon_exit=$ec $(date -Is)" +[ "$ec" -eq 0 ] || exit "$ec" + +PROD=out/target/product/sunfish +BID=$(date -u +%Y%m%dT%H%M%SZ) +DEST=/srv/rom/artifacts/009-axp-los23-port/${BID}-axp-stage1-combo4-cve-hi-batch3 +mkdir -p "$DEST" + +TF_BOOT=$(find "$PROD/obj/PACKAGING/target_files_intermediates" -path "*/IMAGES/boot.img" 2>/dev/null | head -1) +MAKE_BOOT=$PROD/boot.img +if [ -n "${TF_BOOT:-}" ] && [ -f "$TF_BOOT" ]; then + cp -v "$TF_BOOT" "$DEST/boot.img" + cp -v "$MAKE_BOOT" "$DEST/boot-make.img" 2>/dev/null || true +else + cp -v "$MAKE_BOOT" "$DEST/boot.img" +fi +cp -v "$PROD"/lineage-*-UNOFFICIAL-sunfish.zip "$DEST/" 2>/dev/null || true +for f in vbmeta.img dtbo.img; do + [ -f "$PROD/$f" ] && cp -v "$PROD/$f" "$DEST/" +done + +WLAN=$PROD/vendor/lib/modules/wlan.ko +if [ -f "$WLAN" ] && [ -f "$PROD/obj/KERNEL_OBJ/Module.symvers" ]; then + KCRC=$(awk '$2=="kmalloc_caches"{print $1; exit}' "$PROD/obj/KERNEL_OBJ/Module.symvers") + MCRC=$(/sbin/modprobe --dump-modversions "$WLAN" 2>/dev/null | awk '$2=="kmalloc_caches"{print $1; exit}') + echo "wlan kmalloc_caches kernel=$KCRC module=$MCRC" +fi + +if strings "$DEST/boot.img" | grep -qiE 'KernelSU|CONFIG_KSU_SUSFS'; then + echo "FAIL: KernelSU in boot" >&2 + exit 1 +fi + +{ + echo "artifact=$DEST" + echo "list_clean=$LIST_CLEAN (429)" + echo "list_hi1=$LIST_HI1" + echo "list_hi2=$LIST_HI2" + echo "list_hi3=$LIST_HI3" + echo "hardening=Stage1+combo4+FORTIFY + CVE-clean + hi-batch1+2+3" + echo "cve_max_abs_offset_hi=9999" + echo "signing=test-keys" + echo "flash=fastboot flash boot; recover=hi-batch2 BOOT_OK" + date -u +"built=%Y-%m-%dT%H:%M:%SZ" +} | tee "$DEST/README.txt" + +(cd "$DEST" && sha256sum boot.img boot-make.img lineage-*-UNOFFICIAL-sunfish.zip 2>/dev/null || true) \ + | tee "$DEST/SHA256SUMS" + +echo "=== DONE $DEST $(date -Is) ===" +# Force clean exit even if tee gets SIGPIPE on detach wrap +exit 0 diff --git a/scripts/009-bacon-axp-stage1-combo4-cve-hi-releasekeys.sh b/scripts/009-bacon-axp-stage1-combo4-cve-hi-releasekeys.sh new file mode 100755 index 0000000..59faec5 --- /dev/null +++ b/scripts/009-bacon-axp-stage1-combo4-cve-hi-releasekeys.sh @@ -0,0 +1,380 @@ +#!/bin/bash +# 009 bacon — ship pack with project release keys (US-S2). +# Stage1+combo4+FORTIFY + CVE clean + hi-batch1+2+3 + PRODUCT_DEFAULT_DEV_CERTIFICATE. +# Requires $HOME/.android-certs/releasekey.{pk8,x509.pem}. userdebug. +set -e +cd /srv/rom/src/lineage +export HOME=/home/android-build +export CCACHE_DIR=/srv/rom/ccache +export USE_CCACHE=1 +export PATH=/home/android-build/bin:/usr/local/bin:/usr/bin:/bin:$PATH +export ANDROID_BUILD_TOP=/srv/rom/src/lineage +unset OUT_DIR || true +export SUNFISH_A16_MAGISK_PREROOT=1 +export MAGISK_APK=/srv/rom/prebuilts/magisk/Magisk-v30.7.apk + +LOGDIR=/srv/rom/logs/009-build +mkdir -p "$LOGDIR" +LOG=$LOGDIR/bacon-axp-stage1-combo4-cve-hi-releasekeys.log +exec > >(tee -a "$LOG") 2>&1 + +echo "=== START 009-bacon-axp-cve-hi-releasekeys $(date -Is) ===" + +CERT_DIR="${ANDROID_CERTS_DIR:-$HOME/.android-certs}" +if [[ ! -f "$CERT_DIR/releasekey.pk8" || ! -f "$CERT_DIR/releasekey.x509.pem" ]]; then + echo "FAIL: missing $CERT_DIR/releasekey.{pk8,x509.pem}" >&2 + exit 1 +fi +export PRODUCT_DEFAULT_DEV_CERTIFICATE="$CERT_DIR/releasekey" +echo "OK: PRODUCT_DEFAULT_DEV_CERTIFICATE=$PRODUCT_DEFAULT_DEV_CERTIFICATE" + +LIVE=kernel/google/msm-4.14 +BASE=28f9290ae067 +KH=vendor/sunfish-a16/patches/009-kernel-hardening +LIST_CLEAN="$KH/cve-clean-offset.list" +LIST_HI1="$KH/cve-high-offset-batch1.list" +LIST_HI2="$KH/cve-high-offset-batch2.list" +LIST_HI3="$KH/cve-high-offset-batch3.list" +test -f "$LIST_CLEAN" +test -f "$LIST_HI1" +test -f "$LIST_HI2" +test -f "$LIST_HI3" +test -d "$LIVE" + +echo "=== reset kernel @ $BASE ===" +git -C "$LIVE" reset --hard "$BASE" +git -C "$LIVE" clean -fdq + +chmod +x "$KH"/apply_stage1_combo4.sh "$KH"/apply_cve_strict.sh \ + "$KH"/apply_stage1.sh "$KH"/apply_combo4_fortify.sh 2>/dev/null || true + +bash "$KH/apply_stage1_combo4.sh" "$LIVE" + +# US-S5-1 — Yama + SLAB_FREELIST_RANDOM (Graphene/AXP defconfig gaps) +chmod +x "$KH/apply_uss5_1_defconfig.sh" 2>/dev/null || true +bash "$KH/apply_uss5_1_defconfig.sh" "$LIVE" + +export CVE_STRICT_LIST="$LIST_CLEAN" +unset CVE_STRICT_CONTINUE || true +export CVE_MAX_FUZZ=1 +export CVE_MAX_ABS_OFFSET=200 +bash "$KH/apply_cve_strict.sh" "$LIVE" + +export CVE_MAX_ABS_OFFSET=9999 +for L in "$LIST_HI1" "$LIST_HI2" "$LIST_HI3"; do + echo "=== high-offset $(basename "$L") ===" + export CVE_STRICT_LIST="$L" + bash "$KH/apply_cve_strict.sh" "$LIVE" +done + +DEF=$LIVE/arch/arm64/configs/sunfish_defconfig +if grep -qE "^CONFIG_KSU.*=y" "$DEF"; then + echo "FAIL: KernelSU in defconfig" >&2 + exit 1 +fi +for k in FORTIFY_SOURCE INIT_ON_ALLOC_DEFAULT_ON INIT_ON_FREE_DEFAULT_ON \ + SECURITY_DMESG_RESTRICT SLAB_FREELIST_HARDENED \ + SECURITY_YAMA SLAB_FREELIST_RANDOM; do + grep -q "^CONFIG_${k}=y" "$DEF" || { echo "FAIL missing $k" >&2; exit 1; } +done +grep -q "ret = __underlying_strlen(q);" "$LIVE/include/linux/string.h" +grep -q "mmget_still_valid" "$LIVE/mm/madvise.c" +echo "OK: Stage1+combo4+FORTIFY + CVE-clean + hi-batch1+2+3 markers present" + +rm -f out/target/product/sunfish/obj/KERNEL_OBJ/arch/arm64/boot/Image.lz4 \ + out/target/product/sunfish/obj/KERNEL_OBJ/arch/arm64/boot/Image \ + out/target/product/sunfish/kernel + +python3 vendor/sunfish-a16/patches/008-call-rec-flag-secure/apply_wms_disable_secure_debuggable_gate.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_disable_user_apps.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_private_dns_providers.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_connectivity_check.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_unofficial_build_id.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_drop_openssh_packages.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_drop_jelly_gallery2.py + +# Host prebuilts → vendor/sunfish-a16/prebuilt (rsync --delete must not wipe these). +mkdir -p vendor/sunfish-a16/prebuilt +link_prebuilt() { + local name="$1" src="$2" + local dst="vendor/sunfish-a16/prebuilt/$name" + ln -sfn "$src" "$dst" + test -e "$dst" || { echo "FAIL: missing prebuilt $dst -> $src" >&2; exit 1; } +} +link_prebuilt Phonesky.apk /srv/rom/prebuilts/phonesky/Phonesky.apk +link_prebuilt GmsCore.apk /srv/rom/prebuilts/microg/GmsCore.apk +link_prebuilt GsfProxy.apk /srv/rom/prebuilts/microg/GsfProxy.apk +link_prebuilt AuroraStore.apk /srv/rom/prebuilts/axp-apps/AuroraStore.apk +link_prebuilt Droidify.apk /srv/rom/prebuilts/axp-apps/Droidify.apk +link_prebuilt FossifyGallery.apk /srv/rom/prebuilts/axp-apps/FossifyGallery.apk +AAPT=/srv/rom/src/lineage/prebuilts/sdk/tools/linux/bin/aapt +"$AAPT" dump permissions vendor/sunfish-a16/prebuilt/Phonesky.apk 2>/dev/null | grep -q USE_EXACT_ALARM + +# Early hook so LINEAGE_VERSION includes AXP-Resurection-Pro (before version.mk). +mkdir -p vendor/extra +ln -sfn ../sunfish-a16/extra-product.mk vendor/extra/product.mk +test -f vendor/extra/product.mk + +MAGISK_STAGE_DIR=/srv/rom/src/lineage/out/.magisk \ + vendor/sunfish-a16/magisk/prepare_magisk.sh +python3 vendor/sunfish-a16/magisk/apply_releasetools_hook.py --top "$ANDROID_BUILD_TOP" --force +test -f out/.magisk/READY + +rm -rf out/soong/.intermediates/build/make/tools/releasetools/releasetools_common +rm -rf out/soong/.intermediates/build/make/tools/releasetools/add_img_to_target_files +rm -rf out/target/product/sunfish/obj/PACKAGING/target_files_intermediates +rm -f out/target/product/sunfish/lineage-*.zip \ + out/target/product/sunfish/boot.img \ + out/target/product/sunfish/system/priv-app/Phonesky/Phonesky.apk +touch frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java + +set +u +# shellcheck disable=SC1091 +source build/envsetup.sh +set -e +# re-export after envsetup (some trees clear it) +export PRODUCT_DEFAULT_DEV_CERTIFICATE="$CERT_DIR/releasekey" +breakfast sunfish userdebug +test "${TARGET_RELEASE:-}" = "bp4a" +BT_SEPOL=$(get_build_var MAINLINE_BLUETOOTH_SEPOLICY_DEV_CERTIFICATES) +echo "MAINLINE_BLUETOOTH_SEPOLICY_DEV_CERTIFICATES=$BT_SEPOL" +case "$BT_SEPOL" in + *vendor/sunfish-a16/certs*) ;; + *) echo "FAIL: BT sepolicy certs still AOSP default ($BT_SEPOL)" >&2; exit 1 ;; +esac +AVB_KEY=$(get_build_var BOARD_AVB_KEY_PATH) +AVB_ALG=$(get_build_var BOARD_AVB_ALGORITHM) +echo "BOARD_AVB_KEY_PATH=$AVB_KEY" +echo "BOARD_AVB_ALGORITHM=$AVB_ALG" +case "$AVB_KEY" in + *vendor/sunfish-a16/certs/avb.pem) ;; + *) echo "FAIL: AVB key not project certs/avb.pem ($AVB_KEY)" >&2; exit 1 ;; +esac +[[ "$AVB_ALG" == "SHA256_RSA4096" ]] || { echo "FAIL: AVB alg=$AVB_ALG" >&2; exit 1; } + +echo "=== mka bacon $(date -Is) signing=$PRODUCT_DEFAULT_DEV_CERTIFICATE ===" +set -o pipefail +mka bacon -j8 +ec=${PIPESTATUS[0]} +echo "bacon_exit=$ec $(date -Is)" +[ "$ec" -eq 0 ] || exit "$ec" + +# Post-ship gates: drop pipefail. Early-exit awk/head + large pipes otherwise +# yield exit=141 (SIGPIPE) and skip Magisk/AVB/US-S4 checks. +set +o pipefail + +PROD=out/target/product/sunfish +BID=$(date -u +%Y%m%dT%H%M%SZ) +DEST=/srv/rom/artifacts/009-axp-los23-port/${BID}-axp-stage1-combo4-cve-hi-releasekeys +mkdir -p "$DEST" + +# Ship pair = target_files IMAGES (Magisk boot + matching vbmeta). OUT/*.img can be +# stock make images that do NOT match the OTA payload — do not prefer those. +TF_IMG=$(find "$PROD/obj/PACKAGING/target_files_intermediates" -type d -path '*/IMAGES' 2>/dev/null | head -1) +[[ -n "${TF_IMG:-}" && -d "$TF_IMG" ]] || { echo "FAIL: missing target_files IMAGES" >&2; exit 1; } +TF_IMG=$(readlink -f "$TF_IMG") +for f in boot.img vbmeta.img vbmeta_system.img dtbo.img; do + [[ -f "$TF_IMG/$f" ]] || { echo "FAIL: missing $TF_IMG/$f" >&2; exit 1; } + cp -v "$TF_IMG/$f" "$DEST/" +done +# Large partition images: hardlink into DEST so verify_image stays repeatable +# after OUT is cleaned (same FS). Fallback: absolute symlink, then full copy. +for f in vendor.img product.img system.img system_ext.img; do + [[ -f "$TF_IMG/$f" ]] || continue + rm -f "$DEST/$f" + if cp -al "$TF_IMG/$f" "$DEST/$f" 2>/dev/null; then + echo "hardlink $f -> $DEST/$f" + elif ln -sfn "$TF_IMG/$f" "$DEST/$f"; then + echo "symlink-abs $f -> $TF_IMG/$f" + else + cp -v "$TF_IMG/$f" "$DEST/$f" + fi +done +# Keep make OUT boot for forensics only (often stock / non-Magisk). +cp -v "$PROD/boot.img" "$DEST/boot-make-out.img" 2>/dev/null || true +cp -v "$PROD"/lineage-*-UNOFFICIAL*.zip "$DEST/" 2>/dev/null || \ + cp -v "$PROD"/lineage-*.zip "$DEST/" 2>/dev/null || true + +# Publish AXP Resurection Pro ship name (hardlink/copy). Lineage bacon.mk still +# emits lineage-*.zip; do not rebuild solely to rename. +ZIP_LINEAGE=$(ls "$DEST"/lineage-*.zip 2>/dev/null | head -1 || true) +if [[ -n "${ZIP_LINEAGE:-}" ]]; then + # lineage-23.2-YYYYMMDD-UNOFFICIAL[-AXP-Resurection[-Pro]]-sunfish.zip + # → AXP-Resurection-Pro-23.2-YYYYMMDD-sunfish.zip + ZIP_BASE=$(basename "$ZIP_LINEAGE") + ZIP_AXP=$(echo "$ZIP_BASE" | sed -E \ + 's/^lineage-([0-9]+\.[0-9]+)-([0-9]{8})(-[0-9]{6})?-UNOFFICIAL(-AXP-Resurection(-Pro)?)?-sunfish\.zip$/AXP-Resurection-Pro-\1-\2\3-sunfish.zip/') + if [[ "$ZIP_AXP" == "$ZIP_BASE" ]]; then + ZIP_AXP="AXP-Resurection-Pro-${ZIP_BASE#lineage-}" + fi + ln -f "$ZIP_LINEAGE" "$DEST/$ZIP_AXP" 2>/dev/null || cp -v "$ZIP_LINEAGE" "$DEST/$ZIP_AXP" + echo "ship_zip=$ZIP_AXP (from $ZIP_BASE)" +fi + +WLAN=$PROD/vendor/lib/modules/wlan.ko +if [ -f "$WLAN" ] && [ -f "$PROD/obj/KERNEL_OBJ/Module.symvers" ]; then + KCRC=$(awk '$2=="kmalloc_caches"{print $1; exit}' "$PROD/obj/KERNEL_OBJ/Module.symvers") + MCRC=$(/sbin/modprobe --dump-modversions "$WLAN" 2>/dev/null | awk '$2=="kmalloc_caches"{print $1; exit}') + echo "wlan kmalloc_caches kernel=$KCRC module=$MCRC" +fi + +# Avoid pipefail SIGPIPE: never `strings | grep` on large boot.img. +_BOOT_STR=$(mktemp) +strings "$DEST/boot.img" >"$_BOOT_STR" +if grep -iE 'KernelSU|CONFIG_KSU_SUSFS' "$_BOOT_STR" >/dev/null; then + rm -f "$_BOOT_STR" + echo "FAIL: KernelSU in boot" >&2 + exit 1 +fi +rm -f "$_BOOT_STR" + +# Magisk preroot must be present on the ship boot (magiskboot cpio test: 0=stock, 1=Magisk). +MAGISKBOOT="$ANDROID_BUILD_TOP/out/.magisk/magiskboot" +[[ -x "$MAGISKBOOT" ]] || { echo "FAIL: missing $MAGISKBOOT" >&2; exit 1; } +MB_TMP=$(mktemp -d) +cp "$DEST/boot.img" "$MB_TMP/boot.img" +set +e +( cd "$MB_TMP" && "$MAGISKBOOT" unpack boot.img >/dev/null ) +( cd "$MB_TMP" && "$MAGISKBOOT" cpio ramdisk.cpio test ) +MB_EC=$? +set -e +rm -rf "$MB_TMP" +# magiskboot cpio test: 0=stock, non-zero (usually 1) = Magisk present +[[ "$MB_EC" -ne 0 ]] || { echo "FAIL: ship boot is stock (magiskboot cpio test=$MB_EC); expected Magisk" >&2; exit 1; } +echo "magiskboot_cpio_test=$MB_EC (non-zero => Magisk present)" + +ZIP=$(ls "$DEST"/lineage-*-UNOFFICIAL*.zip 2>/dev/null | head -1 || true) +if [[ -n "$ZIP" ]]; then + unzip -p "$ZIP" META-INF/com/android/otacert 2>/dev/null | openssl x509 -noout -subject 2>/dev/null \ + | tee "$DEST/otacert-subject.txt" || true + if grep -qi 'Test Keys\|Android\|AOSP' "$DEST/otacert-subject.txt" 2>/dev/null; then + echo "WARN: otacert subject looks like test/AOSP — check keys wire" | tee -a "$DEST/README.txt" + fi +fi + +# US-S3 artifact gates — fail closed (signing infrastructure; NOT runtime AVB harden). +# flags=3 => HASHTREE_DISABLED|VERIFICATION_DISABLED (libavb); Magisk-friendly unlocked LAB. +AVBTOOL="$ANDROID_BUILD_TOP/out/host/linux-x86/bin/avbtool" +AVB_PEM="$ANDROID_BUILD_TOP/vendor/sunfish-a16/certs/avb.pem" +AVB_PKMD="$ANDROID_BUILD_TOP/vendor/sunfish-a16/certs/avb_pkmd.bin" +[[ -x "$AVBTOOL" ]] || { echo "FAIL: missing $AVBTOOL" >&2; exit 1; } +[[ -f "$DEST/vbmeta.img" ]] || { echo "FAIL: missing $DEST/vbmeta.img" >&2; exit 1; } +[[ -f "$DEST/boot.img" ]] || { echo "FAIL: missing $DEST/boot.img" >&2; exit 1; } +[[ -f "$AVB_PEM" ]] || { echo "FAIL: missing $AVB_PEM" >&2; exit 1; } +if [[ ! -f "$AVB_PKMD" ]]; then + "$AVBTOOL" extract_public_key --key "$AVB_PEM" --output "$AVB_PKMD" +fi + +"$AVBTOOL" info_image --image "$DEST/vbmeta.img" | tee "$DEST/vbmeta-info.txt" +EXP=$(sha1sum "$AVB_PKMD" | awk '{print $1}') +GOT=$(awk '/^Public key \(sha1\):/{print $NF; exit}' "$DEST/vbmeta-info.txt") +FLAGS=$(awk '/^Flags:/{print $2; exit}' "$DEST/vbmeta-info.txt") +echo "avb_pubkey_sha1 artifact=$GOT project=$EXP flags=$FLAGS" +[[ -n "$GOT" ]] || { echo "FAIL: could not parse vbmeta public key sha1" >&2; exit 1; } +[[ "$GOT" == "$EXP" ]] || { echo "FAIL: vbmeta pubkey != project avb_pkmd.bin" >&2; exit 1; } +[[ "$FLAGS" == "3" ]] || { echo "FAIL: expected vbmeta Flags 3 (Magisk track), got '$FLAGS'" >&2; exit 1; } + +# Cryptographic check against TF sibling images in $DEST (hardlinked/copied). +# Magisk boot footer is Algorithm NONE — chain trust is top-level vbmeta + project key. +# Does NOT mean the device will enforce AVB at boot (flags 3 disables that). +set +e +( + cd "$DEST" + "$AVBTOOL" verify_image --image vbmeta.img --key "$AVB_PEM" \ + --expected_chain_partition "vbmeta_system:1:$AVB_PKMD" +) >"$DEST/vbmeta-verify.txt" 2>&1 +ec_v=$? +set -e +cat "$DEST/vbmeta-verify.txt" +[[ "$ec_v" -eq 0 ]] || { echo "FAIL: avbtool verify_image vbmeta.img (TF Magisk boot chain)" >&2; exit 1; } + +set +e +( + cd "$DEST" + "$AVBTOOL" verify_image --image vbmeta_system.img --key "$AVB_PEM" +) >"$DEST/vbmeta_system-verify.txt" 2>&1 +ec_s=$? +set -e +cat "$DEST/vbmeta_system-verify.txt" +[[ "$ec_s" -eq 0 ]] || { echo "FAIL: avbtool verify_image vbmeta_system.img" >&2; exit 1; } + +# Boot footer integrity (unsigned Magisk footer is OK); do not require --key match. +set +e +( + cd "$DEST" + "$AVBTOOL" verify_image --image boot.img +) >"$DEST/boot-verify.txt" 2>&1 +ec_b=$? +set -e +cat "$DEST/boot-verify.txt" +[[ "$ec_b" -eq 0 ]] || { echo "FAIL: avbtool verify_image boot.img footer/hash" >&2; exit 1; } + +# US-S4-1 — AXP PRO product surface (binaries gone; init.openssh.rc kept). +SIMG="$ANDROID_BUILD_TOP/out/host/linux-x86/bin/simg2img" +[[ -x "$SIMG" ]] || { echo "FAIL: missing $SIMG" >&2; exit 1; } +[[ -e "$DEST/product.img" ]] || { echo "FAIL: missing $DEST/product.img" >&2; exit 1; } +PROD_RAW=$(mktemp /tmp/axp-product-XXXX.img) +"$SIMG" "$DEST/product.img" "$PROD_RAW" +for p in /bin/sshd /bin/ssh /bin/scp /bin/sftp /bin/rsync /bin/start-ssh; do + if debugfs -R "stat $p" "$PROD_RAW" 2>&1 | grep -q 'Inode:'; then + rm -f "$PROD_RAW" + echo "FAIL: US-S4 expected absent $p on product.img" >&2 + exit 1 + fi +done +if ! debugfs -R "stat /etc/init/init.openssh.rc" "$PROD_RAW" 2>&1 | grep -q 'Inode:'; then + rm -f "$PROD_RAW" + echo "FAIL: US-S4 expected init.openssh.rc present (AXP surface)" >&2 + exit 1 +fi +echo "US-S4-1 product surface OK (no ssh/rsync bins; init.openssh.rc present)" + +# US-S4-2 — AXP PRO: no Jelly / Gallery2 *apps* on product (Fossify stays). +# Note: LOCAL_OVERRIDES removes Gallery2.apk but stale JNI symlink dirs under +# product/app/Gallery2/lib can remain from older out/ — gate on the APK. +for p in /app/Jelly/Jelly.apk /app/Gallery2/Gallery2.apk; do + if debugfs -R "stat $p" "$PROD_RAW" 2>&1 | grep -q 'Inode:'; then + rm -f "$PROD_RAW" + echo "FAIL: US-S4-2 expected absent $p on product.img" >&2 + exit 1 + fi +done +# Directory-only Gallery2 leftover (jni symlinks) is not a shipped app — warn. +if debugfs -R "stat /app/Gallery2" "$PROD_RAW" 2>&1 | grep -q 'Inode:'; then + echo "WARN: US-S4-2 /app/Gallery2 dir still present (likely stale jni symlinks; no APK)" +fi +if ! debugfs -R "stat /app/FossifyGallery" "$PROD_RAW" 2>&1 | grep -q 'Inode:'; then + rm -f "$PROD_RAW" + echo "FAIL: US-S4-2 expected FossifyGallery present" >&2 + exit 1 +fi +rm -f "$PROD_RAW" +echo "US-S4-2 product surface OK (no Jelly/Gallery2 APK; FossifyGallery present)" + +{ + echo "artifact=$DEST" + echo "list_clean=$LIST_CLEAN (429)" + echo "list_hi=batch1+2+3" + echo "hardening=Stage1+combo4+FORTIFY + CVE-clean + hi-batch1+2+3 + US-S4-1-no-openssh + US-S4-2-no-jelly-gallery2 + US-S5-1-yama-slabrand" + echo "branding=AXP-Resurection-Pro" + echo "signing=$PRODUCT_DEFAULT_DEV_CERTIFICATE" + echo "avb_infra=$AVB_KEY alg=$AVB_ALG flags=3 (HASHTREE_DISABLED|VERIFICATION_DISABLED)" + echo "avb_runtime_enforce=no (unlocked Magisk track; not AVB-hardened boot)" + echo "avb_pubkey_sha1=$GOT" + echo "magiskboot_cpio_test=$MB_EC" + echo "ship_images=target_files/IMAGES (not OUT make images)" + echo "ship_zip_brand=AXP-Resurection-Pro-*-sunfish.zip (sibling of lineage-*.zip; not slim)" + echo "flash=sideload AXP-Resurection-Pro zip (or lineage twin); boot-only insufficient" + echo "recover=20261002T085915Z-axp-stage1-combo4-cve-hi-releasekeys" + echo "bootloader_lock=wont" + echo "oem_unlock=leave_enabled_escape_hatch_not_guaranteed_recovery" + date -u +"built=%Y-%m-%dT%H:%M:%SZ" +} | tee "$DEST/README.txt" + +(cd "$DEST" && sha256sum boot.img boot-make-out.img vbmeta.img vbmeta_system.img dtbo.img \ + lineage-*.zip AXP-Resurection-Pro-*.zip 2>/dev/null || true) \ + | tee "$DEST/SHA256SUMS" + +echo "FLASH_READY $DEST" +echo "=== DONE $DEST $(date -Is) ===" +exit 0 diff --git a/scripts/009-bacon-axp-stage1-combo4-cve.sh b/scripts/009-bacon-axp-stage1-combo4-cve.sh new file mode 100644 index 0000000..cde041b --- /dev/null +++ b/scripts/009-bacon-axp-stage1-combo4-cve.sh @@ -0,0 +1,164 @@ +#!/bin/bash +# 009 bacon — Stage1 + combo4+FORTIFY + CVE-strict (AXP cve_checker allowlist). +# Intentionally test-keys (isolate CVE vs signing). Flash only after LAB boot/Wi‑Fi. +# Do NOT flash old 20260918 *-axp-kh-cve/full (pre-FORTIFY hang). +set -e +cd /srv/rom/src/lineage +export HOME=/home/android-build +export CCACHE_DIR=/srv/rom/ccache +export USE_CCACHE=1 +export PATH=/home/android-build/bin:/usr/local/bin:/usr/bin:/bin:$PATH +export ANDROID_BUILD_TOP=/srv/rom/src/lineage +unset OUT_DIR || true +export SUNFISH_A16_MAGISK_PREROOT=1 +export MAGISK_APK=/srv/rom/prebuilts/magisk/Magisk-v30.7.apk +# Isolate: no release keys on this CVE iteration +unset PRODUCT_DEFAULT_DEV_CERTIFICATE || true + +LOGDIR=/srv/rom/logs/009-build +mkdir -p "$LOGDIR" +LOG=$LOGDIR/bacon-axp-stage1-combo4-cve.log +exec > >(tee -a "$LOG") 2>&1 + +echo "=== START 009-bacon-axp-stage1-combo4-cve $(date -Is) ===" + +LIVE=kernel/google/msm-4.14 +BASE=28f9290ae067 +test -d "$LIVE" + +echo "=== reset kernel @ $BASE ===" +git -C "$LIVE" reset --hard "$BASE" +git -C "$LIVE" clean -fdq + +KH=vendor/sunfish-a16/patches/009-kernel-hardening +chmod +x "$KH"/apply_stage1_combo4.sh "$KH"/apply_cve_strict.sh \ + "$KH"/apply_stage1_combo4_cve.sh "$KH"/apply_stage1.sh \ + "$KH"/apply_combo4_fortify.sh 2>/dev/null || true +bash "$KH/apply_stage1_combo4_cve.sh" "$LIVE" + +DEF=$LIVE/arch/arm64/configs/sunfish_defconfig +if grep -qE "^CONFIG_KSU.*=y" "$DEF"; then + echo "FAIL: $DEF still enables KernelSU" >&2 + exit 1 +fi +for k in FORTIFY_SOURCE INIT_ON_ALLOC_DEFAULT_ON INIT_ON_FREE_DEFAULT_ON \ + SECURITY_DMESG_RESTRICT SLAB_FREELIST_HARDENED; do + if ! grep -q "^CONFIG_${k}=y" "$DEF"; then + echo "FAIL: missing CONFIG_${k}=y" >&2 + exit 1 + fi +done +grep -q "ret = __underlying_strlen(q);" "$LIVE/include/linux/string.h" +echo "OK: Stage1 + combo4+FORTIFY + CVE markers present" + +rm -f out/target/product/sunfish/obj/KERNEL_OBJ/arch/arm64/boot/Image.lz4 \ + out/target/product/sunfish/obj/KERNEL_OBJ/arch/arm64/boot/Image \ + out/target/product/sunfish/kernel +echo "OK: cleared prior Image for kernel rebuild" + +python3 vendor/sunfish-a16/patches/008-call-rec-flag-secure/apply_wms_disable_secure_debuggable_gate.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_disable_user_apps.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_private_dns_providers.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_connectivity_check.py + +PH=/srv/rom/src/lineage/vendor/sunfish-a16/prebuilt/Phonesky.apk +test -e "$PH" +AAPT=/srv/rom/src/lineage/prebuilts/sdk/tools/linux/bin/aapt +if ! "$AAPT" dump permissions "$PH" 2>/dev/null | grep -q USE_EXACT_ALARM; then + echo "FAIL: Phonesky missing USE_EXACT_ALARM" >&2 + exit 1 +fi +echo "OK: Phonesky has USE_EXACT_ALARM" + +MAGISK_STAGE_DIR=/srv/rom/src/lineage/out/.magisk \ + vendor/sunfish-a16/magisk/prepare_magisk.sh +python3 vendor/sunfish-a16/magisk/apply_releasetools_hook.py --top "$ANDROID_BUILD_TOP" --force +test -f out/.magisk/READY + +rm -rf out/soong/.intermediates/build/make/tools/releasetools/releasetools_common +rm -rf out/soong/.intermediates/build/make/tools/releasetools/add_img_to_target_files +rm -rf out/target/product/sunfish/obj/PACKAGING/target_files_intermediates +rm -f out/target/product/sunfish/lineage-*.zip \ + out/target/product/sunfish/boot.img \ + out/target/product/sunfish/system/priv-app/Phonesky/Phonesky.apk +touch frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java + +set +u +# shellcheck disable=SC1091 +source build/envsetup.sh +set -e +# Force test-keys for this CVE pack (signing is a later stage) +unset PRODUCT_DEFAULT_DEV_CERTIFICATE || true +echo "OK: signing=test-keys (CVE isolation)" + +breakfast sunfish userdebug +test "${TARGET_RELEASE:-}" = "bp4a" + +echo "=== mka bacon $(date -Is) ===" +set -o pipefail +mka bacon -j8 +ec=${PIPESTATUS[0]} +echo "bacon_exit=$ec $(date -Is)" +[ "$ec" -eq 0 ] || exit "$ec" + +PROD=out/target/product/sunfish +BID=$(date -u +%Y%m%dT%H%M%SZ) +DEST=/srv/rom/artifacts/009-axp-los23-port/${BID}-axp-stage1-combo4-cve +mkdir -p "$DEST" + +TF_BOOT=$(find "$PROD/obj/PACKAGING/target_files_intermediates" -path "*/IMAGES/boot.img" 2>/dev/null | head -1) +MAKE_BOOT=$PROD/boot.img +if [ -n "${TF_BOOT:-}" ] && [ -f "$TF_BOOT" ]; then + cp -v "$TF_BOOT" "$DEST/boot.img" + cp -v "$MAKE_BOOT" "$DEST/boot-make.img" 2>/dev/null || true + echo "boot_source=target_files_IMAGES" +else + cp -v "$MAKE_BOOT" "$DEST/boot.img" + echo "WARN: no TF IMAGES/boot.img — using Make boot" +fi + +cp -v "$PROD"/lineage-*-UNOFFICIAL-sunfish.zip "$DEST/" 2>/dev/null || true +for f in vbmeta.img dtbo.img; do + [ -f "$PROD/$f" ] && cp -v "$PROD/$f" "$DEST/" +done + +WLAN=$PROD/vendor/lib/modules/wlan.ko +if [ -f "$WLAN" ] && [ -f "$PROD/obj/KERNEL_OBJ/Module.symvers" ]; then + KCRC=$(awk '$2=="kmalloc_caches"{print $1; exit}' "$PROD/obj/KERNEL_OBJ/Module.symvers") + MCRC=$(/sbin/modprobe --dump-modversions "$WLAN" 2>/dev/null | awk '$2=="kmalloc_caches"{print $1; exit}') + echo "wlan kmalloc_caches kernel=$KCRC module=$MCRC" + if [ -n "$KCRC" ] && [ -n "$MCRC" ] && [ "$KCRC" = "$MCRC" ]; then + echo "OK: wlan.ko CRC matches kernel (Wi-Fi pack coherent)" + else + echo "WARN: wlan.ko CRC mismatch or unreadable — check before flash" + fi +fi + +MB=out/.magisk/magiskboot +if [ -x "$MB" ]; then + rm -rf "$DEST/boot-check" && mkdir -p "$DEST/boot-check" + if ! "$MB" unpack "$DEST/boot.img" "$DEST/boot-check" >/dev/null 2>&1; then + echo "WARN: magiskboot unpack failed (host SIGILL flake possible)" + fi +fi +if strings "$DEST/boot.img" | grep -qiE 'KernelSU|CONFIG_KSU_SUSFS'; then + echo "FAIL: KernelSU strings in boot.img" >&2 + exit 1 +fi +echo "OK: no KernelSU strings in boot.img" + +{ + echo "artifact=$DEST" + echo "kernel_base=$BASE" + echo "hardening=Stage1 + combo4+clang-fortify + CVE-strict (~503 AXP allowlist, denylist skipped)" + echo "magisk=preroot EXTENDROM-class v30.7" + echo "signing=test-keys (CVE isolation; release-keys later)" + echo "flash=recovery wipe + sideload zip + reboot system" + echo "note=do not flash 20260918 kh-cve/kh-full (pre-FORTIFY hang)" + date -u +"built=%Y-%m-%dT%H:%M:%SZ" +} | tee "$DEST/README.txt" + +(cd "$DEST" && sha256sum boot.img boot-make.img lineage-*-UNOFFICIAL-sunfish.zip 2>/dev/null || true) \ + | tee "$DEST/SHA256SUMS" + +echo "=== DONE $DEST $(date -Is) ===" diff --git a/scripts/009-bacon-axp-stage1-combo4.sh b/scripts/009-bacon-axp-stage1-combo4.sh new file mode 100755 index 0000000..caf7979 --- /dev/null +++ b/scripts/009-bacon-axp-stage1-combo4.sh @@ -0,0 +1,176 @@ +#!/bin/bash +# 009 bacon — Magisk preroot + Stage1 Graphene/AH + combo4 Clang FORTIFY. +# Full zip so vendor modules match kernel (Wi-Fi). LAB flash only after gates. +set -e +cd /srv/rom/src/lineage +export HOME=/home/android-build +export CCACHE_DIR=/srv/rom/ccache +export USE_CCACHE=1 +export PATH=/home/android-build/bin:/usr/local/bin:/usr/bin:/bin:$PATH +export ANDROID_BUILD_TOP=/srv/rom/src/lineage +unset OUT_DIR || true +export SUNFISH_A16_MAGISK_PREROOT=1 +export MAGISK_APK=/srv/rom/prebuilts/magisk/Magisk-v30.7.apk + +LOGDIR=/srv/rom/logs/009-build +mkdir -p "$LOGDIR" +LOG=$LOGDIR/bacon-axp-stage1-combo4.log +exec > >(tee -a "$LOG") 2>&1 + +echo "=== START 009-bacon-axp-stage1-combo4 $(date -Is) ===" + +LIVE=kernel/google/msm-4.14 +BASE=28f9290ae067 +test -d "$LIVE" + +echo "=== reset kernel @ $BASE ===" +git -C "$LIVE" reset --hard "$BASE" +git -C "$LIVE" clean -fdq + +APPLY=vendor/sunfish-a16/patches/009-kernel-hardening/apply_stage1_combo4.sh +test -x "$APPLY" || chmod +x "$APPLY" +bash "$APPLY" "$LIVE" + +DEF=$LIVE/arch/arm64/configs/sunfish_defconfig +if grep -qE "^CONFIG_KSU.*=y" "$DEF"; then + echo "FAIL: $DEF still enables KernelSU" >&2 + exit 1 +fi +for k in FORTIFY_SOURCE INIT_ON_ALLOC_DEFAULT_ON INIT_ON_FREE_DEFAULT_ON \ + SECURITY_DMESG_RESTRICT SLAB_FREELIST_HARDENED; do + if ! grep -q "^CONFIG_${k}=y" "$DEF"; then + echo "FAIL: missing CONFIG_${k}=y" >&2 + exit 1 + fi +done +grep -q "ret = __underlying_strlen(q);" "$LIVE/include/linux/string.h" +# Stage1 marker (Deny USB / sysctl) +if ! grep -q "deny_new_usb" "$LIVE/kernel/sysctl.c" \ + && ! grep -qE "deny_new_usb|CONFIG_DENY_NEW_USB|usb_device_authorization" \ + "$LIVE/drivers/usb/core/hub.c"; then + echo "FAIL: Stage1 Deny_USB markers missing" >&2 + exit 1 +fi +echo "OK: Stage1 + combo4+FORTIFY markers present" + +rm -f out/target/product/sunfish/obj/KERNEL_OBJ/arch/arm64/boot/Image.lz4 \ + out/target/product/sunfish/obj/KERNEL_OBJ/arch/arm64/boot/Image \ + out/target/product/sunfish/kernel +echo "OK: cleared prior Image for kernel rebuild" + +python3 vendor/sunfish-a16/patches/008-call-rec-flag-secure/apply_wms_disable_secure_debuggable_gate.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_disable_user_apps.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_private_dns_providers.py +python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_connectivity_check.py + +PH=/srv/rom/src/lineage/vendor/sunfish-a16/prebuilt/Phonesky.apk +test -e "$PH" +AAPT=/srv/rom/src/lineage/prebuilts/sdk/tools/linux/bin/aapt +if ! "$AAPT" dump permissions "$PH" 2>/dev/null | grep -q USE_EXACT_ALARM; then + echo "FAIL: Phonesky missing USE_EXACT_ALARM" >&2 + exit 1 +fi +echo "OK: Phonesky has USE_EXACT_ALARM" + +MAGISK_STAGE_DIR=/srv/rom/src/lineage/out/.magisk \ + vendor/sunfish-a16/magisk/prepare_magisk.sh +python3 vendor/sunfish-a16/magisk/apply_releasetools_hook.py --top "$ANDROID_BUILD_TOP" --force +test -f out/.magisk/READY + +rm -rf out/soong/.intermediates/build/make/tools/releasetools/releasetools_common +rm -rf out/soong/.intermediates/build/make/tools/releasetools/add_img_to_target_files +rm -rf out/target/product/sunfish/obj/PACKAGING/target_files_intermediates +rm -f out/target/product/sunfish/lineage-*.zip \ + out/target/product/sunfish/boot.img \ + out/target/product/sunfish/system/priv-app/Phonesky/Phonesky.apk +touch frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java + +set +u +# shellcheck disable=SC1091 +source build/envsetup.sh +set -e + +# US-S2: project release keys when present (Gate G). Fallback = AOSP test-keys. +CERT_DIR="${ANDROID_CERTS_DIR:-$HOME/.android-certs}" +if [[ -f "$CERT_DIR/releasekey.pk8" && -f "$CERT_DIR/releasekey.x509.pem" ]]; then + export PRODUCT_DEFAULT_DEV_CERTIFICATE="$CERT_DIR/releasekey" + echo "OK: PRODUCT_DEFAULT_DEV_CERTIFICATE=$PRODUCT_DEFAULT_DEV_CERTIFICATE" +else + echo "WARN: no $CERT_DIR/releasekey — building with AOSP test-keys" +fi + +breakfast sunfish userdebug +test "${TARGET_RELEASE:-}" = "bp4a" + +echo "=== mka bacon $(date -Is) ===" +set -o pipefail +mka bacon -j8 +ec=${PIPESTATUS[0]} +echo "bacon_exit=$ec $(date -Is)" +[ "$ec" -eq 0 ] || exit "$ec" + +PROD=out/target/product/sunfish +BID=$(date -u +%Y%m%dT%H%M%SZ) +if [[ -n "${PRODUCT_DEFAULT_DEV_CERTIFICATE:-}" ]]; then + DEST=/srv/rom/artifacts/009-axp-los23-port/${BID}-axp-stage1-combo4-releasekeys +else + DEST=/srv/rom/artifacts/009-axp-los23-port/${BID}-axp-stage1-combo4 +fi +mkdir -p "$DEST" + +TF_BOOT=$(find "$PROD/obj/PACKAGING/target_files_intermediates" -path "*/IMAGES/boot.img" 2>/dev/null | head -1) +MAKE_BOOT=$PROD/boot.img +if [ -n "${TF_BOOT:-}" ] && [ -f "$TF_BOOT" ]; then + cp -v "$TF_BOOT" "$DEST/boot.img" + cp -v "$MAKE_BOOT" "$DEST/boot-make.img" 2>/dev/null || true + echo "boot_source=target_files_IMAGES" +else + cp -v "$MAKE_BOOT" "$DEST/boot.img" + echo "WARN: no TF IMAGES/boot.img — using Make boot" +fi + +cp -v "$PROD"/lineage-*-UNOFFICIAL-sunfish.zip "$DEST/" 2>/dev/null || true +for f in vbmeta.img dtbo.img; do + [ -f "$PROD/$f" ] && cp -v "$PROD/$f" "$DEST/" +done + +# Module CRC sanity vs kernel (Wi-Fi) +WLAN=$PROD/vendor/lib/modules/wlan.ko +if [ -f "$WLAN" ] && [ -f "$PROD/obj/KERNEL_OBJ/Module.symvers" ]; then + KCRC=$(awk '$2=="kmalloc_caches"{print $1; exit}' "$PROD/obj/KERNEL_OBJ/Module.symvers") + MCRC=$(/sbin/modprobe --dump-modversions "$WLAN" 2>/dev/null | awk '$2=="kmalloc_caches"{print $1; exit}') + echo "wlan kmalloc_caches kernel=$KCRC module=$MCRC" + if [ -n "$KCRC" ] && [ -n "$MCRC" ] && [ "$KCRC" = "$MCRC" ]; then + echo "OK: wlan.ko CRC matches kernel (Wi-Fi pack coherent)" + else + echo "WARN: wlan.ko CRC mismatch or unreadable — check before flash" + fi +fi + +MB=out/.magisk/magiskboot +if [ -x "$MB" ]; then + rm -rf "$DEST/boot-check" && mkdir -p "$DEST/boot-check" + if ! "$MB" unpack "$DEST/boot.img" "$DEST/boot-check" >/dev/null 2>&1; then + echo "WARN: magiskboot unpack failed (host SIGILL flake possible)" + fi +fi +if strings "$DEST/boot.img" | grep -qiE 'KernelSU|CONFIG_KSU_SUSFS'; then + echo "FAIL: KernelSU strings in boot.img" >&2 + exit 1 +fi +echo "OK: no KernelSU strings in boot.img" + +{ + echo "artifact=$DEST" + echo "kernel_base=$BASE" + echo "hardening=Stage1 Graphene/AH + combo4+clang-fortify (nested __underlying_strlen)" + echo "magisk=preroot EXTENDROM-class v30.7" + echo "signing=${PRODUCT_DEFAULT_DEV_CERTIFICATE:-test-keys}" + echo "flash=recovery wipe + sideload zip + reboot system (do NOT flash boot onto other slot alone)" + date -u +"built=%Y-%m-%dT%H:%M:%SZ" +} | tee "$DEST/README.txt" + +(cd "$DEST" && sha256sum boot.img boot-make.img lineage-*-UNOFFICIAL-sunfish.zip 2>/dev/null || true) \ + | tee "$DEST/SHA256SUMS" + +echo "=== DONE $DEST $(date -Is) ===" diff --git a/scripts/009-bisect-ksync-one.sh b/scripts/009-bisect-ksync-one.sh new file mode 100755 index 0000000..b768bd7 --- /dev/null +++ b/scripts/009-bisect-ksync-one.sh @@ -0,0 +1,113 @@ +#!/bin/bash +# Usage: 009-bisect-ksync-one.sh [CONFIG_FOO] ... +# Rebuilds kernel with optional CONFIG_=y extras, injects into GOODMAKE. +set -eo pipefail +NAME=${1:?name}; shift +cd /srv/rom/src/lineage +export HOME=/home/android-build CCACHE_DIR=/srv/rom/ccache USE_CCACHE=1 +export PATH=/home/android-build/bin:/usr/local/bin:/usr/bin:/bin:$PATH +export ANDROID_BUILD_TOP=/srv/rom/src/lineage +unset OUT_DIR || true +LIVE=kernel/google/msm-4.14 +DEF=$LIVE/arch/arm64/configs/sunfish_defconfig +GOOD=/srv/rom/artifacts/009-axp-los23-port/20260918T143547Z-axp-full/boot-make.img +MB=$(find /srv/rom/prebuilts/magisk -name magiskboot | head -1) + +echo "=== ksync-$NAME START $(date -Is) configs=[$*] ===" +git -C "$LIVE" reset --hard 28f9290ae067 +git -C "$LIVE" clean -fd +sed -i '/CONFIG_KSU/d' "$DEF" +echo '# CONFIG_KSU is not set' >> "$DEF" +for k in FORTIFY_SOURCE INIT_ON_ALLOC_DEFAULT_ON INIT_ON_FREE_DEFAULT_ON SECURITY_DMESG_RESTRICT SLAB_FREELIST_HARDENED SLAB_HARDENED; do + sed -i "/CONFIG_${k}/d" "$DEF" +done +for cfg in "$@"; do + echo "${cfg}=y" >> "$DEF" + echo "enable $cfg" +done + +# Clang FORTIFY port (no BUG stubs). See docs/009-fortify-clang-port.md +case " $* " in + *" CONFIG_FORTIFY_SOURCE "*) + python3 /srv/rom/artifacts/009-axp-los23-port/scripts/apply_fortify_clang.py "$LIVE" + # Driver bounds for Clang/LTO fortify false-path link (docs/009-fortify-pos0-link-failure-20260927.md) + patch -p1 --forward --batch -d "$LIVE" < /srv/rom/artifacts/009-axp-los23-port/scripts/0001-driver-bounds-rtac-fils.patch + if [ "${FORTIFY_DIAG:-0}" = 1 ]; then + python3 /srv/rom/artifacts/009-axp-los23-port/scripts/apply_fortify_diag.py "$LIVE" + fi + ;; +esac + +# Plaintext panic mirror into alt ramoops (no FORTIFY). See docs/009-fortify-diag-capture-plan.md +# Also applied via FORTIFY_DIAG above when building fortify-diag. +if [ "${PSTORE_ALT_PLAIN:-0}" = 1 ]; then + python3 /srv/rom/artifacts/009-axp-los23-port/scripts/apply_fortify_diag.py "$LIVE" +fi + +# FORTIFY stubs DISABLED by default (see docs/009-fortify-clang-port.md). +# Set ALLOW_FORTIFY_BUG_STUBS=1 only for archaeology — not a valid port. +if [ "${ALLOW_FORTIFY_BUG_STUBS:-0}" = 1 ]; then + case " $* " in *" CONFIG_FORTIFY_SOURCE "*) + echo 'WARN: injecting BUG() fortify stubs (ALLOW_FORTIFY_BUG_STUBS=1)' + python3 - <<'PY2' +from pathlib import Path +import re +p = Path("kernel/google/msm-4.14/lib/string.c") +t = p.read_text() +if "EXPORT_SYMBOL(__read_overflow)" not in t: + m = re.search(r"void fortify_panic\(const char \*name\).*?EXPORT_SYMBOL\(fortify_panic\);", t, re.S) + assert m, 'fortify_panic marker missing' + stub = m.group(0) + """ + +void __read_overflow(void) { BUG(); } +EXPORT_SYMBOL(__read_overflow); +void __read_overflow2(void) { BUG(); } +EXPORT_SYMBOL(__read_overflow2); +void __read_overflow3(void) { BUG(); } +EXPORT_SYMBOL(__read_overflow3); +void __write_overflow(void) { BUG(); } +EXPORT_SYMBOL(__write_overflow); +""" + p.write_text(t[:m.start()] + stub + t[m.end():]) +PY2 + ;; esac +fi + +set +u; source build/envsetup.sh; set -e +breakfast sunfish userdebug +echo "TARGET_RELEASE=${TARGET_RELEASE:-unset}" +test "${TARGET_RELEASE:-}" = "bp4a" + +rm -f out/target/product/sunfish/obj/KERNEL_OBJ/arch/arm64/boot/Image.lz4 +rm -f out/target/product/sunfish/boot.img +mka bootimage -j8 + +PROD=/srv/rom/src/lineage/out/target/product/sunfish +BID=$(date -u +%Y%m%dT%H%M%SZ) +DEST=/srv/rom/artifacts/009-axp-los23-port/${BID}-bisect-ksync-${NAME} +mkdir -p "$DEST" +cp -v "$PROD/boot.img" "$DEST/boot-make-native.img" + +WORK=$DEST/work +rm -rf "$WORK"; mkdir -p "$WORK/good" "$WORK/new" "$WORK/check" +(cd "$WORK/good" && "$MB" unpack "$GOOD") +(cd "$WORK/new" && "$MB" unpack "$PROD/boot.img") +cp -f "$WORK/new/kernel" "$WORK/good/kernel" +(cd "$WORK/good" && "$MB" repack "$GOOD" "$DEST/boot-make.img") +(cd "$WORK/check" && "$MB" unpack "$DEST/boot-make.img" >/dev/null && "$MB" cpio ramdisk.cpio extract) +echo "=== VERIFY $NAME ===" +grep -E 'security_patch|sdk_full' "$WORK/check/prop.default" | sort -u +# Prefer header from first successful unpack (WORK/check); do not ||true a SIGILL unpack. +if [[ -f "$WORK/check/kernel" ]]; then + "$MB" unpack "$DEST/boot-make.img" >"$DEST/unpack-hdr.txt" 2>&1 || \ + echo "WARN: magiskboot header unpack failed (host SIGILL?); kernel already verified via WORK/check" | tee -a "$DEST/unpack-hdr.txt" +else + "$MB" unpack "$DEST/boot-make.img" >"$DEST/unpack-hdr.txt" 2>&1 +fi +grep -E 'OS_PATCH|KERNEL_SZ|KERNEL_FMT' "$DEST/unpack-hdr.txt" || true +# ikconfig spot-check +/srv/rom/src/lineage/kernel/google/msm-4.14/scripts/extract-ikconfig "$WORK/check/kernel" 2>/dev/null \ + | grep -E 'CONFIG_(SECURITY_DMESG_RESTRICT|SLAB_FREELIST_HARDENED|FORTIFY_SOURCE|INIT_ON_ALLOC)=' || true +sha256sum "$DEST/boot-make.img" "$DEST/boot-make-native.img" | tee "$DEST/SHA256SUMS" +printf '%s\n' "ksync bisect: $NAME" "configs: $*" "Flash boot-make.img only (GOODMAKE ramdisk)." > "$DEST/README.txt" +echo "=== DONE $DEST $(date -Is) ===" diff --git a/scripts/009-bisect-ksync-pstore-alt-plain.sh b/scripts/009-bisect-ksync-pstore-alt-plain.sh new file mode 100755 index 0000000..c4a3153 --- /dev/null +++ b/scripts/009-bisect-ksync-pstore-alt-plain.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# Channel-proof build (no FORTIFY): diag v4 early_ioremap + ioremap after mm_init. +# Validate (docs/009-fortify-diag-capture-plan.md v4 — mid/late only): +# 0) Wipe first 4K of access-ramoops or fresh attempt id +# 1) Flash boot-make.img, boot, adb root +# 2) Milestone: strings | grep AXPDIAG0 (early_map / perm_map / mm_init) +# 3) ONLY SysRq-c (no SysRq-x) +# 4) Recover combo4 — complete AXPDIAG1,C,,0x...,sysrq-c +# Does NOT prove pre-early_map FORTIFY coverage. Do not flash v3. +set -euo pipefail +export PSTORE_ALT_PLAIN=1 +exec /srv/rom/artifacts/009-axp-los23-port/scripts/009-bisect-ksync-one.sh \ + pstore-alt-plain diff --git a/scripts/009-build-fortify-family-isolated.sh b/scripts/009-build-fortify-family-isolated.sh new file mode 100644 index 0000000..0df6e2d --- /dev/null +++ b/scripts/009-build-fortify-family-isolated.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env bash +# Server-only diagnostic build. Uses its own sources/output; never resets LIVE. +# Usage: bash this-script ROOT +# family: see 009-fortify-select-family.py GROUPS +set -euo pipefail +RUN=${1:?isolated root required} +FAMILY=${2:?family required} +case "$FAMILY" in + full|memory|strings|strings-copy|strings-len|\ + strings-strcpy-strlen|strings-copy-strlen|strings-copy-strnlen|\ + strings-strlen-restcopy|strings-strlen-ncopy|strings-strlen-cat|\ + strings-strlen-strncpy|strings-strlen-strlcpy) ;; + *) echo "bad family: $FAMILY" >&2; exit 2;; +esac +test -d "$RUN/inputs" +# Subdir name matches family (strings-copy → strings-copy/) +test ! -e "$RUN/$FAMILY" +TOP=/srv/rom/src/lineage +LIVE=$TOP/kernel/google/msm-4.14 +PIN=28f9290ae067d3e7857126eb6312720dbe9c7c80 +CLANG=$TOP/prebuilts/clang/host/linux-x86/clang-r563880c +BASE=$RUN/$FAMILY +SRC=$BASE/src +OUT=$BASE/out +mkdir -p "$SRC" "$OUT" +git -C "$LIVE" archive "$PIN" | tar -x -C "$SRC" +python3 "$RUN/inputs/apply_fortify_clang.py" "$SRC" +patch -p1 --batch -d "$SRC" < "$RUN/inputs/0001-driver-bounds-rtac-fils.patch" +python3 "$RUN/inputs/009-fortify-select-family.py" "$SRC" "$FAMILY" +cp "$RUN/inputs/failed-full.config" "$OUT/.config" +cp "$OUT/.config" "$BASE/input.config" +export PATH="$TOP/prebuilts/tools-lineage/linux-x86/bin:$TOP/prebuilts/build-tools/linux-x86/bin:$CLANG/bin:$TOP/out/host/linux-x86/bin:/usr/bin:/bin" +export HIP_PATH=none +export PERL5LIB="$TOP/prebuilts/tools-lineage/common/perl-base" +export BISON_PKGDATADIR="$TOP/prebuilts/build-tools/common/bison" +export KBUILD_BUILD_USER=nobody KBUILD_BUILD_HOST=android-build +# An archived patched tree needs the same release suffix as installed modules. +export LOCALVERSION=-g28f9290ae067-dirty +MAKE=("$TOP/prebuilts/build-tools/linux-x86/bin/make" -j8 + "HOSTCFLAGS=--sysroot=$TOP/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.17-4.8/sysroot -I$TOP/prebuilts/kernel-build-tools/linux-x86/include" + "HOSTLDFLAGS=--sysroot=$TOP/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.17-4.8/sysroot -Wl,-rpath,$TOP/prebuilts/kernel-build-tools/linux-x86/lib64 -L $TOP/prebuilts/kernel-build-tools/linux-x86/lib64 -fuse-ld=lld --rtlib=compiler-rt" + LLVM=1 LLVM_IAS=1 "LZ4=$TOP/prebuilts/kernel-build-tools/linux-x86/bin/lz4" + "LEX=$TOP/prebuilts/build-tools/linux-x86/bin/flex" + "YACC=$TOP/prebuilts/build-tools/linux-x86/bin/bison" + "M4=$TOP/prebuilts/build-tools/linux-x86/bin/m4" + "PAHOLE=$TOP/prebuilts/kernel-build-tools/linux-x86/bin/pahole" + "LIBCLANG_PATH=$CLANG/lib" "DTC_EXT=$TOP/out/host/linux-x86/bin/dtc" + -C "$SRC" "O=$OUT" ARCH=arm64 CC=clang LD=ld.lld) +"${MAKE[@]}" olddefconfig +diff -u "$BASE/input.config" "$OUT/.config" > "$BASE/config.diff" || { + cat "$BASE/config.diff" + echo 'STOP: unexpected configuration drift' >&2 + exit 3 +} +"$CLANG/bin/clang" --version > "$BASE/toolchain.txt" +printf '%s\n' "$PIN" > "$BASE/source-commit.txt" +printf '%q ' "${MAKE[@]}" > "$BASE/make-command.txt" +"${MAKE[@]}" Image.lz4 modules +cp "$OUT/.config" "$BASE/final.config" +test "$(cat "$OUT/include/config/kernel.release")" = '4.14.357-openela-g28f9290ae067-dirty' +if "$CLANG/bin/llvm-nm" "$OUT/vmlinux" | grep -Eq ' [Tt] __((read_overflow[23]?)|(write_overflow))$'; then + echo 'STOP: forbidden overflow stubs' >&2 + exit 4 +fi +mkdir "$BASE/pack" +cd "$BASE/pack" +MB=$(find /srv/rom/prebuilts/magisk -type f -name magiskboot -print -quit) +test -n "$MB" +GOOD=/srv/rom/artifacts/009-axp-los23-port/20260918T143547Z-axp-full/boot-make.img +"$MB" unpack "$GOOD" > "$BASE/good-header.txt" 2>&1 +sha256sum ramdisk.cpio > "$BASE/ramdisk.sha256" +cp "$OUT/arch/arm64/boot/Image" kernel +"$MB" repack "$GOOD" "$BASE/boot-make.img" +sha256sum "$BASE/boot-make.img" "$OUT/arch/arm64/boot/Image" "$OUT/vmlinux" > "$BASE/SHA256SUMS" +printf 'DIAGNOSTIC ONLY: %s family; not full FORTIFY. Requires local unpack/header/kernel verification before LAB use.\n' "$FAMILY" > "$BASE/README.txt" +echo "BUILD COMPLETE: $BASE/boot-make.img" diff --git a/scripts/009-chain-hi3-to-releasekeys.sh b/scripts/009-chain-hi3-to-releasekeys.sh new file mode 100755 index 0000000..84fcd0b --- /dev/null +++ b/scripts/009-chain-hi3-to-releasekeys.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +# After hi-batch3 BOOT_OK: launch release-keys bacon (US-S2) on rom-dev01. +# Does not flash RK zip (needs recovery sideload); only starts bacon + status poll helper. +set -euo pipefail +SSHCFG="${SSHCFG:-/home/aventura/Workspaces/AXP_Resurection/docs/ssh/config}" +BATCH3_LOG="${BATCH3_LOG:-/tmp/009-wait-flash-cve-hi-batch3.log}" +LOG="${LOG:-/tmp/009-chain-hi3-to-releasekeys.log}" +exec > >(tee -a "$LOG") 2>&1 + +echo "CHAIN start $(date -Is) wait HI_BATCH3_BOOT_OK" +for i in $(seq 1 200); do + if grep -q 'HI_BATCH3_BOOT_OK' "$BATCH3_LOG" 2>/dev/null; then + echo "seen HI_BATCH3_BOOT_OK" + break + fi + if grep -qE 'BACON_FAILED|NOT_BOOTED|BOOT_TIMEOUT|TIMEOUT' "$BATCH3_LOG" 2>/dev/null; then + # allow exit=141 path that still boots — only abort on clear fail without OK + if ! grep -q 'HI_BATCH3_BOOT_OK' "$BATCH3_LOG" 2>/dev/null; then + if grep -qE 'BACON_FAILED|NOT_BOOTED|BOOT_TIMEOUT' "$BATCH3_LOG" 2>/dev/null; then + echo CHAIN_ABORT_BATCH3_FAIL + exit 1 + fi + fi + fi + sleep 30 +done +grep -q 'HI_BATCH3_BOOT_OK' "$BATCH3_LOG" || { echo CHAIN_TIMEOUT; exit 1; } + +echo "=== launch release-keys bacon $(date -Is) ===" +ssh -F "$SSHCFG" -o BatchMode=yes rom-dev01 ' +test -f /home/android-build/.android-certs/releasekey.pk8 +install -m 0755 /tmp/009-bacon-axp-stage1-combo4-cve-hi-releasekeys.sh \ + /srv/rom/artifacts/009-axp-los23-port/scripts/ 2>/dev/null || true +# script must already be on host +test -x /srv/rom/artifacts/009-axp-los23-port/scripts/009-bacon-axp-stage1-combo4-cve-hi-releasekeys.sh +/srv/rom/artifacts/bin/rom-detach 009-bacon-cve-hi-releasekeys -- \ + bash /srv/rom/artifacts/009-axp-los23-port/scripts/009-bacon-axp-stage1-combo4-cve-hi-releasekeys.sh +sleep 2 +cat /srv/rom/artifacts/detach-009-bacon-cve-hi-releasekeys.status +' +echo CHAIN_RK_STARTED diff --git a/scripts/009-fortify-select-family.py b/scripts/009-fortify-select-family.py new file mode 100644 index 0000000..ae35d6e --- /dev/null +++ b/scripts/009-fortify-select-family.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 +"""Diagnostic-only split of the existing Clang FORTIFY port; never a ship patch. + +Apply after apply_fortify_clang.py. Omitted wrappers resolve to the existing +unfortified declarations. No overflow stubs or changes to fortify_panic. +""" +import argparse +import re +from pathlib import Path + +STRINGS = {"strncpy", "strcat", "strlen", "strnlen", "strlcpy", "strncat", "strcpy"} +MEMORY = {"memset", "memcpy", "memmove", "memscan", "memcmp", "memchr", "memchr_inv", "kmemdup"} +STRINGS_COPY = {"strcpy", "strncpy", "strlcpy", "strcat", "strncat"} +STRINGS_LEN = {"strlen", "strnlen"} + +GROUPS = { + "full": STRINGS | MEMORY, + "strings": STRINGS, + "memory": MEMORY, + # Split of failing strings family (2026-09-27 LAB): + "strings-copy": STRINGS_COPY, + "strings-len": STRINGS_LEN, + # Cross products (copy boots, len boots, both fail → interaction): + "strings-strcpy-strlen": {"strcpy", "strlen"}, + "strings-copy-strlen": STRINGS_COPY | {"strlen"}, + "strings-copy-strnlen": STRINGS_COPY | {"strnlen"}, + # copy-strlen fails, strcpy-strlen boots → rest of copy + strlen: + "strings-strlen-restcopy": {"strlen", "strncpy", "strlcpy", "strcat", "strncat"}, + "strings-strlen-ncopy": {"strlen", "strncpy", "strlcpy"}, + "strings-strlen-cat": {"strlen", "strcat", "strncat"}, + "strings-strlen-strncpy": {"strlen", "strncpy"}, + "strings-strlen-strlcpy": {"strlen", "strlcpy"}, +} + +def select(text, family): + if "AXP_FORTIFY_DIAGNOSTIC_FAMILY" in text: + raise ValueError("Already selected: start from a fresh fully ported header") + if "__pass_object_size" not in text or "__overloadable" not in text: + raise ValueError("Apply the Clang FORTIFY port first") + pattern = re.compile(r"^__FORTIFY_INLINE[^\n]*?\b(\w+)\([^\n]*\)\n\{", re.M) + matches = list(pattern.finditer(text)) + expected = STRINGS | MEMORY + names = [m.group(1) for m in matches] + if len(names) != len(expected) or set(names) != expected: + raise ValueError(f"Unexpected wrapper inventory: {names}") + enabled = GROUPS[family] + for match in reversed(matches): + name = match.group(1) + if name in enabled: + continue + start = match.end() - 1 + depth = 1 + end = start + 1 + while depth: + depth += (text[end] == "{") - (text[end] == "}") + end += 1 + text = ( + text[: match.start()] + + "#if 0 /* diagnostic: other FORTIFY family */\n" + + text[match.start() : end] + + "\n#endif\n" + + text[end:] + ) + return f"/* AXP_FORTIFY_DIAGNOSTIC_FAMILY={family}; NOT FOR SHIP */\n" + text + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("kernel", type=Path) + parser.add_argument("family", choices=sorted(GROUPS)) + args = parser.parse_args() + path = args.kernel / "include/linux/string.h" + path.write_text(select(path.read_text(), args.family)) + print(f"DIAGNOSTIC ONLY: FORTIFY family={args.family}; panic behavior unchanged") + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/009-generate-release-keys.sh b/scripts/009-generate-release-keys.sh new file mode 100755 index 0000000..0c2a22a --- /dev/null +++ b/scripts/009-generate-release-keys.sh @@ -0,0 +1,101 @@ +#!/usr/bin/env bash +# Generate project Android + AVB signing keys on rom-dev01 only. +# Never run this to a path inside a Git working tree that gets committed. +set -euo pipefail + +OUT="${ANDROID_CERTS_DIR:-}" +if [[ -z "$OUT" ]]; then + if [[ -d /srv/rom/secrets && -w /srv/rom/secrets ]]; then + OUT=/srv/rom/secrets/android-certs + else + # Lineage convention; /srv/rom/secrets is often root-owned (750, no group write). + OUT="${HOME}/.android-certs" + fi +fi +LINEAGE_TOP="${LINEAGE_TOP:-/srv/rom/src/lineage}" +MAKE_KEY="${LINEAGE_TOP}/development/tools/make_key" + +# Distinct from AOSP testkey DN (android@android.com). +SUBJECT="${ANDROID_CERT_SUBJECT:-/C=DE/ST=NA/L=NA/O=AXP-Resurection/OU=sunfish-a16/CN=release}" + +KEYS=(releasekey platform shared media networkstack sdk_sandbox bluetooth nfc) + +if [[ ! -x "$MAKE_KEY" && ! -f "$MAKE_KEY" ]]; then + echo "ERROR: make_key not found at $MAKE_KEY" >&2 + exit 1 +fi + +if [[ "$(id -u)" -eq 0 ]]; then + echo "ERROR: refuse to generate keys as root; run as android-build" >&2 + exit 1 +fi + +mkdir -p "$OUT" +chmod 700 "$OUT" + +existing=0 +for k in "${KEYS[@]}"; do + if [[ -e "$OUT/$k.pk8" || -e "$OUT/$k.x509.pem" ]]; then + echo "EXISTS: $OUT/$k.*" + existing=1 + fi +done +if [[ -e "$OUT/avb.pem" ]]; then + echo "EXISTS: $OUT/avb.pem" + existing=1 +fi +if [[ "$existing" -eq 1 ]]; then + echo "ERROR: refusing to overwrite. Delete specifically if you truly mean to rotate." >&2 + exit 1 +fi + +echo "=== Generating APK/OTA keys in $OUT ===" +echo "subject=$SUBJECT" +for k in "${KEYS[@]}"; do + # make_key always exits 1 because of its EXIT trap — ignore status; check files. + # Blank password (Lineage/build-server norm); protect via directory mode 700. + printf '\n' | bash "$MAKE_KEY" "$OUT/$k" "$SUBJECT" || true + if [[ ! -f "$OUT/$k.pk8" || ! -f "$OUT/$k.x509.pem" ]]; then + echo "ERROR: failed to create $k" >&2 + exit 1 + fi + chmod 600 "$OUT/$k.pk8" + chmod 644 "$OUT/$k.x509.pem" + echo "OK $k" +done + +echo "=== Generating AVB RSA-4096 key ===" +openssl genrsa -out "$OUT/avb.pem" 4096 +chmod 600 "$OUT/avb.pem" +# Public key metadata for avbtool / optional custom key flash (not used for lock ship) +if [[ -x "$LINEAGE_TOP/external/avb/avbtool.py" ]]; then + python3 "$LINEAGE_TOP/external/avb/avbtool.py" extract_public_key \ + --key "$OUT/avb.pem" --output "$OUT/avb_pkmd.bin" + chmod 644 "$OUT/avb_pkmd.bin" +elif command -v avbtool >/dev/null 2>&1; then + avbtool extract_public_key --key "$OUT/avb.pem" --output "$OUT/avb_pkmd.bin" + chmod 644 "$OUT/avb_pkmd.bin" +else + echo "WARN: avbtool not found; skipped avb_pkmd.bin (openssl key still OK)" +fi + +{ + echo "# generated $(date -Is) on $(hostname)" + echo "subject=$SUBJECT" + echo "dir=$OUT" + echo "keys=${KEYS[*]} avb.pem" +} >"$OUT/GENERATED.txt" +chmod 644 "$OUT/GENERATED.txt" + +echo +echo "=== DONE ===" +echo "Public releasekey subject:" +openssl x509 -in "$OUT/releasekey.x509.pem" -noout -subject +echo +echo "NEXT (mandatory before first signed ship bacon):" +echo " 1. Encrypted offline backup of $OUT" +echo " 2. If keys are under \$HOME/.android-certs, have root install -d" +echo " /srv/rom/secrets/android-certs and move/copy there (preferred long-term)." +echo " 3. Record backup location/date in docs/009-hardening-signing-checklist.md" +echo " 4. US-S2: export PRODUCT_DEFAULT_DEV_CERTIFICATE=$OUT/releasekey" +echo " 5. Never copy .pk8 / avb.pem into Git" diff --git a/scripts/009-wait-flash-cve-clean.sh b/scripts/009-wait-flash-cve-clean.sh new file mode 100755 index 0000000..b496591 --- /dev/null +++ b/scripts/009-wait-flash-cve-clean.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash +# Wait for CVE-clean bacon on rom-dev01, then one-shot fastboot flash boot + one reboot. +# No recovery loops. No auto-recover. Exits if not booted in ~4 min. +set -euo pipefail +SSHCFG="${SSHCFG:-/home/aventura/Workspaces/AXP_Resurection/docs/ssh/config}" +SERIAL="${SERIAL:-11231JEC207477}" +LOCAL="${LOCAL:-/home/aventura/Workspaces/AXP_Resurection/.local-artifacts/009-flash-cve-clean}" +STATUS=detach-009-bacon-cve-clean.status +LOG="${LOG:-/tmp/009-wait-flash-cve-clean.log}" +mkdir -p "$LOCAL" +exec > >(tee -a "$LOG") 2>&1 + +echo "WAIT start $(date -Is)" +st="" +for i in $(seq 1 180); do + st=$(ssh -F "$SSHCFG" -o BatchMode=yes -o ConnectTimeout=20 rom-dev01 \ + "cat /srv/rom/artifacts/$STATUS" 2>/dev/null || echo status_unreadable) + echo "poll $i: $st" + if echo "$st" | grep -q '^exit=0'; then + break + fi + if echo "$st" | grep -qE '^exit=[1-9]|^exit=killed'; then + echo BACON_FAILED + exit 1 + fi + sleep 60 +done +echo "$st" | grep -q '^exit=0' || { echo TIMEOUT; exit 1; } + +ART=$(ssh -F "$SSHCFG" -o BatchMode=yes rom-dev01 \ + 'ls -dt /srv/rom/artifacts/009-axp-los23-port/*-axp-stage1-combo4-cve-clean 2>/dev/null | head -1') +echo "ART=$ART" +test -n "$ART" + +rsync -avP -e "ssh -F $SSHCFG -o BatchMode=yes" \ + "rom-dev01:$ART/boot.img" "rom-dev01:$ART/README.txt" "rom-dev01:$ART/SHA256SUMS" "$LOCAL/" +cd "$LOCAL" +grep ' boot.img$' SHA256SUMS | sha256sum -c - + +adb start-server >/dev/null 2>&1 || true +cur=$(adb -s "$SERIAL" get-state 2>/dev/null || true) +if [[ "$cur" == "device" ]]; then + echo "adb reboot bootloader once" + adb -s "$SERIAL" reboot bootloader +fi +for j in $(seq 1 40); do + fastboot devices 2>/dev/null | grep -q "$SERIAL" && break + sleep 2 +done +fastboot devices | grep -q "$SERIAL" || { echo NO_FASTBOOT; exit 1; } + +echo "fastboot flash boot (cve-clean) once" +fastboot -s "$SERIAL" flash boot "$LOCAL/boot.img" +echo "fastboot reboot once" +fastboot -s "$SERIAL" reboot + +for j in $(seq 1 60); do + sleep 5 + cur=$(adb devices | awk -v s="$SERIAL" '$1==s{print $2}') + boot=$(adb -s "$SERIAL" shell getprop sys.boot_completed 2>/dev/null | tr -d '\r' || true) + echo "t=$((j*5))s adb=$cur boot=$boot" + if [[ "$cur" == "device" && "$boot" == "1" ]]; then + adb -s "$SERIAL" shell 'uname -a; getprop ro.boot.slot_suffix; pidof magiskd || true' + echo CLEAN_BOOT_OK + exit 0 + fi + if [[ "$j" -eq 48 ]]; then + echo NOT_BOOTED_4min leave_alone + exit 2 + fi +done +echo BOOT_TIMEOUT +exit 2 diff --git a/scripts/009-wait-flash-cve-hi-batch1.sh b/scripts/009-wait-flash-cve-hi-batch1.sh new file mode 100755 index 0000000..d9d9db4 --- /dev/null +++ b/scripts/009-wait-flash-cve-hi-batch1.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# Wait for hi-batch1 bacon on rom-dev01, then one-shot fastboot flash boot + reboot. +# Serial-pinned. No recovery loops. Exit if not booted in ~4 min. +set -euo pipefail +SSHCFG="${SSHCFG:-/home/aventura/Workspaces/AXP_Resurection/docs/ssh/config}" +SERIAL="${SERIAL:-11231JEC207477}" +LOCAL="${LOCAL:-/home/aventura/Workspaces/AXP_Resurection/.local-artifacts/009-flash-cve-hi-batch1}" +STATUS=detach-009-bacon-cve-hi-batch1.status +LOG="${LOG:-/tmp/009-wait-flash-cve-hi-batch1.log}" +mkdir -p "$LOCAL" +exec > >(tee -a "$LOG") 2>&1 + +echo "WAIT hi-batch1 start $(date -Is)" +st="" +for i in $(seq 1 180); do + st=$(ssh -F "$SSHCFG" -o BatchMode=yes -o ConnectTimeout=20 rom-dev01 \ + "cat /srv/rom/artifacts/$STATUS" 2>/dev/null || echo status_unreadable) + echo "poll $i: $st" + # exit=141 = SIGPIPE from tee after successful bacon (false fail) + if echo "$st" | grep -qE '^exit=0|^exit=141'; then + break + fi + if echo "$st" | grep -qE '^exit=[1-9]|^exit=killed'; then + if echo "$st" | grep -q '^exit=141'; then + break + fi + echo BACON_FAILED + exit 1 + fi + sleep 60 +done +echo "$st" | grep -qE '^exit=0|^exit=141' || { echo TIMEOUT; exit 1; } + +ART=$(ssh -F "$SSHCFG" -o BatchMode=yes rom-dev01 \ + 'ls -dt /srv/rom/artifacts/009-axp-los23-port/*-axp-stage1-combo4-cve-hi-batch1 2>/dev/null | head -1') +echo "ART=$ART" +test -n "$ART" + +rsync -avP -e "ssh -F $SSHCFG -o BatchMode=yes" \ + "rom-dev01:$ART/boot.img" "rom-dev01:$ART/README.txt" "rom-dev01:$ART/SHA256SUMS" "$LOCAL/" +cd "$LOCAL" +grep ' boot.img$' SHA256SUMS | sha256sum -c - + +adb start-server >/dev/null 2>&1 || true +cur=$(adb -s "$SERIAL" get-state 2>/dev/null || true) +if [[ "$cur" == "device" ]]; then + echo "adb reboot bootloader once" + adb -s "$SERIAL" reboot bootloader +fi +for j in $(seq 1 40); do + fastboot devices 2>/dev/null | grep -q "$SERIAL" && break + sleep 2 +done +fastboot devices | grep -q "$SERIAL" || { echo NO_FASTBOOT; exit 1; } + +echo "fastboot flash boot (hi-batch1) once" +fastboot -s "$SERIAL" flash boot "$LOCAL/boot.img" +echo "fastboot reboot once" +fastboot -s "$SERIAL" reboot + +for j in $(seq 1 60); do + sleep 5 + cur=$(adb devices | awk -v s="$SERIAL" '$1==s{print $2}') + boot=$(adb -s "$SERIAL" shell getprop sys.boot_completed 2>/dev/null | tr -d '\r' || true) + echo "t=$((j*5))s adb=$cur boot=$boot" + if [[ "$cur" == "device" && "$boot" == "1" ]]; then + adb -s "$SERIAL" shell 'uname -a; getprop ro.boot.slot_suffix; pidof magiskd || true' + echo HI_BATCH1_BOOT_OK + exit 0 + fi + if [[ "$j" -eq 48 ]]; then + echo NOT_BOOTED_4min leave_alone + exit 2 + fi +done +echo BOOT_TIMEOUT +exit 2 diff --git a/scripts/009-wait-flash-cve-hi-batch2.sh b/scripts/009-wait-flash-cve-hi-batch2.sh new file mode 100755 index 0000000..26d3a82 --- /dev/null +++ b/scripts/009-wait-flash-cve-hi-batch2.sh @@ -0,0 +1,81 @@ +#!/usr/bin/env bash +# Wait for hi-batch2 bacon on rom-dev01, then one-shot fastboot flash boot + reboot. +# Serial-pinned. No recovery loops. Exit if not booted in ~4 min. +set -euo pipefail +SSHCFG="${SSHCFG:-/home/aventura/Workspaces/AXP_Resurection/docs/ssh/config}" +SERIAL="${SERIAL:-11231JEC207477}" +LOCAL="${LOCAL:-/home/aventura/Workspaces/AXP_Resurection/.local-artifacts/009-flash-cve-hi-batch2}" +STATUS=detach-009-bacon-cve-hi-batch2.status +LOG="${LOG:-/tmp/009-wait-flash-cve-hi-batch2.log}" +mkdir -p "$LOCAL" +exec > >(tee -a "$LOG") 2>&1 + +echo "WAIT hi-batch2 start $(date -Is)" +st="" +for i in $(seq 1 180); do + st=$(ssh -F "$SSHCFG" -o BatchMode=yes -o ConnectTimeout=20 rom-dev01 \ + "cat /srv/rom/artifacts/$STATUS" 2>/dev/null || echo status_unreadable) + echo "poll $i: $st" + # exit=141 = SIGPIPE from tee after successful bacon (false fail) + if echo "$st" | grep -qE '^exit=0|^exit=141'; then + break + fi + if echo "$st" | grep -qE '^exit=[1-9]|^exit=killed'; then + if echo "$st" | grep -q '^exit=141'; then + break + fi + echo BACON_FAILED + exit 1 + fi + sleep 60 +done +echo "$st" | grep -qE '^exit=0|^exit=141' || { echo TIMEOUT; exit 1; } +# Confirm artifact exists (guards real failures that somehow report 141) +ART_PROBE=$(ssh -F "$SSHCFG" -o BatchMode=yes rom-dev01 \ + 'ls -dt /srv/rom/artifacts/009-axp-los23-port/*-axp-stage1-combo4-cve-hi-batch2 2>/dev/null | head -1') +test -n "$ART_PROBE" || { echo NO_ARTIFACT; exit 1; } + +ART=$(ssh -F "$SSHCFG" -o BatchMode=yes rom-dev01 \ + 'ls -dt /srv/rom/artifacts/009-axp-los23-port/*-axp-stage1-combo4-cve-hi-batch2 2>/dev/null | head -1') +echo "ART=$ART" +test -n "$ART" + +rsync -avP -e "ssh -F $SSHCFG -o BatchMode=yes" \ + "rom-dev01:$ART/boot.img" "rom-dev01:$ART/README.txt" "rom-dev01:$ART/SHA256SUMS" "$LOCAL/" +cd "$LOCAL" +grep ' boot.img$' SHA256SUMS | sha256sum -c - + +adb start-server >/dev/null 2>&1 || true +cur=$(adb -s "$SERIAL" get-state 2>/dev/null || true) +if [[ "$cur" == "device" ]]; then + echo "adb reboot bootloader once" + adb -s "$SERIAL" reboot bootloader +fi +for j in $(seq 1 40); do + fastboot devices 2>/dev/null | grep -q "$SERIAL" && break + sleep 2 +done +fastboot devices | grep -q "$SERIAL" || { echo NO_FASTBOOT; exit 1; } + +echo "fastboot flash boot (hi-batch2) once" +fastboot -s "$SERIAL" flash boot "$LOCAL/boot.img" +echo "fastboot reboot once" +fastboot -s "$SERIAL" reboot + +for j in $(seq 1 60); do + sleep 5 + cur=$(adb devices | awk -v s="$SERIAL" '$1==s{print $2}') + boot=$(adb -s "$SERIAL" shell getprop sys.boot_completed 2>/dev/null | tr -d '\r' || true) + echo "t=$((j*5))s adb=$cur boot=$boot" + if [[ "$cur" == "device" && "$boot" == "1" ]]; then + adb -s "$SERIAL" shell 'uname -a; getprop ro.boot.slot_suffix; pidof magiskd || true' + echo HI_BATCH2_BOOT_OK + exit 0 + fi + if [[ "$j" -eq 48 ]]; then + echo NOT_BOOTED_4min leave_alone + exit 2 + fi +done +echo BOOT_TIMEOUT +exit 2 diff --git a/scripts/009-wait-flash-cve-hi-batch3.sh b/scripts/009-wait-flash-cve-hi-batch3.sh new file mode 100755 index 0000000..933aaa9 --- /dev/null +++ b/scripts/009-wait-flash-cve-hi-batch3.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env bash +# Wait for hi-batch3 bacon on rom-dev01, then one-shot fastboot flash boot + reboot. +# Treats exit=141 (tee SIGPIPE) as OK when artifact exists. +set -euo pipefail +SSHCFG="${SSHCFG:-/home/aventura/Workspaces/AXP_Resurection/docs/ssh/config}" +SERIAL="${SERIAL:-11231JEC207477}" +LOCAL="${LOCAL:-/home/aventura/Workspaces/AXP_Resurection/.local-artifacts/009-flash-cve-hi-batch3}" +STATUS=detach-009-bacon-cve-hi-batch3.status +LOG="${LOG:-/tmp/009-wait-flash-cve-hi-batch3.log}" +mkdir -p "$LOCAL" +exec > >(tee -a "$LOG") 2>&1 + +echo "WAIT hi-batch3 start $(date -Is)" +st="" +for i in $(seq 1 180); do + st=$(ssh -F "$SSHCFG" -o BatchMode=yes -o ConnectTimeout=20 rom-dev01 \ + "cat /srv/rom/artifacts/$STATUS" 2>/dev/null || echo status_unreadable) + echo "poll $i: $st" + if echo "$st" | grep -qE '^exit=0|^exit=141'; then + break + fi + if echo "$st" | grep -qE '^exit=[1-9]|^exit=killed'; then + echo BACON_FAILED + exit 1 + fi + sleep 60 +done +echo "$st" | grep -qE '^exit=0|^exit=141' || { echo TIMEOUT; exit 1; } + +ART=$(ssh -F "$SSHCFG" -o BatchMode=yes rom-dev01 \ + 'ls -dt /srv/rom/artifacts/009-axp-los23-port/*-axp-stage1-combo4-cve-hi-batch3 2>/dev/null | head -1') +echo "ART=$ART" +test -n "$ART" +# ensure SHA256SUMS exists (tee may have truncated post-bacon) +ssh -F "$SSHCFG" -o BatchMode=yes rom-dev01 \ + "test -f $ART/SHA256SUMS || (cd $ART && sha256sum boot.img boot-make.img lineage-*-UNOFFICIAL-sunfish.zip 2>/dev/null | tee SHA256SUMS)" + +rsync -avP -e "ssh -F $SSHCFG -o BatchMode=yes" \ + "rom-dev01:$ART/boot.img" "rom-dev01:$ART/README.txt" "rom-dev01:$ART/SHA256SUMS" "$LOCAL/" +cd "$LOCAL" +grep ' boot.img$' SHA256SUMS | sha256sum -c - + +adb start-server >/dev/null 2>&1 || true +cur=$(adb -s "$SERIAL" get-state 2>/dev/null || true) +if [[ "$cur" == "device" ]]; then + echo "adb reboot bootloader once" + adb -s "$SERIAL" reboot bootloader +fi +for j in $(seq 1 40); do + fastboot devices 2>/dev/null | grep -q "$SERIAL" && break + sleep 2 +done +fastboot devices | grep -q "$SERIAL" || { echo NO_FASTBOOT; exit 1; } + +echo "fastboot flash boot (hi-batch3) once" +fastboot -s "$SERIAL" flash boot "$LOCAL/boot.img" +echo "fastboot reboot once" +fastboot -s "$SERIAL" reboot + +for j in $(seq 1 60); do + sleep 5 + cur=$(adb devices | awk -v s="$SERIAL" '$1==s{print $2}') + boot=$(adb -s "$SERIAL" shell getprop sys.boot_completed 2>/dev/null | tr -d '\r' || true) + echo "t=$((j*5))s adb=$cur boot=$boot" + if [[ "$cur" == "device" && "$boot" == "1" ]]; then + adb -s "$SERIAL" shell 'uname -a; getprop ro.boot.slot_suffix; pidof magiskd || true' + echo HI_BATCH3_BOOT_OK + exit 0 + fi + if [[ "$j" -eq 48 ]]; then + echo NOT_BOOTED_4min leave_alone + exit 2 + fi +done +echo BOOT_TIMEOUT +exit 2 diff --git a/scripts/009-watch-then-cve-bacon.sh b/scripts/009-watch-then-cve-bacon.sh new file mode 100644 index 0000000..366162f --- /dev/null +++ b/scripts/009-watch-then-cve-bacon.sh @@ -0,0 +1,54 @@ +#!/bin/bash +# Wait for release-keys bacon to finish, then start Stage1+combo4+CVE bacon. +set -euo pipefail +RK_STATUS=/srv/rom/artifacts/detach-009-bacon-axp-stage1-combo4-rk.status +CVE_NAME=009-bacon-axp-stage1-combo4-cve +CVE_SCRIPT=/srv/rom/artifacts/bin/009-bacon-axp-stage1-combo4-cve.sh +DETACH=/srv/rom/artifacts/bin/rom-detach + +echo "watcher: waiting for RK bacon to leave 'running' ($(date -Is))" +while true; do + if [[ -f "$RK_STATUS" ]]; then + if grep -q '^exit=' "$RK_STATUS" 2>/dev/null; then + break + fi + if ! grep -q '^running ' "$RK_STATUS" 2>/dev/null; then + break + fi + else + # no status → assume free + break + fi + # still building? + if ! pgrep -f 'm bacon -j' >/dev/null 2>&1 \ + && ! pgrep -f 'combined-lineage_sunfish.ninja' >/dev/null 2>&1; then + # status stale? + sleep 30 + if ! pgrep -f 'm bacon -j' >/dev/null 2>&1; then + echo "watcher: no mka/ninja; treating RK as done ($(date -Is))" + break + fi + fi + sleep 60 +done + +echo "watcher: RK status now:" +cat "$RK_STATUS" 2>/dev/null || true + +if grep -q '^exit=0' "$RK_STATUS" 2>/dev/null; then + echo "watcher: RK bacon OK" +elif grep -q '^exit=' "$RK_STATUS" 2>/dev/null; then + echo "watcher: RK bacon FAILED — still launching CVE (kernel will reset)" +else + echo "watcher: RK status unclear — launching CVE after short settle" + sleep 15 +fi + +# Ensure scripts synced into lineage vendor +KH=/srv/rom/src/lineage/vendor/sunfish-a16/patches/009-kernel-hardening +test -x "$CVE_SCRIPT" +test -f "$KH/cve-strict.list" +test -x "$KH/apply_stage1_combo4_cve.sh" + +"$DETACH" "$CVE_NAME" -- bash "$CVE_SCRIPT" +echo "watcher: CVE bacon detached ($(date -Is))" diff --git a/specs/008-call-rec-flag-secure/contracts/flag-secure-surface.md b/specs/008-call-rec-flag-secure/contracts/flag-secure-surface.md index 45d4b5a..fd8ade6 100644 --- a/specs/008-call-rec-flag-secure/contracts/flag-secure-surface.md +++ b/specs/008-call-rec-flag-secure/contracts/flag-secure-surface.md @@ -12,7 +12,7 @@ | Readback | `adb shell settings get secure disable_secure_windows` | | UI preference key | `allow_flag_secure_override` (writes the Secure key above) | | Scope | **Global** (all apps); per-app lists not planned | -| Note | WMS only applies this on **debuggable** builds (`ro.debuggable`) | +| Note | Stock AOSP gated WMS on `ro.debuggable`; project removes that gate (`SUNFISH_A16_008_WMS_DISABLE_SECURE_NO_DEBUGGABLE_GATE`) so `ro.debuggable` stays `0` | ## Capture behaviour diff --git a/specs/008-call-rec-flag-secure/research.md b/specs/008-call-rec-flag-secure/research.md index fafe1cd..593d8e8 100644 --- a/specs/008-call-rec-flag-secure/research.md +++ b/specs/008-call-rec-flag-secure/research.md @@ -39,8 +39,12 @@ has `Settings.Secure.DISABLE_SECURE_WINDOWS` wired through Options switch (preference key `allow_flag_secure_override`) that writes `disable_secure_windows`. -**Constraint**: WMS applies the setting only on debuggable builds -(`ro.debuggable`). LAB `userdebug` is in scope; `user` retest before release. +**Constraint (stock AOSP)**: WMS applied the setting only on debuggable builds +(`ro.debuggable`). **Project decision (2026-09-18):** remove that gate in +`updateDisableSecureWindows()` (`apply_wms_disable_secure_debuggable_gate.py`) +so ship images keep `ro.debuggable=0` while the DO toggle works. No other +secondary gate found in `WindowState.isSecureLocked` / `Task.isSecure`. +LAB `userdebug` with `ro.debuggable=0` was the motivating case. **Alternatives rejected**: Magisk `services.jar` dex patchers as shipping mechanism. diff --git a/specs/009-axp-los23-port/contracts/acceptance-gates.md b/specs/009-axp-los23-port/contracts/acceptance-gates.md index 3f01f71..54a997e 100644 --- a/specs/009-axp-los23-port/contracts/acceptance-gates.md +++ b/specs/009-axp-los23-port/contracts/acceptance-gates.md @@ -27,27 +27,39 @@ - [ ] Activation documented and completed on LAB - [ ] DenyList-class hides root from a test/banking package -## Gate E — Banking +## Gate E — Banking *(deferred — not MVP)* -- [ ] Island present; Swissquote PASS in managed profile workflow -- [ ] Yuh recorded; not worse than GOLDEN for packaging/spoofing reasons -- [ ] Banks do not receive root +- [ ] *(Later)* Island present; Swissquote PASS in managed profile workflow +- [ ] *(Later)* Yuh recorded; not worse than GOLDEN for packaging/spoofing +- [ ] *(Later)* Banks do not receive root ## Gate F — Usability / WebView -- [ ] Bundled AXP categories present or documented impossible +- [ ] Bundled AXP categories present or documented impossible/deferred - [ ] Versions newest workable (except Phonesky rule) - [ ] WebView default LOS; chooser unlocked -## Gate G — Hardening / signing class +## Gate G — Hardening / signing + kernel -- [ ] GOLDEN-class hardening/signing/AVB posture present **or** each gap - documented as impossible on this stack (no silent omit) -- [ ] Staged known-good images retained for bisect +- [ ] Project **release / definitive signing keys** on ship images/OTAs (not + AOSP test-keys); Phonesky / update identity on that key +- [ ] GOLDEN-class **userspace** hardening + AVB *build* posture as applicable + on unlocked sunfish **or** each in-scope gap documented (no silent omit) +- [x] Updated LOS23-compatible sunfish kernel + hardening attribution list + (FR-017 / SC-010) — see `docs/009-gate-g-kernel-attribution.md` + (Stage1 + combo4 + Clang FORTIFY; LAB 2026-09-29) +- [x] Staged known-good images retained for bisect + (`20260929T123401Z-axp-stage1-combo4`, prior combo4-fortify, GOODMAKE) +- [x] Localization/location AXP-vs-LOS compare **not** required yet (FR-018) +- [x] Bootloader relock **not** a Gate G requirement (AXP/LOS unlocked norm; + IOdes-class lock is non-goal) — see research 2026-09-29 ## Non-gates - KernelSU presence or SusFS - FLAG_SECURE override (optional) - Custom AXP backup ROM feature +- Banking / Swissquote / Yuh (deferred owner future) +- Localization hardening policy freeze (FR-018 later) - Yuh PASS if GOLDEN attestation path still FAILs equivalently +- Bootloader lock / relock (IOdes-class); unlocked sunfish is the ship model diff --git a/specs/009-axp-los23-port/plan.md b/specs/009-axp-los23-port/plan.md index 160d1b7..376aef0 100644 --- a/specs/009-axp-los23-port/plan.md +++ b/specs/009-axp-los23-port/plan.md @@ -6,11 +6,13 @@ ## Summary -Resurrect **AXP.OS Pro on LOS22 / GOLDEN** as a single shippable LineageOS -23.2 / Android 16 `sunfish` ROM on **LAB**: vanilla `003` base + full AXP -capability set (Google stack, selectable spoofing, Island banking workflow, -selectable call-recording unlock, Magisk like GOLDEN, bundled usability apps, -GOLDEN-class hardening/signing/AVB posture). +Resurrect **AXP.OS Pro on LOS22 / GOLDEN** as an **updated AXP-class clone** +on LineageOS 23.2 / Android 16 `sunfish` (**LAB**): vanilla `003` base + AXP +capability set (Google stack, selectable spoofing, selectable call-recording +unlock, Magisk like GOLDEN, bundled usability apps / options surface, +GOLDEN-class userspace hardening/signing/AVB, **updated hardened sunfish +kernel**). **Banking/Island/Swissquote validation deferred** (owner future). +**Localization hardening AXP-vs-LOS compare deferred** (FR-018). **Explicit exceptions:** LOS23 WebView default (Aosmium EOL) with unlocked provider chooser; Phonesky = project's recent patched artifact (reconsider if @@ -22,7 +24,9 @@ packaging where they already match; replace the KernelSU ship path with AXP-style Magisk preinstall (newest Magisk); pin newest stable microG and bundled apps; keep Phonesky on the existing host pipeline; measure Magisk “preinstalled but not fully activated” behaviour on GOLDEN before freezing LAB -setup docs. +setup docs; port attributable kernel hardening onto current LOS23 sunfish +kernel; stage userspace hardening; leave location-policy compare for later. + ## Technical Context @@ -88,7 +92,7 @@ specs/009-axp-los23-port/ │ ├── magisk-preinstall.md │ ├── webview-surface.md │ └── acceptance-gates.md -└── tasks.md # /speckit-tasks (not this command) +└── tasks.md # /speckit-tasks (generated) ``` ### Host + tree diff --git a/specs/009-axp-los23-port/quickstart.md b/specs/009-axp-los23-port/quickstart.md index 94a9b31..746e496 100644 --- a/specs/009-axp-los23-port/quickstart.md +++ b/specs/009-axp-los23-port/quickstart.md @@ -49,29 +49,31 @@ adb -s 11231JEC207477 shell settings get secure extendrom_call_recording 3. Configure DenyList-class hide for a banking package **before** first open. 4. Save Magisk version + screenshots under `…/magisk/`. -## 4. Banking (Gate E) +## 4. Banking (Gate E) — deferred -1. Aurora → install Swissquote → **do not open**. -2. DenyList → Island clone → first launch in Island → login. -3. Repeat attempt for Yuh; classify PASS / attestation-like-GOLDEN / - packaging regression. -4. Confirm banks lack root. +Skip for MVP. Owner future. Magisk DenyList can still be smoke-tested with a +non-bank test package under Gate D. ## 5. Usability + WebView (Gate F) 1. Confirm bundled categories vs pin record. 2. `adb shell cmd webviewupdate current` → LOS default; chooser still listed. -## 6. Hardening / signing class (Gate G) +## 6. Hardening / signing + kernel (Gate G) -1. Run the hardening/signing checklist defined for this build stage. -2. Any missing GOLDEN-class item → written impossible/gap note (no silent +1. Userspace: follow `docs/009-hardening-signing-checklist.md` (release keys; + unlocked AVB; no bootloader lock). +2. Kernel: `docs/009-gate-g-kernel-attribution.md` (Stage1+combo4+FORTIFY). +2. Record kernel rev + hardening patches applied/skipped (FR-017). +3. Any missing GOLDEN-class item → written impossible/gap note (no silent skip). +4. Do **not** block on localization AXP-vs-LOS compare (FR-018 later). ## Pass criteria All boxes in [acceptance-gates.md](./contracts/acceptance-gates.md) for the -claimed stage. Full resurrection acceptance = Gates A–G. +claimed stage **except Gate E** (deferred). Full clone acceptance for current +owner priority = Gates A–D + F–G. ## Notes @@ -79,3 +81,4 @@ claimed stage. Full resurrection acceptance = Gates A–G. - Call-recording legality is the user’s responsibility. - If project Phonesky misbehaves vs GOLDEN needs → stop and reconsider; do not accept Gate B. +- Localization hardening compare is explicitly postponed. diff --git a/specs/009-axp-los23-port/research.md b/specs/009-axp-los23-port/research.md index dbd0e50..06073ce 100644 --- a/specs/009-axp-los23-port/research.md +++ b/specs/009-axp-los23-port/research.md @@ -111,15 +111,140 @@ Document impossible-on-sunfish gaps rather than silent omit. **Alternatives considered**: Defer all of `011`–`013` — rejected by owner. One mega-commit everything — rejected (attribution / bisect). -## Decision: Banking workflow = GOLDEN Magisk DenyList + Island +## Decision: Release keys yes; bootloader lock no (2026-09-29) -**Decision**: Restore constitution banking steps with **Magisk DenyList** -(not KSU profiles) + Island: Aurora install → do not open → DenyList → clone -to Island → first launch in Island. Swissquote PASS hard gate; Yuh honest vs -GOLDEN attestation FAIL. +**Decision**: + +1. **Sign with definitive / project release keys** — required for Gate G + userspace. Move off AOSP test-keys for ship images/OTAs; keep Phonesky and + update identity on that key. Keys live only on `rom-dev01` + (`/srv/rom/secrets/`), never in the laptop Git tree. +2. **Do not pursue bootloader relock** as a ship goal. AXP and LineageOS do + not lock the bootloader as their normal product path; Magisk preroot and + recovery sideload assume unlocked. IOdes-style locked bootloader is an + explicit non-goal for this track. + +**Rationale**: Clone AXP/LOS norms; avoid a locked-device model that fights +Magisk EXTENDROM preroot. Signing still matters for update trust and +PRESIGNED / same-identity sideload. + +**Alternatives considered**: IOdes-class locked AVB ship — rejected by owner +(2026-09-29). Skip release keys entirely — rejected (Gate G / FR signing). + +## Decision: Banking workflow deferred (owner future) + +**Decision (2026-09-17)**: Banking / Island / Swissquote / Yuh validation is +**deferred**. Not an MVP acceptance gate. Magisk DenyList-class capability +still ships (general). Owner may resume US3 later. + +**Rationale**: Owner wants updated AXP clone (features, options, hardening, +security, kernel) first; banks are a personal future problem. + +**Alternatives considered**: Keep Swissquote as hard gate — rejected by owner. + +## Decision: Updated hardened LOS23 sunfish kernel (FR-017) + +**Decision (refined 2026-09-18):** Ship current LineageOS 23.2–compatible +`sunfish` kernel (`msm-4.14`) with attributable hardening. **Not** an +unrelated Graphene A13 / stock prebuilt as base. Record applied/skipped list +in `docs/009-kernel-hardening-map.md`. + +**Source priority (owner):** + +1. **AXP** — maximum priority; clone their sunfish kernel hardening first + (build sources / OTA oracle / GOLDEN). Inherited Divest-era commits that + already live *inside* the AXP stack are fine as part of that clone; do + **not** separately mine DivestOS EOL trees. +2. **LOS 23.2** — inventory what the lineage kernel already has; avoid + duplicate work. +3. **IodéOS** — LOS fork, more hardened/deblobbed; clone sources on + `rom-dev01` and diff for 4.14-safe ideas worth porting. +4. **GrapheneOS** — optional extras only when they make sense on non-GKI + 4.14 sunfish: prefer portable techniques from modern Pixel kernels / + docs; historical sunfish A13 patches only if still clearly valuable. + Do **not** treat GOS A13 sunfish tree as the base. + +**Out of hunt:** DivestOS as a separate research target (EOL). + +**Rationale**: AXP-first resurrection; GOS/Iodé as additive; honest skips on +4.14. + +**Inventory (2026-09-18):** LOS `msm-4.14` @ `28f9290ae067` (`4.14.357-openela`). +AXP `kernel_patches` @ `df3cab2155b3` on host. Graphene/AH sequential probe: +OK=30 / SKIP_ALREADY=4 / FAIL=12. Iodé `v5-staging` manifest has no sunfish +4.14 kernel fork. Stage 1 allowlist + apply script under +`vendor/sunfish-a16/patches/009-kernel-hardening/`. CVE mega deferred. +Ledger: `docs/009-kernel-hardening-map.md`. + +## Decision: Location / localization hardening — do not extra-cap (FR-018) + +**Decision (2026-09-18):** For this Magisk track, **do not** port AXP-class +aggressive location lockdown (kernel or userspace) beyond stock LOS 23.2 +defaults. No “non-hardening location” Settings toggle for MVP — that is +extra product surface; simpler and matches owner GPS frustration to **leave +LOS location behaviour**. FR-018 compare doc may still note what AXP did, +for later curiosity, without shipping those caps. + +**Alternatives considered**: (1) Clone AXP location caps — rejected (slow / +frustrating fixes). (2) Owner toggle to disable caps — deferred; only if +LOS defaults prove insufficient and owner asks later. + + +## Decision: Bundled store client = Droidify; no NeoLauncher + +**Decision (2026-09-17):** Ship **Droidify** as the F-Droid-class client +instead of stock F-Droid (lighter; many repos by default). Do **not** +integrate NeoLauncher — keep LOS Launcher3. Aurora remains for Play-sideload +workflow. + +## Decision: No AXP external repos / OTA servers + +**Decision:** Do not wire AXP market/F-Droid remote repos or AXP OTA update +endpoints. AXP infra is EOL / servers down — no product sense. Periodic +system-package refresh is **owner sideload** (FR-019), not network OTA. + +## Decision: Sideloadable system package refreshes (FR-019) + +**Decision (2026-09-17):** Final ROM MUST keep **microG**, **Magisk**, +**project Phonesky**, and other bundled system/privileged apps +**updateable without full reflash**, on a ~**2–3 month** cadence the owner +drives. Prefer PackageManager-compatible sideload (same signing identity; +PRESIGNED microG; continuous project key for Phonesky). Magisk: document +manager self-update and/or recovery/boot re-patch when APK sideload alone is +not enough. Deliver a short recovery/sideload runbook before ship; do **not** +reintroduce AXP OTA. + +## Decision: Private DNS + Internet connectivity (sans axp.os) + +**Decision:** Port AXP-class **Private DNS** provider presets. Keep AXP-class +**Internet connectivity** / special INTERNET permission behaviour where it +still fits LOS 23.2, but strip any hard dependency on `axp.os` branding or +endpoints. + +## Decision: Restore Disable app on Android 16 + +**Decision:** Investigate and re-expose classic **Disable application** UX on +A16/LOS23 where Archive replaced or hid it. Owner prefers Disable over +Archive. Exact Settings/PackageManager patch path TBD from AXP/LOS delta +research — must remain attributable and reversible. + +## Decision: AXP build sources as compile oracle + +**Decision:** On `rom-dev01`, prefer cloning/checking out AXP **build** + +EXTENDROM (and axpos.org developer building docs already mirrored under +`/srv/rom/references/axp/archive/`) to see how Magisk preroot / product packages +are wired — before treating GOLDEN `adb` as the compile guide. GOLDEN stays the +runtime compatibility oracle. + +**Decision**: Do **not** freeze localization/location lockdown policy in this +feature’s acceptance. Later compare how much AXP “capea” location vs stock +LOS (owner historically complains AXP is aggressive). Until then, avoid +inventing extra location lockdown beyond what the clone already implies; +matrix row = deferred. + +**Alternatives considered**: Blind-copy all AXP location patches now — +rejected (owner wants a deliberate compare first). -**Alternatives considered**: Rootless-only banking gate — incomplete vs AXP. -Insular rename — GOLDEN runs Island. ## Decision: Version freshness policy diff --git a/specs/009-axp-los23-port/spec.md b/specs/009-axp-los23-port/spec.md index a213b38..6c727a9 100644 --- a/specs/009-axp-los23-port/spec.md +++ b/specs/009-axp-los23-port/spec.md @@ -4,7 +4,8 @@ **Created**: 2026-09-16 -**Status**: Clarified — ready for `/speckit-plan` +**Status**: Spec clarified 2026-09-17 (banking deferred; kernel hardening in; +localization compare later) — tasks updated; ready for `/speckit-implement` **Input**: User description: "009-axp based LOS22 feature port to LOS23 — take vanilla LineageOS 23 for sunfish and integrate the full AXP.OS (LOS22 / @@ -24,6 +25,29 @@ with that Phonesky; signature spoofing and call recording **selectable** existing functional kernels if useful; otherwise everything equal to AXP/GOLDEN. +**Owner clarifications (2026-09-17):** Primary ship interest = an **updated +AXP clone on LOS23** (features, options, userspace hardening/security, updated +hardened sunfish kernel). Banking / Island / Swissquote / Yuh **deferred** +(owner future). Localization AXP-vs-LOS compare **later** (FR-018). Prefer AXP +**build sources + docs** on `rom-dev01` as the compile oracle (how Magisk / +product packaging is wired); GOLDEN `adb` for *runtime* behaviour, not the +first place to reverse “how to build”. **Do not** ship NeoLauncher — keep LOS +Launcher3. Prefer **Droidify** over stock F-Droid client (lighter; many repos +by default) unless packaging forces otherwise. **Do not** integrate AXP +**external** market repos or AXP **OTA** servers (EOL / servers down — no +sense). **Do** clone AXP-class **Private DNS** presets (many provider entries). +**Do** keep AXP-class **Internet connectivity** / special INTERNET permission +UX where practical, but **do not** hard-wire `axp.os` branding/endpoints. +**Wanted:** restore classic **Disable app** behaviour on Android 16 (LOS/AOSP +replaced much of this with **Archive**, which the owner dislikes) — research +and re-expose Disable where still feasible on A16. **Later (final ROM):** +system components (microG, Magisk, project Phonesky, other bundled system +apps) MUST remain **sideload-updatable** on a shipping build — owner plans +refreshes every **2–3 months** without a full ROM reflash. Packaging MUST +preserve update paths (same signing identity / PRESIGNED where applicable; +document Magisk update path separately from APK sideload if boot-preroot). + + ## Context / non-goals **Product intent (this feature is normative for the AXP resurrection ship):** @@ -83,30 +107,39 @@ AXP/GOLDEN. - Building a custom AXP-style backup/restore ROM feature (personal backup remains an external user tool if needed). - Claiming Yuh hardware-attestation PASS if GOLDEN itself currently FAILs that - path — reproduce GOLDEN's *workflow* and document attestation parity honestly. + path — banking attestation is deferred with the banking workflow (owner + future); do not treat Swissquote/Yuh as ship gates here. - Deleting or rewriting the standby KernelSU / split-roadmap specs (`004`–`008`/`007`) — they remain valid on the standby branch/track. - Shipping KernelSU-Next as this track’s root (out of ship here; Magisk is the resurrection root). Optional later reuse of `007` kernels is allowed under FR-016 but MUST NOT delay Magisk acceptance. +- Resolving localization/location-hardening policy vs LOS defaults in this + feature’s acceptance (deferred research FR-018 — compare AXP vs LOS later). +- Integrating AXP **external** F-Droid/market repos or AXP **OTA** update + servers (EOL; servers down — no sense). +- Shipping NeoLauncher. +- Hard-wiring `axp.os` branding/endpoints into Internet-connectivity / + network UX (keep the permission/connectivity *behaviour* where practical). ## User Scenarios & Testing *(mandatory)* ### User Story 1 - AXP resurrection daily-driver on LAB (Priority: P1) As the owner, after flashing one LAB build produced under this feature, the -phone boots and presents the same class of daily-driver capabilities I rely on -with AXP on GOLDEN (Google compatibility stack, Play, managed banking profile -workflow, selectable call recording unlock, Magisk root/hide workflow like -GOLDEN, AXP hardening/signing posture, and AXP bundled usability apps — -except WebView as defined here), without a checklist of deferred AXP features. +phone boots and presents an **updated AXP-class clone on LOS23**: Google +compatibility stack, Play, selectable call recording unlock, Magisk root/hide +workflow like GOLDEN, AXP options/settings surface, userspace hardening / +signing posture, bundled usability apps, and an updated hardened sunfish +kernel — except WebView as defined here. Banking/Island validation is +**out of this story’s acceptance** (deferred to owner future / US3). **Why this priority**: This is the whole reason for the resurrection. **Independent Test**: Flash one `009` build to LAB; walk the GOLDEN daily -checklist (microG Self-Check, Play open/install, Island profile, call-record +checklist minus banking (microG Self-Check, Play open/install, call-record toggle off/on, spoofing toggle off/on, Magisk present in AXP-like install -state, bundled apps present, hardening/signing checks that GOLDEN implies); +state, bundled apps present, hardening/signing + kernel hardening checks); compare against `002` inventory categories. **Acceptance Scenarios**: @@ -115,13 +148,13 @@ compare against `002` inventory categories. **When** the `009` image is flashed, **Then** the device boots to home and cellular/Wi‑Fi/basic hardware still work as in the vanilla smoke. 2. **Given** that build, **When** I compare shipped capability categories to - GOLDEN/AXP Pro (Google stack, Play, selectable spoofing, managed profile - tool, selectable call recording unlock, Magisk/DenyList-class path, - DNS/hosts privacy helpers if present on GOLDEN, F‑Droid/Aurora/launcher/ - gallery-class bundled apps, hardening/signing/AVB class), **Then** no - category is left as “decide / later” without an explicit obsolescence note - tied to Android 16 / sunfish impossibility (WebView exception allowed per - FR-015). + GOLDEN/AXP Pro (Google stack, Play, selectable spoofing, selectable call + recording unlock, Magisk/DenyList-class path, DNS/hosts privacy helpers if + present on GOLDEN, F‑Droid/Aurora/launcher/gallery-class bundled apps, + userspace hardening/signing/AVB class, kernel update + hardening class), + **Then** no category is left as “decide / later” without an explicit + obsolescence or **deferred** note (WebView exception FR-015; banking + deferred FR-006/FR-007; localization hardening compare deferred FR-018). 3. **Given** Git and host artifact policy, **When** inspected, **Then** no proprietary Phonesky APK bytes or secrets were committed. @@ -165,22 +198,22 @@ behaviour; push notifications smoke for a known test app. --- -### User Story 3 - Banking profile workflow parity (Priority: P1) +### User Story 3 - Banking profile workflow parity (Priority: P3 — deferred) -As the owner, I can recreate the GOLDEN banking layout on LAB: install via the -same store path I use on AXP, place banks in Island, and keep banking apps -free of root via Magisk DenyList-class hiding like GOLDEN. +As the owner, **later** I can recreate the GOLDEN banking layout on LAB: +Island + Magisk DenyList-class hiding + Swissquote/Yuh. This is explicitly +**not** required to accept the AXP-on-LOS23 clone for functionalities, +options, hardening, security, or kernel work. -**Why this priority**: Compatibility hard gates; daily-driver without banks -fails the resurrection. +**Why this priority**: Owner (2026-09-17) — banking is a future personal +problem; do not block the updated AXP clone on bank gates. -**Independent Test**: Install Swissquote (hard gate) and attempt Yuh; run -inside Island; Magisk DenyList (or AXP-equivalent) applied; record PASS/FAIL -honestly vs GOLDEN. +**Independent Test** *(when owner resumes)*: Install Swissquote and attempt +Yuh; Island; Magisk DenyList; record PASS/FAIL honestly vs GOLDEN. -**Acceptance Scenarios**: +**Acceptance Scenarios** *(deferred — not ship gates)*: -1. **Given** Island on LAB, **When** I follow the documented GOLDEN banking +1. **Given** Island on LAB, **When** the owner follows the GOLDEN banking install order, **Then** Swissquote reaches a usable logged-in state in the managed profile. 2. **Given** Yuh on the same workflow, **When** tested, **Then** either it @@ -211,32 +244,38 @@ recording unlock off (restricted) and on (record allowed). with GOLDEN measurement, using the newest Magisk stable that works on this stack. 2. **Given** Magisk setup completed on LAB, **When** DenyList-class hiding is - configured for a banking package, **Then** that package does not receive - root. + configured for a test package, **Then** that package does not receive root + (banking packages deferred with US3). 3. **Given** selectable call recording unlock, **When** OFF, **Then** stock LOS country/carrier style restrictions apply; **When** ON, **Then** Dialer can record on LAB without that block. --- -### User Story 5 - AXP usability, privacy, hardening (Priority: P2) +### User Story 5 - AXP usability, options, hardening + kernel (Priority: P1) -As the owner, the ROM ships the rest of the AXP usability/privacy surface and -GOLDEN-class hardening/signing/AVB posture at newest workable stables, with -LOS23 WebView default and an unlocked provider chooser. +As the owner, the ROM ships the rest of the AXP usability/privacy surface, +AXP-class options/settings behaviour, GOLDEN-class userspace hardening / +signing / AVB posture, and an **updated LOS 23.2 sunfish kernel with +attributable hardening** (AXP / Graphene / Divest class where still valid on +non-GKI 4.14), at newest workable stables, with LOS23 WebView default and an +unlocked provider chooser. Localization/location-hardening delta vs LOS is +**out of scope for now** (FR-018 later). -**Why this priority**: Completes resurrection beyond Google/banking/root core. +**Why this priority**: Owner (2026-09-17) — this is the core of “clon +actualizado de AXP”, ahead of banking. **Independent Test**: Package list vs `002`; open bundled apps; confirm -default WebView is LOS and another WebView can be selected if installed; -hardening/signing checks agreed for GOLDEN-class parity. +default WebView is LOS; userspace hardening/signing checks; kernel version / +hardening patch attribution recorded for the accepted build. **Acceptance Scenarios**: 1. **Given** the `009` build, **When** I list bundled system/user apps in the AXP usability set, **Then** each GOLDEN/AXP category is present or explicitly marked impossible on Android 16/sunfish with rationale - (Aosmium absence is the allowed WebView exception). + (Aosmium absence is the allowed WebView exception; banking tools may ship + as packages without Gate E validation). 2. **Given** Developer options, **When** I open WebView implementation, **Then** LOS23 WebView is available/default and the chooser is not locked against future alternate providers. @@ -244,9 +283,13 @@ hardening/signing checks agreed for GOLDEN-class parity. FR-004) are recorded, **Then** each is newest stable that still runs on the ROM. 4. **Given** GOLDEN/AXP hardening and signing expectations, **When** the - accepted build is evaluated, **Then** equivalent class of protections / - signing posture is present or each gap is documented as impossible on - this stack — not silently dropped. + accepted build is evaluated, **Then** equivalent class of userspace + protections / signing posture is present or each gap is documented as + impossible on this stack — not silently dropped. +5. **Given** the LOS 23.2 sunfish kernel tree, **When** the accepted boot + image is built, **Then** it is an updated lineage/sunfish-compatible + kernel (not an unrelated prebuilt) with attributable hardening patches + applied or each skipped hardening item documented. --- @@ -291,6 +334,9 @@ work when published. silently fall back to FakeStore. - Alternate WebView installed by user later: selection must remain possible; default remains LOS23 WebView until the user changes it. +- Localization/location hardening: AXP historically more aggressive than LOS + in places the owner dislikes; **do not decide** AXP-vs-LOS location policy + in this feature’s acceptance — compare later (FR-018). ## Requirements *(mandatory)* @@ -298,9 +344,11 @@ work when published. - **FR-001**: The project MUST produce a flashable LineageOS 23.2 / Android 16 `sunfish` build that resurrects the AXP.OS on LOS22 / GOLDEN capability set - (including Magisk-class root and GOLDEN-class hardening / signing / AVB - posture), without leaving AXP capabilities as open “decide” omissions - except the WebView exception in FR-015. + (including Magisk-class root, GOLDEN-class userspace hardening / signing / + AVB posture, and an updated hardened sunfish kernel per FR-017), without + leaving AXP capabilities as open “decide” omissions except documented + exceptions/deferrals (WebView FR-015; banking FR-006/FR-007; localization + compare FR-018). - **FR-002**: Version selection for system and bundled components (except Phonesky per FR-004) MUST prefer the newest stable (or newest tagged pre-release upstream currently ships) that still works on sunfish / @@ -316,10 +364,13 @@ work when published. microG + Phonesky path (owner-controlled toggle; default safe/off or project-documented default). Spoofing MUST remain restricted/controlled — not unrestricted platform spoofing for all apps. -- **FR-006**: The ROM MUST support the GOLDEN managed-profile banking workflow - (Island as measured on GOLDEN) including Swissquote PASS as a hard gate. -- **FR-007**: Banking applications MUST run without being granted root - (Magisk DenyList-class hiding). +- **FR-006**: *(Deferred — owner future)* The ROM SHOULD support the GOLDEN + managed-profile banking workflow (Island as measured on GOLDEN) including + Swissquote PASS. This is **not** an acceptance gate for the AXP clone MVP. +- **FR-007**: *(Deferred — owner future)* Banking applications SHOULD run + without being granted root (Magisk DenyList-class hiding). Magisk MUST still + provide DenyList-class capability for general use (FR-010); bank-specific + validation is deferred with FR-006. - **FR-008**: The ROM MUST include **selectable** AXP-equivalent call recording unlock (toggle; OFF = stock LOS restrictions, ON = unlock). - **FR-009**: The ROM MUST include the AXP usability/privacy bundled surface @@ -329,12 +380,12 @@ work when published. - **FR-010**: The ROM MUST ship **Magisk** like GOLDEN: newest Magisk stable that works on this stack, in an AXP-like preinstalled but not fully activated layout (exact first-boot/setup behaviour measured from GOLDEN), - with DenyList-class hiding sufficient for FR-007. KernelSU is **out of - ship for now** (not the resurrection root path). + with DenyList-class hiding available. KernelSU is **out of ship for now** + (not the resurrection root path). - **FR-011**: The feature acceptance gate MUST include GOLDEN/AXP-class - hardening and signing / AVB posture (as applicable on LOS 23.2 / sunfish), - not only apps and Google compatibility. Gaps MUST be documented as - impossible on this stack rather than silently omitted. + userspace hardening and signing / AVB posture (as applicable on LOS 23.2 / + sunfish), not only apps and Google compatibility. Gaps MUST be documented + as impossible on this stack rather than silently omitted. - **FR-012**: Acceptance flashing MUST use LAB only; GOLDEN MUST remain unmodified by this feature's work. - **FR-013**: Each shipped capability MUST be attributable (what upstream or @@ -354,6 +405,32 @@ work when published. Such reuse is **optional** (“si se puede, ok”), MUST NOT become an acceptance requirement for Magisk resurrection, and MUST NOT imply KernelSU is back in the ship path unless a future spec explicitly says so. +- **FR-017**: The ship MUST use an **updated** LineageOS 23.2–compatible + `sunfish` kernel (current lineage/kernel_google_sunfish or project-tracked + equivalent — not an unrelated Graphene A13 / stock A13 prebuilt), with + **attributable kernel hardening** ported from AXP / Graphene / Divest where + still valid on non-GKI 4.14. Skipped items MUST be documented with rationale. +- **FR-018**: *(Deferred research — look later)* Compare how AXP/GOLDEN + hardens or constrains **localization / location** (network location, + backends, permissions, privacy toggles) versus stock LineageOS 23 behaviour. + Owner historically finds AXP aggressive here; do **not** freeze a + clone-or-LOS policy in this feature’s acceptance until that comparison + exists. Default until then: do not silently invent extra location lockdown + beyond what the rest of the AXP clone already implies; record the open + question in the capability matrix. +- **FR-019**: On a **final** shipping `009` image, owner MUST be able to + refresh bundled **system / privileged** packages by **sideload** (or the + documented Magisk-equivalent path) roughly every **2–3 months**, without + requiring a full ROM reflash for routine bumps of at least: **microG + (GmsCore / companions)**, **Magisk**, **project Phonesky**, and other + project-bundled system apps that the capability inventory treats as + updatable. Packaging MUST preserve PackageManager update eligibility + (matching signing identity; **PRESIGNED** where upstream expects + self-updates; project-key continuity for Phonesky). Magisk MAY use its + normal manager / boot-image update flow when APK-only sideload is + insufficient — that path MUST be documented in the recovery/sideload + runbook. This does **not** restore AXP external repos or OTA (still + forbidden); updates are owner-driven sideload / recovery packages. ### Key Entities @@ -364,13 +441,16 @@ work when published. (resurrection target). - **Version pin record**: Documented package/component versions chosen for the accepted `009` build (newest workable stable each; Phonesky = project - artifact id/version). + artifact id/version; kernel rev + hardening patch list). - **Phonesky host artifact**: Project patched/signed Play APK and permission metadata kept outside Git on the build host. - **Magisk preinstall state**: Measured GOLDEN/AXP layout for Magisk present but not fully activated, plus LAB setup steps. -- **LAB acceptance build**: Flashable image set + hashes + smoke/banking / - Magisk / hardening results for this feature. +- **Hardened sunfish kernel**: Updated LOS23-compatible kernel build + + attributed hardening patch set for FR-017. +- **LAB acceptance build**: Flashable image set + hashes + smoke / Magisk / + userspace+kernel hardening results for this feature (banking evidence + optional/deferred). ## Success Criteria *(mandatory)* @@ -380,15 +460,16 @@ work when published. hardware smoke within the same session as flash (owner can place a call, use Wi‑Fi, and unlock the device). - **SC-002**: 100% of AXP resurrection capability categories from the agreed - inventory are either demonstrated on LAB or explicitly documented as - impossible on Android 16/sunfish — zero silent omissions (WebView exception - allowed only as FR-015). + inventory are either demonstrated on LAB, marked deferred (banking, + localization compare), or explicitly documented as impossible on Android + 16/sunfish — zero silent omissions (WebView exception allowed only as + FR-015). - **SC-003**: With spoofing enabled as required, microG Self-Check required items and project Phonesky open/install succeed on LAB for ordinary apps on the first accepted build candidate (or within one documented fix iteration). -- **SC-004**: Swissquote managed-profile + Magisk DenyList-class workflow - PASSes on LAB; Yuh result is recorded and is not worse than GOLDEN for - packaging/spoofing reasons. +- **SC-004**: *(Deferred with US3)* Swissquote managed-profile + Magisk + DenyList-class workflow PASSes on LAB when owner resumes banking; not + required for AXP-clone MVP acceptance. - **SC-005**: Every bundled/system app version in the acceptance record (except Phonesky) is newer than or equal to GOLDEN's measured version, unless a newer release was tried and failed with a written regression note; @@ -399,7 +480,16 @@ work when published. can be fully activated on LAB using documented steps measured from GOLDEN. - **SC-008**: Default WebView is LOS23's; provider selection remains available. - **SC-009**: Owner can perform the GOLDEN-equivalent daily checklist on LAB - without consulting a scatter of conflicting feature specs for what “ships”. + **excluding deferred banking** without consulting a scatter of conflicting + feature specs for what “ships”. +- **SC-010**: Accepted build records kernel revision + hardening attribution + list (applied / skipped+why) satisfying FR-017. +- **SC-011**: Acceptance docs list, for each FR-019 component, the intended + update channel (sideload APK / recovery zip / Magisk self-update) and confirm + signing identity is not broken by packaging (PRESIGNED or project key as + applicable). Full 2–3 month refresh drill MAY wait until a final ROM + candidate; packaging regressions that block updates MUST be fixed before + ship. ## Assumptions @@ -408,11 +498,12 @@ work when published. - GOLDEN inventory (`002`) plus AXP Pro docs are sufficient to enumerate the capability set; live `adb` re-query of GOLDEN is allowed (especially Magisk preinstall/activation details). -- “AXP resurrection” means Magisk + GOLDEN-class hardening/signing/AVB + full - AXP user surface on LOS23, with only the stated WebView and Phonesky-artifact - exceptions. -- Island remains the managed-profile tool because that is what GOLDEN - actually runs (AXP docs saying “Insular” are historical naming). +- “AXP resurrection” / updated clone means Magisk + GOLDEN-class userspace + hardening/signing/AVB + AXP user/options surface + updated hardened kernel + on LOS23, with WebView, Phonesky-artifact, banking-deferral, and + localization-compare exceptions as stated. +- Island / banking validation is owner-future; shipping Island as a bundled + app is optional and does not imply Gate E. - FakeStore is never the primary Play path. - Selectable spoofing and selectable call recording follow the same class of Developer Options UX already explored in `005`/`008` runbooks where useful. @@ -424,3 +515,10 @@ work when published. - Prior KernelSU LAB experiments (including the two functional kernels already built) are **out of ship for now** but kept as recyclable assets: reuse if helpful, never required for Magisk acceptance. +- Localization hardening AXP-vs-LOS comparison is intentionally postponed + (FR-018); do not block MVP on it. +- No AXP-style OTA or external repos; periodic system-package refresh is + **owner sideload** (FR-019), not a network updater in the ROM. +- microG stays PRESIGNED / replace-prebuilt so same-signer updates remain + possible; Phonesky stays on the project signing key across releases; + Magisk update docs cover manager + any boot re-patch when needed. diff --git a/specs/009-axp-los23-port/tasks.md b/specs/009-axp-los23-port/tasks.md new file mode 100644 index 0000000..ff461a1 --- /dev/null +++ b/specs/009-axp-los23-port/tasks.md @@ -0,0 +1,339 @@ +# Tasks: AXP LOS22 feature port to LOS23 (resurrection) + +**Input**: Design documents from `/specs/009-axp-los23-port/` +**Prerequisites**: `plan.md`, `spec.md`, `research.md`, `data-model.md`, +`contracts/`, `quickstart.md`; constitution Magisk-resurrection track; +standby KernelSU track (`004`–`008`/`007`) remains untouched + +**Tests**: LAB acceptance only (Gates A–G in `contracts/acceptance-gates.md`). +No unit/contract TDD suite requested — validation tasks are adb/flash checks. + +**Organization**: Setup → Foundational → US1 / US2 / US4 / US5 (MVP) → US6 → +Polish. **US3 banking is deferred (P3)** — skip for MVP. US5 includes +**kernel update + hardening** (FR-017). Localization AXP-vs-LOS (FR-018) = +look later, not a ship gate. Full US1 Independent Test needs US2+US4+US5 +(not banking). + +## Format: `[ID] [P?] [Story] Description` + +- **[P]**: Can run in parallel (different files, no incomplete deps) +- **[Story]**: US1…US6 from `spec.md` +- Include exact file paths in descriptions + +## Path conventions + +- Meta repo: `vendor/sunfish-a16/`, `docs/`, `specs/009-axp-los23-port/` +- Build host: `/srv/rom/src/lineage/`, `/srv/rom/prebuilts/`, + `/srv/rom/artifacts/009-axp-los23-port/`, `/srv/rom/secrets/` +- LAB: `11231JEC207477` only — never GOLDEN flash/modify +- GOLDEN: `adb` read-only oracle (esp. Magisk preinstall layout) + +--- + +## Phase 1: Setup (Shared Infrastructure) + +**Purpose**: Host dirs, runbook stubs, capability inventory scaffold + +- [x] T001 Create host dirs `/srv/rom/prebuilts/{magisk,axp-apps}/`, + `/srv/rom/artifacts/009-axp-los23-port/`, `/srv/rom/logs/009-build/` + on `rom-dev01` (android-build writable) +- [x] T002 [P] Add stub `docs/009-magisk-preinstall-runbook.md` (GOLDEN + measure checklist, activation steps, DenyList banking order, LAB serial) +- [x] T003 [P] Add stub `docs/009-version-pins.md` (VersionPinRecord table: + component / version_name / version_code / upstream_ref / policy / + verified_on) +- [x] T004 [P] Add stub `docs/009-capability-matrix.md` mapping + `docs/002-golden-inventory.md` + `docs/axp-pro-parity.md` rows → + `required` / `exception` / `impossible` per `data-model.md` + AxpCapabilitySet +- [x] T005 [P] Create `vendor/sunfish-a16/patches/009-axp-los23-port/README.md` + (Magisk-resurrection apply order; reuse `005`/`008`; no KernelSU ship; + attribute upstreams) + +**Checkpoint**: Dirs + stubs exist; no bacon yet + +--- + +## Phase 2: Foundational (Blocking Prerequisites) + +**Purpose**: Freshness policy, GOLDEN Magisk measurement, product wiring +baseline — MUST complete before story packages land on LAB acceptance builds + +**⚠️ CRITICAL**: Blocks user-story packaging/flash acceptance + +- [x] T006 Refresh microG + GSF to newest stable upstream (fetch tags / + releases; no stale host cache) into `/srv/rom/prebuilts/microg/` + + `VERSIONS.txt`; record pins in `docs/009-version-pins.md` +- [x] T007 [P] Confirm project patched Phonesky still present under + `/srv/rom/prebuilts/phonesky/` + XMLs; record artifact id in + `docs/009-version-pins.md` (`policy=project_phonesky`); halt note if + GOLDEN-class gap suspected +- [x] T008 [P] Fetch newest Magisk stable that targets this stack into + `/srv/rom/prebuilts/magisk/` + `VERSIONS.txt`; record pin in + `docs/009-version-pins.md` +- [x] T009 Measure GOLDEN Magisk/Magia preinstall layout via `adb` only + (paths, packages, first-boot/setup UX) and write results into + `docs/009-magisk-preinstall-runbook.md` (FR-010 / contracts/ + magisk-preinstall.md) +- [x] T010 Fill `docs/009-capability-matrix.md` for all GOLDEN/AXP categories + (google-stack, spoofing, call-rec, Magisk, bundled apps, DNS/hosts, + userspace hardening/signing/AVB, **kernel hardening**, WebView=exception, + banking=deferred, localization=deferred FR-018); zero silent omissions +- [x] T011 Wire Magisk-resurrection product includes in + `vendor/sunfish-a16/` (extend `gms.mk` / add `magisk.mk` or equivalent; + keep Phonesky priv-app path; **no FakeStore**; **no KernelSU** product + packages) and document include hook in + `vendor/sunfish-a16/patches/009-axp-los23-port/README.md` +- [x] T012 Confirm `003` vanilla (or documented equivalent) known-good + baseline is available for LAB clean-flash acceptance; note rev in + `docs/009-version-pins.md` VanillaBaseline row +- [x] T013 [P] Confirm optional `007` kernel artifacts remain on host under + `/srv/rom/artifacts/007-*/` for FR-016 recycle only; list paths in + `docs/009-magisk-preinstall-runbook.md` as non-ship + +**Checkpoint**: Prebuilts fresh, Magisk UX measured, product wire documented — +story work can begin + +--- + +## Phase 3: User Story 1 — AXP resurrection daily-driver on LAB (Priority: P1) 🎯 MVP framing + +**Goal**: One flashable `009` composition path and Gate A smoke; full +daily-driver Independent Test completes after US2+US4+US5 (banking deferred) + +**Independent Test**: Flash one `009` build to LAB; walk GOLDEN checklist +**minus banking** from `docs/009-capability-matrix.md` + +### Implementation for User Story 1 + +- [x] T014 [US1] Define staged known-good image policy in + `docs/009-magisk-preinstall-runbook.md` (retain prior LAB image hashes + under `/srv/rom/artifacts/009-axp-los23-port//` per FR-013) +- [ ] T015 [US1] Add LAB flash/acceptance checklist linking Gates A–G to + `specs/009-axp-los23-port/quickstart.md` and + `contracts/acceptance-gates.md` (artifact subdirs `gate-a/`…`gate-g/`) +- [ ] T016 [US1] Produce first Magisk-track bacon on `rom-dev01` (detached + `/srv/rom/artifacts/bin/rom-detach` / tmux) with current wired packages; + logs under `/srv/rom/logs/009-build/`; images + SHA-256 under + `/srv/rom/artifacts/009-axp-los23-port//` +- [ ] T017 [US1] Clean-flash LAB `11231JEC207477` only; complete Gate A + (boot/home/call/Wi‑Fi/unlock); save `getprop` + notes under + `…//gate-a/` +- [ ] T018 [US1] After US2+US4+US5 land, re-flash accepted candidate and mark + SC-001…SC-003 + SC-005…SC-010 / Gates A–D + F–G in + `/srv/rom/artifacts/009-axp-los23-port//acceptance.md` + against `docs/009-capability-matrix.md` (skip Gate E / SC-004) +- [ ] T019 [US1] Verify Git/meta-repo contains no proprietary Phonesky APK + bytes or secrets; document check in + `/srv/rom/artifacts/009-axp-los23-port//acceptance.md` + +**Checkpoint**: Gate A proven; full US1 Independent Test after US2+US4+US5 + +--- + +## Phase 4: User Story 2 — Google stack: newest microG + project Phonesky (Priority: P1) + +**Goal**: Newest microG/GSF + project Phonesky + selectable restricted spoofing + +**Independent Test**: microG Self-Check; Phonesky open/install; spoofing +OFF/ON per `contracts/toggles-surface.md` + +### Implementation for User Story 2 + +- [ ] T020 [P] [US2] Ensure `vendor/sunfish-a16/gms.mk` + + `vendor/sunfish-a16/Android.mk` package refreshed microG/GSF + Phonesky + without FakeStore; privilege XMLs remain under + `vendor/sunfish-a16/permissions/` and + `vendor/sunfish-a16/default-permissions/` +- [ ] T021 [P] [US2] Re-apply / verify selectable signature spoofing via + `vendor/sunfish-a16/patches/005-sigspoof/apply_005_sigspoof.py` on LOS + 23.2 tree; document A16 deltas in `docs/005-spoofing-runbook.md` (or + `docs/009-magisk-preinstall-runbook.md` cross-link) +- [ ] T022 [US2] Build+flash LAB image including Google stack; run Gate B + (Self-Check, Phonesky open, ordinary app install/update); evidence under + `/srv/rom/artifacts/009-axp-los23-port//gate-b/` +- [ ] T023 [US2] Verify Secure key `allow_signature_fake` OFF/ON behaviour per + `contracts/toggles-surface.md`; record in + `…//gate-c/spoofing.md` +- [x] T024 [US2] Finalize microG/GSF/Phonesky rows in `docs/009-version-pins.md`; + if Phonesky lacks GOLDEN-class daily fix → FAIL closed note in + `…//gate-b/phonesky-halt.md` (do not accept) + +**Checkpoint**: Gate B + spoofing half of Gate C pass (or explicit Phonesky halt) + +--- + +## Phase 5: User Story 3 — Banking (Priority: P3 — deferred) + +**Goal**: Island + Magisk DenyList banking — **owner future; not MVP** + +**Independent Test**: *(when resumed)* Swissquote in Island; Yuh honest; no root + +### Deferred tasks (do not block acceptance) + +- [ ] T025 [P] [US3] *(Deferred)* Stage Island under + `/srv/rom/prebuilts/axp-apps/` and wire into `vendor/sunfish-a16/` if + desired as optional package; pin in `docs/009-version-pins.md` +- [ ] T026 [US3] *(Deferred)* Document GOLDEN banking order in + `docs/009-magisk-preinstall-runbook.md` +- [ ] T027 [US3] *(Deferred)* Swissquote Gate E under + `/srv/rom/artifacts/009-axp-los23-port//gate-e/swissquote/` +- [ ] T028 [US3] *(Deferred)* Yuh classify in `…/gate-e/yuh.md` +- [ ] T029 [US3] *(Deferred)* Banks lack root note in `…/gate-e/root-check.md` + +**Checkpoint**: Skipped for MVP — resume only when owner asks + +--- + +## Phase 6: User Story 4 — Magisk like GOLDEN + selectable call recording (Priority: P1) + +**Goal**: Magisk AXP-like preinstall + DenyList; selectable call-rec unlock + +**Independent Test**: Preinstall state vs GOLDEN notes; activation; DenyList +test app; call-rec OFF/ON + +### Implementation for User Story 4 + +- [ ] T030 [US4] Implement Magisk AXP-like preinstall packaging from + `/srv/rom/prebuilts/magisk/` into `vendor/sunfish-a16/magisk.mk` (or + equivalent) matching `docs/009-magisk-preinstall-runbook.md` measured + layout (`contracts/magisk-preinstall.md`) +- [ ] T031 [P] [US4] Re-apply / verify selectable call-rec unlock via + `vendor/sunfish-a16/patches/008-call-rec-flag-secure/apply_008_call_rec_flag_secure.py` + (`extendrom_call_recording`); keep default OFF; optional FLAG_SECURE + not required for AXP acceptance — document in + `docs/008-call-rec-flag-secure-runbook.md` +- [ ] T032 [US4] Build+flash LAB; document pre-activation Magisk state vs + GOLDEN under `…//magisk/pre-activation.md` (Gate D) +- [ ] T033 [US4] Complete Magisk activation on LAB per runbook; configure + DenyList-class hide for a **test** package (not bank gate); save version + + screenshots under `…//magisk/` +- [ ] T034 [US4] Verify `extendrom_call_recording` OFF = stock restrictions, + ON = Dialer can record; evidence under + `…//gate-c/call-rec.md` +- [ ] T035 [US4] Record Magisk version pin (newest workable stable) in + `docs/009-version-pins.md` + +**Checkpoint**: Gates C (call-rec) + D pass + +--- + +## Phase 7: User Story 5 — Usability, options, hardening + kernel (Priority: P1) + +**Goal**: Bundled AXP surface; LOS23 WebView; userspace hardening/signing; +**updated hardened sunfish kernel** (FR-017). Localization compare = later. + +**Independent Test**: Packages vs matrix; WebView LOS; Gate G userspace + +kernel attribution (SC-010) + +### Implementation for User Story 5 + +- [ ] T036 [P] [US5] Enumerate bundled usability packages from + `docs/009-capability-matrix.md` (Aurora, F-Droid/repos as on GOLDEN, + launcher/gallery-class, DNS/hosts helpers if required); stage newest + workable APKs under `/srv/rom/prebuilts/axp-apps/` +- [ ] T037 [US5] Wire bundled apps into `vendor/sunfish-a16/` product + makefiles; pin all versions in `docs/009-version-pins.md` +- [ ] T038 [P] [US5] Verify WebView policy: no Aosmium; default LOS23 + provider; chooser unlocked — document in + `…//gate-f/webview.md` per `contracts/webview-surface.md` +- [ ] T039 [US5] Build+flash LAB; confirm bundled categories present or + marked impossible/deferred in `docs/009-capability-matrix.md`; Gate F + evidence under `…//gate-f/` +- [x] T040 [US5] Define staged userspace hardening/signing/AVB checklist in + `docs/009-hardening-signing-checklist.md` (GOLDEN vs LAB measured + 2026-09-29; release keys yes / bootloader lock wont; stages US-S0…S6) +- [ ] T041 [US5] Implement first attributable userspace hardening/signing + stage under `vendor/sunfish-a16/patches/009-axp-los23-port/` (US-S1 + keygen + US-S2 wire); keep known-good prior image + (`20260929T123401Z-axp-stage1-combo4`) +- [ ] T042 [US5] Inventory LOS23 sunfish kernel tree on `rom-dev01` + (`/srv/rom/src/lineage/kernel/google/sunfish` or manifest path); record + baseline rev in `docs/009-version-pins.md` +- [ ] T043 [US5] Build attributable kernel hardening patch list (AXP / + Graphene / Divest → 4.14-safe) in + `docs/009-kernel-hardening-map.md` (applied vs skip+why) +- [ ] T044 [US5] Apply first kernel hardening stage on LOS23 sunfish kernel; + rebuild boot; flash LAB; evidence under `…//gate-g/kernel/` +- [ ] T045 [US5] Run Gate G userspace+kernel on accepted candidate; gaps in + `…//gate-g/gaps.md`; **do not** block on FR-018 localization +- [x] T046 [P] [US5] *(Look later — FR-018)* Stub only: + `docs/009-localization-axp-vs-los.md` outlining what to compare later + (AXP location lockdown vs stock LOS); no policy decision in MVP +- [ ] T046a [P] [US5] *(FR-019 — before final ship)* Write + `docs/009-sideload-system-updates.md`: how to refresh microG, Magisk, + Phonesky, and other system apps every ~2–3 months without full reflash + (signing identity / PRESIGNED / Magisk manager+boot path); verify + packaging does not break update eligibility + +**Checkpoint**: Gates F + G (userspace + kernel) for claimed stage; FR-018 stub +only; FR-019 runbook before final ship + +--- + +## Phase 8: User Story 6 — Parallel tracks stay honest (Priority: P2) + +**Goal**: Docs/branches make Magisk `009` active vs KernelSU standby clear + +**Independent Test**: `specs/004`–`008`/`007` still present; `009` does not +retire standby track + +### Implementation for User Story 6 + +- [ ] T047 [P] [US6] Update `docs/README.md` (and `AGENTS.md` if needed) to + state active Magisk-resurrection track = `009` / this repo; standby + KernelSU = sibling `sunfish-a16-rom` + specs `004`–`008`/`007` +- [ ] T048 [P] [US6] Add short track note to + `specs/009-axp-los23-port/spec.md` only if needed (do **not** rewrite + standby feature specs) +- [ ] T049 [US6] Remap relevant `docs/axp-pro-parity.md` rows to `009` +- [ ] T050 [US6] Confirm `specs/001`–`008`/`007` directories still exist; record in + `/srv/rom/artifacts/009-axp-los23-port//acceptance.md` +- [ ] T051 [P] [US6] Document optional FR-016 KSU recycle (non-ship) in + `docs/009-magisk-preinstall-runbook.md` + `docs/007-kernelsu-runbook.md` + cross-link + +**Checkpoint**: Parallel-track honesty readable without rewriting history + +--- + +## Phase 9: Polish & Cross-Cutting Concerns + +**Purpose**: Freshness audit, quickstart validation, handoff + +- [ ] T052 [P] Audit all `docs/009-version-pins.md` rows against freshness + policy; fix stale host copies if found +- [ ] T053 [P] Run `specs/009-axp-los23-port/quickstart.md` on LAB + (**skip Gate E**); fix doc gaps +- [ ] T054 Collect final artifacts under + `/srv/rom/artifacts/009-axp-los23-port//` +- [ ] T055 [P] Add/update `docs/009-gate-handoff.md` (next: banking later; + localization compare FR-018 later; sideload refresh cadence FR-019) +- [ ] T056 Mark `specs/009-axp-los23-port/spec.md` Status after Gates A–D + + F–G + +--- + +## Dependencies & Execution Order + +### MVP order (owner 2026-09-17) + +1. Setup + Foundational +2. US2 Google stack +3. US4 Magisk + call-rec +4. US5 usability + **hardening + kernel** +5. US1 full acceptance (T018) **without banking** +6. US6 docs +7. *(Later)* US3 banking + FR-018 localization compare + +### Suggested MVP scope + +**T001–T024 + T030–T046** (skip T025–T029) + +## Notes + +- Banking Gate E / T025–T029 = deferred (owner future) +- Kernel hardening = in-scope (FR-017); localization policy = later (FR-018) +- LAB only; never flash GOLDEN +- Long builds detached on `rom-dev01` +- Owner handles git commit / push / MR diff --git a/vendor/sunfish-a16/.gitignore b/vendor/sunfish-a16/.gitignore new file mode 100644 index 0000000..df91287 --- /dev/null +++ b/vendor/sunfish-a16/.gitignore @@ -0,0 +1 @@ +certs/ diff --git a/vendor/sunfish-a16/Android.mk b/vendor/sunfish-a16/Android.mk index e90e8a7..75fc25a 100644 --- a/vendor/sunfish-a16/Android.mk +++ b/vendor/sunfish-a16/Android.mk @@ -13,6 +13,8 @@ LOCAL_OVERRIDES_PACKAGES := com.google.android.gms LOCAL_SRC_FILES := prebuilt/GmsCore.apk LOCAL_REPLACE_PREBUILT_APK_INSTALLED := $(LOCAL_PATH)/prebuilt/GmsCore.apk LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX) +# microG v0.3.16+ declares required uses-library com.android.location.provider +LOCAL_USES_LIBRARIES := com.android.location.provider LOCAL_OPTIONAL_USES_LIBRARIES := \ org.apache.http.legacy \ androidx.window.extensions \ @@ -47,3 +49,49 @@ LOCAL_OPTIONAL_USES_LIBRARIES := \ androidx.window.extensions \ androidx.window.sidecar include $(BUILD_PREBUILT) + +# 009 bundled apps (PRESIGNED; host prebuilts via symlink) → product +# Optional window libs: same manifest tags as Phonesky/GmsCore (A16 enforce check). +include $(CLEAR_VARS) +LOCAL_MODULE := AuroraStore +LOCAL_MODULE_CLASS := APPS +LOCAL_PRODUCT_MODULE := true +LOCAL_CERTIFICATE := PRESIGNED +LOCAL_SRC_FILES := prebuilt/AuroraStore.apk +LOCAL_REPLACE_PREBUILT_APK_INSTALLED := $(LOCAL_PATH)/prebuilt/AuroraStore.apk +LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX) +LOCAL_OPTIONAL_USES_LIBRARIES := \ + androidx.window.extensions \ + androidx.window.sidecar +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) +LOCAL_MODULE := Droidify +LOCAL_MODULE_CLASS := APPS +LOCAL_PRODUCT_MODULE := true +LOCAL_CERTIFICATE := PRESIGNED +LOCAL_SRC_FILES := prebuilt/Droidify.apk +LOCAL_REPLACE_PREBUILT_APK_INSTALLED := $(LOCAL_PATH)/prebuilt/Droidify.apk +LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX) +LOCAL_OPTIONAL_USES_LIBRARIES := \ + androidx.window.extensions \ + androidx.window.sidecar +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) +LOCAL_MODULE := FossifyGallery +LOCAL_MODULE_CLASS := APPS +LOCAL_PRODUCT_MODULE := true +LOCAL_CERTIFICATE := PRESIGNED +LOCAL_OVERRIDES_PACKAGES := Gallery Gallery2 Glimpse +LOCAL_SRC_FILES := prebuilt/FossifyGallery.apk +LOCAL_REPLACE_PREBUILT_APK_INSTALLED := $(LOCAL_PATH)/prebuilt/FossifyGallery.apk +LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX) +include $(BUILD_PREBUILT) + +# US-S4-2 — AXP PRO has no Jelly (system_ext noDefaultBrowserWebView). +include $(CLEAR_VARS) +LOCAL_MODULE := NoLineageJelly +LOCAL_MODULE_TAGS := optional +LOCAL_OVERRIDES_PACKAGES := Jelly +include $(BUILD_PHONY_PACKAGE) diff --git a/vendor/sunfish-a16/BoardConfig.mk b/vendor/sunfish-a16/BoardConfig.mk index 720385f..925479f 100644 --- a/vendor/sunfish-a16/BoardConfig.mk +++ b/vendor/sunfish-a16/BoardConfig.mk @@ -7,3 +7,22 @@ # official microG (which breaks F-Droid same-signer updates). BOARD_SUPER_PARTITION_ERROR_LIMIT := 9441378304 + +# Product LINEAGE_VERSION id: set in vendor/extra/product.mk (via bacon +# symlink to extra-product.mk) — BoardConfig is too late for version.mk. +# Keep a duplicate here only as documentation / get_build_var fallback. +TARGET_UNOFFICIAL_BUILD_ID := AXP-Resurection-Pro + +# US-S3 — project AVB *signing* key (Gate G infrastructure). +# Included after device/google/sunfish BoardConfig-common.mk → override here. +# Keep WITH_AVB unset → BoardConfigLineage adds vbmeta --flags 3 +# (HASHTREE_DISABLED|VERIFICATION_DISABLED). Magisk-friendly unlocked LAB; +# NOT runtime AVB enforcement / "hardened verified boot". +# Bootloader relock = wont. OEM unlocking: leave enabled (escape hatch only). +_AXP_AVB_KEY := vendor/sunfish-a16/certs/avb.pem +ifneq ($(wildcard $(_AXP_AVB_KEY)),) + BOARD_AVB_ALGORITHM := SHA256_RSA4096 + BOARD_AVB_KEY_PATH := $(_AXP_AVB_KEY) + BOARD_AVB_VBMETA_SYSTEM_ALGORITHM := SHA256_RSA4096 + BOARD_AVB_VBMETA_SYSTEM_KEY_PATH := $(_AXP_AVB_KEY) +endif diff --git a/vendor/sunfish-a16/apps.mk b/vendor/sunfish-a16/apps.mk new file mode 100644 index 0000000..b522576 --- /dev/null +++ b/vendor/sunfish-a16/apps.mk @@ -0,0 +1,8 @@ +# Bundled user apps (009) — Aurora Store, Droidify, Fossify Gallery. +# APKs live on host at /srv/rom/prebuilts/axp-apps/ (never Git). +# Symlink into vendor/sunfish-a16/prebuilt/ before bacon. + +PRODUCT_PACKAGES += \ + AuroraStore \ + Droidify \ + FossifyGallery diff --git a/vendor/sunfish-a16/branding.mk b/vendor/sunfish-a16/branding.mk new file mode 100644 index 0000000..ba98154 --- /dev/null +++ b/vendor/sunfish-a16/branding.mk @@ -0,0 +1,13 @@ +# AXP Resurection Pro product / OTA identity (009). +# +# "Pro" marks the full Magisk-resurrection track (not a future slim/minimal +# variant). GOLDEN used releasetype PRO + ro.lineage.version=…-sunfish-pro. +# +# TARGET_UNOFFICIAL_BUILD_ID is set in vendor/extra/product.mk (early Lineage +# hook, before version.mk). BoardConfig + this file are not early enough alone. +# Ship scripts also publish AXP-Resurection-Pro-*.zip from lineage-*.zip. + +# Identity props (not axp.os endpoints). Empty on GOLDEN for ro.axp.version — +# local track marker only. +PRODUCT_PRODUCT_PROPERTIES += \ + ro.axp.resurection.track=pro diff --git a/vendor/sunfish-a16/extra-product.mk b/vendor/sunfish-a16/extra-product.mk new file mode 100644 index 0000000..b126be3 --- /dev/null +++ b/vendor/sunfish-a16/extra-product.mk @@ -0,0 +1,5 @@ +# Early Lineage hook (vendor/lineage/config/common.mk inherits this *before* +# version.mk). Required so LINEAGE_VERSION picks up the unofficial id. +# BoardConfig.mk is too late for TARGET_UNOFFICIAL_BUILD_ID. + +TARGET_UNOFFICIAL_BUILD_ID := AXP-Resurection-Pro diff --git a/vendor/sunfish-a16/hardening.mk b/vendor/sunfish-a16/hardening.mk new file mode 100644 index 0000000..478e78e --- /dev/null +++ b/vendor/sunfish-a16/hardening.mk @@ -0,0 +1,29 @@ +# US-S4 — userspace hardening (AXP Resurection Pro). +# Match AXP.OS PRO sunfish product surface (see hardening/README.md + +# docs/009-axp-pro-product-apps-20260324.md). +# +# Real strips: +# US-S4-1 apply_009_drop_openssh_packages.py (common.mk) +# US-S4-2 apply_009_drop_jelly_gallery2.py (Jelly + Gallery2) +# PRODUCT_PACKAGES filter-out via inherit alone has failed before — keep as +# belt-and-suspenders only. + +PRODUCT_PACKAGES := $(filter-out \ + scp \ + sftp \ + ssh \ + sshd \ + sshd_config \ + ssh-keygen \ + start-ssh \ + rsync \ + Jelly \ + Gallery2 \ + Glimpse \ + ,$(PRODUCT_PACKAGES)) + +PRODUCT_PACKAGES += NoLineageJelly + +PRODUCT_PACKAGES_DEBUG := $(filter-out procmem,$(PRODUCT_PACKAGES_DEBUG)) + +# Keep init.openssh.rc — AXP PRO still ships it (mkdir /data/ssh* only). diff --git a/vendor/sunfish-a16/magisk.mk b/vendor/sunfish-a16/magisk.mk new file mode 100644 index 0000000..3d14480 --- /dev/null +++ b/vendor/sunfish-a16/magisk.mk @@ -0,0 +1,15 @@ +# Magisk preroot (009) — clean Magisk, stock UI, no modules. +# Wiring: vendor/sunfish-a16/magisk/{prepare_magisk.sh,patch.sh,apply_releasetools_hook.py} +# Runtime: SUNFISH_A16_MAGISK_PREROOT=1 + prepare_magisk.sh before packaging. +# Magisk is NOT a PRODUCT_PACKAGE (EXTENDROM-style preroot). + +# No packages — boot is patched at releasetools time. + +# US-S2 release keys (PRODUCT_DEFAULT_DEV_CERTIFICATE) — see signing.mk +$(call inherit-product-if-exists, vendor/sunfish-a16/signing.mk) + +# OTA / version branding (TARGET_UNOFFICIAL_BUILD_ID=AXP-Resurection-Pro) +$(call inherit-product-if-exists, vendor/sunfish-a16/branding.mk) + +# US-S4-1 userspace hardening (drop product OpenSSH, etc.) +$(call inherit-product-if-exists, vendor/sunfish-a16/hardening.mk) diff --git a/vendor/sunfish-a16/magisk/README.md b/vendor/sunfish-a16/magisk/README.md new file mode 100644 index 0000000..41c5b1b --- /dev/null +++ b/vendor/sunfish-a16/magisk/README.md @@ -0,0 +1,26 @@ +# Magisk preroot (sunfish-a16 / 009) + +**Policy:** clone AXP / EXTENDROM `EXTENDROM_PREROOT_BOOT` — do not invent. +Diverge only if LOS23 or Magisk version breaks that path. + +**Clean Magisk**, stock UI. No GOLDEN modules. No KernelSU in ship kernel. + +| File | Role | +|------|------| +| `prepare_magisk.sh` | Unzip Magisk APK → `$OUT_DIR/.magisk` (same as extendrom `er.sh`) | +| `patch.sh` | From sfX extendrom — patches boot.img via Magisk `boot_patch.sh` | +| `apply_releasetools_hook.py` | Inject into releasetools `common.py` (A16) | + +AXP virgin UX: Magisk not a `PRODUCT_PACKAGE`; root inactive until user +Additional Setup. See `docs/009-magisk-preinstall-runbook.md`. + +```bash +export SUNFISH_A16_MAGISK_PREROOT=1 # optional; READY file is the real gate +MAGISK_STAGE_DIR=$ANDROID_BUILD_TOP/out/.magisk \ + vendor/sunfish-a16/magisk/prepare_magisk.sh +python3 vendor/sunfish-a16/magisk/apply_releasetools_hook.py --top "$ANDROID_BUILD_TOP" --force +``` + +Hook **v2** runs when `out/.magisk/READY` exists (preferred) and/or +`SUNFISH_A16_MAGISK_PREROOT=1`. Env alone is unreliable under soong/ninja. +Without READY / env the hook no-ops. diff --git a/vendor/sunfish-a16/magisk/apply_releasetools_hook.py b/vendor/sunfish-a16/magisk/apply_releasetools_hook.py new file mode 100755 index 0000000..66d2c57 --- /dev/null +++ b/vendor/sunfish-a16/magisk/apply_releasetools_hook.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python3 +"""Idempotent Magisk preroot hook into releasetools common.py (LOS 23.2 / A16). + +Gate (either is enough): + - ``out/.magisk/READY`` present (preferred — survives ninja/soong env scrubbing) + - ``SUNFISH_A16_MAGISK_PREROOT=1`` + +Matches sfX extendrom inject (always-on once staged), adapted for A16 + our +vendor path. ``RunAndCheckOutput`` env is merged with ``os.environ`` so PATH / +ANDROID_BUILD_TOP survive (extendrom only passed ``system_root_image``; that +works via shebang but is fragile under sandboxes). +""" +from __future__ import annotations + +import argparse +import os +import pathlib +import re +import sys + +MARKER = "SUNFISH_A16: Magisk preroot hook" +MARKER_VER = "SUNFISH_A16: Magisk preroot hook v2" + +BUILD_HOOK = ''' + # SUNFISH_A16: Magisk preroot hook v2 (before AVB) + # Gate: staged out/.magisk/READY and/or SUNFISH_A16_MAGISK_PREROOT=1 + _sf_top = os.getenv("ANDROID_BUILD_TOP") or os.environ.get("PWD") or os.getcwd() + _sf_ready = os.path.isfile(os.path.join(_sf_top, "out", ".magisk", "READY")) + _sf_env = os.environ.get("SUNFISH_A16_MAGISK_PREROOT") == "1" + if _sf_ready or _sf_env: + if ((partition_name == "boot" and info_dict.get("init_boot") != "true") + or partition_name == "init_boot"): + mpatcher = [ + os.path.join(_sf_top, "vendor/sunfish-a16/magisk/patch.sh"), + img.name, + _sf_top, + ] + logger.info("SUNFISH_A16 Magisk patching (build): %s", img.name) + _sf_penv = os.environ.copy() + _sf_penv["system_root_image"] = info_dict.get("system_root_image", "false") + _sf_penv.setdefault("ANDROID_BUILD_TOP", _sf_top) + RunAndCheckOutput(mpatcher, verbose=True, env=_sf_penv) +''' + +PREBUILT_HOOK = ''' + # SUNFISH_A16: Magisk preroot hook v2 (prebuilt) + _sf_top = os.getenv("ANDROID_BUILD_TOP") or os.environ.get("PWD") or os.getcwd() + _sf_ready = os.path.isfile(os.path.join(_sf_top, "out", ".magisk", "READY")) + _sf_env = os.environ.get("SUNFISH_A16_MAGISK_PREROOT") == "1" + if _sf_ready or _sf_env: + if ((prebuilt_name == "boot.img" or prebuilt_name == "init_boot.img") + and os.path.exists(prebuilt_path)): + if info_dict is None: + info_dict = OPTIONS.info_dict + bimg = os.path.join(_sf_top, prebuilt_path) + logger.info("SUNFISH_A16 Magisk patching (prebuilt): %s", bimg) + mpatcher = [ + os.path.join(_sf_top, "vendor/sunfish-a16/magisk/patch.sh"), + bimg, + _sf_top, + ] + _sf_penv = os.environ.copy() + _sf_penv["system_root_image"] = info_dict.get("system_root_image", "false") + _sf_penv.setdefault("ANDROID_BUILD_TOP", _sf_top) + RunAndCheckOutput(mpatcher, verbose=True, env=_sf_penv) +''' + + +def _strip_old_hooks(text: str) -> str: + """Remove prior SUNFISH Magisk hook blocks (v1 gated or v2).""" + # Build hook: from our comment through just before AVB block + text = re.sub( + r"\n # SUNFISH_A16: Magisk preroot hook(?: v2)? \(before AVB\).*?" + r"(?=\n # AVB: if enabled)", + "\n", + text, + count=1, + flags=re.S, + ) + # Prebuilt hook: after BOOTABLE_IMAGES assign, before "if os.path.exists(prebuilt_path)" + text = re.sub( + r"( prebuilt_path = os\.path\.join\(unpack_dir, \"BOOTABLE_IMAGES\", prebuilt_name\)\n)" + r"\n # SUNFISH_A16: Magisk preroot hook(?: v2)? \(prebuilt\).*?" + r"(?=\n if os\.path\.exists\(prebuilt_path\):)", + r"\1", + text, + count=1, + flags=re.S, + ) + return text + + +def main() -> int: + ap = argparse.ArgumentParser() + ap.add_argument("--top", default=os.environ.get("ANDROID_BUILD_TOP", "")) + ap.add_argument("--dry-run", action="store_true") + ap.add_argument( + "--force", + action="store_true", + help="Replace an existing SUNFISH Magisk hook with v2", + ) + args = ap.parse_args() + top = pathlib.Path(args.top or ".") + target = top / "build/make/tools/releasetools/common.py" + if not target.is_file(): + print(f"ERROR: missing {target}", file=sys.stderr) + return 2 + text = target.read_text() + + if MARKER_VER in text and not args.force: + print(f"already applied (v2): {target}") + return 0 + + if MARKER in text or MARKER_VER in text: + if not args.force and MARKER_VER not in text: + # old v1 present — upgrade + pass + text = _strip_old_hooks(text) + + needle_avb = ( + ' # AVB: if enabled, calculate and add hash to boot.img or recovery.img.\n' + ' if info_dict.get("avb_enable") == "true":\n' + ' avbtool = info_dict["avb_avbtool"]\n' + ' if partition_name == "recovery":' + ) + idx = text.find(needle_avb) + if idx < 0: + print("ERROR: AVB anchor not found", file=sys.stderr) + return 3 + text = text[:idx] + BUILD_HOOK + "\n" + text[idx:] + + assign = ' prebuilt_path = os.path.join(unpack_dir, "BOOTABLE_IMAGES", prebuilt_name)\n' + idx2 = text.find(assign) + if idx2 < 0: + print("ERROR: prebuilt assign not found", file=sys.stderr) + return 4 + insert_at = idx2 + len(assign) + text = text[:insert_at] + PREBUILT_HOOK + "\n" + text[insert_at:] + + if args.dry_run: + print("dry-run OK (v2)") + return 0 + target.write_text(text) + print(f"applied v2 -> {target}") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/vendor/sunfish-a16/magisk/patch.sh b/vendor/sunfish-a16/magisk/patch.sh new file mode 100755 index 0000000..1b1237a --- /dev/null +++ b/vendor/sunfish-a16/magisk/patch.sh @@ -0,0 +1,122 @@ +#!/bin/bash +######################################################################################################### +# +# simple patch wrapper for patching a boot.img during the build process +# +######################################################################################################### +# +# Copyright (C) 2023-2024 steadfasterX +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +######################################################################################################### +# +# usage: +# ./patch.sh +# +######################################################################################################### + +# DO NOT set -e ! + +# parse calling params +export BOOTIMG="$1" +export TOP="$2" +[ -z "$TOP" -o ! -d "$TOP" ] && TOP=$PWD + +# colored (optional) output +PRINT(){ + MSG="$2" + case $1 in + [1-9]*|E|ERROR) + echo -e "\e[0;31m$0 - ERROR: ${MSG}\e[0m" ;; + I|INFO) + echo -e "\e[1;34m$0 - INFO: ${MSG}\e[0m" ;; + 0|OK|SUCCESS) + echo -e "\e[0;32m$0 - OK: ${MSG}\e[0m" ;; + *) + echo -e "$0 - ${MSG}" ;; + esac +} + +PRINT I "Starting: $0 with: >$BOOTIMG< (TOP=$TOP)" + +# LEGACYSAR can't be detected by the magisk patcher so must be set by us where needed (e.g. fajita). +# LEGACYSAR ensures kernel gets patched if required. +# https://github.com/topjohnwu/Magisk/blob/9aa466c7730ef4ef73195b476f9804ebf86932d2/scripts/boot_patch.sh#L220-L243 +export LEGACYSAR=${system_root_image} +PRINT I "system_root_image=$LEGACYSAR" + +# PREINITDEVICE can't be detected during build so must be set manually +# otherwise "Requires Additional Setup" on first start will not be able to patch w/o direct flash +# which is a problem on locked devices (obviously) +# https://github.com/AXP-OS/build/wiki/Frequently-Asked-Questions#magisk-requires-additional-setup-on-start +export PREINITDEVICE=userdata + +# tell magisk that we are not in booted android +export BOOTMODE=false + +# set output file descriptor to pts0 which *should* be the current shell +export OUTFD=0 + +# do not remove verity nor encryption +export KEEPVERITY=true +export KEEPFORCEENCRYPT=true + +# set magisk environment +export OUT_DIR=$TOP/out +export MAG_DIR="$OUT_DIR/.magisk" + +# disable due to not allowed binary or useless within the build process +alias dos2unix= +alias mount=echo +alias umount=echo + +# enable a fallback to get properties, according to: +# https://github.com/topjohnwu/Magisk/blob/4eaf701cb79cd9255333abad8482e69987f86280/scripts/util_functions.sh#L59 +getprop(){ + find $OUT_DIR/target/product -type f -name build.prop -exec grep $1 {} \; | tail -n1 +}; export -f getprop + +test -e $BOOTIMG +PRINT $? "testing existence of >$BOOTIMG< returned: $?" + +# do the magisk magic +/bin/bash $MAG_DIR/boot_patch.sh "$BOOTIMG" \ + && cp -v $MAG_DIR/new-boot.img "$BOOTIMG" +RET=$? + +# simple check if magisk can be found in the resulting boot.img +grep -q --text 'magisk' $BOOTIMG +MCHK=$? + +# sometimes the above is not valid even though patching was successful +if [ $MCHK -ne 0 ];then + PRINT I "Simple magisk check failed, unpacking for a detailed test..\n" + [ -d "$MAG_DIR/test" ] && rm -rf $MAG_DIR/test + mkdir $MAG_DIR/test + cd $MAG_DIR/test + $MAG_DIR/magiskboot unpack $BOOTIMG && $MAG_DIR/magiskboot cpio ramdisk.cpio test + case $? in + 1|4) MCHK=0;; + *) ;; + esac + cd $TOP + rm -rf $MAG_DIR/test +fi + +# check & print result +if [ "$MCHK" -eq 0 ];then PRINT OK "MAGISK found in $BOOTIMG!";else PRINT E "Magisk not found in $BOOTIMG!";fi +RET=$((RET + $MCHK)) + +PRINT $RET "ended with: $RET\n\n" +exit $RET diff --git a/vendor/sunfish-a16/magisk/prepare_magisk.sh b/vendor/sunfish-a16/magisk/prepare_magisk.sh new file mode 100755 index 0000000..b4753ad --- /dev/null +++ b/vendor/sunfish-a16/magisk/prepare_magisk.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# Stage Magisk v22+ APK into $OUT_DIR/.magisk (or MAGISK_STAGE_DIR) for preroot. +# Attribute: sfX-android extendrom er.sh MAGISK block + Magisk upstream. +set -euo pipefail +TOP="${ANDROID_BUILD_TOP:-${1:-}}" +OUT_DIR="${OUT_DIR:-$TOP/out}" +STAGE="${MAGISK_STAGE_DIR:-$OUT_DIR/.magisk}" +APK="${MAGISK_APK:-/srv/rom/prebuilts/magisk/Magisk-v30.7.apk}" +ARCH="${MAGISK_TARGET_ARCH:-arm64}" + +if [ -z "$TOP" ] || [ ! -d "$TOP" ]; then + echo "Usage: ANDROID_BUILD_TOP=/path prepare_magisk.sh" >&2 + exit 2 +fi +test -f "$APK" || { echo "Missing Magisk APK: $APK" >&2; exit 4; } + +rm -rf "$STAGE" +mkdir -p "$STAGE" +unzip -q "$APK" -d "$STAGE/src" + +# Host tools (x86_64) for patching during build +cp "$STAGE/src/lib/x86_64/libmagiskboot.so" "$STAGE/magiskboot" 2>/dev/null \ + || cp "$STAGE/src/lib/x86/libmagiskboot.so" "$STAGE/magiskboot" +chmod 755 "$STAGE/magiskboot" + +if [ "$ARCH" = "arm64" ]; then + if [ -f "$STAGE/src/lib/arm64-v8a/libmagisk64.so" ]; then + cp "$STAGE/src/lib/arm64-v8a/libmagisk64.so" "$STAGE/magisk64" + else + cp "$STAGE/src/lib/arm64-v8a/libmagisk.so" "$STAGE/magisk" + fi + cp "$STAGE/src/lib/arm64-v8a/libmagiskinit.so" "$STAGE/magiskinit" + [ -f "$STAGE/src/lib/arm64-v8a/libinit-ld.so" ] && cp "$STAGE/src/lib/arm64-v8a/libinit-ld.so" "$STAGE/init-ld" + [ -f "$STAGE/src/lib/arm64-v8a/libmagiskpolicy.so" ] && cp "$STAGE/src/lib/arm64-v8a/libmagiskpolicy.so" "$STAGE/magiskpolicy" +else + echo "Unsupported MAGISK_TARGET_ARCH=$ARCH" >&2 + exit 4 +fi + +chmod 755 "$STAGE/src/assets/boot_patch.sh" +rm -rf "$STAGE/src/assets/dexopt" "$STAGE/src/assets/chromeos" 2>/dev/null || true +cp "$STAGE/src/assets/"* "$STAGE/" +cp "$STAGE/src/assets/boot_patch.sh" "$STAGE/root_boot.sh" +chmod 755 "$STAGE/boot_patch.sh" "$STAGE/magiskinit" "$STAGE/magiskboot" +[ -f "$STAGE/magisk64" ] && chmod 755 "$STAGE/magisk64" +[ -f "$STAGE/magisk" ] && chmod 755 "$STAGE/magisk" +[ -f "$STAGE/init-ld" ] && chmod 755 "$STAGE/init-ld" + +# Point patch.sh at our vendor copy +MARKER="$STAGE/READY" +echo "apk=$(basename "$APK")" > "$MARKER" +echo "arch=$ARCH" >> "$MARKER" +echo "staged=$(date -u -Iseconds)" >> "$MARKER" +echo "OK Magisk staged at $STAGE" +cat "$MARKER" diff --git a/vendor/sunfish-a16/patches/008-call-rec-flag-secure/README.md b/vendor/sunfish-a16/patches/008-call-rec-flag-secure/README.md index 14d4a8b..e3bf581 100644 --- a/vendor/sunfish-a16/patches/008-call-rec-flag-secure/README.md +++ b/vendor/sunfish-a16/patches/008-call-rec-flag-secure/README.md @@ -10,9 +10,11 @@ python3 vendor/sunfish-a16/patches/008-call-rec-flag-secure/apply_008_call_rec_f - **Call recording**: EXTENDROM `er.sh` F_CALLREC / AXP GOLDEN (`extendrom_call_recording`). steadfasterX EXTENDROM. -- **FLAG_SECURE**: AOSP `Settings.Secure.DISABLE_SECURE_WINDOWS` already - wired in `WindowManagerService` on A16; DO preference - `allow_flag_secure_override` writes that key. +- **FLAG_SECURE**: AOSP `Settings.Secure.DISABLE_SECURE_WINDOWS` + DO + preference `allow_flag_secure_override`. Stock WMS only applies the + setting when `ro.debuggable=1`; we remove that gate via + `apply_wms_disable_secure_debuggable_gate.py` so ship images keep + `ro.debuggable=0` while the toggle still works. ## Touched paths @@ -24,9 +26,15 @@ python3 vendor/sunfish-a16/patches/008-call-rec-flag-secure/apply_008_call_rec_f | Settings controllers | `…/ER_CallRec*.java`, `…/FlagSecureOverride*.java` | | Settings DO XML + strings | `res/xml/development_settings.xml`, `res/values/strings.xml` | | Dashboard | `DevelopmentSettingsDashboardFragment.java` | -| Capture path | stock WMS `disable_secure_windows` (no extra WM patch) | +| Capture path | WMS `updateDisableSecureWindows()` — **no** `ro.debuggable` gate | +| WMS apply | `apply_wms_disable_secure_debuggable_gate.py` | + +```bash +python3 vendor/sunfish-a16/patches/008-call-rec-flag-secure/apply_wms_disable_secure_debuggable_gate.py +``` Backups: `/srv/rom/artifacts/008-call-rec-flag-secure/bak-snapshots/` -Marker: `SUNFISH_A16_008_CALL_REC_FLAG_SECURE` +Markers: `SUNFISH_A16_008_CALL_REC_FLAG_SECURE`, +`SUNFISH_A16_008_WMS_DISABLE_SECURE_NO_DEBUGGABLE_GATE` See `docs/008-call-rec-flag-secure-runbook.md`. diff --git a/vendor/sunfish-a16/patches/008-call-rec-flag-secure/apply_008_call_rec_flag_secure.py b/vendor/sunfish-a16/patches/008-call-rec-flag-secure/apply_008_call_rec_flag_secure.py index 3c02503..b971ecb 100644 --- a/vendor/sunfish-a16/patches/008-call-rec-flag-secure/apply_008_call_rec_flag_secure.py +++ b/vendor/sunfish-a16/patches/008-call-rec-flag-secure/apply_008_call_rec_flag_secure.py @@ -5,16 +5,18 @@ Call recording (AXP GOLDEN / EXTENDROM F_CALLREC): - Settings.Secure.ER_ALLOW_ANY_CALL_REC = \"extendrom_call_recording\" - DO switch + Dialer CallRecorder.canRecordInCurrentCountry early-return -FLAG_SECURE (AOSP A16 already implements WM path): +FLAG_SECURE (AOSP A16 WM path + project WMS gate removal): - DO switch writes Settings.Secure.DISABLE_SECURE_WINDOWS - (\"disable_secure_windows\"). WindowManagerService.updateDisableSecureWindows() - already honours it on debuggable builds (LAB userdebug). + (\"disable_secure_windows\"). +- Also run apply_wms_disable_secure_debuggable_gate.py so WMS honours the + setting with ro.debuggable=0 (stock AOSP required debuggable). Attribution: EXTENDROM (steadfasterX) for call-rec; AOSP DISABLE_SECURE_WINDOWS -for capture; sunfish-a16 DO wiring. +for capture; sunfish-a16 DO + WMS gate wiring. Run on rom-dev01: python3 vendor/sunfish-a16/patches/008-call-rec-flag-secure/apply_008_call_rec_flag_secure.py + python3 vendor/sunfish-a16/patches/008-call-rec-flag-secure/apply_wms_disable_secure_debuggable_gate.py """ from __future__ import annotations @@ -125,8 +127,9 @@ public class ER_CallRecInfo extends DeveloperOptionsPreferenceController FLAG_SECURE_CTRL = """/* * sunfish-a16-rom ({marker}): Developer Options gate for AOSP - * Settings.Secure.DISABLE_SECURE_WINDOWS (WindowManagerService already - * honours this on debuggable builds). + * Settings.Secure.DISABLE_SECURE_WINDOWS. Pair with + * apply_wms_disable_secure_debuggable_gate.py so WMS honours the setting + * when ro.debuggable=0. */ package com.android.settings.development; @@ -406,8 +409,8 @@ def patch_strings() -> None: Secure window screenshots Allow screenshots of secure windows - When enabled, apps that set FLAG_SECURE can still be captured by the system screenshot / screen record paths (debuggable builds). Weakens app privacy. - Writes Settings.Secure.disable_secure_windows. On userdebug/eng, WindowManager treats FLAG_SECURE windows as capturable. Default OFF restores stock secure-window behaviour. + When enabled, apps that set FLAG_SECURE can still be captured by the system screenshot / screen record paths. Weakens app privacy. Does not change ro.debuggable. + Writes Settings.Secure.disable_secure_windows. WindowManager treats FLAG_SECURE windows as capturable while this is ON (project build; ro.debuggable stays 0). Default OFF restores stock secure-window behaviour. """ text = text.replace("", add + "", 1) path.write_text(text) @@ -458,6 +461,17 @@ def verify_dialer_config() -> None: print("Dialer config.xml: call_recording_audio_source=4 (OK)") +def apply_wms_gate() -> None: + """Invoke sibling script that drops the ro.debuggable gate in WMS.""" + import subprocess + import sys + + sibling = Path(__file__).resolve().parent / "apply_wms_disable_secure_debuggable_gate.py" + r = subprocess.run([sys.executable, str(sibling)], check=False) + if r.returncode != 0: + raise SystemExit(f"WMS disable-secure gate apply failed: {r.returncode}") + + def main() -> None: if not TREE.is_dir(): raise SystemExit(f"LOS tree missing: {TREE}") @@ -475,6 +489,7 @@ def main() -> None: patch_development_xml() patch_dashboard() verify_dialer_config() + apply_wms_gate() print("done:", MARKER) diff --git a/vendor/sunfish-a16/patches/008-call-rec-flag-secure/apply_wms_disable_secure_debuggable_gate.py b/vendor/sunfish-a16/patches/008-call-rec-flag-secure/apply_wms_disable_secure_debuggable_gate.py new file mode 100644 index 0000000..f90b4e5 --- /dev/null +++ b/vendor/sunfish-a16/patches/008-call-rec-flag-secure/apply_wms_disable_secure_debuggable_gate.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 +"""Remove AOSP ro.debuggable gate on Settings.Secure.DISABLE_SECURE_WINDOWS. + +LOS 23.2 / A16 WindowManagerService.updateDisableSecureWindows() returns early +unless SystemProperties.getBoolean(\"ro.debuggable\") is true. That blocks the +Developer Options toggle on builds that keep ro.debuggable=0 (including this +project's LAB image labelled userdebug). + +This patch removes ONLY that gate. Behaviour: + disable_secure_windows=0 → stock FLAG_SECURE (mDisableSecureWindows=false) + disable_secure_windows=1 → mDisableSecureWindows=true; isSecureLocked()/Task.isSecure() + honour the override (no second debuggable check elsewhere) + +Does NOT change ro.debuggable, Build.IS_DEBUGGABLE, ViewServer, or screen-share +protections (DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS). + +Audit (LOS23 frameworks/base, 2026-09-18): sole gate is updateDisableSecureWindows(); +WindowState.isSecureLocked / Task.isSecure only call getDisableSecureWindows(). + +Run on rom-dev01: + python3 vendor/sunfish-a16/patches/008-call-rec-flag-secure/\\ + apply_wms_disable_secure_debuggable_gate.py +""" +from __future__ import annotations + +import shutil +from pathlib import Path + +TREE = Path("/srv/rom/src/lineage") +MARKER = "SUNFISH_A16_008_WMS_DISABLE_SECURE_NO_DEBUGGABLE_GATE" +BAK_ROOT = Path("/srv/rom/artifacts/008-call-rec-flag-secure/bak-snapshots") +WMS = ( + TREE + / "frameworks/base/services/core/java/com/android/server/wm/" + "WindowManagerService.java" +) + +OLD = """ void updateDisableSecureWindows() { + if (!SystemProperties.getBoolean(SYSTEM_DEBUGGABLE, false)) { + return; + } + + boolean disableSecureWindows; +""" + +NEW = f""" void updateDisableSecureWindows() {{ + // {MARKER}: honour Settings.Secure.DISABLE_SECURE_WINDOWS even when + // ro.debuggable=0. Stock AOSP gated this on SYSTEM_DEBUGGABLE; ship + // builds keep debuggable off and use the Secure setting alone. + boolean disableSecureWindows; +""" + + +def backup(path: Path) -> None: + BAK_ROOT.mkdir(parents=True, exist_ok=True) + dest = BAK_ROOT / path.name + if not dest.exists(): + shutil.copy2(path, dest) + print(f"backup -> {dest}") + + +def main() -> int: + if not WMS.is_file(): + print(f"ERROR: missing {WMS}") + return 2 + text = WMS.read_text() + if MARKER in text: + print(f"already applied: {WMS}") + return 0 + if OLD not in text: + print("ERROR: expected updateDisableSecureWindows debuggable gate not found") + print("(tree already diverged — inspect manually)") + return 3 + backup(WMS) + WMS.write_text(text.replace(OLD, NEW, 1)) + print(f"applied -> {WMS}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/vendor/sunfish-a16/patches/009-axp-los23-port/ConnectivityCheckPreferenceController.java b/vendor/sunfish-a16/patches/009-axp-los23-port/ConnectivityCheckPreferenceController.java new file mode 100644 index 0000000..8db4f9b --- /dev/null +++ b/vendor/sunfish-a16/patches/009-axp-los23-port/ConnectivityCheckPreferenceController.java @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Attribute: AXP GOLDEN ConnectivityCheckPreferenceController (Settings.apk), + * cloned for LOS 23.2 without axp.os / captiveportal.axpos.org endpoints. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + */ +package com.android.settings.network; + +import android.content.ContentResolver; +import android.content.Context; +import android.provider.Settings; + +import androidx.preference.ListPreference; +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.core.BasePreferenceController; +import com.android.settings.core.PreferenceControllerMixin; +import com.android.settingslib.RestrictedLockUtils; +import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; +import com.android.settingslib.RestrictedLockUtilsInternal; +import com.android.settingslib.core.lifecycle.events.OnResume; + +import android.os.UserHandle; +import android.os.UserManager; + +/** Internet connectivity check provider list (captive portal URLs). */ +public class ConnectivityCheckPreferenceController extends BasePreferenceController + implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener, OnResume { + + private static final String KEY = "connectivity_check_settings"; + + private static final int DISABLED = 0; + private static final int AMAZON = 1; + private static final int CLOUDFLARE = 2; + private static final int GOOGLE = 3; + private static final int HUAWEI = 4; + private static final int KUKETZ = 5; + private static final int MICROSOFT = 6; + private static final int OPENSUSE = 7; + private static final int UBUNTU = 8; + + private ListPreference mConnectivityPreference; + + public ConnectivityCheckPreferenceController(Context context) { + super(context, KEY); + } + + @Override + public int getAvailabilityStatus() { + return isDisabledByAdmin() ? DISABLED_FOR_USER : AVAILABLE; + } + + @Override + public String getPreferenceKey() { + return KEY; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + ListPreference pref = new ListPreference(screen.getContext()); + pref.setKey(KEY); + pref.setOrder(30); + pref.setIcon(R.drawable.ic_settings_language); + pref.setTitle(R.string.connectivity_check_title); + pref.setSummary(R.string.connectivity_check_summary); + pref.setEntries(R.array.connectivity_check_entries); + pref.setEntryValues(R.array.connectivity_check_values); + pref.setOnPreferenceChangeListener(this); + if (mConnectivityPreference == null) { + screen.addPreference(pref); + mConnectivityPreference = pref; + } + super.displayPreference(screen); + updatePreferenceState(); + } + + private void updatePreferenceState() { + if (mConnectivityPreference == null) { + return; + } + ContentResolver cr = mContext.getContentResolver(); + int mode = Settings.Global.getInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, 1); + if (mode == 0) { + mConnectivityPreference.setValueIndex(DISABLED); + return; + } + String http = Settings.Global.getString(cr, Settings.Global.CAPTIVE_PORTAL_HTTP_URL); + int idx = GOOGLE; + if ("http://fireoscaptiveportal.com/generate_204".equals(http)) { + idx = AMAZON; + } else if ("http://cp.cloudflare.com".equals(http)) { + idx = CLOUDFLARE; + } else if ("http://connectivitycheck.gstatic.com/generate_204".equals(http)) { + idx = GOOGLE; + } else if ("http://connectivitycheck.platform.hicloud.com/generate_204".equals(http)) { + idx = HUAWEI; + } else if ("http://captiveportal.kuketz.de".equals(http)) { + idx = KUKETZ; + } else if ("http://edge-http.microsoft.com/captiveportal/generate_204".equals(http)) { + idx = MICROSOFT; + } else if ("http://conncheck.opensuse.org".equals(http)) { + idx = OPENSUSE; + } else if ("http://connectivity-check.ubuntu.com".equals(http)) { + idx = UBUNTU; + } + mConnectivityPreference.setValueIndex(idx); + } + + private void setCaptivePortalURLs(ContentResolver cr, int value) { + final String httpKey = Settings.Global.CAPTIVE_PORTAL_HTTP_URL; + final String httpsKey = Settings.Global.CAPTIVE_PORTAL_HTTPS_URL; + final String fallbackKey = Settings.Global.CAPTIVE_PORTAL_FALLBACK_URL; + final String otherKey = Settings.Global.CAPTIVE_PORTAL_OTHER_FALLBACK_URLS; + final String modeKey = Settings.Global.CAPTIVE_PORTAL_MODE; + + String http; + String https; + String fallback; + String other; + int mode = 1; + + switch (value) { + case DISABLED: + // Match GOLDEN: write Google URLs then mode=0 + http = "http://connectivitycheck.gstatic.com/generate_204"; + https = "https://www.google.com/generate_204"; + fallback = "http://www.google.com/gen_204"; + other = "http://play.googleapis.com/generate_204"; + mode = 0; + break; + case AMAZON: + http = "http://fireoscaptiveportal.com/generate_204"; + https = "https://fireoscaptiveportal.com/generate_204"; + fallback = http; + other = http; + break; + case CLOUDFLARE: + http = "http://cp.cloudflare.com"; + https = "https://cp.cloudflare.com"; + fallback = http; + other = http; + break; + case HUAWEI: + http = "http://connectivitycheck.platform.hicloud.com/generate_204"; + https = "https://connectivitycheck.platform.hicloud.com/generate_204"; + fallback = http; + other = http; + break; + case KUKETZ: + http = "http://captiveportal.kuketz.de"; + https = "https://captiveportal.kuketz.de"; + fallback = http; + other = http; + break; + case MICROSOFT: + http = "http://edge-http.microsoft.com/captiveportal/generate_204"; + https = http; + fallback = http; + other = http; + break; + case OPENSUSE: + http = "http://conncheck.opensuse.org"; + https = "https://conncheck.opensuse.org"; + fallback = http; + other = http; + break; + case UBUNTU: + http = "http://connectivity-check.ubuntu.com"; + https = "https://connectivity-check.ubuntu.com"; + fallback = http; + other = http; + break; + case GOOGLE: + default: + http = "http://connectivitycheck.gstatic.com/generate_204"; + https = "https://www.google.com/generate_204"; + fallback = "http://www.google.com/gen_204"; + other = "http://play.googleapis.com/generate_204"; + break; + } + + Settings.Global.putString(cr, httpKey, http); + Settings.Global.putString(cr, httpsKey, https); + Settings.Global.putString(cr, fallbackKey, fallback); + Settings.Global.putString(cr, otherKey, other); + Settings.Global.putInt(cr, modeKey, mode); + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + if (KEY.equals(preference.getKey())) { + setCaptivePortalURLs( + mContext.getContentResolver(), Integer.parseInt((String) newValue)); + return true; + } + return false; + } + + @Override + public void onResume() { + updatePreferenceState(); + if (mConnectivityPreference != null && mConnectivityPreference.getValue() != null) { + setCaptivePortalURLs( + mContext.getContentResolver(), + Integer.parseInt(mConnectivityPreference.getValue())); + } + } + + private EnforcedAdmin getEnforcedAdmin() { + return RestrictedLockUtilsInternal.checkIfRestrictionEnforced( + mContext, UserManager.DISALLOW_CONFIG_PRIVATE_DNS, UserHandle.myUserId()); + } + + private boolean isDisabledByAdmin() { + return getEnforcedAdmin() != null; + } +} diff --git a/vendor/sunfish-a16/patches/009-axp-los23-port/README.md b/vendor/sunfish-a16/patches/009-axp-los23-port/README.md new file mode 100644 index 0000000..143ffb5 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-axp-los23-port/README.md @@ -0,0 +1,58 @@ +# 009 AXP LOS23 port — patch / packaging README + +**Track**: Magisk AXP resurrection on LOS 23.2 sunfish (`AXP_Resurection`). +**Not ship**: KernelSU / SusFS (`007` standby / optional recycle only). + +## Apply order (host tree under `/srv/rom/src/lineage/`) + +1. **Google stack** — `vendor/sunfish-a16/gms.mk` + `Android.mk` (microG, GSF, + Phonesky). Host APKs: `/srv/rom/prebuilts/{microg,phonesky}/` (never Git). +2. **Signature spoofing** — `vendor/sunfish-a16/patches/005-sigspoof/` + (`apply_005_sigspoof.py`). Attribute: LOS restricted spoofing + AXP/005. +3. **Call recording unlock** — `vendor/sunfish-a16/patches/008-call-rec-flag-secure/` + (`extendrom_call_recording`). Attribute: EXTENDROM `F_CALLREC`. +4. **Magisk preroot** — EXTENDROM-class boot/`init_boot` patch using Magisk APK + from `/srv/rom/prebuilts/magisk/` (see `docs/009-magisk-preinstall-runbook.md`). + Stub: `vendor/sunfish-a16/magisk.mk`. Attribute: Magisk upstream + sfX + extendrom Magisk patcher. **Host tree currently has no `vendor/extendrom`** + — must vendor minimal patcher or checkout extendrom before first Magisk bacon. +5. **Bundled apps** — `/srv/rom/prebuilts/axp-apps/` + `apps.mk` (Aurora, + Droidify, Fossify Gallery). Symlink APKs into `vendor/sunfish-a16/prebuilt/`. +6. **Private DNS presets** — `apply_009_private_dns_providers.py` (GOLDEN list). +7. **Internet connectivity check** — `apply_009_connectivity_check.py` (GOLDEN + list **minus** AXP.OS / `axpos.org`). +8. **Disable for user apps** — `apply_009_disable_user_apps.py` (SPA gate). +9. **Userspace hardening / signing** — staged: see `signing/README.md`, + `hardening/README.md` (US-S4-1 OpenSSH trim), and + `docs/009-hardening-signing-checklist.md` (US-S1 keys → US-S2 wire → + US-S3 AVB → US-S4+ harden). Bootloader lock = wont. +10. **Kernel hardening** — LOS23 `msm-4.14` + map in + `docs/009-kernel-hardening-map.md` (FR-017). Stage 1: + `vendor/sunfish-a16/patches/009-kernel-hardening/apply_stage1.sh` + (AXP Graphene/AH allowlist). Priority: AXP → LOS → Iodé → optional + Graphene; no Divest hunt; no extra location lockdown. + +## Product includes + +Wire Magisk-resurrection product from `vendor/sunfish-a16/` into +`lineage_sunfish` (same pattern as `004`/`005`). Keep Phonesky priv-app path. +**No FakeStore. No KernelSU product packages.** + +## Deferred + +- Banking Gate E / Island validation (owner future). +- Localization AXP-vs-LOS compare (`docs/009-localization-axp-vs-los.md` stub). + +## Host paths (rom-dev01) + +| What | Path | +|------|------| +| Magisk APK | `/srv/rom/prebuilts/magisk/Magisk-v30.7.apk` | +| EXTENDROM Magisk patcher | `/srv/rom/references/extendrom/config/magisk/` | +| Kernel source | `/srv/rom/src/lineage/kernel/google/msm-4.14` | +| Product include (gms) | `device/google/sunfish/lineage_sunfish.mk` → `vendor/sunfish-a16/gms.mk` | +| Vanilla baseline | `/srv/rom/artifacts/003-vanilla/20260914-lineage-23.2-sunfish/` | +| Optional KSU boots | `/srv/rom/artifacts/007-kernelsu/` (non-ship) | + +**Gap:** `vendor/extendrom` is **not** checked out in the lineage tree yet. +Magisk bacon blocked on T011 (symlink/checkout + PREROOT or slim wire). diff --git a/vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_connectivity_check.py b/vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_connectivity_check.py new file mode 100644 index 0000000..dc81e05 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_connectivity_check.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python3 +"""009: port GOLDEN Internet connectivity check UI (sans axp.os). + +Copies ConnectivityCheckPreferenceController, adds string/array resources, +wires into NetworkDashboardFragment. Idempotent. +""" +from __future__ import annotations + +import pathlib +import shutil +import sys + +MARKER = "sunfish-a16-009-connectivity-check" + +ENTRIES = """ + + Disabled + Amazon Fire OS (US) + Cloudflare (US) + Google (US) [default] + Huawei (CN) + Kuketz (DE) + Microsoft Edge (US) + openSUSE (DE) + Ubuntu (UK) + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + +""".format( + m=MARKER +) + +STRINGS = f""" + Internet connectivity check + HTTP endpoints to use for performing internet connectivity checks. +""" + + +def ensure_arrays(path: pathlib.Path) -> None: + text = path.read_text(encoding="utf-8") + if "connectivity_check_entries" in text: + return + if "" not in text: + raise SystemExit(f"FAIL: no in {path}") + path.write_text(text.replace("", ENTRIES + "", 1), encoding="utf-8") + + +def ensure_strings(path: pathlib.Path) -> None: + text = path.read_text(encoding="utf-8") + if "connectivity_check_title" in text: + return + path.write_text(text.replace("", STRINGS + "", 1), encoding="utf-8") + + +def wire_fragment(path: pathlib.Path) -> None: + text = path.read_text(encoding="utf-8") + if "ConnectivityCheckPreferenceController" in text: + return + if "controllers.add(privateDnsPreferenceController);" not in text: + raise SystemExit("FAIL: expected PrivateDns add site missing") + text = text.replace( + "controllers.add(privateDnsPreferenceController);", + "controllers.add(privateDnsPreferenceController);\n" + f" // {MARKER}\n" + " controllers.add(new ConnectivityCheckPreferenceController(context));", + 1, + ) + path.write_text(text, encoding="utf-8") + + +def main() -> int: + root = pathlib.Path(sys.argv[1] if len(sys.argv) > 1 else ".") + here = pathlib.Path(__file__).resolve().parent + src = here / "ConnectivityCheckPreferenceController.java" + dst = root / ( + "packages/apps/Settings/src/com/android/settings/network/" + "ConnectivityCheckPreferenceController.java" + ) + arrays = root / "packages/apps/Settings/res/values/arrays.xml" + # Prefer cm_strings for non-translated titles; fall back to strings.xml end + cm = root / "packages/apps/Settings/res/values/cm_strings.xml" + frag = root / ( + "packages/apps/Settings/src/com/android/settings/network/NetworkDashboardFragment.java" + ) + for p in (src, arrays, cm, frag): + if not p.is_file(): + print(f"FAIL: missing {p}", file=sys.stderr) + return 1 + + if dst.is_file() and MARKER.split("-")[0] and "sans axp" in dst.read_text(encoding="utf-8"): + # already copied + pass + else: + dst.parent.mkdir(parents=True, exist_ok=True) + shutil.copy2(src, dst) + + ensure_arrays(arrays) + ensure_strings(cm) + wire_fragment(frag) + print(f"OK: connectivity check wired -> {dst}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_disable_user_apps.py b/vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_disable_user_apps.py new file mode 100644 index 0000000..2b21daa --- /dev/null +++ b/vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_disable_user_apps.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +"""009: allow classic Disable for non-system apps (A16 Archive era). + +LOS AppDisableButton returns null for !isSystemApp. Graphene/AXP-class UX +keeps Disable usable for user apps. Attribute: AXP/owner preference over Archive. +Idempotent. +""" +from __future__ import annotations + +import pathlib +import sys + +MARKER = "sunfish-a16-009-disable-user-apps" + +CANDIDATES = [ + pathlib.Path("packages/apps/Settings/src/com/android/settings/spa/app/appinfo/AppDisableButton.kt"), +] + + +def main() -> int: + root = pathlib.Path(sys.argv[1] if len(sys.argv) > 1 else ".") + path = None + for rel in CANDIDATES: + p = root / rel + if p.is_file(): + path = p + break + if path is None: + print("FAIL: AppDisableButton.kt not found", file=sys.stderr) + return 1 + + text = path.read_text(encoding="utf-8") + if MARKER in text: + print(f"OK: already applied ({path})") + return 0 + + old = " if (!app.isSystemApp) return null\n" + if old not in text: + print("FAIL: expected isSystemApp gate not found", file=sys.stderr) + return 2 + + new = ( + f" // {MARKER}: allow Disable for user apps (not only system)\n" + f" // if (!app.isSystemApp) return null\n" + ) + path.write_text(text.replace(old, new, 1), encoding="utf-8") + print(f"OK: patched {path}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_drop_jelly_gallery2.py b/vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_drop_jelly_gallery2.py new file mode 100644 index 0000000..242bbff --- /dev/null +++ b/vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_drop_jelly_gallery2.py @@ -0,0 +1,161 @@ +#!/usr/bin/env python3 +"""US-S4-2 — drop Lineage Jelly + Gallery2 to match AXP.OS PRO product surface. + +Oracle: AXP.OS-22.2-20260324-PRO-sunfish.zip product/app has neither Jelly nor +Gallery2 (browser stub + FossifyGallery_FD live on system_ext). See +docs/009-axp-pro-product-apps-20260324.md. + +FossifyGallery already declares LOCAL_OVERRIDES_PACKAGES := Gallery Gallery2 +Glimpse, but Gallery2 still landed in product/app on the 162840Z ship — same +class of failure as OpenSSH filter-out. Patch the Lineage PRODUCT_PACKAGES +add sites and add belt-and-suspenders stubs. + +Usage (from ANDROID_BUILD_TOP): + python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_drop_jelly_gallery2.py +""" + +from __future__ import annotations + +import os +import re +import sys +from pathlib import Path + +MARKER = "sunfish-a16-009-uss4-2-jelly-gallery2" + +# Common Lineage shapes (tolerant). +JELLY_BLOCK = re.compile( + r"# Browser\n" + r"PRODUCT_PACKAGES \+= \\\n" + r" Jelly\n", + re.MULTILINE, +) + +# ExactCalculator + Jelly list (common Lineage shape) → keep ExactCalculator only. +JELLY_WITH_CALC = re.compile( + r"(PRODUCT_PACKAGES \+= \\\n" + r" ExactCalculator) \\\n" + r" Jelly\n", + re.MULTILINE, +) + +GALLERY2_IN_LIST = re.compile( + r"( DeskClock \\\n)" + r" Gallery2 \\\n", + re.MULTILINE, +) + + +def patch_text(text: str, path: Path) -> tuple[str, list[str]]: + notes: list[str] = [] + bad = f"# Jelly stripped ({MARKER})" in text or f"# Gallery2 stripped ({MARKER})" in text + has_pkg = bool(re.search(r"(?m)^[ \t]*Jelly( \\)?$", text)) or bool( + re.search(r"(?m)^[ \t]*Gallery2( \\)?$", text) + ) + if MARKER in text and not bad and not has_pkg: + notes.append("already") + return text, notes + + orig = text + + text, n = JELLY_BLOCK.subn( + f"# Browser (Jelly) omitted ({MARKER}) — AXP PRO uses noDefaultBrowserWebView\n", + text, + count=1, + ) + if n: + notes.append(f"jelly_block={n}") + + text, n = JELLY_WITH_CALC.subn( + rf"\1\n", + text, + count=1, + ) + if n: + notes.append(f"jelly_calc={n}") + + text, n = GALLERY2_IN_LIST.subn( + rf"\1", + text, + count=1, + ) + if n: + notes.append(f"gallery2_list={n}") + + # Remove leftover broken comment-only continuations from older applicator. + text2 = re.sub( + r"^[ \t]*# (?:Jelly|Gallery2) stripped \(" + re.escape(MARKER) + r"\)\n", + "", + text, + flags=re.MULTILINE, + ) + if text2 != text: + notes.append("scrub_bad_comments") + text = text2 + + if text == orig and not notes: + return orig, notes + if MARKER not in text and text != orig: + text = f"# {MARKER}\n" + text + return text, notes + + +def main() -> int: + top = Path(os.environ.get("ANDROID_BUILD_TOP", ".")).resolve() + candidates = [ + top / "vendor/lineage/config/common.mk", + top / "vendor/lineage/config/common_mobile.mk", + top / "vendor/lineage/config/common_full.mk", + top / "vendor/lineage/config/telephony.mk", + top / "build/make/target/product/handheld_product.mk", + top / "build/make/target/product/handheld_system.mk", + top / "build/make/target/product/generic_system.mk", + ] + # Also scan device trees that often force Gallery2 + for p in (top / "device").rglob("*.mk") if (top / "device").is_dir() else []: + if p.name in ("device.mk", "lineage.mk", "lineage_sunfish.mk", "aosp_sunfish.mk"): + candidates.append(p) + + touched = 0 + still_present = [] + for mk in candidates: + if not mk.is_file(): + continue + text = mk.read_text(encoding="utf-8", errors="replace") + if "Jelly" not in text and "Gallery2" not in text: + continue + # Ignore mention-only in comments/docs after a clean strip. + has_pkg = bool(re.search(r"(?m)^[ \t]*Jelly( \\)?$", text)) or bool( + re.search(r"(?m)^[ \t]*Gallery2( \\)?$", text) + ) + bad = f"# Jelly stripped ({MARKER})" in text or f"# Gallery2 stripped ({MARKER})" in text + if not has_pkg and not bad: + continue + new, notes = patch_text(text, mk) + if notes == ["already"]: + print(f"OK: already applied ({mk})") + touched += 1 + continue + if new == text: + print(f"WARN: {mk} mentions Jelly/Gallery2 but no pattern matched: {notes}") + still_present.append(str(mk)) + continue + mk.write_text(new, encoding="utf-8") + print(f"OK: patched {mk} ({', '.join(notes)})") + touched += 1 + + if still_present: + print( + "FAIL: Jelly/Gallery2 still present, patterns missed: " + + ", ".join(still_present), + file=sys.stderr, + ) + return 1 + if touched == 0: + print("OK: Jelly/Gallery2 already absent from PRODUCT_PACKAGES sites") + return 0 + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_drop_openssh_packages.py b/vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_drop_openssh_packages.py new file mode 100644 index 0000000..19e549f --- /dev/null +++ b/vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_drop_openssh_packages.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python3 +"""US-S4-1 — strip OpenSSH/rsync/procmem packages from Lineage common.mk. + +AXP.OS PRO sunfish (A15) product/system lack sshd/ssh/rsync/procmem binaries but +still ship init.openssh.rc. PRODUCT_PACKAGES filter-out via inherit-product did +*not* remove them from the 20261002T125259Z ship image — patch the source block +instead (same place Lineage adds them). + +Keeps PRODUCT_COPY_FILES for init.openssh.rc (AXP surface). + +Usage: + python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_drop_openssh_packages.py +""" + +from __future__ import annotations + +import os +import re +import sys +from pathlib import Path + +MARKER = "sunfish-a16-009-uss4-openssh" + +OPENSSH_PACKAGES = re.compile( + r"# Openssh\n" + r"PRODUCT_PACKAGES \+= \\\n" + r"(?: \S+ \\\n)*" + r" start-ssh\n", + re.MULTILINE, +) + +RSYNC_PACKAGES = re.compile( + r"# rsync\n" + r"PRODUCT_PACKAGES \+= \\\n" + r" rsync\n", + re.MULTILINE, +) + +PROCMEM_DEBUG = re.compile( + r"# These packages are excluded from user builds\n" + r"PRODUCT_PACKAGES_DEBUG \+= \\\n" + r" procmem\n" + r"\n" + r"ifneq \(\$\(TARGET_BUILD_VARIANT\),user\)\n" + r"PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST \+= \\\n" + r" system/bin/procmem\n" + r"endif\n", + re.MULTILINE, +) + + +def main() -> int: + top = Path(os.environ.get("ANDROID_BUILD_TOP", ".")).resolve() + mk = top / "vendor/lineage/config/common.mk" + if not mk.is_file(): + print(f"FAIL: missing {mk}", file=sys.stderr) + return 1 + text = mk.read_text() + if MARKER in text: + print(f"OK: already applied ({mk})") + return 0 + + orig = text + text, n1 = OPENSSH_PACKAGES.subn( + f"# Openssh packages stripped ({MARKER}) — keep init.openssh.rc below\n", + text, + count=1, + ) + text, n2 = RSYNC_PACKAGES.subn( + f"# rsync stripped ({MARKER})\n", + text, + count=1, + ) + text, n3 = PROCMEM_DEBUG.subn( + f"# procmem debug package stripped ({MARKER})\n", + text, + count=1, + ) + if n1 != 1 or n2 != 1: + print( + f"FAIL: Openssh/rsync block match n1={n1} n2={n2} n3={n3}", + file=sys.stderr, + ) + return 1 + # procmem block optional if layout drifted + if n3 == 0: + print("WARN: procmem debug block not matched (layout drift)") + + if "init.openssh.rc" not in text: + print("FAIL: init.openssh.rc COPY_FILES missing after patch", file=sys.stderr) + return 1 + + mk.write_text(text) + print(f"OK: patched {mk} (openssh_pkgs={n1} rsync={n2} procmem={n3})") + return 0 if text != orig else 1 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_private_dns_providers.py b/vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_private_dns_providers.py new file mode 100644 index 0000000..4c21187 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_private_dns_providers.py @@ -0,0 +1,498 @@ +#!/usr/bin/env python3 +"""009: expand Private DNS presets to AXP GOLDEN list (no axp.os). + +Clones GOLDEN Settings radios/hostnames into LOS PrivateDnsModeDialogPreference +(which already has a Cloudflare stub). Idempotent via marker comments. +""" +from __future__ import annotations + +import pathlib +import re +import sys + +MARKER = "sunfish-a16-009-private-dns" + +# key, UI label, DoT hostname — GOLDEN order (cloudflare hostname = security.*) +PROVIDERS = [ + ("adguard", "AdGuard (CT)", "dns.adguard.com"), + ("appliedprivacy", "AppliedPrivacy (AT)", "dot1.applied-privacy.net"), + ("cira", "CIRA (CA)", "protected.canadianshield.cira.ca"), + ("controld", "Control D (CA)", "p2.freedns.controld.com"), + ("cleanbrowsing", "CleanBrowsing (US)", "security-filter-dns.cleanbrowsing.org"), + ("cznic", "CZ.NIC (CZ)", "odvr.nic.cz"), + ("cloudflare", "Cloudflare (US)", "security.cloudflare-dns.com"), + ("dnszero", "DNS0 (FR)", "zero.dns0.eu"), + ("dnssb", "DNS.SB (DE)", "dot.sb"), + ("google", "Google (US)", "dns.google"), + ("mullvad", "Mullvad (SE)", "base.dns.mullvad.net"), + ("quadnine", "Quad9 (CH)", "dns.quad9.net"), + ("restena", "Restena (LU)", "kaitain.restena.lu"), + ("switch", "SWITCH (CH)", "dns.switch.ch"), + ("uncensoreddns", "UncensoredDNS (DK)", "anycast.censurfridns.dk"), +] + + +def patch_layout(path: pathlib.Path) -> bool: + text = path.read_text(encoding="utf-8") + if MARKER in text: + return False + # Insert provider radios after off, before opportunistic (keep provider+hostname) + includes = [] + for key, _, _ in PROVIDERS: + includes.append( + f' \n' + f' \n' + ) + block = "".join(includes) + # Remove ALL existing cloudflare includes (re-added once via PROVIDERS) + text2 = re.sub( + r'\s*(?:\s*)?\s*', + "\n", + text, + flags=re.DOTALL, + ) + text2 = re.sub( + r'\s*\s*', + "\n", + text2, + ) + needle = ( + ' ' + ) + if needle not in text2: + # alternate formatting + needle = 'android:id="@+id/private_dns_mode_opportunistic"' + idx = text2.find(needle) + if idx < 0: + raise SystemExit(f"FAIL: opportunistic radio not in {path}") + # find start of include element + start = text2.rfind(" bool: + text = path.read_text(encoding="utf-8") + if MARKER in text and "private_dns_hostname_quadnine" in text: + return False + # Replace/extend cloudflare hostname to GOLDEN security.cloudflare-dns.com + text = re.sub( + r']*>.*?', + '' + "security.cloudflare-dns.com", + text, + count=1, + ) + text = re.sub( + r']*>.*?', + '' + "Cloudflare (US)", + text, + count=1, + ) + lines = [f" "] + for key, label, host in PROVIDERS: + if key == "cloudflare": + continue # already present + lines.append( + f' {label}' + ) + lines.append( + f' {host}' + ) + insert = "\n".join(lines) + "\n" + if "" not in text: + raise SystemExit(f"FAIL: no in {path}") + text = text.replace("", insert + "", 1) + path.write_text(text, encoding="utf-8") + return True + + +def write_preference_java(path: pathlib.Path) -> None: + """Rewrite PrivateDnsModeDialogPreference with data-driven GOLDEN presets.""" + # Keep copyright / package; replace body after class declaration via full file. + providers_java = ",\n".join( + f' new Provider("{key}", R.id.private_dns_mode_{key}, ' + f"R.string.private_dns_mode_{key}, R.string.private_dns_hostname_{key})" + for key, _, _ in PROVIDERS + ) + # Assign custom mode ints starting at 4 (LOS cloudflare used 4) + mode_consts = "\n".join( + f" private static final int PRIVATE_DNS_MODE_{key.upper()} = {4 + i};" + for i, (key, _, _) in enumerate(PROVIDERS) + ) + map_puts = "\n".join( + f" PRIVATE_DNS_MAP.put(PRIVATE_DNS_MODE_{key.upper()}, " + f"R.id.private_dns_mode_{key});" + for key, _, _ in PROVIDERS + ) + content = f'''/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.settings.network; + +import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OFF; +import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OPPORTUNISTIC; +import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME; + +import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; + +import android.app.Dialog; +import android.app.settings.SettingsEnums; +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.net.ConnectivitySettingsManager; +import android.os.UserHandle; +import android.os.UserManager; +import android.text.Editable; +import android.text.TextWatcher; +import android.text.method.LinkMovementMethod; +import android.util.AttributeSet; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.RadioButton; +import android.widget.RadioGroup; +import android.widget.TextView; + +import androidx.annotation.VisibleForTesting; +import androidx.appcompat.app.AlertDialog; +import androidx.preference.PreferenceViewHolder; + +import com.android.settings.R; +import com.android.settings.overlay.FeatureFactory; +import com.android.settings.utils.AnnotationSpan; +import com.android.settingslib.CustomDialogPreferenceCompat; +import com.android.settingslib.HelpUtils; +import com.android.settingslib.RestrictedLockUtils; +import com.android.settingslib.RestrictedLockUtilsInternal; + +import com.google.android.material.textfield.TextInputLayout; +import com.google.common.net.InternetDomainName; + +import java.util.HashMap; +import java.util.Map; + +/** + * Dialog to set the Private DNS. + * {MARKER}: AXP GOLDEN provider presets (hostnames from GOLDEN Settings.apk). + */ +public class PrivateDnsModeDialogPreference extends CustomDialogPreferenceCompat implements + RadioGroup.OnCheckedChangeListener, TextWatcher {{ + + public static final String ANNOTATION_URL = "url"; + + private static final String TAG = "PrivateDnsModeDialog"; + private static final Map PRIVATE_DNS_MAP; + +{mode_consts} + + private static final Provider[] PROVIDERS = new Provider[] {{ +{providers_java} + }}; + + static {{ + PRIVATE_DNS_MAP = new HashMap<>(); + PRIVATE_DNS_MAP.put(PRIVATE_DNS_MODE_OFF, R.id.private_dns_mode_off); + PRIVATE_DNS_MAP.put(PRIVATE_DNS_MODE_OPPORTUNISTIC, R.id.private_dns_mode_opportunistic); + PRIVATE_DNS_MAP.put(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, R.id.private_dns_mode_provider); +{map_puts} + }} + + private static final class Provider {{ + final String key; + final int radioId; + final int labelRes; + final int hostnameRes; + + Provider(String key, int radioId, int labelRes, int hostnameRes) {{ + this.key = key; + this.radioId = radioId; + this.labelRes = labelRes; + this.hostnameRes = hostnameRes; + }} + }} + + @VisibleForTesting + TextInputLayout mHostnameLayout; + @VisibleForTesting + EditText mHostnameText; + @VisibleForTesting + RadioGroup mRadioGroup; + @VisibleForTesting + int mMode; + + public PrivateDnsModeDialogPreference(Context context) {{ + super(context); + }} + + public PrivateDnsModeDialogPreference(Context context, AttributeSet attrs) {{ + super(context, attrs); + }} + + public PrivateDnsModeDialogPreference(Context context, AttributeSet attrs, int defStyleAttr) {{ + super(context, attrs, defStyleAttr); + }} + + public PrivateDnsModeDialogPreference(Context context, AttributeSet attrs, int defStyleAttr, + int defStyleRes) {{ + super(context, attrs, defStyleAttr, defStyleRes); + }} + + private final AnnotationSpan.LinkInfo mUrlLinkInfo = new AnnotationSpan.LinkInfo( + ANNOTATION_URL, (widget) -> {{ + final Context context = widget.getContext(); + final Intent intent = HelpUtils.getHelpIntent(context, + context.getString(R.string.help_uri_private_dns), + context.getClass().getName()); + if (intent != null) {{ + try {{ + widget.startActivityForResult(intent, 0); + }} catch (ActivityNotFoundException e) {{ + Log.w(TAG, "Activity was not found for intent, " + intent.toString()); + }} + }} + }}); + + private static int modeForRadioId(int radioId) {{ + if (radioId == R.id.private_dns_mode_off) return PRIVATE_DNS_MODE_OFF; + if (radioId == R.id.private_dns_mode_opportunistic) return PRIVATE_DNS_MODE_OPPORTUNISTIC; + if (radioId == R.id.private_dns_mode_provider) return PRIVATE_DNS_MODE_PROVIDER_HOSTNAME; + for (int i = 0; i < PROVIDERS.length; i++) {{ + if (PROVIDERS[i].radioId == radioId) {{ + return 4 + i; + }} + }} + return PRIVATE_DNS_MODE_OPPORTUNISTIC; + }} + + private static Provider providerForMode(int mode) {{ + int idx = mode - 4; + if (idx >= 0 && idx < PROVIDERS.length) {{ + return PROVIDERS[idx]; + }} + return null; + }} + + @Override + public void onBindViewHolder(PreferenceViewHolder holder) {{ + super.onBindViewHolder(holder); + if (isDisabledByAdmin()) {{ + holder.itemView.setEnabled(true); + }} + setSaveButtonListener(); + }} + + @Override + protected void onBindDialogView(View view) {{ + final Context context = getContext(); + mMode = ConnectivitySettingsManager.getPrivateDnsMode(context); + if (mMode == PRIVATE_DNS_MODE_PROVIDER_HOSTNAME) {{ + final String host = ConnectivitySettingsManager.getPrivateDnsHostname(context); + for (int i = 0; i < PROVIDERS.length; i++) {{ + if (host != null && host.equals(context.getString(PROVIDERS[i].hostnameRes))) {{ + mMode = 4 + i; + break; + }} + }} + }} + mRadioGroup = view.findViewById(R.id.private_dns_radio_group); + mRadioGroup.check(PRIVATE_DNS_MAP.getOrDefault(mMode, R.id.private_dns_mode_opportunistic)); + mRadioGroup.setOnCheckedChangeListener(this); + + final RadioButton offRadioButton = view.findViewById(R.id.private_dns_mode_off); + offRadioButton.setText(com.android.settingslib.R.string.private_dns_mode_off); + for (Provider p : PROVIDERS) {{ + final RadioButton rb = view.findViewById(p.radioId); + if (rb != null) {{ + rb.setText(p.labelRes); + }} + }} + final RadioButton opportunisticRadioButton = + view.findViewById(R.id.private_dns_mode_opportunistic); + opportunisticRadioButton.setText( + com.android.settingslib.R.string.private_dns_mode_opportunistic); + final RadioButton providerRadioButton = view.findViewById(R.id.private_dns_mode_provider); + providerRadioButton.setText(com.android.settingslib.R.string.private_dns_mode_provider); + + mHostnameLayout = view.findViewById(R.id.private_dns_mode_provider_hostname_layout); + mHostnameText = view.findViewById(R.id.private_dns_mode_provider_hostname); + if (mHostnameText != null) {{ + mHostnameText.setText(ConnectivitySettingsManager.getPrivateDnsHostname(context)); + mHostnameText.addTextChangedListener(this); + }} + + final TextView helpTextView = view.findViewById(R.id.private_dns_help_info); + helpTextView.setMovementMethod(LinkMovementMethod.getInstance()); + final Intent helpIntent = HelpUtils.getHelpIntent(context, + context.getString(R.string.help_uri_private_dns), + context.getClass().getName()); + final AnnotationSpan.LinkInfo linkInfo = new AnnotationSpan.LinkInfo(context, + ANNOTATION_URL, helpIntent); + if (linkInfo.isActionable()) {{ + helpTextView.setText(AnnotationSpan.linkify( + context.getText(R.string.private_dns_help_message), linkInfo)); + }} else {{ + helpTextView.setText(""); + }} + + updateDialogInfo(); + }} + + @Override + public void onCheckedChanged(RadioGroup group, int checkedId) {{ + mMode = modeForRadioId(checkedId); + updateDialogInfo(); + }} + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) {{ + }} + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) {{ + }} + + @Override + public void afterTextChanged(Editable s) {{ + updateDialogInfo(); + }} + + @Override + public void performClick() {{ + EnforcedAdmin enforcedAdmin = getEnforcedAdmin(); + if (enforcedAdmin == null) {{ + super.performClick(); + }} else {{ + RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getContext(), enforcedAdmin); + }} + }} + + private EnforcedAdmin getEnforcedAdmin() {{ + return RestrictedLockUtilsInternal.checkIfRestrictionEnforced( + getContext(), UserManager.DISALLOW_CONFIG_PRIVATE_DNS, UserHandle.myUserId()); + }} + + private boolean isDisabledByAdmin() {{ + return getEnforcedAdmin() != null; + }} + + private void updateDialogInfo() {{ + final boolean modeProvider = PRIVATE_DNS_MODE_PROVIDER_HOSTNAME == mMode; + if (mHostnameLayout != null) {{ + mHostnameLayout.setEnabled(modeProvider); + mHostnameLayout.setErrorEnabled(false); + }} + }} + + private void setSaveButtonListener() {{ + View.OnClickListener onClickListener = v -> doSaveButton(); + DialogInterface.OnShowListener onShowListener = dialog -> {{ + if (dialog == null) {{ + Log.e(TAG, "The DialogInterface is null!"); + return; + }} + Button saveButton = ((AlertDialog) dialog).getButton(DialogInterface.BUTTON_POSITIVE); + if (saveButton == null) {{ + Log.e(TAG, "Can't get the save button!"); + return; + }} + saveButton.setOnClickListener(onClickListener); + }}; + setOnShowListener(onShowListener); + }} + + @VisibleForTesting + void doSaveButton() {{ + Context context = getContext(); + int modeToSet = mMode; + Provider preset = providerForMode(mMode); + if (preset != null) {{ + ConnectivitySettingsManager.setPrivateDnsHostname(context, + context.getString(preset.hostnameRes)); + modeToSet = PRIVATE_DNS_MODE_PROVIDER_HOSTNAME; + }} else if (mMode == PRIVATE_DNS_MODE_PROVIDER_HOSTNAME) {{ + if (mHostnameLayout == null || mHostnameText == null) {{ + Log.e(TAG, "Can't find hostname resources!"); + return; + }} + if (mHostnameText.getText().isEmpty()) {{ + mHostnameLayout.setError(context.getString(R.string.private_dns_field_require)); + Log.w(TAG, "The hostname is empty!"); + return; + }} + if (!InternetDomainName.isValid(mHostnameText.getText().toString())) {{ + mHostnameLayout.setError(context.getString(R.string.private_dns_hostname_invalid)); + Log.w(TAG, "The hostname is invalid!"); + return; + }} + ConnectivitySettingsManager.setPrivateDnsHostname(context, + mHostnameText.getText().toString()); + }} + + ConnectivitySettingsManager.setPrivateDnsMode(context, modeToSet); + FeatureFactory.getFeatureFactory().getMetricsFeatureProvider() + .action(context, SettingsEnums.ACTION_PRIVATE_DNS_MODE, modeToSet); + Dialog dialog = getDialog(); + if (dialog != null) {{ + dialog.dismiss(); + }} + }} +}} +''' + # Fix f-string doubled braces - we used {{ for literal braces in the template + # But MARKER was intended as comment - replace + content = content.replace("{MARKER}", MARKER) + path.write_text(content, encoding="utf-8") + + +def main() -> int: + root = pathlib.Path(sys.argv[1] if len(sys.argv) > 1 else ".") + layout = root / "packages/apps/Settings/res/layout/private_dns_mode_dialog.xml" + cm = root / "packages/apps/Settings/res/values/cm_strings.xml" + java = root / ( + "packages/apps/Settings/src/com/android/settings/network/" + "PrivateDnsModeDialogPreference.java" + ) + for p in (layout, cm, java): + if not p.is_file(): + print(f"FAIL: missing {p}", file=sys.stderr) + return 1 + + if MARKER in java.read_text(encoding="utf-8") and "quadnine" in layout.read_text( + encoding="utf-8" + ): + print("OK: private DNS already applied") + return 0 + + patch_layout(layout) + patch_cm_strings(cm) + write_preference_java(java) + print(f"OK: private DNS providers applied ({len(PROVIDERS)} presets)") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_unofficial_build_id.py b/vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_unofficial_build_id.py new file mode 100644 index 0000000..1315079 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_unofficial_build_id.py @@ -0,0 +1,41 @@ +# Apply early TARGET_UNOFFICIAL_BUILD_ID to device product makefile. +# Must run before breakfast: inherit-product of vendor/lineage parses version.mk +# immediately; vendor/extra inherit-product is too late. +# +# Usage (on rom-dev01 tree): +# python3 vendor/sunfish-a16/patches/009-axp-los23-port/apply_009_unofficial_build_id.py + +from __future__ import annotations + +from pathlib import Path +import os +import sys + +MARKER = "TARGET_UNOFFICIAL_BUILD_ID := AXP-Resurection-Pro" +NEEDLE = "# Inherit some common Lineage stuff.\n" +INSERT = ( + "# sunfish-a16: must precede vendor/lineage version.mk (via inherit below)\n" + f"{MARKER}\n\n" +) + + +def main() -> int: + top = Path(os.environ.get("ANDROID_BUILD_TOP", ".")).resolve() + mk = top / "device/google/sunfish/lineage_sunfish.mk" + if not mk.is_file(): + print(f"FAIL: missing {mk}", file=sys.stderr) + return 1 + text = mk.read_text() + if MARKER in text: + print(f"OK: already applied ({mk})") + return 0 + if NEEDLE not in text: + print(f"FAIL: needle not found in {mk}", file=sys.stderr) + return 1 + mk.write_text(text.replace(NEEDLE, INSERT + NEEDLE, 1)) + print(f"OK: patched {mk}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/vendor/sunfish-a16/patches/009-axp-los23-port/hardening/README.md b/vendor/sunfish-a16/patches/009-axp-los23-port/hardening/README.md new file mode 100644 index 0000000..59803f8 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-axp-los23-port/hardening/README.md @@ -0,0 +1,67 @@ +# US-S4-1 — drop Lineage product OpenSSH binaries / rsync / procmem + +**Track**: AXP Resurection Pro (Magisk), unlocked sunfish. +**Not**: slim variant; not bootloader lock; not Yama (kernel). + +## AXP reference (mandatory) + +Oracle: `AXP.OS-22.2-20260324-PRO-sunfish.zip` → `payload.bin` → `product.img` +(+ GOLDEN `ro.lineage.version=22.2-2026.003-sunfish-pro`, Android 15): + +| Path | AXP PRO (A15) | +|------|----------------| +| `/bin/sshd`, `ssh`, `scp`, `sftp`, `ssh-keygen`, `start-ssh` | **absent** | +| `/bin/rsync`, `/bin/procmem` | **absent** | +| `/etc/init/init.openssh.rc` | **present** (`mkdir /data/ssh*`) | + +### Was this an A16 Lineage add? + +**No.** Lineage `vendor/lineage/config/common.mk` has shipped the Openssh +block since 2012; lineage-20 / 21 / 22.2 all still include it. AXP PRO on +A15 therefore **actively omitted** the binaries (same lineage generation +still lists them upstream). Public `AXP.OS/android_vendor_lineage` +`upstream_*` mirrors keep the Lineage Openssh block — use the **PRO zip / +GOLDEN**, not that mirror, as product oracle. + +## What we ship + +Match AXP PRO product surface by stripping Lineage `common.mk` package +adds (see `apply_009_drop_openssh_packages.py`) — a plain +`PRODUCT_PACKAGES := $(filter-out …)` inherit did **not** drop `sshd` from +ship `20261002T125259Z`: + +- Remove packages: `scp`, `sftp`, `ssh`, `sshd`, `sshd_config`, `ssh-keygen`, + `start-ssh`, `rsync`, `procmem` (debug) +- **Keep** `init.openssh.rc` copy (AXP has it) + +Remote shell / file transfer on this track remains **adb** (+ Magisk); the +rc only creates `/data/ssh*` and does not start `sshd` without the binary. + +## Verify (LAB after flash) + +```text +adb shell ls /product/bin/sshd # expect: No such file +adb shell ls /product/bin/rsync # expect: No such file +adb shell ls /product/etc/init/init.openssh.rc # expect: present (AXP) +adb shell pidof magiskd # expect: non-empty +``` + +## US-S4-2 — drop Jelly + Gallery2 (AXP PRO product) + +**Oracle**: same PRO zip — `product/app` has **no** Jelly / Gallery2; +`system_ext` ships Fossify + `noDefaultBrowserWebView`. Inventory: +`docs/009-axp-pro-product-apps-20260324.md`. + +- `apply_009_drop_jelly_gallery2.py` — remove Lineage `PRODUCT_PACKAGES` + adds for Jelly / Gallery2 +- `NoLineageJelly` uninstallable override module (AXP stub class) +- Keep `FossifyGallery` (already overrides Gallery/Gallery2/Glimpse) + +LAB after flash: no `/product/app/Jelly`, no `/product/app/Gallery2`, +FossifyGallery present. + +## Out of scope + +- `CONFIG_SECURITY_YAMA` (kernel / US-S5 — **done** on `162840Z`) +- Switching lunch to `user` (US-S6) +- NeoLauncher / Aosmium (wont / exception) diff --git a/vendor/sunfish-a16/patches/009-axp-los23-port/signing/README.md b/vendor/sunfish-a16/patches/009-axp-los23-port/signing/README.md new file mode 100644 index 0000000..94e34e6 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-axp-los23-port/signing/README.md @@ -0,0 +1,89 @@ +# 009 signing / AVB (userspace Gate G) + +Clone AXP/GOLDEN posture: **`user` + `release-keys`**, device **unlocked** +(`orange`). Not IOdes locked-bootloader. + +Full checklist: `docs/009-hardening-signing-checklist.md`. + +## Stages + +| Stage | What | +|-------|------| +| US-S1 | Generate keys → `/srv/rom/secrets/android-certs/` | +| US-S2 | Wire `PRODUCT_DEFAULT_DEV_CERTIFICATE` into bacon | +| US-S3 | Project AVB key (`AVB_CUSTOM_KEY_PATH`); decide `WITH_AVB` | +| US-S4+ | Userspace harden / CVE — separate patches | + +## Generate (rom-dev01 only) + +```bash +# from synced repo copy or laptop scp of scripts/ +sudo -u android-build bash /srv/rom/src/lineage/vendor/sunfish-a16/../../../../\ + # prefer: +bash /path/to/AXP_Resurection/scripts/009-generate-release-keys.sh +``` + +Script writes under `/srv/rom/secrets/android-certs/` when that parent is +writable, otherwise `$HOME/.android-certs` (Lineage default). On rom-dev01 +(2026-09-29) secrets/ is root-owned without group write → keys live in +`/home/android-build/.android-certs/`. Refuses overwrite. Reminds about +encrypted offline backup before first signed ship bacon. + +## Wire (US-S2 — after keys exist) + +In the bacon environment (not committed secrets): + +```bash +export PRODUCT_DEFAULT_DEV_CERTIFICATE=$HOME/.android-certs/releasekey +# after root relocate: /srv/rom/secrets/android-certs/releasekey +# lunch lineage_sunfish-userdebug # first signed build +# later: lineage_sunfish-user +``` + +`009-bacon-axp-stage1-combo4.sh` auto-exports when `$HOME/.android-certs/releasekey.pk8` exists. +## AVB (US-S3) + +Default tree falls back to AOSP `external/avb/test/data/testkey_rsa2048.pem` +(and LAB has been observed with `testkey_rsa4096`) plus +`BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS += --flags 3` unless `WITH_AVB=true` +(`device/google/sunfish/BoardConfigLineage.mk`). + +Project key generation is in `009-generate-release-keys.sh` +(`avb.pem` + `avb_pkmd.bin`). **Wire in tree** (soong-safe path), not only env: + +`vendor/sunfish-a16/BoardConfig.mk` sets `BOARD_AVB_KEY_PATH` / +`BOARD_AVB_ALGORITHM=SHA256_RSA4096` when `certs/avb.pem` exists. Keep +`WITH_AVB` unset → vbmeta **flags 3** = +`HASHTREE_DISABLED|VERIFICATION_DISABLED` (libavb) → Magisk preroot on +unlocked/orange. That is **signing infrastructure**, not runtime AVB harden. + +Validate after bacon (script fail-closed) on **target_files `IMAGES/`** (the +OTA pair). Do not use `out/target/product/$DEVICE/{boot,vbmeta}.img` alone — +those make images can be stock and disagree with the Magisk payload in the zip. +Gates: pubkey sha1 == `avb_pkmd.bin` (not AOSP testkey); flags 3; +`verify_image --key` + `--expected_chain_partition vbmeta_system:1:avb_pkmd.bin`; +`magiskboot cpio test` ≠ 0; LAB stays `flash.locked=0` + Magisk works. + +**OEM unlocking:** leave enabled as a best-effort escape hatch (not a recovery +guarantee). Do not relock the bootloader on this Magisk track. + +## Branding + +`TARGET_UNOFFICIAL_BUILD_ID=AXP-Resurection-Pro` is set at the **top** of +`device/google/sunfish/lineage_sunfish.mk` (before inheriting +`vendor/lineage` → `version.mk`). Helper: +`apply_009_unofficial_build_id.py`. **Pro** = full Magisk resurrection track +(not a future slim/minimal variant). Mirrors GOLDEN’s `…-sunfish-pro` / +releasetype `PRO` intent without patching `vendor/lineage/config/version.mk`. + +`branding.mk` adds `ro.axp.resurection.track=pro`. Ship scripts also publish +`AXP-Resurection-Pro---sunfish.zip` as a hardlink/copy of the +Lineage `bacon` zip (no rebuild solely to rename). + + +## Never + +- Commit `*.pk8`, private `*.pem`, or pass files. +- Relock LAB/GOLDEN as a project requirement (OEM unlock-always-on does not + make Magisk+relock safe). +- Flash old `kh-cve` / `kh-full` zips from 2026-09-18. diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/BUILD-FIXES.md b/vendor/sunfish-a16/patches/009-kernel-hardening/BUILD-FIXES.md new file mode 100644 index 0000000..e6c6a4a --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/BUILD-FIXES.md @@ -0,0 +1,22 @@ +# Stage1 build fixes (FR-017) + +> **2026-09-26 audit:** The FORTIFY BUG stubs below are a historical link +> workaround, **not an accepted fix**. The latest ksync FORTIFY image fails +> boot according to the owner. Clang exclusion in Kconfig references an +> undefined CC_IS_CLANG symbol. See +> [the FORTIFY audit](../../../../docs/009-fortify-boot-audit-20260926.md) +> before reusing this workaround. + +Applied on host `msm-4.14` when Stage1 Graphene/AH hit compile/link issues: + +1. **slab 0014 misfuzz** — Graphene patch targeted `slab_equal_or_root`; + fuzz applied to `is_root_cache`. Reverted `is_root_cache` to `return true`. + LOS already has `slab_equal_or_root` → `s == p`. +2. **FORTIFY + Clang LTO (historical, invalid as ship fix)** — + `CONFIG_FORTIFY_SOURCE=y` caused modpost undefined `__read_overflow*` / + `__write_overflow` in qcacld/techpack. Temporary `BUG()` stubs were + added in `lib/string.c` to force a link; LAB then failed to boot. + **Do not reuse.** Real work: Clang FORTIFY port — see + `docs/009-fortify-clang-port.md` and `docs/009-fortify-boot-audit-20260926.md`. + +See `docs/009-kernel-hardening-map.md`. diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/README.md b/vendor/sunfish-a16/patches/009-kernel-hardening/README.md new file mode 100644 index 0000000..40fbbc8 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/README.md @@ -0,0 +1,83 @@ +# 009 kernel hardening Stage 1 (FR-017) + +**Source**: AXP `kernel_patches` @ `df3cab2155b3` (GrapheneOS / AndroidHardening +series in Divest-era layout). +**Base**: LOS `kernel/google/msm-4.14` @ `28f9290ae067` (`4.14.357-openela`). +**Map**: `docs/009-kernel-hardening-map.md`. + +## Files + +| File | Role | +|------|------| +| `stage1.list` | Ordered allowlist (30 patches) | +| `apply_stage1.sh` | Applies list onto a kernel tree | + +## Host usage (`rom-dev01`) + +```bash +# dry-run +bash vendor/sunfish-a16/patches/009-kernel-hardening/apply_stage1.sh \ + /srv/rom/src/lineage/kernel/google/msm-4.14 --dry-run + +# apply (dirties the lineage kernel checkout) +bash vendor/sunfish-a16/patches/009-kernel-hardening/apply_stage1.sh \ + /srv/rom/src/lineage/kernel/google/msm-4.14 +``` + +Optional: `AXP_KERNEL_PATCHES=/path/to/kernel_patches`. + +After apply, flip `sunfish_defconfig` options that the new Kconfig allows +(at least `CONFIG_FORTIFY_SOURCE=y`); see map `KH-CFG`. + +## Boot-OK pack (2026-09-28 LAB) — prefer for Magisk bacon + +Stage1 Graphene alone historically hung at the Google logo on LOS23/Clang. +The pack that boots with Magisk-track `boot-make` is **combo4 + Clang FORTIFY** +(no Stage1 mega-pack): + +```bash +# on a reset msm-4.14 @ 28f9290ae067: +bash vendor/sunfish-a16/patches/009-kernel-hardening/apply_combo4_fortify.sh \ + /path/to/msm-4.14 +``` + +That applies `fortify-clang/` (incl. nested `__underlying_strlen` fix) + +driver bounds + defconfig: +`FORTIFY_SOURCE`, `INIT_ON_*`, `SECURITY_DMESG_RESTRICT`, +`SLAB_FREELIST_HARDENED`. Bacon entrypoint: +`scripts/009-bacon-axp-combo4-fortify.sh`. + +## Stage1 + combo4 (full bacon, Wi‑Fi coherent) + +```bash +# reset msm-4.14 @ 28f9290ae067, then: +bash vendor/sunfish-a16/patches/009-kernel-hardening/apply_stage1_combo4.sh \ + /path/to/msm-4.14 +# bacon: scripts/009-bacon-axp-stage1-combo4.sh +``` + +Order: Stage1 (30) → slab BUILD-FIXES if needed → combo4+FORTIFY. +Ship via **sideload of the zip** (matching vendor/`wlan.ko`). Do not flash +only the new boot onto an old slot. + +**LAB accepted 2026-09-29:** see `docs/009-gate-g-kernel-attribution.md`. + +## GPS / location (FR-018 — do not regress) + +Owner wants **precise, fast GPS** (stock LOS behaviour). **Never** apply AXP +location lockdown, SUPL/IMSI stripping that hurts TTFF, or extra location +caps vs LOS 23.2. Stage1 list, `cve-strict.list`, and denylist must stay +free of location-lockdown series (`KH-LOC` = skip). If a future CVE hunk +touches GNSS/GPS paths only for a real security fix, keep LOS-equivalent +behaviour and document; do not “harden location” as a side goal. + +## Not in Stage 1 alone + +- CVE mega — now staged via `apply_stage1_combo4_cve.sh` + `cve-strict.list` + (~503 AXP allowlist from 2026-09-18 strict pass; `cve-denylist.txt` skipped). + Bacon: `scripts/009-bacon-axp-stage1-combo4-cve.sh` (test-keys; after + boot-OK Stage1 pack). **Do not** flash `20260918*-axp-kh-cve/full`. +- LinuxIncrementals +- Failed probe patches (port later) +- Location lockdown (FR-018) +- Iodé kernel (no sunfish 4.14 fork found) diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/apply_combo4_fortify.sh b/vendor/sunfish-a16/patches/009-kernel-hardening/apply_combo4_fortify.sh new file mode 100755 index 0000000..860f6dd --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/apply_combo4_fortify.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# Apply the LAB-verified combo4 + Clang FORTIFY pack onto a clean msm-4.14 tree. +# +# Boot-OK on sunfish LAB 2026-09-28 (ksync combo4-fortify-fix). This is NOT +# the full Graphene Stage1 pack (Stage1 alone historically hung at Google logo). +# +# Usage: apply_combo4_fortify.sh +# Expects a virgin / reset tree (apply_fortify_clang.py is not idempotent). +set -e + +K=${1:?kernel tree} +HERE=$(cd "$(dirname "$0")" && pwd) +FC="$HERE/fortify-clang" + +test -d "$K/include/linux" +test -f "$FC/apply_fortify_clang.py" +test -f "$FC/0001-driver-bounds-rtac-fils.patch" + +python3 "$FC/apply_fortify_clang.py" "$K" +patch -p1 --forward --batch -d "$K" < "$FC/0001-driver-bounds-rtac-fils.patch" + +DEF="$K/arch/arm64/configs/sunfish_defconfig" +test -f "$DEF" + +# Drop any prior toggles we manage, then enable the boot-OK set. +for k in \ + FORTIFY_SOURCE \ + INIT_ON_ALLOC_DEFAULT_ON \ + INIT_ON_FREE_DEFAULT_ON \ + SECURITY_DMESG_RESTRICT \ + SLAB_FREELIST_HARDENED \ + SLAB_HARDENED +do + sed -i "/CONFIG_${k}/d" "$DEF" +done + +# Keep KernelSU off on this Magisk track. +sed -i '/CONFIG_KSU/d' "$DEF" +echo '# CONFIG_KSU is not set' >> "$DEF" + +for k in \ + CONFIG_FORTIFY_SOURCE \ + CONFIG_INIT_ON_ALLOC_DEFAULT_ON \ + CONFIG_INIT_ON_FREE_DEFAULT_ON \ + CONFIG_SECURITY_DMESG_RESTRICT \ + CONFIG_SLAB_FREELIST_HARDENED +do + echo "${k}=y" >> "$DEF" +done + +echo "OK: combo4+FORTIFY applied on $K" diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/apply_cve_strict.sh b/vendor/sunfish-a16/patches/009-kernel-hardening/apply_cve_strict.sh new file mode 100644 index 0000000..ee5a7f2 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/apply_cve_strict.sh @@ -0,0 +1,164 @@ +#!/usr/bin/env bash +# Apply AXP CVE allowlist onto msm-4.14 (after Stage1+combo4). +# Source: AXP kernel_patches + cve_checker strict list / bisect slices. +# +# Safety (2026-09-29 review): +# - Default: ABORT on first patch failure (no continue-with-partial-tree). +# - Keep *.rej / *.orig under CVE_REJECT_DIR (do not silently delete). +# - Treat large line-offsets / fuzz as WARN or FAIL (mis-apply risk). +# - Set CVE_STRICT_CONTINUE=1 only for forensic runs (explicit). +set -euo pipefail + +KP="${AXP_KERNEL_PATCHES:-/srv/rom/references/axp/kernel_patches}" +KERNEL_DIR="${1:-/srv/rom/src/lineage/kernel/google/msm-4.14}" +HERE="$(cd "$(dirname "$0")" && pwd)" +LIST="${CVE_STRICT_LIST:-$HERE/cve-strict.list}" +DENY="${CVE_DENYLIST:-$HERE/cve-denylist.txt}" +LOG_DIR="${CVE_APPLY_LOG_DIR:-/srv/rom/artifacts/009-axp-los23-port/cve-stage}" +CONTINUE="${CVE_STRICT_CONTINUE:-0}" +# Reject apply if GNU patch reports fuzz >= this (0 = disable fuzz fail) +MAX_FUZZ="${CVE_MAX_FUZZ:-1}" +# Reject if any hunk offset abs(lines) >= this (0 = disable) +MAX_ABS_OFFSET="${CVE_MAX_ABS_OFFSET:-200}" +DRY_RUN=0 +[[ "${2:-}" == "--dry-run" ]] && DRY_RUN=1 + +if [[ ! -d "$KERNEL_DIR/include/linux" ]]; then + echo "error: kernel dir missing: $KERNEL_DIR" >&2 + exit 1 +fi +if [[ ! -d "$KP" ]]; then + echo "error: AXP kernel_patches missing: $KP" >&2 + exit 1 +fi +if [[ ! -f "$LIST" ]]; then + echo "error: list missing: $LIST" >&2 + exit 1 +fi + +mkdir -p "$LOG_DIR" +STAMP=$(date -u +%Y%m%dT%H%M%SZ) +LOG="$LOG_DIR/apply-cve-strict-${STAMP}.log" +FAIL_LIST="$LOG_DIR/apply-cve-strict-${STAMP}.fail.txt" +REJECT_DIR="${CVE_REJECT_DIR:-$LOG_DIR/rejects-${STAMP}}" +mkdir -p "$REJECT_DIR" +: >"$FAIL_LIST" + +declare -A DENY_MAP=() +if [[ -f "$DENY" ]]; then + while IFS= read -r d || [[ -n "$d" ]]; do + [[ -z "$d" || "$d" =~ ^# ]] && continue + if [[ "$d" == *"/kernel_patches/"* ]]; then + DENY_MAP["${d##*/kernel_patches/}"]=1 + else + DENY_MAP["$d"]=1 + fi + done <"$DENY" +fi + +ok=0 +fail=0 +skip=0 +miss=0 +quality_fail=0 + +echo "=== CVE strict apply kernel=$KERNEL_DIR dry_run=$DRY_RUN continue=$CONTINUE max_fuzz=$MAX_FUZZ max_abs_offset=$MAX_ABS_OFFSET ===" | tee "$LOG" + +while IFS= read -r rel || [[ -n "$rel" ]]; do + [[ -z "$rel" || "$rel" =~ ^# ]] && continue + if [[ -n "${DENY_MAP[$rel]:-}" ]]; then + echo "SKIP_DENY $rel" | tee -a "$LOG" + skip=$((skip + 1)) + continue + fi + p="$KP/$rel" + if [[ ! -f "$p" ]]; then + echo "MISS $rel" | tee -a "$LOG" + miss=$((miss + 1)) + echo "$rel" >>"$FAIL_LIST" + if [[ "$CONTINUE" != "1" ]]; then + echo "error: missing patch (abort)" >&2 + exit 1 + fi + continue + fi + + args=(-p1 --batch -d "$KERNEL_DIR" --forward --no-backup-if-mismatch) + if [[ "$DRY_RUN" -eq 1 ]]; then + args+=(--dry-run) + fi + + patch_log=$(mktemp) + set +e + patch "${args[@]}" <"$p" >"$patch_log" 2>&1 + prc=$? + set -e + cat "$patch_log" >>"$LOG" + + # Quality: fuzz / large offsets even when exit 0 + fuzz_max=0 + abs_off_max=0 + eval "$(python3 -c ' +import re, sys +text = open(sys.argv[1], errors="replace").read() +fuzz = off = 0 +for m in re.finditer(r"with fuzz (\d+)", text): + fuzz = max(fuzz, int(m.group(1))) +for m in re.finditer(r"\(offset ([+-]?\d+) lines\)", text): + off = max(off, abs(int(m.group(1)))) +print(f"fuzz_max={fuzz}") +print(f"abs_off_max={off}") +' "$patch_log")" + rm -f "$patch_log" + + qbad=0 + if [[ "$MAX_FUZZ" -gt 0 && "$fuzz_max" -ge "$MAX_FUZZ" ]]; then + echo "QUALITY_FAIL fuzz=$fuzz_max>=$MAX_FUZZ $rel" | tee -a "$LOG" + qbad=1 + fi + if [[ "$MAX_ABS_OFFSET" -gt 0 && "$abs_off_max" -ge "$MAX_ABS_OFFSET" ]]; then + echo "QUALITY_FAIL abs_offset=$abs_off_max>=$MAX_ABS_OFFSET $rel" | tee -a "$LOG" + qbad=1 + fi + + if [[ "$prc" -eq 0 && "$qbad" -eq 0 ]]; then + echo "OK $rel (fuzz_max=$fuzz_max abs_off_max=$abs_off_max)" | tee -a "$LOG" + ok=$((ok + 1)) + continue + fi + + # Failure path: preserve rejects + echo "FAIL $rel patch_rc=$prc fuzz_max=$fuzz_max abs_off_max=$abs_off_max" | tee -a "$LOG" + echo "$rel" >>"$FAIL_LIST" + fail=$((fail + 1)) + [[ "$qbad" -eq 1 ]] && quality_fail=$((quality_fail + 1)) + + safe=$(echo "$rel" | tr '/' '_') + dest="$REJECT_DIR/$safe" + mkdir -p "$dest" + # move any rej/orig created under kernel tree + while IFS= read -r -d '' rej; do + mv "$rej" "$dest/" 2>/dev/null || cp -a "$rej" "$dest/" || true + done < <(find "$KERNEL_DIR" -name '*.rej' -print0 2>/dev/null) + while IFS= read -r -d '' orig; do + mv "$orig" "$dest/" 2>/dev/null || cp -a "$orig" "$dest/" || true + done < <(find "$KERNEL_DIR" -name '*.orig' -print0 2>/dev/null) + cp -a "$p" "$dest/patch" 2>/dev/null || true + echo "rejects_kept=$dest" | tee -a "$LOG" + + if [[ "$CONTINUE" != "1" ]]; then + echo "error: abort on FAIL (set CVE_STRICT_CONTINUE=1 to keep going)" >&2 + echo "CVE strict ABORT OK=$ok FAIL=$fail QUALITY_FAIL=$quality_fail SKIP_DENY=$skip MISS=$miss log=$LOG" | tee -a "$LOG" + exit 1 + fi +done <"$LIST" + +echo "CVE strict done OK=$ok FAIL=$fail QUALITY_FAIL=$quality_fail SKIP_DENY=$skip MISS=$miss dry_run=$DRY_RUN continue=$CONTINUE log=$LOG rejects=$REJECT_DIR" | tee -a "$LOG" + +if [[ "$fail" -gt 0 && "$CONTINUE" != "1" ]]; then + exit 1 +fi +if [[ "$ok" -eq 0 && "$DRY_RUN" -eq 0 ]]; then + echo "error: zero CVE patches applied" >&2 + exit 1 +fi diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/apply_stage1.sh b/vendor/sunfish-a16/patches/009-kernel-hardening/apply_stage1.sh new file mode 100755 index 0000000..a8b75b2 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/apply_stage1.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +# Apply FR-017 Stage 1 AXP Graphene/AH patches to LOS msm-4.14. +# Attribute: AXP kernel_patches (GrapheneOS / AndroidHardening series via Divest-era layout). +set -euo pipefail + +KP="${AXP_KERNEL_PATCHES:-/srv/rom/references/axp/kernel_patches}" +KERNEL_DIR="${1:-/srv/rom/src/lineage/kernel/google/msm-4.14}" +LIST="$(cd "$(dirname "$0")" && pwd)/stage1.list" +DRY_RUN=0 +if [[ "${2:-}" == "--dry-run" ]]; then + DRY_RUN=1 +fi + +if [[ ! -d "$KERNEL_DIR" ]]; then + echo "error: kernel dir missing: $KERNEL_DIR" >&2 + exit 1 +fi +if [[ ! -d "$KP" ]]; then + echo "error: AXP kernel_patches missing: $KP" >&2 + exit 1 +fi + +ok=0 +fail=0 +while IFS= read -r rel || [[ -n "$rel" ]]; do + [[ -z "$rel" || "$rel" =~ ^# ]] && continue + p="$KP/$rel" + if [[ ! -f "$p" ]]; then + echo "FAIL missing $rel" + fail=$((fail + 1)) + continue + fi + args=(-p1 --batch -d "$KERNEL_DIR") + if [[ "$DRY_RUN" -eq 1 ]]; then + args+=(--dry-run) + fi + if patch "${args[@]}" < "$p"; then + echo "OK $rel" + ok=$((ok + 1)) + else + echo "FAIL $rel" + fail=$((fail + 1)) + find "$KERNEL_DIR" -name '*.rej' -delete 2>/dev/null || true + find "$KERNEL_DIR" -name '*.orig' -delete 2>/dev/null || true + exit 1 + fi +done < "$LIST" + +echo "Stage1 done OK=$ok FAIL=$fail dry_run=$DRY_RUN" diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/apply_stage1_combo4.sh b/vendor/sunfish-a16/patches/009-kernel-hardening/apply_stage1_combo4.sh new file mode 100755 index 0000000..60f9444 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/apply_stage1_combo4.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# Stage1 Graphene/AH (30 patches) + combo4 Clang FORTIFY pack on a clean msm-4.14. +# +# Order: Stage1 first (virgin tree), then apply_combo4_fortify.sh (Clang POS + +# nested __underlying_strlen + driver bounds + combo4 defconfig). +# Expects reset tree @ 28f9290ae067 (apply_fortify_clang.py is not idempotent). +# +# Full bacon with this pack ships matching vendor modules (Wi-Fi). Boot-only +# flash onto an older vendor can break wlan CRC — prefer sideload of the zip. +set -e + +K=${1:?kernel tree} +HERE=$(cd "$(dirname "$0")" && pwd) + +test -d "$K/include/linux" +test -x "$HERE/apply_stage1.sh" || chmod +x "$HERE/apply_stage1.sh" +test -x "$HERE/apply_combo4_fortify.sh" || chmod +x "$HERE/apply_combo4_fortify.sh" + +bash "$HERE/apply_stage1.sh" "$K" + +# Historical Stage1 slab/0014 misfuzz: if is_root_cache was corrupted, restore. +python3 - <<'PY' "$K" +from pathlib import Path +import sys +p = Path(sys.argv[1]) / "mm/slab.h" +t = p.read_text() +bad = """static inline bool is_root_cache(struct kmem_cache *s) +{ +#ifdef CONFIG_SLAB_HARDENED +\treturn p == s; +#else +\treturn true; +#endif +}""" +good = """static inline bool is_root_cache(struct kmem_cache *s) +{ +\treturn true; +}""" +if bad in t: + p.write_text(t.replace(bad, good, 1)) + print("OK: reverted Stage1 slab/0014 misfuzz in is_root_cache") +else: + print("OK: is_root_cache looks unmisfuzzed (no BUILD-FIXES edit)") +PY + +bash "$HERE/apply_combo4_fortify.sh" "$K" +echo "OK: Stage1 + combo4+FORTIFY applied on $K" diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/apply_stage1_combo4_cve.sh b/vendor/sunfish-a16/patches/009-kernel-hardening/apply_stage1_combo4_cve.sh new file mode 100644 index 0000000..55008c1 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/apply_stage1_combo4_cve.sh @@ -0,0 +1,12 @@ +#!/bin/bash +# Stage1 + combo4+FORTIFY + AXP CVE strict allowlist on clean msm-4.14. +# Boot-OK baseline first (LAB 2026-09-29), then CVE mega that compiled 2026-09-18. +# FR-018: no location lockdown — keep GPS precise/fast (LOS defaults). +set -e +K=${1:?kernel tree} +HERE=$(cd "$(dirname "$0")" && pwd) + +test -d "$K/include/linux" +bash "$HERE/apply_stage1_combo4.sh" "$K" +bash "$HERE/apply_cve_strict.sh" "$K" +echo "OK: Stage1 + combo4+FORTIFY + CVE-strict applied on $K (no location lockdown)" diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/apply_uss5_1_defconfig.sh b/vendor/sunfish-a16/patches/009-kernel-hardening/apply_uss5_1_defconfig.sh new file mode 100755 index 0000000..e1e55cb --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/apply_uss5_1_defconfig.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# US-S5-1 — enable remaining Graphene/AXP-class defconfig knobs on msm-4.14. +# +# Oracle: AXP/Graphene kernel hardening expects Yama + slab freelist random +# (combo4 already ships SLAB_FREELIST_HARDENED). LOS sunfish_defconfig left both +# off; CONFIG_LSM already lists yama but SECURITY_YAMA was unset so the LSM +# never built. +# +# Does NOT apply high-offset CVE leftovers (nf_tables deliberately skipped) or +# CVE-2022-49980 (denylist until lock-scope port). +# +# Usage: apply_uss5_1_defconfig.sh +set -euo pipefail + +K=${1:?kernel tree} +DEF="$K/arch/arm64/configs/sunfish_defconfig" +test -f "$DEF" +test -f "$K/security/yama/Kconfig" + +for k in SECURITY_YAMA SLAB_FREELIST_RANDOM; do + sed -i "/CONFIG_${k}/d" "$DEF" + # drop "# CONFIG_FOO is not set" lines too (sed above only matches CONFIG_FOO=) + sed -i "/# CONFIG_${k} is not set/d" "$DEF" +done + +{ + echo "CONFIG_SECURITY_YAMA=y" + echo "CONFIG_SLAB_FREELIST_RANDOM=y" +} >> "$DEF" + +echo "OK: US-S5-1 defconfig (YAMA + SLAB_FREELIST_RANDOM) on $K" diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-49980-only.list b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-49980-only.list new file mode 100644 index 0000000..dd59fc1 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-49980-only.list @@ -0,0 +1 @@ +CVE-2022-49980/ANY/0001.patch diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1.list b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1.list new file mode 100644 index 0000000..e802d79 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1.list @@ -0,0 +1,215 @@ +0003-syzkaller-Misc/ANY/0008.patch +CVE-2015-7837/ANY/0001.patch +CVE-2016-3695/ANY/0001.patch +CVE-2017-5754/^4.19/0157.patch +CVE-2017-18232/4.14/0002.patch +CVE-2018-5897/ANY/0001.patch +CVE-2018-9415/ANY/0005.patch +CVE-2018-20855/^4.18/0001.patch +CVE-2019-3874/^5.1/0002.patch +CVE-2019-9444/ANY/0001.patch +CVE-2019-10520/ANY/0001.patch +CVE-2019-11191/^5.0/0001.patch +CVE-2019-12378/^5.1.5/0001.patch +CVE-2019-12455/^5.2/0001.patch +CVE-2019-12456/^5.1.5/0002.patch +CVE-2019-15291/4.14/0004.patch +CVE-2019-16921/^4.16/0001.patch +CVE-2019-18786/4.14/0002.patch +CVE-2019-19051/4.14/0008.patch +CVE-2019-19068/4.14/0002.patch +CVE-2019-19602/^5.4/0001.patch +CVE-2019-20908/^5.2/0001.patch +CVE-2020-0255/^5.6/0001.patch +CVE-2020-8832/^4.14/0001.patch +CVE-2020-15780/^5.8/0001.patch +CVE-2020-16119/^5.10/0002.patch +CVE-2020-BleedingToothExtras/^5.10/0001.patch +CVE-2021-3493/^5.10/0001.patch +CVE-2021-28039/^5.11/0001.patch +CVE-2021-28950/4.14/0002.patch +CVE-2021-29154/^5.12/0002.patch +CVE-2021-30337/4.14/0018.patch +CVE-2021-46912/^5.12/0001.patch +CVE-2021-46958/^5.12/0001.patch +CVE-2021-46999/^5.12/0001.patch +CVE-2021-47010/^5.12/0001.patch +CVE-2021-47058/^5.12/0001.patch +CVE-2021-47173/4.14/0003.patch +CVE-2021-47234/^5.13/0001.patch +CVE-2021-47266/^5.13/0001.patch +CVE-2021-47346/^5.13/0001.patch +CVE-2021-47430/^5.15/0001.patch +CVE-2021-47472/4.14/0003.patch +CVE-2021-47583/^5.15/0001.patch +CVE-2021-47616/^5.16/0001.patch +CVE-2021-47618/^5.16/0001.patch +CVE-2021-47636/ANY/0001.patch +CVE-2022-3061/^5.18/0001.patch +CVE-2022-3903/^6.0/0001.patch +CVE-2022-4382/^6.2/0001.patch +CVE-2022-21546/ANY/0001.patch +CVE-2022-27950/^5.16/0001.patch +CVE-2022-48674/^6.0/0001.patch +CVE-2022-48713/^5.17/0001.patch +CVE-2022-48781/^5.17/0001.patch +CVE-2022-48785/^5.17/0001.patch +CVE-2022-48966/4.14/0002.patch +CVE-2022-49034/ANY/0002.patch +CVE-2022-49061/4.14/0002.patch +CVE-2022-49073/ANY/0001.patch +CVE-2022-49078/ANY/0001.patch +CVE-2022-49146/ANY/0001.patch +CVE-2022-49194/ANY/0001.patch +CVE-2022-49205/ANY/0001.patch +CVE-2022-49209/ANY/0001.patch +CVE-2022-49285/ANY/0001.patch +CVE-2022-49318/ANY/0001.patch +CVE-2022-49363/ANY/0001.patch +CVE-2022-49364/ANY/0001.patch +CVE-2022-49380/ANY/0001.patch +CVE-2022-49425/ANY/0001.patch +CVE-2022-49428/ANY/0001.patch +CVE-2022-49433/ANY/0001.patch +CVE-2022-49500/ANY/0001.patch +CVE-2022-49513/ANY/0001.patch +CVE-2022-49563/ANY/0001.patch +CVE-2022-49564/ANY/0001.patch +CVE-2022-49566/ANY/0001.patch +CVE-2022-49642/ANY/0001.patch +CVE-2022-49705/ANY/0001.patch +CVE-2022-49710/ANY/0001.patch +CVE-2022-49777/ANY/0001.patch +CVE-2022-49779/ANY/0001.patch +CVE-2022-49784/ANY/0001.patch +CVE-2022-49823/ANY/0001.patch +CVE-2022-49824/ANY/0001.patch +CVE-2022-49825/ANY/0001.patch +CVE-2022-49839/ANY/0001.patch +CVE-2022-49863/ANY/0001.patch +CVE-2022-49980/ANY/0001.patch +CVE-2022-49990/ANY/0001.patch +CVE-2022-49993/4.14/0003.patch +CVE-2022-50013/ANY/0001.patch +CVE-2022-50062/ANY/0001.patch +CVE-2022-50074/ANY/0001.patch +CVE-2022-50248/ANY/0001.patch +CVE-2022-50273/ANY/0001.patch +CVE-2022-50326/ANY/0001.patch +CVE-2022-50358/ANY/0001.patch +CVE-2022-50364/ANY/0001.patch +CVE-2022-50397/ANY/0001.patch +CVE-2022-50473/ANY/0001.patch +CVE-2022-50522/4.14/0003.patch +CVE-2022-50537/ANY/0001.patch +CVE-2023-1989/4.14/0003.patch +CVE-2023-21657/4.14/0005.patch +CVE-2023-23000/^5.16/0001.patch +CVE-2023-28554/ANY/0002.patch +CVE-2023-33070/ANY/0001.patch +CVE-2023-52523/^6.6/0001.patch +CVE-2023-52595/^6.6/0001.patch +CVE-2023-52604/4.14/0009.patch +CVE-2023-52746/^6.2/0001.patch +CVE-2023-52884/^6.5/0001.patch +CVE-2023-52979/4.14/0003.patch +CVE-2023-53001/ANY/0001.patch +CVE-2023-53016/ANY/0001.patch +CVE-2023-53098/ANY/0001.patch +CVE-2023-53125/4.14/0003.patch +CVE-2023-53131/ANY/0001.patch +CVE-2023-53137/ANY/0001.patch +CVE-2023-53214/ANY/0001.patch +CVE-2023-53227/4.14/0003.patch +CVE-2023-53250/ANY/0001.patch +CVE-2023-53259/ANY/0002.patch +CVE-2023-53265/4.14/0003.patch +CVE-2023-53288/ANY/0001.patch +CVE-2023-53312/ANY/0001.patch +CVE-2023-53436/4.14/0003.patch +CVE-2023-53443/ANY/0001.patch +CVE-2023-53487/ANY/0002.patch +CVE-2023-53537/ANY/0001.patch +CVE-2023-53599/ANY/0001.patch +CVE-2023-53641/ANY/0001.patch +CVE-2023-53693/ANY/0001.patch +CVE-2023-53695/ANY/0001.patch +CVE-2023-53712/ANY/0001.patch +CVE-2023-53719/ANY/0001.patch +CVE-2024-26645/^6.8/0001.patch +CVE-2024-26720/4.14/0009.patch +CVE-2024-26760/^6.8/0001.patch +CVE-2024-26920/4.14/0009.patch +CVE-2024-26961/^6.7/0001.patch +CVE-2024-26972/^6.8/0001.patch +CVE-2024-27009/^6.9/0001.patch +CVE-2024-27033/^6.8/0001.patch +CVE-2024-27393/^6.9/0001.patch +CVE-2024-33032/ANY/0002.patch +CVE-2024-34027/^6.9/0001.patch +CVE-2024-35812/4.14/0009.patch +CVE-2024-35824/^6.8/0001.patch +CVE-2024-35879/^6.9/0001.patch +CVE-2024-35933/4.14/0008.patch +CVE-2024-35950/^6.9/0001.patch +CVE-2024-35954/^6.9/0001.patch +CVE-2024-35962/^6.9/0001.patch +CVE-2024-40996/^6.10/0001.patch +CVE-2024-41041/^6.10/0001.patch +CVE-2024-42077/^6.10/0001.patch +CVE-2024-42102/4.14/0009.patch +CVE-2024-42296/^6.10/0001.patch +CVE-2024-43894/^6.11/0001.patch +CVE-2024-44938/^6.9/0001.patch +CVE-2024-44939/^6.9/0001.patch +CVE-2024-44952/4.14/0008.patch +CVE-2024-46681/^6.11/0001.patch +CVE-2024-47747/^6.11/0001.patch +CVE-2024-50017/^6.11/0001.patch +CVE-2024-50019/^6.12/0001.patch +CVE-2024-50184/^6.11/0001.patch +CVE-2024-50195/3.17-^6.12/0001.patch +CVE-2024-50201/^6.12/0001.patch +CVE-2024-50210/3.17-^6.6/0001.patch +CVE-2024-50265/^6.12/0001.patch +CVE-2024-50267/^6.12/0001.patch +CVE-2024-50269/^6.12/0001.patch +CVE-2024-50279/^6.12/0001.patch +CVE-2024-50287/^6.12/0001.patch +CVE-2024-50290/^6.12/0001.patch +CVE-2024-50292/^6.12/0001.patch +CVE-2024-50295/^6.12/0001.patch +CVE-2024-50299/^6.12/0001.patch +CVE-2024-50301/^6.12/0001.patch +CVE-2024-52332/ANY/0002.patch +CVE-2024-53045/^6.12/0001.patch +CVE-2024-53101/^6.12/0001.patch +CVE-2024-53103/^6.12/0001.patch +CVE-2024-53112/^6.12/0001.patch +CVE-2024-53127/^6.12/0001.patch +CVE-2024-53140/^6.12/0001.patch +CVE-2024-53141/^6.12/0001.patch +CVE-2024-53156/ANY/0002.patch +CVE-2024-53157/ANY/0002.patch +CVE-2024-53165/ANY/0002.patch +CVE-2024-53171/ANY/0001.patch +CVE-2024-53172/ANY/0002.patch +CVE-2024-53183/ANY/0002.patch +CVE-2024-53190/ANY/0001.patch +CVE-2024-53194/ANY/0002.patch +CVE-2024-53214/ANY/0002.patch +CVE-2024-53227/ANY/0002.patch +CVE-2024-53239/ANY/0001.patch +CVE-2024-53680/ANY/0002.patch +CVE-2024-53690/ANY/0001.patch +CVE-2024-56531/ANY/0002.patch +CVE-2024-56532/ANY/0002.patch +CVE-2024-56536/ANY/0001.patch +CVE-2024-56539/ANY/0002.patch +CVE-2024-56548/ANY/0002.patch +CVE-2024-56570/ANY/0001.patch +CVE-2024-56586/ANY/0001.patch +CVE-2024-56587/ANY/0002.patch +CVE-2024-56593/ANY/0001.patch +CVE-2024-56595/ANY/0002.patch +CVE-2024-56597/ANY/0002.patch diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a.list b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a.list new file mode 100644 index 0000000..148e4f7 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a.list @@ -0,0 +1,108 @@ +0003-syzkaller-Misc/ANY/0008.patch +CVE-2015-7837/ANY/0001.patch +CVE-2016-3695/ANY/0001.patch +CVE-2017-5754/^4.19/0157.patch +CVE-2017-18232/4.14/0002.patch +CVE-2018-5897/ANY/0001.patch +CVE-2018-9415/ANY/0005.patch +CVE-2018-20855/^4.18/0001.patch +CVE-2019-3874/^5.1/0002.patch +CVE-2019-9444/ANY/0001.patch +CVE-2019-10520/ANY/0001.patch +CVE-2019-11191/^5.0/0001.patch +CVE-2019-12378/^5.1.5/0001.patch +CVE-2019-12455/^5.2/0001.patch +CVE-2019-12456/^5.1.5/0002.patch +CVE-2019-15291/4.14/0004.patch +CVE-2019-16921/^4.16/0001.patch +CVE-2019-18786/4.14/0002.patch +CVE-2019-19051/4.14/0008.patch +CVE-2019-19068/4.14/0002.patch +CVE-2019-19602/^5.4/0001.patch +CVE-2019-20908/^5.2/0001.patch +CVE-2020-0255/^5.6/0001.patch +CVE-2020-8832/^4.14/0001.patch +CVE-2020-15780/^5.8/0001.patch +CVE-2020-16119/^5.10/0002.patch +CVE-2020-BleedingToothExtras/^5.10/0001.patch +CVE-2021-3493/^5.10/0001.patch +CVE-2021-28039/^5.11/0001.patch +CVE-2021-28950/4.14/0002.patch +CVE-2021-29154/^5.12/0002.patch +CVE-2021-30337/4.14/0018.patch +CVE-2021-46912/^5.12/0001.patch +CVE-2021-46958/^5.12/0001.patch +CVE-2021-46999/^5.12/0001.patch +CVE-2021-47010/^5.12/0001.patch +CVE-2021-47058/^5.12/0001.patch +CVE-2021-47173/4.14/0003.patch +CVE-2021-47234/^5.13/0001.patch +CVE-2021-47266/^5.13/0001.patch +CVE-2021-47346/^5.13/0001.patch +CVE-2021-47430/^5.15/0001.patch +CVE-2021-47472/4.14/0003.patch +CVE-2021-47583/^5.15/0001.patch +CVE-2021-47616/^5.16/0001.patch +CVE-2021-47618/^5.16/0001.patch +CVE-2021-47636/ANY/0001.patch +CVE-2022-3061/^5.18/0001.patch +CVE-2022-3903/^6.0/0001.patch +CVE-2022-4382/^6.2/0001.patch +CVE-2022-21546/ANY/0001.patch +CVE-2022-27950/^5.16/0001.patch +CVE-2022-48674/^6.0/0001.patch +CVE-2022-48713/^5.17/0001.patch +CVE-2022-48781/^5.17/0001.patch +CVE-2022-48785/^5.17/0001.patch +CVE-2022-48966/4.14/0002.patch +CVE-2022-49034/ANY/0002.patch +CVE-2022-49061/4.14/0002.patch +CVE-2022-49073/ANY/0001.patch +CVE-2022-49078/ANY/0001.patch +CVE-2022-49146/ANY/0001.patch +CVE-2022-49194/ANY/0001.patch +CVE-2022-49205/ANY/0001.patch +CVE-2022-49209/ANY/0001.patch +CVE-2022-49285/ANY/0001.patch +CVE-2022-49318/ANY/0001.patch +CVE-2022-49363/ANY/0001.patch +CVE-2022-49364/ANY/0001.patch +CVE-2022-49380/ANY/0001.patch +CVE-2022-49425/ANY/0001.patch +CVE-2022-49428/ANY/0001.patch +CVE-2022-49433/ANY/0001.patch +CVE-2022-49500/ANY/0001.patch +CVE-2022-49513/ANY/0001.patch +CVE-2022-49563/ANY/0001.patch +CVE-2022-49564/ANY/0001.patch +CVE-2022-49566/ANY/0001.patch +CVE-2022-49642/ANY/0001.patch +CVE-2022-49705/ANY/0001.patch +CVE-2022-49710/ANY/0001.patch +CVE-2022-49777/ANY/0001.patch +CVE-2022-49779/ANY/0001.patch +CVE-2022-49784/ANY/0001.patch +CVE-2022-49823/ANY/0001.patch +CVE-2022-49824/ANY/0001.patch +CVE-2022-49825/ANY/0001.patch +CVE-2022-49839/ANY/0001.patch +CVE-2022-49863/ANY/0001.patch +CVE-2022-49980/ANY/0001.patch +CVE-2022-49990/ANY/0001.patch +CVE-2022-49993/4.14/0003.patch +CVE-2022-50013/ANY/0001.patch +CVE-2022-50062/ANY/0001.patch +CVE-2022-50074/ANY/0001.patch +CVE-2022-50248/ANY/0001.patch +CVE-2022-50273/ANY/0001.patch +CVE-2022-50326/ANY/0001.patch +CVE-2022-50358/ANY/0001.patch +CVE-2022-50364/ANY/0001.patch +CVE-2022-50397/ANY/0001.patch +CVE-2022-50473/ANY/0001.patch +CVE-2022-50522/4.14/0003.patch +CVE-2022-50537/ANY/0001.patch +CVE-2023-1989/4.14/0003.patch +CVE-2023-21657/4.14/0005.patch +CVE-2023-23000/^5.16/0001.patch +CVE-2023-28554/ANY/0002.patch diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a1.list b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a1.list new file mode 100644 index 0000000..8ddfd31 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a1.list @@ -0,0 +1,54 @@ +0003-syzkaller-Misc/ANY/0008.patch +CVE-2015-7837/ANY/0001.patch +CVE-2016-3695/ANY/0001.patch +CVE-2017-5754/^4.19/0157.patch +CVE-2017-18232/4.14/0002.patch +CVE-2018-5897/ANY/0001.patch +CVE-2018-9415/ANY/0005.patch +CVE-2018-20855/^4.18/0001.patch +CVE-2019-3874/^5.1/0002.patch +CVE-2019-9444/ANY/0001.patch +CVE-2019-10520/ANY/0001.patch +CVE-2019-11191/^5.0/0001.patch +CVE-2019-12378/^5.1.5/0001.patch +CVE-2019-12455/^5.2/0001.patch +CVE-2019-12456/^5.1.5/0002.patch +CVE-2019-15291/4.14/0004.patch +CVE-2019-16921/^4.16/0001.patch +CVE-2019-18786/4.14/0002.patch +CVE-2019-19051/4.14/0008.patch +CVE-2019-19068/4.14/0002.patch +CVE-2019-19602/^5.4/0001.patch +CVE-2019-20908/^5.2/0001.patch +CVE-2020-0255/^5.6/0001.patch +CVE-2020-8832/^4.14/0001.patch +CVE-2020-15780/^5.8/0001.patch +CVE-2020-16119/^5.10/0002.patch +CVE-2020-BleedingToothExtras/^5.10/0001.patch +CVE-2021-3493/^5.10/0001.patch +CVE-2021-28039/^5.11/0001.patch +CVE-2021-28950/4.14/0002.patch +CVE-2021-29154/^5.12/0002.patch +CVE-2021-30337/4.14/0018.patch +CVE-2021-46912/^5.12/0001.patch +CVE-2021-46958/^5.12/0001.patch +CVE-2021-46999/^5.12/0001.patch +CVE-2021-47010/^5.12/0001.patch +CVE-2021-47058/^5.12/0001.patch +CVE-2021-47173/4.14/0003.patch +CVE-2021-47234/^5.13/0001.patch +CVE-2021-47266/^5.13/0001.patch +CVE-2021-47346/^5.13/0001.patch +CVE-2021-47430/^5.15/0001.patch +CVE-2021-47472/4.14/0003.patch +CVE-2021-47583/^5.15/0001.patch +CVE-2021-47616/^5.16/0001.patch +CVE-2021-47618/^5.16/0001.patch +CVE-2021-47636/ANY/0001.patch +CVE-2022-3061/^5.18/0001.patch +CVE-2022-3903/^6.0/0001.patch +CVE-2022-4382/^6.2/0001.patch +CVE-2022-21546/ANY/0001.patch +CVE-2022-27950/^5.16/0001.patch +CVE-2022-48674/^6.0/0001.patch +CVE-2022-48713/^5.17/0001.patch diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2.list b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2.list new file mode 100644 index 0000000..a8c4cf8 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2.list @@ -0,0 +1,54 @@ +CVE-2022-48781/^5.17/0001.patch +CVE-2022-48785/^5.17/0001.patch +CVE-2022-48966/4.14/0002.patch +CVE-2022-49034/ANY/0002.patch +CVE-2022-49061/4.14/0002.patch +CVE-2022-49073/ANY/0001.patch +CVE-2022-49078/ANY/0001.patch +CVE-2022-49146/ANY/0001.patch +CVE-2022-49194/ANY/0001.patch +CVE-2022-49205/ANY/0001.patch +CVE-2022-49209/ANY/0001.patch +CVE-2022-49285/ANY/0001.patch +CVE-2022-49318/ANY/0001.patch +CVE-2022-49363/ANY/0001.patch +CVE-2022-49364/ANY/0001.patch +CVE-2022-49380/ANY/0001.patch +CVE-2022-49425/ANY/0001.patch +CVE-2022-49428/ANY/0001.patch +CVE-2022-49433/ANY/0001.patch +CVE-2022-49500/ANY/0001.patch +CVE-2022-49513/ANY/0001.patch +CVE-2022-49563/ANY/0001.patch +CVE-2022-49564/ANY/0001.patch +CVE-2022-49566/ANY/0001.patch +CVE-2022-49642/ANY/0001.patch +CVE-2022-49705/ANY/0001.patch +CVE-2022-49710/ANY/0001.patch +CVE-2022-49777/ANY/0001.patch +CVE-2022-49779/ANY/0001.patch +CVE-2022-49784/ANY/0001.patch +CVE-2022-49823/ANY/0001.patch +CVE-2022-49824/ANY/0001.patch +CVE-2022-49825/ANY/0001.patch +CVE-2022-49839/ANY/0001.patch +CVE-2022-49863/ANY/0001.patch +CVE-2022-49980/ANY/0001.patch +CVE-2022-49990/ANY/0001.patch +CVE-2022-49993/4.14/0003.patch +CVE-2022-50013/ANY/0001.patch +CVE-2022-50062/ANY/0001.patch +CVE-2022-50074/ANY/0001.patch +CVE-2022-50248/ANY/0001.patch +CVE-2022-50273/ANY/0001.patch +CVE-2022-50326/ANY/0001.patch +CVE-2022-50358/ANY/0001.patch +CVE-2022-50364/ANY/0001.patch +CVE-2022-50397/ANY/0001.patch +CVE-2022-50473/ANY/0001.patch +CVE-2022-50522/4.14/0003.patch +CVE-2022-50537/ANY/0001.patch +CVE-2023-1989/4.14/0003.patch +CVE-2023-21657/4.14/0005.patch +CVE-2023-23000/^5.16/0001.patch +CVE-2023-28554/ANY/0002.patch diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2a.list b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2a.list new file mode 100644 index 0000000..72f07e2 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2a.list @@ -0,0 +1,27 @@ +CVE-2022-48781/^5.17/0001.patch +CVE-2022-48785/^5.17/0001.patch +CVE-2022-48966/4.14/0002.patch +CVE-2022-49034/ANY/0002.patch +CVE-2022-49061/4.14/0002.patch +CVE-2022-49073/ANY/0001.patch +CVE-2022-49078/ANY/0001.patch +CVE-2022-49146/ANY/0001.patch +CVE-2022-49194/ANY/0001.patch +CVE-2022-49205/ANY/0001.patch +CVE-2022-49209/ANY/0001.patch +CVE-2022-49285/ANY/0001.patch +CVE-2022-49318/ANY/0001.patch +CVE-2022-49363/ANY/0001.patch +CVE-2022-49364/ANY/0001.patch +CVE-2022-49380/ANY/0001.patch +CVE-2022-49425/ANY/0001.patch +CVE-2022-49428/ANY/0001.patch +CVE-2022-49433/ANY/0001.patch +CVE-2022-49500/ANY/0001.patch +CVE-2022-49513/ANY/0001.patch +CVE-2022-49563/ANY/0001.patch +CVE-2022-49564/ANY/0001.patch +CVE-2022-49566/ANY/0001.patch +CVE-2022-49642/ANY/0001.patch +CVE-2022-49705/ANY/0001.patch +CVE-2022-49710/ANY/0001.patch diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2b.list b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2b.list new file mode 100644 index 0000000..19dfcb6 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2b.list @@ -0,0 +1,27 @@ +CVE-2022-49777/ANY/0001.patch +CVE-2022-49779/ANY/0001.patch +CVE-2022-49784/ANY/0001.patch +CVE-2022-49823/ANY/0001.patch +CVE-2022-49824/ANY/0001.patch +CVE-2022-49825/ANY/0001.patch +CVE-2022-49839/ANY/0001.patch +CVE-2022-49863/ANY/0001.patch +CVE-2022-49980/ANY/0001.patch +CVE-2022-49990/ANY/0001.patch +CVE-2022-49993/4.14/0003.patch +CVE-2022-50013/ANY/0001.patch +CVE-2022-50062/ANY/0001.patch +CVE-2022-50074/ANY/0001.patch +CVE-2022-50248/ANY/0001.patch +CVE-2022-50273/ANY/0001.patch +CVE-2022-50326/ANY/0001.patch +CVE-2022-50358/ANY/0001.patch +CVE-2022-50364/ANY/0001.patch +CVE-2022-50397/ANY/0001.patch +CVE-2022-50473/ANY/0001.patch +CVE-2022-50522/4.14/0003.patch +CVE-2022-50537/ANY/0001.patch +CVE-2023-1989/4.14/0003.patch +CVE-2023-21657/4.14/0005.patch +CVE-2023-23000/^5.16/0001.patch +CVE-2023-28554/ANY/0002.patch diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2b1.list b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2b1.list new file mode 100644 index 0000000..40a1d72 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2b1.list @@ -0,0 +1,14 @@ +CVE-2022-49777/ANY/0001.patch +CVE-2022-49779/ANY/0001.patch +CVE-2022-49784/ANY/0001.patch +CVE-2022-49823/ANY/0001.patch +CVE-2022-49824/ANY/0001.patch +CVE-2022-49825/ANY/0001.patch +CVE-2022-49839/ANY/0001.patch +CVE-2022-49863/ANY/0001.patch +CVE-2022-49980/ANY/0001.patch +CVE-2022-49990/ANY/0001.patch +CVE-2022-49993/4.14/0003.patch +CVE-2022-50013/ANY/0001.patch +CVE-2022-50062/ANY/0001.patch +CVE-2022-50074/ANY/0001.patch diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2b1a.list b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2b1a.list new file mode 100644 index 0000000..c5224c5 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2b1a.list @@ -0,0 +1,7 @@ +CVE-2022-49777/ANY/0001.patch +CVE-2022-49779/ANY/0001.patch +CVE-2022-49784/ANY/0001.patch +CVE-2022-49823/ANY/0001.patch +CVE-2022-49824/ANY/0001.patch +CVE-2022-49825/ANY/0001.patch +CVE-2022-49839/ANY/0001.patch diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2b1b-no49980.list b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2b1b-no49980.list new file mode 100644 index 0000000..159e31c --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2b1b-no49980.list @@ -0,0 +1,6 @@ +CVE-2022-49863/ANY/0001.patch +CVE-2022-49990/ANY/0001.patch +CVE-2022-49993/4.14/0003.patch +CVE-2022-50013/ANY/0001.patch +CVE-2022-50062/ANY/0001.patch +CVE-2022-50074/ANY/0001.patch diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2b1b.list b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2b1b.list new file mode 100644 index 0000000..dbffbe5 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2b1b.list @@ -0,0 +1,7 @@ +CVE-2022-49863/ANY/0001.patch +CVE-2022-49980/ANY/0001.patch +CVE-2022-49990/ANY/0001.patch +CVE-2022-49993/4.14/0003.patch +CVE-2022-50013/ANY/0001.patch +CVE-2022-50062/ANY/0001.patch +CVE-2022-50074/ANY/0001.patch diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2b2.list b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2b2.list new file mode 100644 index 0000000..d5bcc60 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1a2b2.list @@ -0,0 +1,13 @@ +CVE-2022-50248/ANY/0001.patch +CVE-2022-50273/ANY/0001.patch +CVE-2022-50326/ANY/0001.patch +CVE-2022-50358/ANY/0001.patch +CVE-2022-50364/ANY/0001.patch +CVE-2022-50397/ANY/0001.patch +CVE-2022-50473/ANY/0001.patch +CVE-2022-50522/4.14/0003.patch +CVE-2022-50537/ANY/0001.patch +CVE-2023-1989/4.14/0003.patch +CVE-2023-21657/4.14/0005.patch +CVE-2023-23000/^5.16/0001.patch +CVE-2023-28554/ANY/0002.patch diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1b.list b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1b.list new file mode 100644 index 0000000..6b0d655 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h1b.list @@ -0,0 +1,107 @@ +CVE-2023-33070/ANY/0001.patch +CVE-2023-52523/^6.6/0001.patch +CVE-2023-52595/^6.6/0001.patch +CVE-2023-52604/4.14/0009.patch +CVE-2023-52746/^6.2/0001.patch +CVE-2023-52884/^6.5/0001.patch +CVE-2023-52979/4.14/0003.patch +CVE-2023-53001/ANY/0001.patch +CVE-2023-53016/ANY/0001.patch +CVE-2023-53098/ANY/0001.patch +CVE-2023-53125/4.14/0003.patch +CVE-2023-53131/ANY/0001.patch +CVE-2023-53137/ANY/0001.patch +CVE-2023-53214/ANY/0001.patch +CVE-2023-53227/4.14/0003.patch +CVE-2023-53250/ANY/0001.patch +CVE-2023-53259/ANY/0002.patch +CVE-2023-53265/4.14/0003.patch +CVE-2023-53288/ANY/0001.patch +CVE-2023-53312/ANY/0001.patch +CVE-2023-53436/4.14/0003.patch +CVE-2023-53443/ANY/0001.patch +CVE-2023-53487/ANY/0002.patch +CVE-2023-53537/ANY/0001.patch +CVE-2023-53599/ANY/0001.patch +CVE-2023-53641/ANY/0001.patch +CVE-2023-53693/ANY/0001.patch +CVE-2023-53695/ANY/0001.patch +CVE-2023-53712/ANY/0001.patch +CVE-2023-53719/ANY/0001.patch +CVE-2024-26645/^6.8/0001.patch +CVE-2024-26720/4.14/0009.patch +CVE-2024-26760/^6.8/0001.patch +CVE-2024-26920/4.14/0009.patch +CVE-2024-26961/^6.7/0001.patch +CVE-2024-26972/^6.8/0001.patch +CVE-2024-27009/^6.9/0001.patch +CVE-2024-27033/^6.8/0001.patch +CVE-2024-27393/^6.9/0001.patch +CVE-2024-33032/ANY/0002.patch +CVE-2024-34027/^6.9/0001.patch +CVE-2024-35812/4.14/0009.patch +CVE-2024-35824/^6.8/0001.patch +CVE-2024-35879/^6.9/0001.patch +CVE-2024-35933/4.14/0008.patch +CVE-2024-35950/^6.9/0001.patch +CVE-2024-35954/^6.9/0001.patch +CVE-2024-35962/^6.9/0001.patch +CVE-2024-40996/^6.10/0001.patch +CVE-2024-41041/^6.10/0001.patch +CVE-2024-42077/^6.10/0001.patch +CVE-2024-42102/4.14/0009.patch +CVE-2024-42296/^6.10/0001.patch +CVE-2024-43894/^6.11/0001.patch +CVE-2024-44938/^6.9/0001.patch +CVE-2024-44939/^6.9/0001.patch +CVE-2024-44952/4.14/0008.patch +CVE-2024-46681/^6.11/0001.patch +CVE-2024-47747/^6.11/0001.patch +CVE-2024-50017/^6.11/0001.patch +CVE-2024-50019/^6.12/0001.patch +CVE-2024-50184/^6.11/0001.patch +CVE-2024-50195/3.17-^6.12/0001.patch +CVE-2024-50201/^6.12/0001.patch +CVE-2024-50210/3.17-^6.6/0001.patch +CVE-2024-50265/^6.12/0001.patch +CVE-2024-50267/^6.12/0001.patch +CVE-2024-50269/^6.12/0001.patch +CVE-2024-50279/^6.12/0001.patch +CVE-2024-50287/^6.12/0001.patch +CVE-2024-50290/^6.12/0001.patch +CVE-2024-50292/^6.12/0001.patch +CVE-2024-50295/^6.12/0001.patch +CVE-2024-50299/^6.12/0001.patch +CVE-2024-50301/^6.12/0001.patch +CVE-2024-52332/ANY/0002.patch +CVE-2024-53045/^6.12/0001.patch +CVE-2024-53101/^6.12/0001.patch +CVE-2024-53103/^6.12/0001.patch +CVE-2024-53112/^6.12/0001.patch +CVE-2024-53127/^6.12/0001.patch +CVE-2024-53140/^6.12/0001.patch +CVE-2024-53141/^6.12/0001.patch +CVE-2024-53156/ANY/0002.patch +CVE-2024-53157/ANY/0002.patch +CVE-2024-53165/ANY/0002.patch +CVE-2024-53171/ANY/0001.patch +CVE-2024-53172/ANY/0002.patch +CVE-2024-53183/ANY/0002.patch +CVE-2024-53190/ANY/0001.patch +CVE-2024-53194/ANY/0002.patch +CVE-2024-53214/ANY/0002.patch +CVE-2024-53227/ANY/0002.patch +CVE-2024-53239/ANY/0001.patch +CVE-2024-53680/ANY/0002.patch +CVE-2024-53690/ANY/0001.patch +CVE-2024-56531/ANY/0002.patch +CVE-2024-56532/ANY/0002.patch +CVE-2024-56536/ANY/0001.patch +CVE-2024-56539/ANY/0002.patch +CVE-2024-56548/ANY/0002.patch +CVE-2024-56570/ANY/0001.patch +CVE-2024-56586/ANY/0001.patch +CVE-2024-56587/ANY/0002.patch +CVE-2024-56593/ANY/0001.patch +CVE-2024-56595/ANY/0002.patch +CVE-2024-56597/ANY/0002.patch diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h2.list b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h2.list new file mode 100644 index 0000000..fcc7909 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-bisect-h2.list @@ -0,0 +1,215 @@ +CVE-2024-56600/ANY/0001.patch +CVE-2024-56602/ANY/0001.patch +CVE-2024-56603/ANY/0002.patch +CVE-2024-56619/ANY/0002.patch +CVE-2024-56629/ANY/0001.patch +CVE-2024-56637/ANY/0002.patch +CVE-2024-56643/ANY/0002.patch +CVE-2024-56659/ANY/0002.patch +CVE-2024-56670/ANY/0002.patch +CVE-2024-56681/ANY/0001.patch +CVE-2024-56687/ANY/0001.patch +CVE-2024-56700/ANY/0002.patch +CVE-2024-56739/ANY/0002.patch +CVE-2024-56747/ANY/0001.patch +CVE-2024-56767/ANY/0002.patch +CVE-2024-56769/ANY/0002.patch +CVE-2024-57802/ANY/0002.patch +CVE-2024-57850/ANY/0002.patch +CVE-2024-57893/ANY/0001.patch +CVE-2024-57901/ANY/0001.patch +CVE-2024-57902/ANY/0001.patch +CVE-2024-57904/ANY/0001.patch +CVE-2024-57908/ANY/0001.patch +CVE-2024-57912/ANY/0001.patch +CVE-2024-57929/ANY/0001.patch +CVE-2024-57938/ANY/0002.patch +CVE-2024-57948/ANY/0001.patch +CVE-2024-57973/ANY/0001.patch +CVE-2024-58001/ANY/0001.patch +CVE-2024-58010/ANY/0001.patch +CVE-2024-58055/ANY/0001.patch +CVE-2024-58094/ANY/0001.patch +CVE-2024-58095/ANY/0001.patch +CVE-2025-21664/ANY/0001.patch +CVE-2025-21689/ANY/0001.patch +CVE-2025-21699/ANY/0001.patch +CVE-2025-21704/ANY/0001.patch +CVE-2025-21718/ANY/0001.patch +CVE-2025-21735/ANY/0001.patch +CVE-2025-21736/ANY/0001.patch +CVE-2025-21744/ANY/0001.patch +CVE-2025-21772/ANY/0001.patch +CVE-2025-21776/ANY/0001.patch +CVE-2025-21781/ANY/0001.patch +CVE-2025-21782/ANY/0001.patch +CVE-2025-21785/ANY/0001.patch +CVE-2025-21791/ANY/0001.patch +CVE-2025-21835/ANY/0001.patch +CVE-2025-21877/ANY/0001.patch +CVE-2025-21904/ANY/0001.patch +CVE-2025-21910/ANY/0001.patch +CVE-2025-21916/ANY/0001.patch +CVE-2025-21928/ANY/0001.patch +CVE-2025-21934/ANY/0001.patch +CVE-2025-21935/ANY/0001.patch +CVE-2025-21948/ANY/0001.patch +CVE-2025-21993/ANY/0001.patch +CVE-2025-21996/ANY/0001.patch +CVE-2025-22007/ANY/0001.patch +CVE-2025-22018/ANY/0001.patch +CVE-2025-22063/ANY/0001.patch +CVE-2025-22073/ANY/0001.patch +CVE-2025-22079/ANY/0001.patch +CVE-2025-22086/ANY/0001.patch +CVE-2025-23150/ANY/0001.patch +CVE-2025-23163/ANY/0001.patch +CVE-2025-37738/ANY/0001.patch +CVE-2025-37739/ANY/0001.patch +CVE-2025-37740/ANY/0001.patch +CVE-2025-37741/ANY/0001.patch +CVE-2025-37749/ANY/0001.patch +CVE-2025-37757/ANY/0001.patch +CVE-2025-37758/ANY/0001.patch +CVE-2025-37780/ANY/0001.patch +CVE-2025-37781/ANY/0001.patch +CVE-2025-37782/ANY/0001.patch +CVE-2025-37796/ANY/0001.patch +CVE-2025-37797/ANY/0001.patch +CVE-2025-37798/ANY/0001.patch +CVE-2025-37817/ANY/0001.patch +CVE-2025-37823/ANY/0001.patch +CVE-2025-37825/ANY/0001.patch +CVE-2025-37833/ANY/0001.patch +CVE-2025-37838/ANY/0001.patch +CVE-2025-37841/ANY/0001.patch +CVE-2025-37851/ANY/0001.patch +CVE-2025-37857/ANY/0001.patch +CVE-2025-37858/ANY/0001.patch +CVE-2025-37892/ANY/0001.patch +CVE-2025-37925/ANY/0001.patch +CVE-2025-37937/ANY/0002.patch +CVE-2025-37982/ANY/0001.patch +CVE-2025-37983/ANY/0001.patch +CVE-2025-37990/ANY/0001.patch +CVE-2025-38046/ANY/0001.patch +CVE-2025-38058/ANY/0001.patch +CVE-2025-38061/ANY/0001.patch +CVE-2025-38066/ANY/0001.patch +CVE-2025-38075/ANY/0001.patch +CVE-2025-38090/ANY/0001.patch +CVE-2025-38114/ANY/0001.patch +CVE-2025-38115/ANY/0001.patch +CVE-2025-38147/ANY/0001.patch +CVE-2025-38157/ANY/0001.patch +CVE-2025-38163/ANY/0001.patch +CVE-2025-38174/ANY/0001.patch +CVE-2025-38177/ANY/0001.patch +CVE-2025-38180/ANY/0001.patch +CVE-2025-38181/ANY/0001.patch +CVE-2025-38184/ANY/0001.patch +CVE-2025-38185/ANY/0001.patch +CVE-2025-38190/ANY/0001.patch +CVE-2025-38194/ANY/0001.patch +CVE-2025-38203/ANY/0001.patch +CVE-2025-38212/ANY/0001.patch +CVE-2025-38213/ANY/0001.patch +CVE-2025-38219/ANY/0001.patch +CVE-2025-38222/ANY/0001.patch +CVE-2025-38245/ANY/0001.patch +CVE-2025-38251/ANY/0001.patch +CVE-2025-38265/ANY/0001.patch +CVE-2025-38312/ANY/0001.patch +CVE-2025-38320/ANY/0001.patch +CVE-2025-38324/ANY/0001.patch +CVE-2025-38328/ANY/0001.patch +CVE-2025-38336/ANY/0001.patch +CVE-2025-38344/ANY/0001.patch +CVE-2025-38345/ANY/0001.patch +CVE-2025-38348/ANY/0001.patch +CVE-2025-38386/ANY/0001.patch +CVE-2025-38403/ANY/0001.patch +CVE-2025-38406/ANY/0001.patch +CVE-2025-38416/ANY/0001.patch +CVE-2025-38420/ANY/0001.patch +CVE-2025-38428/ANY/0001.patch +CVE-2025-38445/ANY/0001.patch +CVE-2025-38448/ANY/0001.patch +CVE-2025-38458/ANY/0001.patch +CVE-2025-38459/ANY/0001.patch +CVE-2025-38460/ANY/0001.patch +CVE-2025-38467/ANY/0001.patch +CVE-2025-38468/ANY/0001.patch +CVE-2025-38470/ANY/0001.patch +CVE-2025-38474/ANY/0001.patch +CVE-2025-38513/ANY/0001.patch +CVE-2025-38514/ANY/0001.patch +CVE-2025-38538/ANY/0001.patch +CVE-2025-38542/ANY/0001.patch +CVE-2025-38544/ANY/0001.patch +CVE-2025-38546/ANY/0001.patch +CVE-2025-38555/ANY/0001.patch +CVE-2025-38574/ANY/0001.patch +CVE-2025-38578/ANY/0001.patch +CVE-2025-38581/ANY/0001.patch +CVE-2025-38604/ANY/0001.patch +CVE-2025-38611/ANY/0001.patch +CVE-2025-38612/ANY/0001.patch +CVE-2025-38618/ANY/0001.patch +CVE-2025-38639/ANY/0001.patch +CVE-2025-38691/ANY/0001.patch +CVE-2025-38693/ANY/0001.patch +CVE-2025-38694/ANY/0001.patch +CVE-2025-38697/ANY/0001.patch +CVE-2025-38698/ANY/0001.patch +CVE-2025-38699/ANY/0001.patch +CVE-2025-38701/ANY/0001.patch +CVE-2025-38708/ANY/0001.patch +CVE-2025-38712/ANY/0001.patch +CVE-2025-38713/ANY/0001.patch +CVE-2025-38717/ANY/0001.patch +CVE-2025-39676/ANY/0001.patch +CVE-2025-39691/ANY/0001.patch +CVE-2025-39710/ANY/0001.patch +CVE-2025-39714/ANY/0001.patch +CVE-2025-39743/ANY/0001.patch +CVE-2025-39756/ANY/0001.patch +CVE-2025-39782/ANY/0001.patch +CVE-2025-39794/ANY/0001.patch +CVE-2025-39796/ANY/0001.patch +CVE-2025-39808/ANY/0001.patch +CVE-2025-39812/ANY/0001.patch +CVE-2025-39817/ANY/0001.patch +CVE-2025-39839/ANY/0001.patch +CVE-2025-39846/ANY/0001.patch +CVE-2025-39848/ANY/0001.patch +CVE-2025-39885/ANY/0001.patch +CVE-2025-39889/ANY/0001.patch +CVE-2025-39898/ANY/0001.patch +CVE-2025-39903/ANY/0001.patch +CVE-2025-39913/ANY/0001.patch +CVE-2025-39920/ANY/0001.patch +CVE-2025-39945/ANY/0001.patch +CVE-2025-39964/ANY/0001.patch +CVE-2025-39967/ANY/0001.patch +CVE-2025-39973/ANY/0001.patch +CVE-2025-39996/ANY/0001.patch +CVE-2025-40011/ANY/0001.patch +CVE-2025-40020/ANY/0001.patch +CVE-2025-40022/ANY/0001.patch +CVE-2025-40028/ANY/0001.patch +CVE-2025-40030/ANY/0001.patch +CVE-2025-40035/ANY/0001.patch +CVE-2025-40044/ANY/0001.patch +CVE-2025-40049/ANY/0001.patch +CVE-2025-40055/ANY/0001.patch +CVE-2025-40082/ANY/0001.patch +CVE-2019-12819/4.14/0006.patch +CVE-2021-47472/4.14/0003.patch +CVE-2023-53129/ANY/0001.patch +CVE-2023-53626/ANY/0001.patch +CVE-2024-26720/4.14/0009.patch +CVE-2024-39501/4.14/0009.patch +CVE-2024-42102/4.14/0009.patch +CVE-2024-50195/3.17-^6.12/0001.patch +CVE-2024-50210/3.17-^6.6/0001.patch diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/cve-clean-offset.list b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-clean-offset.list new file mode 100644 index 0000000..86e6e0d --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-clean-offset.list @@ -0,0 +1,429 @@ +0003-syzkaller-Misc/ANY/0008.patch +CVE-2015-7837/ANY/0001.patch +CVE-2016-3695/ANY/0001.patch +CVE-2017-5754/^4.19/0157.patch +CVE-2017-18232/4.14/0002.patch +CVE-2018-5897/ANY/0001.patch +CVE-2018-9415/ANY/0005.patch +CVE-2018-20855/^4.18/0001.patch +CVE-2019-3874/^5.1/0002.patch +CVE-2019-9444/ANY/0001.patch +CVE-2019-10520/ANY/0001.patch +CVE-2019-11191/^5.0/0001.patch +CVE-2019-12378/^5.1.5/0001.patch +CVE-2019-12455/^5.2/0001.patch +CVE-2019-12456/^5.1.5/0002.patch +CVE-2019-15291/4.14/0004.patch +CVE-2019-16921/^4.16/0001.patch +CVE-2019-18786/4.14/0002.patch +CVE-2019-19051/4.14/0008.patch +CVE-2019-19068/4.14/0002.patch +CVE-2019-19602/^5.4/0001.patch +CVE-2019-20908/^5.2/0001.patch +CVE-2020-0255/^5.6/0001.patch +CVE-2020-8832/^4.14/0001.patch +CVE-2020-15780/^5.8/0001.patch +CVE-2020-16119/^5.10/0002.patch +CVE-2020-BleedingToothExtras/^5.10/0001.patch +CVE-2021-3493/^5.10/0001.patch +CVE-2021-28039/^5.11/0001.patch +CVE-2021-28950/4.14/0002.patch +CVE-2021-29154/^5.12/0002.patch +CVE-2021-30337/4.14/0018.patch +CVE-2021-46912/^5.12/0001.patch +CVE-2021-46958/^5.12/0001.patch +CVE-2021-46999/^5.12/0001.patch +CVE-2021-47010/^5.12/0001.patch +CVE-2021-47058/^5.12/0001.patch +CVE-2021-47173/4.14/0003.patch +CVE-2021-47234/^5.13/0001.patch +CVE-2021-47266/^5.13/0001.patch +CVE-2021-47346/^5.13/0001.patch +CVE-2021-47430/^5.15/0001.patch +CVE-2021-47472/4.14/0003.patch +CVE-2021-47583/^5.15/0001.patch +CVE-2021-47616/^5.16/0001.patch +CVE-2021-47618/^5.16/0001.patch +CVE-2021-47636/ANY/0001.patch +CVE-2022-3061/^5.18/0001.patch +CVE-2022-3903/^6.0/0001.patch +CVE-2022-4382/^6.2/0001.patch +CVE-2022-21546/ANY/0001.patch +CVE-2022-27950/^5.16/0001.patch +CVE-2022-48674/^6.0/0001.patch +CVE-2022-48713/^5.17/0001.patch +CVE-2022-48781/^5.17/0001.patch +CVE-2022-48785/^5.17/0001.patch +CVE-2022-48966/4.14/0002.patch +CVE-2022-49034/ANY/0002.patch +CVE-2022-49061/4.14/0002.patch +CVE-2022-49073/ANY/0001.patch +CVE-2022-49078/ANY/0001.patch +CVE-2022-49146/ANY/0001.patch +CVE-2022-49194/ANY/0001.patch +CVE-2022-49205/ANY/0001.patch +CVE-2022-49209/ANY/0001.patch +CVE-2022-49285/ANY/0001.patch +CVE-2022-49318/ANY/0001.patch +CVE-2022-49363/ANY/0001.patch +CVE-2022-49364/ANY/0001.patch +CVE-2022-49380/ANY/0001.patch +CVE-2022-49425/ANY/0001.patch +CVE-2022-49428/ANY/0001.patch +CVE-2022-49433/ANY/0001.patch +CVE-2022-49500/ANY/0001.patch +CVE-2022-49513/ANY/0001.patch +CVE-2022-49563/ANY/0001.patch +CVE-2022-49564/ANY/0001.patch +CVE-2022-49566/ANY/0001.patch +CVE-2022-49642/ANY/0001.patch +CVE-2022-49705/ANY/0001.patch +CVE-2022-49710/ANY/0001.patch +CVE-2022-49777/ANY/0001.patch +CVE-2022-49779/ANY/0001.patch +CVE-2022-49784/ANY/0001.patch +CVE-2022-49823/ANY/0001.patch +CVE-2022-49824/ANY/0001.patch +CVE-2022-49825/ANY/0001.patch +CVE-2022-49839/ANY/0001.patch +CVE-2022-49863/ANY/0001.patch +CVE-2022-49990/ANY/0001.patch +CVE-2022-49993/4.14/0003.patch +CVE-2022-50013/ANY/0001.patch +CVE-2022-50062/ANY/0001.patch +CVE-2022-50074/ANY/0001.patch +CVE-2022-50248/ANY/0001.patch +CVE-2022-50273/ANY/0001.patch +CVE-2022-50326/ANY/0001.patch +CVE-2022-50358/ANY/0001.patch +CVE-2022-50364/ANY/0001.patch +CVE-2022-50397/ANY/0001.patch +CVE-2022-50473/ANY/0001.patch +CVE-2022-50522/4.14/0003.patch +CVE-2022-50537/ANY/0001.patch +CVE-2023-1989/4.14/0003.patch +CVE-2023-21657/4.14/0005.patch +CVE-2023-23000/^5.16/0001.patch +CVE-2023-28554/ANY/0002.patch +CVE-2023-33070/ANY/0001.patch +CVE-2023-52523/^6.6/0001.patch +CVE-2023-52595/^6.6/0001.patch +CVE-2023-52604/4.14/0009.patch +CVE-2023-52746/^6.2/0001.patch +CVE-2023-52884/^6.5/0001.patch +CVE-2023-52979/4.14/0003.patch +CVE-2023-53001/ANY/0001.patch +CVE-2023-53016/ANY/0001.patch +CVE-2023-53098/ANY/0001.patch +CVE-2023-53125/4.14/0003.patch +CVE-2023-53131/ANY/0001.patch +CVE-2023-53137/ANY/0001.patch +CVE-2023-53214/ANY/0001.patch +CVE-2023-53227/4.14/0003.patch +CVE-2023-53250/ANY/0001.patch +CVE-2023-53259/ANY/0002.patch +CVE-2023-53265/4.14/0003.patch +CVE-2023-53288/ANY/0001.patch +CVE-2023-53312/ANY/0001.patch +CVE-2023-53436/4.14/0003.patch +CVE-2023-53443/ANY/0001.patch +CVE-2023-53487/ANY/0002.patch +CVE-2023-53537/ANY/0001.patch +CVE-2023-53599/ANY/0001.patch +CVE-2023-53641/ANY/0001.patch +CVE-2023-53693/ANY/0001.patch +CVE-2023-53695/ANY/0001.patch +CVE-2023-53712/ANY/0001.patch +CVE-2023-53719/ANY/0001.patch +CVE-2024-26645/^6.8/0001.patch +CVE-2024-26720/4.14/0009.patch +CVE-2024-26760/^6.8/0001.patch +CVE-2024-26920/4.14/0009.patch +CVE-2024-26961/^6.7/0001.patch +CVE-2024-26972/^6.8/0001.patch +CVE-2024-27009/^6.9/0001.patch +CVE-2024-27033/^6.8/0001.patch +CVE-2024-27393/^6.9/0001.patch +CVE-2024-33032/ANY/0002.patch +CVE-2024-34027/^6.9/0001.patch +CVE-2024-35812/4.14/0009.patch +CVE-2024-35824/^6.8/0001.patch +CVE-2024-35879/^6.9/0001.patch +CVE-2024-35933/4.14/0008.patch +CVE-2024-35950/^6.9/0001.patch +CVE-2024-35954/^6.9/0001.patch +CVE-2024-35962/^6.9/0001.patch +CVE-2024-40996/^6.10/0001.patch +CVE-2024-41041/^6.10/0001.patch +CVE-2024-42077/^6.10/0001.patch +CVE-2024-42102/4.14/0009.patch +CVE-2024-42296/^6.10/0001.patch +CVE-2024-43894/^6.11/0001.patch +CVE-2024-44938/^6.9/0001.patch +CVE-2024-44939/^6.9/0001.patch +CVE-2024-44952/4.14/0008.patch +CVE-2024-46681/^6.11/0001.patch +CVE-2024-47747/^6.11/0001.patch +CVE-2024-50017/^6.11/0001.patch +CVE-2024-50019/^6.12/0001.patch +CVE-2024-50184/^6.11/0001.patch +CVE-2024-50195/3.17-^6.12/0001.patch +CVE-2024-50201/^6.12/0001.patch +CVE-2024-50210/3.17-^6.6/0001.patch +CVE-2024-50265/^6.12/0001.patch +CVE-2024-50267/^6.12/0001.patch +CVE-2024-50269/^6.12/0001.patch +CVE-2024-50279/^6.12/0001.patch +CVE-2024-50287/^6.12/0001.patch +CVE-2024-50290/^6.12/0001.patch +CVE-2024-50292/^6.12/0001.patch +CVE-2024-50295/^6.12/0001.patch +CVE-2024-50299/^6.12/0001.patch +CVE-2024-50301/^6.12/0001.patch +CVE-2024-52332/ANY/0002.patch +CVE-2024-53045/^6.12/0001.patch +CVE-2024-53101/^6.12/0001.patch +CVE-2024-53103/^6.12/0001.patch +CVE-2024-53112/^6.12/0001.patch +CVE-2024-53127/^6.12/0001.patch +CVE-2024-53140/^6.12/0001.patch +CVE-2024-53141/^6.12/0001.patch +CVE-2024-53156/ANY/0002.patch +CVE-2024-53157/ANY/0002.patch +CVE-2024-53165/ANY/0002.patch +CVE-2024-53171/ANY/0001.patch +CVE-2024-53172/ANY/0002.patch +CVE-2024-53183/ANY/0002.patch +CVE-2024-53190/ANY/0001.patch +CVE-2024-53194/ANY/0002.patch +CVE-2024-53214/ANY/0002.patch +CVE-2024-53227/ANY/0002.patch +CVE-2024-53239/ANY/0001.patch +CVE-2024-53680/ANY/0002.patch +CVE-2024-53690/ANY/0001.patch +CVE-2024-56531/ANY/0002.patch +CVE-2024-56532/ANY/0002.patch +CVE-2024-56536/ANY/0001.patch +CVE-2024-56539/ANY/0002.patch +CVE-2024-56548/ANY/0002.patch +CVE-2024-56570/ANY/0001.patch +CVE-2024-56586/ANY/0001.patch +CVE-2024-56587/ANY/0002.patch +CVE-2024-56593/ANY/0001.patch +CVE-2024-56595/ANY/0002.patch +CVE-2024-56597/ANY/0002.patch +CVE-2024-56600/ANY/0001.patch +CVE-2024-56602/ANY/0001.patch +CVE-2024-56603/ANY/0002.patch +CVE-2024-56619/ANY/0002.patch +CVE-2024-56629/ANY/0001.patch +CVE-2024-56637/ANY/0002.patch +CVE-2024-56643/ANY/0002.patch +CVE-2024-56659/ANY/0002.patch +CVE-2024-56670/ANY/0002.patch +CVE-2024-56681/ANY/0001.patch +CVE-2024-56687/ANY/0001.patch +CVE-2024-56700/ANY/0002.patch +CVE-2024-56739/ANY/0002.patch +CVE-2024-56747/ANY/0001.patch +CVE-2024-56767/ANY/0002.patch +CVE-2024-56769/ANY/0002.patch +CVE-2024-57802/ANY/0002.patch +CVE-2024-57850/ANY/0002.patch +CVE-2024-57893/ANY/0001.patch +CVE-2024-57901/ANY/0001.patch +CVE-2024-57902/ANY/0001.patch +CVE-2024-57904/ANY/0001.patch +CVE-2024-57908/ANY/0001.patch +CVE-2024-57912/ANY/0001.patch +CVE-2024-57929/ANY/0001.patch +CVE-2024-57938/ANY/0002.patch +CVE-2024-57948/ANY/0001.patch +CVE-2024-57973/ANY/0001.patch +CVE-2024-58001/ANY/0001.patch +CVE-2024-58010/ANY/0001.patch +CVE-2024-58055/ANY/0001.patch +CVE-2024-58094/ANY/0001.patch +CVE-2024-58095/ANY/0001.patch +CVE-2025-21664/ANY/0001.patch +CVE-2025-21689/ANY/0001.patch +CVE-2025-21699/ANY/0001.patch +CVE-2025-21704/ANY/0001.patch +CVE-2025-21718/ANY/0001.patch +CVE-2025-21735/ANY/0001.patch +CVE-2025-21736/ANY/0001.patch +CVE-2025-21744/ANY/0001.patch +CVE-2025-21772/ANY/0001.patch +CVE-2025-21776/ANY/0001.patch +CVE-2025-21781/ANY/0001.patch +CVE-2025-21782/ANY/0001.patch +CVE-2025-21785/ANY/0001.patch +CVE-2025-21791/ANY/0001.patch +CVE-2025-21835/ANY/0001.patch +CVE-2025-21877/ANY/0001.patch +CVE-2025-21904/ANY/0001.patch +CVE-2025-21910/ANY/0001.patch +CVE-2025-21916/ANY/0001.patch +CVE-2025-21928/ANY/0001.patch +CVE-2025-21934/ANY/0001.patch +CVE-2025-21935/ANY/0001.patch +CVE-2025-21948/ANY/0001.patch +CVE-2025-21993/ANY/0001.patch +CVE-2025-21996/ANY/0001.patch +CVE-2025-22007/ANY/0001.patch +CVE-2025-22018/ANY/0001.patch +CVE-2025-22063/ANY/0001.patch +CVE-2025-22073/ANY/0001.patch +CVE-2025-22079/ANY/0001.patch +CVE-2025-22086/ANY/0001.patch +CVE-2025-23150/ANY/0001.patch +CVE-2025-23163/ANY/0001.patch +CVE-2025-37738/ANY/0001.patch +CVE-2025-37739/ANY/0001.patch +CVE-2025-37740/ANY/0001.patch +CVE-2025-37741/ANY/0001.patch +CVE-2025-37749/ANY/0001.patch +CVE-2025-37757/ANY/0001.patch +CVE-2025-37758/ANY/0001.patch +CVE-2025-37780/ANY/0001.patch +CVE-2025-37781/ANY/0001.patch +CVE-2025-37782/ANY/0001.patch +CVE-2025-37796/ANY/0001.patch +CVE-2025-37797/ANY/0001.patch +CVE-2025-37798/ANY/0001.patch +CVE-2025-37817/ANY/0001.patch +CVE-2025-37823/ANY/0001.patch +CVE-2025-37825/ANY/0001.patch +CVE-2025-37833/ANY/0001.patch +CVE-2025-37838/ANY/0001.patch +CVE-2025-37841/ANY/0001.patch +CVE-2025-37851/ANY/0001.patch +CVE-2025-37857/ANY/0001.patch +CVE-2025-37858/ANY/0001.patch +CVE-2025-37892/ANY/0001.patch +CVE-2025-37925/ANY/0001.patch +CVE-2025-37937/ANY/0002.patch +CVE-2025-37982/ANY/0001.patch +CVE-2025-37983/ANY/0001.patch +CVE-2025-37990/ANY/0001.patch +CVE-2025-38046/ANY/0001.patch +CVE-2025-38058/ANY/0001.patch +CVE-2025-38061/ANY/0001.patch +CVE-2025-38066/ANY/0001.patch +CVE-2025-38075/ANY/0001.patch +CVE-2025-38090/ANY/0001.patch +CVE-2025-38114/ANY/0001.patch +CVE-2025-38115/ANY/0001.patch +CVE-2025-38147/ANY/0001.patch +CVE-2025-38157/ANY/0001.patch +CVE-2025-38163/ANY/0001.patch +CVE-2025-38174/ANY/0001.patch +CVE-2025-38177/ANY/0001.patch +CVE-2025-38180/ANY/0001.patch +CVE-2025-38181/ANY/0001.patch +CVE-2025-38184/ANY/0001.patch +CVE-2025-38185/ANY/0001.patch +CVE-2025-38190/ANY/0001.patch +CVE-2025-38194/ANY/0001.patch +CVE-2025-38203/ANY/0001.patch +CVE-2025-38212/ANY/0001.patch +CVE-2025-38213/ANY/0001.patch +CVE-2025-38219/ANY/0001.patch +CVE-2025-38222/ANY/0001.patch +CVE-2025-38245/ANY/0001.patch +CVE-2025-38251/ANY/0001.patch +CVE-2025-38265/ANY/0001.patch +CVE-2025-38312/ANY/0001.patch +CVE-2025-38320/ANY/0001.patch +CVE-2025-38324/ANY/0001.patch +CVE-2025-38328/ANY/0001.patch +CVE-2025-38336/ANY/0001.patch +CVE-2025-38344/ANY/0001.patch +CVE-2025-38345/ANY/0001.patch +CVE-2025-38348/ANY/0001.patch +CVE-2025-38386/ANY/0001.patch +CVE-2025-38403/ANY/0001.patch +CVE-2025-38406/ANY/0001.patch +CVE-2025-38416/ANY/0001.patch +CVE-2025-38420/ANY/0001.patch +CVE-2025-38428/ANY/0001.patch +CVE-2025-38445/ANY/0001.patch +CVE-2025-38448/ANY/0001.patch +CVE-2025-38458/ANY/0001.patch +CVE-2025-38459/ANY/0001.patch +CVE-2025-38460/ANY/0001.patch +CVE-2025-38467/ANY/0001.patch +CVE-2025-38468/ANY/0001.patch +CVE-2025-38470/ANY/0001.patch +CVE-2025-38474/ANY/0001.patch +CVE-2025-38513/ANY/0001.patch +CVE-2025-38514/ANY/0001.patch +CVE-2025-38538/ANY/0001.patch +CVE-2025-38542/ANY/0001.patch +CVE-2025-38544/ANY/0001.patch +CVE-2025-38546/ANY/0001.patch +CVE-2025-38555/ANY/0001.patch +CVE-2025-38574/ANY/0001.patch +CVE-2025-38578/ANY/0001.patch +CVE-2025-38581/ANY/0001.patch +CVE-2025-38604/ANY/0001.patch +CVE-2025-38611/ANY/0001.patch +CVE-2025-38612/ANY/0001.patch +CVE-2025-38618/ANY/0001.patch +CVE-2025-38639/ANY/0001.patch +CVE-2025-38691/ANY/0001.patch +CVE-2025-38693/ANY/0001.patch +CVE-2025-38694/ANY/0001.patch +CVE-2025-38697/ANY/0001.patch +CVE-2025-38698/ANY/0001.patch +CVE-2025-38699/ANY/0001.patch +CVE-2025-38701/ANY/0001.patch +CVE-2025-38708/ANY/0001.patch +CVE-2025-38712/ANY/0001.patch +CVE-2025-38713/ANY/0001.patch +CVE-2025-38717/ANY/0001.patch +CVE-2025-39676/ANY/0001.patch +CVE-2025-39691/ANY/0001.patch +CVE-2025-39710/ANY/0001.patch +CVE-2025-39714/ANY/0001.patch +CVE-2025-39743/ANY/0001.patch +CVE-2025-39756/ANY/0001.patch +CVE-2025-39782/ANY/0001.patch +CVE-2025-39794/ANY/0001.patch +CVE-2025-39796/ANY/0001.patch +CVE-2025-39808/ANY/0001.patch +CVE-2025-39812/ANY/0001.patch +CVE-2025-39817/ANY/0001.patch +CVE-2025-39839/ANY/0001.patch +CVE-2025-39846/ANY/0001.patch +CVE-2025-39848/ANY/0001.patch +CVE-2025-39885/ANY/0001.patch +CVE-2025-39889/ANY/0001.patch +CVE-2025-39898/ANY/0001.patch +CVE-2025-39903/ANY/0001.patch +CVE-2025-39913/ANY/0001.patch +CVE-2025-39920/ANY/0001.patch +CVE-2025-39945/ANY/0001.patch +CVE-2025-39964/ANY/0001.patch +CVE-2025-39967/ANY/0001.patch +CVE-2025-39973/ANY/0001.patch +CVE-2025-39996/ANY/0001.patch +CVE-2025-40011/ANY/0001.patch +CVE-2025-40020/ANY/0001.patch +CVE-2025-40022/ANY/0001.patch +CVE-2025-40028/ANY/0001.patch +CVE-2025-40030/ANY/0001.patch +CVE-2025-40035/ANY/0001.patch +CVE-2025-40044/ANY/0001.patch +CVE-2025-40049/ANY/0001.patch +CVE-2025-40055/ANY/0001.patch +CVE-2025-40082/ANY/0001.patch +CVE-2019-12819/4.14/0006.patch +CVE-2021-47472/4.14/0003.patch +CVE-2023-53129/ANY/0001.patch +CVE-2023-53626/ANY/0001.patch +CVE-2024-26720/4.14/0009.patch +CVE-2024-39501/4.14/0009.patch +CVE-2024-42102/4.14/0009.patch +CVE-2024-50195/3.17-^6.12/0001.patch +CVE-2024-50210/3.17-^6.6/0001.patch diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/cve-denylist.txt b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-denylist.txt new file mode 100644 index 0000000..e3447a0 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-denylist.txt @@ -0,0 +1,38 @@ +# relative to AXP kernel_patches +# LAB 2026-10-01: alone ⇒ Google-logo hang (udc_lock recursive deadlock on +# msm-4.14; needs lock-scope companion, not one-liner). Do not re-apply. +CVE-2022-49980/ANY/0001.patch +CVE-2017-15832/qcacld-3.0/0001.patch +CVE-2021-29648/^5.11/0001.patch +CVE-2022-33246/audio-kernel/0002.patch +CVE-2022-49545/ANY/0001.patch +CVE-2022-49552/ANY/0001.patch +CVE-2022-49801/ANY/0001.patch +CVE-2022-50421/ANY/0001.patch +CVE-2023-33064/audio-kernel/0001.patch +CVE-2023-33065/audio-kernel/0001.patch +CVE-2023-43528/audio-kernel/0001.patch +CVE-2023-52741/^6.2/0001.patch +CVE-2023-53103/ANY/0001.patch +CVE-2023-53660/ANY/0001.patch +CVE-2024-21459/qca-wifi-host-cmn/0001.patch +CVE-2024-38564/^6.9/0001.patch +CVE-2024-56553/ANY/0001.patch +CVE-2024-56554/ANY/0001.patch +CVE-2024-56692/ANY/0001.patch +CVE-2024-56780/ANY/0001.patch +CVE-2025-21629/ANY/0001.patch +CVE-2025-21653/ANY/0001.patch +CVE-2025-21762/ANY/0001.patch +CVE-2025-21764/ANY/0001.patch +CVE-2025-21765/ANY/0001.patch +CVE-2025-21859/ANY/0001.patch +CVE-2025-21954/ANY/0001.patch +CVE-2025-22035/ANY/0001.patch +CVE-2025-37785/ANY/0001.patch +CVE-2025-37960/ANY/0001.patch +CVE-2025-38099/ANY/0001.patch +CVE-2025-38253/ANY/0001.patch +CVE-2025-38677/ANY/0001.patch +CVE-2025-39770/ANY/0001.patch +CVE-2025-39813/ANY/0001.patch diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/cve-high-offset-batch1.list b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-high-offset-batch1.list new file mode 100644 index 0000000..0e9d7fd --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-high-offset-batch1.list @@ -0,0 +1,9 @@ +# High-offset sunfish batch1 (fuzz=0 spot-checked). Applied with CVE_MAX_ABS_OFFSET=9999 +# after cve-clean-offset. Dropped CVE-2023-3777: nft_chain_is_bound missing on 4.14. +CVE-2020-29372/^5.7/0001.patch +CVE-2021-47209/^5.15/0001.patch +CVE-2022-50246/ANY/0001.patch +CVE-2023-53669/ANY/0001.patch +CVE-2024-40954/^6.10/0001.patch +CVE-2024-50186/^6.12/0001.patch +CVE-2024-43879/^6.10/0001.patch diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/cve-high-offset-batch2.list b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-high-offset-batch2.list new file mode 100644 index 0000000..2b8ee29 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-high-offset-batch2.list @@ -0,0 +1,10 @@ +# High-offset sunfish batch2 (after batch1 BOOT_OK #48). Elevated CVE_MAX_ABS_OFFSET=9999. +# Prefer mm/sched/sysctl/f2fs/wifi/driver-core; skip nf_tables-style (missing helpers). +CVE-2022-49641/ANY/0001.patch +CVE-2023-52707/^6.2/0001.patch +CVE-2023-53594/ANY/0001.patch +CVE-2023-53709/ANY/0001.patch +CVE-2024-40917/^6.10/0001.patch +CVE-2024-56569/ANY/0001.patch +CVE-2025-21909/ANY/0001.patch +CVE-2025-38218/ANY/0001.patch diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/cve-high-offset-batch3.list b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-high-offset-batch3.list new file mode 100644 index 0000000..979b760 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-high-offset-batch3.list @@ -0,0 +1,11 @@ +# High-offset sunfish batch3 — remaining KEEP after batch1+2 BOOT_OK #49. +# Skip CVE-2023-3777 / CVE-2024-26643 (nf_tables helpers missing on 4.14). +CVE-2021-47299/^5.13/0001.patch +CVE-2022-49341/ANY/0001.patch +CVE-2022-49412/ANY/0001.patch +CVE-2023-52676/^6.7/0001.patch +CVE-2024-46754/^6.10/0001.patch +CVE-2025-37923/ANY/0001.patch +CVE-2025-38285/ANY/0001.patch +CVE-2025-39751/ANY/0001.patch +CVE-2025-40078/ANY/0001.patch diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/cve-high-offset-ge200.txt b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-high-offset-ge200.txt new file mode 100644 index 0000000..75ae8f7 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-high-offset-ge200.txt @@ -0,0 +1,73 @@ +CVE-2020-29372/^5.7/0001.patch +CVE-2021-47209/^5.15/0001.patch +CVE-2021-47299/^5.13/0001.patch +CVE-2022-48825/^5.17/0001.patch +CVE-2022-48969/^6.1/0001.patch +CVE-2022-49086/ANY/0001.patch +CVE-2022-49341/ANY/0001.patch +CVE-2022-49412/ANY/0001.patch +CVE-2022-49641/ANY/0001.patch +CVE-2022-49687/ANY/0001.patch +CVE-2022-49695/ANY/0001.patch +CVE-2022-49715/ANY/0001.patch +CVE-2022-50246/ANY/0001.patch +CVE-2022-50304/ANY/0001.patch +CVE-2023-3777/^6.5/0001.patch +CVE-2023-52486/^6.7/0001.patch +CVE-2023-52676/^6.7/0001.patch +CVE-2023-52707/^6.2/0001.patch +CVE-2023-52847/^6.6/0001.patch +CVE-2023-53594/ANY/0001.patch +CVE-2023-53669/ANY/0001.patch +CVE-2023-53709/ANY/0001.patch +CVE-2024-2201/^6.9/0001.patch +CVE-2024-24855/^6.4/0001.patch +CVE-2024-26643/^6.8/0001.patch +CVE-2024-26900/^6.8/0001.patch +CVE-2024-39296/^6.9/0001.patch +CVE-2024-40917/^6.10/0001.patch +CVE-2024-40923/^6.10/0001.patch +CVE-2024-40954/^6.10/0001.patch +CVE-2024-41014/^6.10/0001.patch +CVE-2024-43879/^6.10/0001.patch +CVE-2024-46754/^6.10/0001.patch +CVE-2024-46830/^6.11/0001.patch +CVE-2024-50186/^6.12/0001.patch +CVE-2024-50273/^6.11/0001.patch +CVE-2024-53066/^6.12/0001.patch +CVE-2024-53173/ANY/0002.patch +CVE-2024-53217/ANY/0002.patch +CVE-2024-53240/ANY/0001.patch +CVE-2024-56558/ANY/0001.patch +CVE-2024-56569/ANY/0001.patch +CVE-2024-56596/ANY/0002.patch +CVE-2024-56598/ANY/0002.patch +CVE-2024-56605/ANY/0002.patch +CVE-2024-56779/ANY/0002.patch +CVE-2024-57849/ANY/0002.patch +CVE-2024-58009/ANY/0001.patch +CVE-2024-58083/ANY/0001.patch +CVE-2025-21671/ANY/0001.patch +CVE-2025-21909/ANY/0001.patch +CVE-2025-37789/ANY/0001.patch +CVE-2025-37795/ANY/0001.patch +CVE-2025-37839/ANY/0001.patch +CVE-2025-37923/ANY/0001.patch +CVE-2025-37932/ANY/0001.patch +CVE-2025-38034/ANY/0001.patch +CVE-2025-38044/ANY/0001.patch +CVE-2025-38200/ANY/0001.patch +CVE-2025-38204/ANY/0001.patch +CVE-2025-38218/ANY/0001.patch +CVE-2025-38285/ANY/0001.patch +CVE-2025-38473/ANY/0001.patch +CVE-2025-38495/ANY/0001.patch +CVE-2025-38498/ANY/0002.patch +CVE-2025-39742/ANY/0001.patch +CVE-2025-39751/ANY/0001.patch +CVE-2025-39824/ANY/0001.patch +CVE-2025-39847/ANY/0001.patch +CVE-2025-39874/ANY/0001.patch +CVE-2025-39998/ANY/0001.patch +CVE-2025-40078/ANY/0001.patch +CVE-2025-40080/ANY/0001.patch diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/cve-high-offset-sunfish-candidate.list b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-high-offset-sunfish-candidate.list new file mode 100644 index 0000000..0b15c8b --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-high-offset-sunfish-candidate.list @@ -0,0 +1,26 @@ +CVE-2020-29372/^5.7/0001.patch +CVE-2021-47209/^5.15/0001.patch +CVE-2021-47299/^5.13/0001.patch +CVE-2022-49341/ANY/0001.patch +CVE-2022-49412/ANY/0001.patch +CVE-2022-49641/ANY/0001.patch +CVE-2022-50246/ANY/0001.patch +CVE-2023-3777/^6.5/0001.patch +CVE-2023-52676/^6.7/0001.patch +CVE-2023-52707/^6.2/0001.patch +CVE-2023-53594/ANY/0001.patch +CVE-2023-53669/ANY/0001.patch +CVE-2023-53709/ANY/0001.patch +CVE-2024-26643/^6.8/0001.patch +CVE-2024-40917/^6.10/0001.patch +CVE-2024-40954/^6.10/0001.patch +CVE-2024-43879/^6.10/0001.patch +CVE-2024-46754/^6.10/0001.patch +CVE-2024-50186/^6.12/0001.patch +CVE-2024-56569/ANY/0001.patch +CVE-2025-21909/ANY/0001.patch +CVE-2025-37923/ANY/0001.patch +CVE-2025-38218/ANY/0001.patch +CVE-2025-38285/ANY/0001.patch +CVE-2025-39751/ANY/0001.patch +CVE-2025-40078/ANY/0001.patch diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/cve-high-offset-sunfish-skip.list b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-high-offset-sunfish-skip.list new file mode 100644 index 0000000..ac55beb --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-high-offset-sunfish-skip.list @@ -0,0 +1,47 @@ +CVE-2022-48825/^5.17/0001.patch # no_live_path_match +CVE-2022-48969/^6.1/0001.patch # deadnet +CVE-2022-49086/ANY/0001.patch # deadnet +CVE-2022-49687/ANY/0001.patch # deadnet +CVE-2022-49695/ANY/0001.patch # deadnet +CVE-2022-49715/ANY/0001.patch # no_live_path_match +CVE-2022-50304/ANY/0001.patch # no_live_path_match +CVE-2023-52486/^6.7/0001.patch # no_live_path_match +CVE-2023-52847/^6.6/0001.patch # no_live_path_match +CVE-2024-2201/^6.9/0001.patch # offarch +CVE-2024-24855/^6.4/0001.patch # no_live_path_match +CVE-2024-26900/^6.8/0001.patch # no_live_path_match +CVE-2024-39296/^6.9/0001.patch # deadnet +CVE-2024-40923/^6.10/0001.patch # deadnet +CVE-2024-41014/^6.10/0001.patch # deadfs +CVE-2024-46830/^6.11/0001.patch # offarch +CVE-2024-50273/^6.11/0001.patch # deadfs +CVE-2024-53066/^6.12/0001.patch # deadfs +CVE-2024-53173/ANY/0002.patch # deadfs +CVE-2024-53217/ANY/0002.patch # deadfs +CVE-2024-53240/ANY/0001.patch # deadnet +CVE-2024-56558/ANY/0001.patch # deadfs +CVE-2024-56596/ANY/0002.patch # no_live_path_match +CVE-2024-56598/ANY/0002.patch # no_live_path_match +CVE-2024-56605/ANY/0002.patch # no_live_path_match +CVE-2024-56779/ANY/0002.patch # deadfs +CVE-2024-57849/ANY/0002.patch # offarch +CVE-2024-58009/ANY/0001.patch # no_live_path_match +CVE-2024-58083/ANY/0001.patch # no_live_path_match +CVE-2025-21671/ANY/0001.patch # no_live_path_match +CVE-2025-37789/ANY/0001.patch # deadnet +CVE-2025-37795/ANY/0001.patch # no_live_path_match +CVE-2025-37839/ANY/0001.patch # no_live_path_match +CVE-2025-37932/ANY/0001.patch # no_live_path_match +CVE-2025-38034/ANY/0001.patch # no_live_path_match +CVE-2025-38044/ANY/0001.patch # no_live_path_match +CVE-2025-38200/ANY/0001.patch # no_live_path_match +CVE-2025-38204/ANY/0001.patch # no_live_path_match +CVE-2025-38473/ANY/0001.patch # no_live_path_match +CVE-2025-38495/ANY/0001.patch # no_live_path_match +CVE-2025-38498/ANY/0002.patch # no_live_path_match +CVE-2025-39742/ANY/0001.patch # no_live_path_match +CVE-2025-39824/ANY/0001.patch # no_live_path_match +CVE-2025-39847/ANY/0001.patch # no_live_path_match +CVE-2025-39874/ANY/0001.patch # no_live_path_match +CVE-2025-39998/ANY/0001.patch # no_live_path_match +CVE-2025-40080/ANY/0001.patch # no_live_path_match diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/cve-strict.list b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-strict.list new file mode 100644 index 0000000..4cf0c9a --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/cve-strict.list @@ -0,0 +1,503 @@ +0003-syzkaller-Misc/ANY/0008.patch +CVE-2015-7837/ANY/0001.patch +CVE-2016-3695/ANY/0001.patch +CVE-2017-5754/^4.19/0157.patch +CVE-2017-18232/4.14/0002.patch +CVE-2018-5897/ANY/0001.patch +CVE-2018-9415/ANY/0005.patch +CVE-2018-20855/^4.18/0001.patch +CVE-2019-3874/^5.1/0002.patch +CVE-2019-9444/ANY/0001.patch +CVE-2019-10520/ANY/0001.patch +CVE-2019-11191/^5.0/0001.patch +CVE-2019-12378/^5.1.5/0001.patch +CVE-2019-12455/^5.2/0001.patch +CVE-2019-12456/^5.1.5/0002.patch +CVE-2019-15291/4.14/0004.patch +CVE-2019-16921/^4.16/0001.patch +CVE-2019-18786/4.14/0002.patch +CVE-2019-19051/4.14/0008.patch +CVE-2019-19068/4.14/0002.patch +CVE-2019-19602/^5.4/0001.patch +CVE-2019-20908/^5.2/0001.patch +CVE-2020-0255/^5.6/0001.patch +CVE-2020-8832/^4.14/0001.patch +CVE-2020-15780/^5.8/0001.patch +CVE-2020-16119/^5.10/0002.patch +CVE-2020-29372/^5.7/0001.patch +CVE-2020-BleedingToothExtras/^5.10/0001.patch +CVE-2021-3493/^5.10/0001.patch +CVE-2021-28039/^5.11/0001.patch +CVE-2021-28950/4.14/0002.patch +CVE-2021-29154/^5.12/0002.patch +CVE-2021-30337/4.14/0018.patch +CVE-2021-46912/^5.12/0001.patch +CVE-2021-46958/^5.12/0001.patch +CVE-2021-46999/^5.12/0001.patch +CVE-2021-47010/^5.12/0001.patch +CVE-2021-47058/^5.12/0001.patch +CVE-2021-47173/4.14/0003.patch +CVE-2021-47209/^5.15/0001.patch +CVE-2021-47234/^5.13/0001.patch +CVE-2021-47266/^5.13/0001.patch +CVE-2021-47299/^5.13/0001.patch +CVE-2021-47346/^5.13/0001.patch +CVE-2021-47430/^5.15/0001.patch +CVE-2021-47472/4.14/0003.patch +CVE-2021-47583/^5.15/0001.patch +CVE-2021-47616/^5.16/0001.patch +CVE-2021-47618/^5.16/0001.patch +CVE-2021-47636/ANY/0001.patch +CVE-2022-3061/^5.18/0001.patch +CVE-2022-3903/^6.0/0001.patch +CVE-2022-4382/^6.2/0001.patch +CVE-2022-21546/ANY/0001.patch +CVE-2022-27950/^5.16/0001.patch +CVE-2022-48674/^6.0/0001.patch +CVE-2022-48713/^5.17/0001.patch +CVE-2022-48781/^5.17/0001.patch +CVE-2022-48785/^5.17/0001.patch +CVE-2022-48825/^5.17/0001.patch +CVE-2022-48966/4.14/0002.patch +CVE-2022-48969/^6.1/0001.patch +CVE-2022-49034/ANY/0002.patch +CVE-2022-49061/4.14/0002.patch +CVE-2022-49073/ANY/0001.patch +CVE-2022-49078/ANY/0001.patch +CVE-2022-49086/ANY/0001.patch +CVE-2022-49146/ANY/0001.patch +CVE-2022-49194/ANY/0001.patch +CVE-2022-49205/ANY/0001.patch +CVE-2022-49209/ANY/0001.patch +CVE-2022-49285/ANY/0001.patch +CVE-2022-49318/ANY/0001.patch +CVE-2022-49341/ANY/0001.patch +CVE-2022-49363/ANY/0001.patch +CVE-2022-49364/ANY/0001.patch +CVE-2022-49380/ANY/0001.patch +CVE-2022-49412/ANY/0001.patch +CVE-2022-49425/ANY/0001.patch +CVE-2022-49428/ANY/0001.patch +CVE-2022-49433/ANY/0001.patch +CVE-2022-49500/ANY/0001.patch +CVE-2022-49513/ANY/0001.patch +CVE-2022-49563/ANY/0001.patch +CVE-2022-49564/ANY/0001.patch +CVE-2022-49566/ANY/0001.patch +CVE-2022-49641/ANY/0001.patch +CVE-2022-49642/ANY/0001.patch +CVE-2022-49687/ANY/0001.patch +CVE-2022-49695/ANY/0001.patch +CVE-2022-49705/ANY/0001.patch +CVE-2022-49710/ANY/0001.patch +CVE-2022-49715/ANY/0001.patch +CVE-2022-49777/ANY/0001.patch +CVE-2022-49779/ANY/0001.patch +CVE-2022-49784/ANY/0001.patch +CVE-2022-49823/ANY/0001.patch +CVE-2022-49824/ANY/0001.patch +CVE-2022-49825/ANY/0001.patch +CVE-2022-49839/ANY/0001.patch +CVE-2022-49863/ANY/0001.patch +CVE-2022-49980/ANY/0001.patch +CVE-2022-49990/ANY/0001.patch +CVE-2022-49993/4.14/0003.patch +CVE-2022-50013/ANY/0001.patch +CVE-2022-50062/ANY/0001.patch +CVE-2022-50074/ANY/0001.patch +CVE-2022-50246/ANY/0001.patch +CVE-2022-50248/ANY/0001.patch +CVE-2022-50273/ANY/0001.patch +CVE-2022-50304/ANY/0001.patch +CVE-2022-50326/ANY/0001.patch +CVE-2022-50358/ANY/0001.patch +CVE-2022-50364/ANY/0001.patch +CVE-2022-50397/ANY/0001.patch +CVE-2022-50473/ANY/0001.patch +CVE-2022-50522/4.14/0003.patch +CVE-2022-50537/ANY/0001.patch +CVE-2023-1989/4.14/0003.patch +CVE-2023-3777/^6.5/0001.patch +CVE-2023-21657/4.14/0005.patch +CVE-2023-23000/^5.16/0001.patch +CVE-2023-28554/ANY/0002.patch +CVE-2023-33070/ANY/0001.patch +CVE-2023-52486/^6.7/0001.patch +CVE-2023-52523/^6.6/0001.patch +CVE-2023-52595/^6.6/0001.patch +CVE-2023-52604/4.14/0009.patch +CVE-2023-52676/^6.7/0001.patch +CVE-2023-52707/^6.2/0001.patch +CVE-2023-52746/^6.2/0001.patch +CVE-2023-52847/^6.6/0001.patch +CVE-2023-52884/^6.5/0001.patch +CVE-2023-52979/4.14/0003.patch +CVE-2023-53001/ANY/0001.patch +CVE-2023-53016/ANY/0001.patch +CVE-2023-53098/ANY/0001.patch +CVE-2023-53125/4.14/0003.patch +CVE-2023-53131/ANY/0001.patch +CVE-2023-53137/ANY/0001.patch +CVE-2023-53214/ANY/0001.patch +CVE-2023-53227/4.14/0003.patch +CVE-2023-53250/ANY/0001.patch +CVE-2023-53259/ANY/0002.patch +CVE-2023-53265/4.14/0003.patch +CVE-2023-53288/ANY/0001.patch +CVE-2023-53312/ANY/0001.patch +CVE-2023-53436/4.14/0003.patch +CVE-2023-53443/ANY/0001.patch +CVE-2023-53487/ANY/0002.patch +CVE-2023-53537/ANY/0001.patch +CVE-2023-53594/ANY/0001.patch +CVE-2023-53599/ANY/0001.patch +CVE-2023-53641/ANY/0001.patch +CVE-2023-53669/ANY/0001.patch +CVE-2023-53693/ANY/0001.patch +CVE-2023-53695/ANY/0001.patch +CVE-2023-53709/ANY/0001.patch +CVE-2023-53712/ANY/0001.patch +CVE-2023-53719/ANY/0001.patch +CVE-2024-2201/^6.9/0001.patch +CVE-2024-24855/^6.4/0001.patch +CVE-2024-26643/^6.8/0001.patch +CVE-2024-26645/^6.8/0001.patch +CVE-2024-26720/4.14/0009.patch +CVE-2024-26760/^6.8/0001.patch +CVE-2024-26900/^6.8/0001.patch +CVE-2024-26920/4.14/0009.patch +CVE-2024-26961/^6.7/0001.patch +CVE-2024-26972/^6.8/0001.patch +CVE-2024-27009/^6.9/0001.patch +CVE-2024-27033/^6.8/0001.patch +CVE-2024-27393/^6.9/0001.patch +CVE-2024-33032/ANY/0002.patch +CVE-2024-34027/^6.9/0001.patch +CVE-2024-35812/4.14/0009.patch +CVE-2024-35824/^6.8/0001.patch +CVE-2024-35879/^6.9/0001.patch +CVE-2024-35933/4.14/0008.patch +CVE-2024-35950/^6.9/0001.patch +CVE-2024-35954/^6.9/0001.patch +CVE-2024-35962/^6.9/0001.patch +CVE-2024-39296/^6.9/0001.patch +CVE-2024-40917/^6.10/0001.patch +CVE-2024-40923/^6.10/0001.patch +CVE-2024-40954/^6.10/0001.patch +CVE-2024-40996/^6.10/0001.patch +CVE-2024-41014/^6.10/0001.patch +CVE-2024-41041/^6.10/0001.patch +CVE-2024-42077/^6.10/0001.patch +CVE-2024-42102/4.14/0009.patch +CVE-2024-42296/^6.10/0001.patch +CVE-2024-43879/^6.10/0001.patch +CVE-2024-43894/^6.11/0001.patch +CVE-2024-44938/^6.9/0001.patch +CVE-2024-44939/^6.9/0001.patch +CVE-2024-44952/4.14/0008.patch +CVE-2024-46681/^6.11/0001.patch +CVE-2024-46754/^6.10/0001.patch +CVE-2024-46830/^6.11/0001.patch +CVE-2024-47747/^6.11/0001.patch +CVE-2024-50017/^6.11/0001.patch +CVE-2024-50019/^6.12/0001.patch +CVE-2024-50184/^6.11/0001.patch +CVE-2024-50186/^6.12/0001.patch +CVE-2024-50195/3.17-^6.12/0001.patch +CVE-2024-50201/^6.12/0001.patch +CVE-2024-50210/3.17-^6.6/0001.patch +CVE-2024-50265/^6.12/0001.patch +CVE-2024-50267/^6.12/0001.patch +CVE-2024-50269/^6.12/0001.patch +CVE-2024-50273/^6.11/0001.patch +CVE-2024-50279/^6.12/0001.patch +CVE-2024-50287/^6.12/0001.patch +CVE-2024-50290/^6.12/0001.patch +CVE-2024-50292/^6.12/0001.patch +CVE-2024-50295/^6.12/0001.patch +CVE-2024-50299/^6.12/0001.patch +CVE-2024-50301/^6.12/0001.patch +CVE-2024-52332/ANY/0002.patch +CVE-2024-53045/^6.12/0001.patch +CVE-2024-53066/^6.12/0001.patch +CVE-2024-53101/^6.12/0001.patch +CVE-2024-53103/^6.12/0001.patch +CVE-2024-53112/^6.12/0001.patch +CVE-2024-53127/^6.12/0001.patch +CVE-2024-53140/^6.12/0001.patch +CVE-2024-53141/^6.12/0001.patch +CVE-2024-53156/ANY/0002.patch +CVE-2024-53157/ANY/0002.patch +CVE-2024-53165/ANY/0002.patch +CVE-2024-53171/ANY/0001.patch +CVE-2024-53172/ANY/0002.patch +CVE-2024-53173/ANY/0002.patch +CVE-2024-53183/ANY/0002.patch +CVE-2024-53190/ANY/0001.patch +CVE-2024-53194/ANY/0002.patch +CVE-2024-53214/ANY/0002.patch +CVE-2024-53217/ANY/0002.patch +CVE-2024-53227/ANY/0002.patch +CVE-2024-53239/ANY/0001.patch +CVE-2024-53240/ANY/0001.patch +CVE-2024-53680/ANY/0002.patch +CVE-2024-53690/ANY/0001.patch +CVE-2024-56531/ANY/0002.patch +CVE-2024-56532/ANY/0002.patch +CVE-2024-56536/ANY/0001.patch +CVE-2024-56539/ANY/0002.patch +CVE-2024-56548/ANY/0002.patch +CVE-2024-56558/ANY/0001.patch +CVE-2024-56569/ANY/0001.patch +CVE-2024-56570/ANY/0001.patch +CVE-2024-56586/ANY/0001.patch +CVE-2024-56587/ANY/0002.patch +CVE-2024-56593/ANY/0001.patch +CVE-2024-56595/ANY/0002.patch +CVE-2024-56596/ANY/0002.patch +CVE-2024-56597/ANY/0002.patch +CVE-2024-56598/ANY/0002.patch +CVE-2024-56600/ANY/0001.patch +CVE-2024-56602/ANY/0001.patch +CVE-2024-56603/ANY/0002.patch +CVE-2024-56605/ANY/0002.patch +CVE-2024-56619/ANY/0002.patch +CVE-2024-56629/ANY/0001.patch +CVE-2024-56637/ANY/0002.patch +CVE-2024-56643/ANY/0002.patch +CVE-2024-56659/ANY/0002.patch +CVE-2024-56670/ANY/0002.patch +CVE-2024-56681/ANY/0001.patch +CVE-2024-56687/ANY/0001.patch +CVE-2024-56700/ANY/0002.patch +CVE-2024-56739/ANY/0002.patch +CVE-2024-56747/ANY/0001.patch +CVE-2024-56767/ANY/0002.patch +CVE-2024-56769/ANY/0002.patch +CVE-2024-56779/ANY/0002.patch +CVE-2024-57802/ANY/0002.patch +CVE-2024-57849/ANY/0002.patch +CVE-2024-57850/ANY/0002.patch +CVE-2024-57893/ANY/0001.patch +CVE-2024-57901/ANY/0001.patch +CVE-2024-57902/ANY/0001.patch +CVE-2024-57904/ANY/0001.patch +CVE-2024-57908/ANY/0001.patch +CVE-2024-57912/ANY/0001.patch +CVE-2024-57929/ANY/0001.patch +CVE-2024-57938/ANY/0002.patch +CVE-2024-57948/ANY/0001.patch +CVE-2024-57973/ANY/0001.patch +CVE-2024-58001/ANY/0001.patch +CVE-2024-58009/ANY/0001.patch +CVE-2024-58010/ANY/0001.patch +CVE-2024-58055/ANY/0001.patch +CVE-2024-58083/ANY/0001.patch +CVE-2024-58094/ANY/0001.patch +CVE-2024-58095/ANY/0001.patch +CVE-2025-21664/ANY/0001.patch +CVE-2025-21671/ANY/0001.patch +CVE-2025-21689/ANY/0001.patch +CVE-2025-21699/ANY/0001.patch +CVE-2025-21704/ANY/0001.patch +CVE-2025-21718/ANY/0001.patch +CVE-2025-21735/ANY/0001.patch +CVE-2025-21736/ANY/0001.patch +CVE-2025-21744/ANY/0001.patch +CVE-2025-21772/ANY/0001.patch +CVE-2025-21776/ANY/0001.patch +CVE-2025-21781/ANY/0001.patch +CVE-2025-21782/ANY/0001.patch +CVE-2025-21785/ANY/0001.patch +CVE-2025-21791/ANY/0001.patch +CVE-2025-21835/ANY/0001.patch +CVE-2025-21877/ANY/0001.patch +CVE-2025-21904/ANY/0001.patch +CVE-2025-21909/ANY/0001.patch +CVE-2025-21910/ANY/0001.patch +CVE-2025-21916/ANY/0001.patch +CVE-2025-21928/ANY/0001.patch +CVE-2025-21934/ANY/0001.patch +CVE-2025-21935/ANY/0001.patch +CVE-2025-21948/ANY/0001.patch +CVE-2025-21993/ANY/0001.patch +CVE-2025-21996/ANY/0001.patch +CVE-2025-22007/ANY/0001.patch +CVE-2025-22018/ANY/0001.patch +CVE-2025-22063/ANY/0001.patch +CVE-2025-22073/ANY/0001.patch +CVE-2025-22079/ANY/0001.patch +CVE-2025-22086/ANY/0001.patch +CVE-2025-23150/ANY/0001.patch +CVE-2025-23163/ANY/0001.patch +CVE-2025-37738/ANY/0001.patch +CVE-2025-37739/ANY/0001.patch +CVE-2025-37740/ANY/0001.patch +CVE-2025-37741/ANY/0001.patch +CVE-2025-37749/ANY/0001.patch +CVE-2025-37757/ANY/0001.patch +CVE-2025-37758/ANY/0001.patch +CVE-2025-37780/ANY/0001.patch +CVE-2025-37781/ANY/0001.patch +CVE-2025-37782/ANY/0001.patch +CVE-2025-37789/ANY/0001.patch +CVE-2025-37795/ANY/0001.patch +CVE-2025-37796/ANY/0001.patch +CVE-2025-37797/ANY/0001.patch +CVE-2025-37798/ANY/0001.patch +CVE-2025-37817/ANY/0001.patch +CVE-2025-37823/ANY/0001.patch +CVE-2025-37825/ANY/0001.patch +CVE-2025-37833/ANY/0001.patch +CVE-2025-37838/ANY/0001.patch +CVE-2025-37839/ANY/0001.patch +CVE-2025-37841/ANY/0001.patch +CVE-2025-37851/ANY/0001.patch +CVE-2025-37857/ANY/0001.patch +CVE-2025-37858/ANY/0001.patch +CVE-2025-37892/ANY/0001.patch +CVE-2025-37923/ANY/0001.patch +CVE-2025-37925/ANY/0001.patch +CVE-2025-37932/ANY/0001.patch +CVE-2025-37937/ANY/0002.patch +CVE-2025-37982/ANY/0001.patch +CVE-2025-37983/ANY/0001.patch +CVE-2025-37990/ANY/0001.patch +CVE-2025-38034/ANY/0001.patch +CVE-2025-38044/ANY/0001.patch +CVE-2025-38046/ANY/0001.patch +CVE-2025-38058/ANY/0001.patch +CVE-2025-38061/ANY/0001.patch +CVE-2025-38066/ANY/0001.patch +CVE-2025-38075/ANY/0001.patch +CVE-2025-38090/ANY/0001.patch +CVE-2025-38114/ANY/0001.patch +CVE-2025-38115/ANY/0001.patch +CVE-2025-38147/ANY/0001.patch +CVE-2025-38157/ANY/0001.patch +CVE-2025-38163/ANY/0001.patch +CVE-2025-38174/ANY/0001.patch +CVE-2025-38177/ANY/0001.patch +CVE-2025-38180/ANY/0001.patch +CVE-2025-38181/ANY/0001.patch +CVE-2025-38184/ANY/0001.patch +CVE-2025-38185/ANY/0001.patch +CVE-2025-38190/ANY/0001.patch +CVE-2025-38194/ANY/0001.patch +CVE-2025-38200/ANY/0001.patch +CVE-2025-38203/ANY/0001.patch +CVE-2025-38204/ANY/0001.patch +CVE-2025-38212/ANY/0001.patch +CVE-2025-38213/ANY/0001.patch +CVE-2025-38218/ANY/0001.patch +CVE-2025-38219/ANY/0001.patch +CVE-2025-38222/ANY/0001.patch +CVE-2025-38245/ANY/0001.patch +CVE-2025-38251/ANY/0001.patch +CVE-2025-38265/ANY/0001.patch +CVE-2025-38285/ANY/0001.patch +CVE-2025-38312/ANY/0001.patch +CVE-2025-38320/ANY/0001.patch +CVE-2025-38324/ANY/0001.patch +CVE-2025-38328/ANY/0001.patch +CVE-2025-38336/ANY/0001.patch +CVE-2025-38344/ANY/0001.patch +CVE-2025-38345/ANY/0001.patch +CVE-2025-38348/ANY/0001.patch +CVE-2025-38386/ANY/0001.patch +CVE-2025-38403/ANY/0001.patch +CVE-2025-38406/ANY/0001.patch +CVE-2025-38416/ANY/0001.patch +CVE-2025-38420/ANY/0001.patch +CVE-2025-38428/ANY/0001.patch +CVE-2025-38445/ANY/0001.patch +CVE-2025-38448/ANY/0001.patch +CVE-2025-38458/ANY/0001.patch +CVE-2025-38459/ANY/0001.patch +CVE-2025-38460/ANY/0001.patch +CVE-2025-38467/ANY/0001.patch +CVE-2025-38468/ANY/0001.patch +CVE-2025-38470/ANY/0001.patch +CVE-2025-38473/ANY/0001.patch +CVE-2025-38474/ANY/0001.patch +CVE-2025-38495/ANY/0001.patch +CVE-2025-38498/ANY/0002.patch +CVE-2025-38513/ANY/0001.patch +CVE-2025-38514/ANY/0001.patch +CVE-2025-38538/ANY/0001.patch +CVE-2025-38542/ANY/0001.patch +CVE-2025-38544/ANY/0001.patch +CVE-2025-38546/ANY/0001.patch +CVE-2025-38555/ANY/0001.patch +CVE-2025-38574/ANY/0001.patch +CVE-2025-38578/ANY/0001.patch +CVE-2025-38581/ANY/0001.patch +CVE-2025-38604/ANY/0001.patch +CVE-2025-38611/ANY/0001.patch +CVE-2025-38612/ANY/0001.patch +CVE-2025-38618/ANY/0001.patch +CVE-2025-38639/ANY/0001.patch +CVE-2025-38691/ANY/0001.patch +CVE-2025-38693/ANY/0001.patch +CVE-2025-38694/ANY/0001.patch +CVE-2025-38697/ANY/0001.patch +CVE-2025-38698/ANY/0001.patch +CVE-2025-38699/ANY/0001.patch +CVE-2025-38701/ANY/0001.patch +CVE-2025-38708/ANY/0001.patch +CVE-2025-38712/ANY/0001.patch +CVE-2025-38713/ANY/0001.patch +CVE-2025-38717/ANY/0001.patch +CVE-2025-39676/ANY/0001.patch +CVE-2025-39691/ANY/0001.patch +CVE-2025-39710/ANY/0001.patch +CVE-2025-39714/ANY/0001.patch +CVE-2025-39742/ANY/0001.patch +CVE-2025-39743/ANY/0001.patch +CVE-2025-39751/ANY/0001.patch +CVE-2025-39756/ANY/0001.patch +CVE-2025-39782/ANY/0001.patch +CVE-2025-39794/ANY/0001.patch +CVE-2025-39796/ANY/0001.patch +CVE-2025-39808/ANY/0001.patch +CVE-2025-39812/ANY/0001.patch +CVE-2025-39817/ANY/0001.patch +CVE-2025-39824/ANY/0001.patch +CVE-2025-39839/ANY/0001.patch +CVE-2025-39846/ANY/0001.patch +CVE-2025-39847/ANY/0001.patch +CVE-2025-39848/ANY/0001.patch +CVE-2025-39874/ANY/0001.patch +CVE-2025-39885/ANY/0001.patch +CVE-2025-39889/ANY/0001.patch +CVE-2025-39898/ANY/0001.patch +CVE-2025-39903/ANY/0001.patch +CVE-2025-39913/ANY/0001.patch +CVE-2025-39920/ANY/0001.patch +CVE-2025-39945/ANY/0001.patch +CVE-2025-39964/ANY/0001.patch +CVE-2025-39967/ANY/0001.patch +CVE-2025-39973/ANY/0001.patch +CVE-2025-39996/ANY/0001.patch +CVE-2025-39998/ANY/0001.patch +CVE-2025-40011/ANY/0001.patch +CVE-2025-40020/ANY/0001.patch +CVE-2025-40022/ANY/0001.patch +CVE-2025-40028/ANY/0001.patch +CVE-2025-40030/ANY/0001.patch +CVE-2025-40035/ANY/0001.patch +CVE-2025-40044/ANY/0001.patch +CVE-2025-40049/ANY/0001.patch +CVE-2025-40055/ANY/0001.patch +CVE-2025-40078/ANY/0001.patch +CVE-2025-40080/ANY/0001.patch +CVE-2025-40082/ANY/0001.patch +CVE-2019-12819/4.14/0006.patch +CVE-2021-47472/4.14/0003.patch +CVE-2023-53129/ANY/0001.patch +CVE-2023-53626/ANY/0001.patch +CVE-2024-26720/4.14/0009.patch +CVE-2024-39501/4.14/0009.patch +CVE-2024-42102/4.14/0009.patch +CVE-2024-50195/3.17-^6.12/0001.patch +CVE-2024-50210/3.17-^6.6/0001.patch diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/fortify-clang/0001-driver-bounds-rtac-fils.patch b/vendor/sunfish-a16/patches/009-kernel-hardening/fortify-clang/0001-driver-bounds-rtac-fils.patch new file mode 100644 index 0000000..f8bebe5 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/fortify-clang/0001-driver-bounds-rtac-fils.patch @@ -0,0 +1,27 @@ +--- a/techpack/audio/dsp/rtac.c ++++ b/techpack/audio/dsp/rtac.c +@@ -652,6 +652,12 @@ + pr_debug("%s\n", __func__); + + mutex_lock(&rtac_voice_mutex); ++ if (rtac_voice_data.num_of_voice_combos > ARRAY_SIZE(rtac_voice_data.voice)) { ++ pr_err("%s: invalid voice count %u\n", __func__, ++ rtac_voice_data.num_of_voice_combos); ++ mutex_unlock(&rtac_voice_mutex); ++ return; ++ } + /* look for device */ + for (i = 0; i < rtac_voice_data.num_of_voice_combos; i++) { + if (rtac_voice_data.voice[i].cvs_handle == cvs_handle) { +--- a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_fils.c ++++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_fils.c +@@ -1092,6 +1092,9 @@ + return false; + } + ++ if (dot11f_ie_rsn.pmkid_count > ARRAY_SIZE(dot11f_ie_rsn.pmkid)) ++ return false; ++ + for (i = 0; i < dot11f_ie_rsn.pmkid_count; i++) { + if (qdf_mem_cmp(dot11f_ie_rsn.pmkid[i], + pe_session->fils_info->fils_pmkid, diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/fortify-clang/README.md b/vendor/sunfish-a16/patches/009-kernel-hardening/fortify-clang/README.md new file mode 100644 index 0000000..ddaea85 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/fortify-clang/README.md @@ -0,0 +1,36 @@ +# FORTIFY Clang port for msm-4.14 (LOS sunfish) + +Based on Kees Cook *fortify: Add Clang support* (upstream ~2022), adapted +to 4.14’s in-`string.h` FORTIFY (no `fortify-string.h` yet). + +**Not** AXP `0004` (strict-string). **Not** `BUG()` link stubs. + +See `docs/009-fortify-clang-port.md`. + +## Apply + +```bash +# on rom-dev01, after git reset of msm-4.14: +python3 apply_fortify_clang.py /path/to/msm-4.14 +patch -p1 -d /path/to/msm-4.14 < 0001-driver-bounds-rtac-fils.patch +``` + +`ksync-one.sh` with `CONFIG_FORTIFY_SOURCE` runs both automatically. + +Then enable `CONFIG_FORTIFY_SOURCE=y` and build **without** +`ALLOW_FORTIFY_BUG_STUBS`. + +## Nested strlen (required) + +With Clang `__pass_object_size`, fortified `strlcpy`/`strcpy` must call +`__underlying_strlen(q)`, not fortified `strlen(q)`. Otherwise a known +source object size makes `strlen` panic at boot (LAB: `strlen+strlcpy` +fail; `strlen+strncpy` OK). `apply_fortify_clang.py` rewrites both. + +## Diag capture (v4) + +`apply_fortify_diag.py` — `early_ioremap` before `parse_early_param`, ordinary +`ioremap` only after `mm_init`, never map from the failure handler; failure +and milestone zones separated. See `docs/009-fortify-diag-capture-plan.md` +and `docs/009-fortify-diag-v3-review-20260927.md`. Control: +`PSTORE_ALT_PLAIN=1` / `scripts/009-bisect-ksync-pstore-alt-plain.sh`. diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/fortify-clang/apply_fortify_clang.py b/vendor/sunfish-a16/patches/009-kernel-hardening/fortify-clang/apply_fortify_clang.py new file mode 100644 index 0000000..c382b3a --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/fortify-clang/apply_fortify_clang.py @@ -0,0 +1,244 @@ +#!/usr/bin/env python3 +"""Apply minimal Clang FORTIFY adaptations to msm-4.14 (Kees-style). + +Edits: + - include/linux/compiler-clang.h — __pass_object_size / __overloadable / __diagnose_as + - include/linux/string.h — __FORTIFY_INLINE + POS/POS0 on fortified params + - security/Kconfig — allow FORTIFY on Clang when this port is present + (tree lacks CC_IS_CLANG Kconfig symbols; !CC_IS_CLANG was a no-op) + +Idempotent. Exit 0 on success. +""" +from __future__ import annotations + +import re +import sys +from pathlib import Path + +MARKER = "/* AXP_Resurection: fortify-clang port (Kees-style) */" + + +def patch_compiler_clang(path: Path) -> None: + t = path.read_text() + if MARKER in t and "__pass_object_size" in t: + print(f"skip {path} (already patched)") + return + if "__pass_object_size" in t: + print(f"skip {path} (attrs already present)") + return + block = f""" +{MARKER} +/* + * Clang FORTIFY helpers (upstream fortify Clang support / Kees Cook). + * pass_object_size makes __builtin_object_size work through fortified inlines. + */ +#if __has_attribute(pass_object_size) +# define __pass_object_size(type) __attribute__((__pass_object_size__(type))) +#else +# define __pass_object_size(type) +#endif +#if __has_attribute(overloadable) +# define __overloadable __attribute__((__overloadable__)) +#else +# define __overloadable +#endif +#if __has_attribute(diagnose_as_builtin) +# define __diagnose_as(builtin...) __attribute__((__diagnose_as_builtin__(builtin))) +#else +# define __diagnose_as(builtin...) +#endif +""" + path.write_text(t.rstrip() + "\n" + block + "\n") + print(f"patched {path}") + + +def patch_kconfig(path: Path) -> None: + t = path.read_text() + old = ( + "\t# https://bugs.llvm.org/show_bug.cgi?id=50322\n" + "\t# https://bugs.llvm.org/show_bug.cgi?id=41459\n" + "\tdepends on !CC_IS_CLANG\n" + ) + new = ( + "\t# Clang: upstream disabled FORTIFY until wrappers existed (LLVM 41459).\n" + "\t# This tree never defined CC_IS_CLANG, so !CC_IS_CLANG was a no-op.\n" + "\t# Fortify-clang port (vendor/.../fortify-clang) supplies Kees-style\n" + "\t# __pass_object_size / __overloadable wrappers for Clang 12+.\n" + "\t# https://bugs.llvm.org/show_bug.cgi?id=41459\n" + ) + if MARKER.split()[2] in t and "Fortify-clang port" in t: + print(f"skip {path} (already patched)") + return + if old not in t: + if "depends on !CC_IS_CLANG" in t: + t2 = t.replace( + "\tdepends on !CC_IS_CLANG\n", + new, + 1, + ) + if t2 == t: + raise SystemExit(f"could not patch {path}") + path.write_text(t2) + print(f"patched {path} (depends line only)") + return + raise SystemExit(f"FORTIFY depends block not found in {path}") + path.write_text(t.replace(old, new, 1)) + print(f"patched {path}") + + +def patch_string_h(path: Path) -> None: + t = path.read_text() + if "AXP_Resurection: fortify-clang" in t and "POS0" in t: + print(f"skip {path} (already patched)") + return + + old_inline = ( + "#define __FORTIFY_INLINE extern __always_inline __attribute__((gnu_inline))\n" + ) + # 4.14 fortify bodies all use __builtin_object_size(*, 0) (whole object). + # pass_object_size(N) must match that N or Clang returns -1 (no checking). + # Do NOT use pass_object_size(1) here — that is STRICT_STRING / type-1 policy + # (AXP 0004), a separate step. See docs/009-fortify-port-review-20260926.md. + new_inline = ( + f"{MARKER}\n" + "/* Clang: __overloadable + __pass_object_size matching bos type 0. */\n" + "#ifdef __clang__\n" + "# define __FORTIFY_INLINE extern __always_inline __attribute__((gnu_inline)) __overloadable\n" + "# define POS __pass_object_size(0)\n" + "# define POS0 __pass_object_size(0)\n" + "#else\n" + "# define __FORTIFY_INLINE extern __always_inline __attribute__((gnu_inline))\n" + "# define POS\n" + "# define POS0\n" + "#endif\n" + ) + if old_inline not in t: + raise SystemExit("__FORTIFY_INLINE define not found") + t = t.replace(old_inline, new_inline, 1) + + # Rewrite fortified prototypes to pass object size (Kees-style POS/POS0). + replacements = [ + ( + "__FORTIFY_INLINE char *strncpy(char *p, const char *q, __kernel_size_t size)", + "__FORTIFY_INLINE char *strncpy(char * const POS0 p, const char * const POS q, __kernel_size_t size)", + ), + ( + "__FORTIFY_INLINE char *strcat(char *p, const char *q)", + "__FORTIFY_INLINE char *strcat(char * const POS0 p, const char * const POS q)", + ), + ( + "__FORTIFY_INLINE __kernel_size_t strlen(const char *p)", + "__FORTIFY_INLINE __kernel_size_t strlen(const char * const POS p)", + ), + ( + "__FORTIFY_INLINE __kernel_size_t strnlen(const char *p, __kernel_size_t maxlen)", + "__FORTIFY_INLINE __kernel_size_t strnlen(const char * const POS p, __kernel_size_t maxlen)", + ), + ( + "__FORTIFY_INLINE size_t strlcpy(char *p, const char *q, size_t size)", + "__FORTIFY_INLINE size_t strlcpy(char * const POS0 p, const char * const POS q, size_t size)", + ), + ( + "__FORTIFY_INLINE char *strncat(char *p, const char *q, __kernel_size_t count)", + "__FORTIFY_INLINE char *strncat(char * const POS0 p, const char * const POS q, __kernel_size_t count)", + ), + ( + "__FORTIFY_INLINE void *memset(void *p, int c, __kernel_size_t size)", + "__FORTIFY_INLINE void *memset(void * const POS0 p, int c, __kernel_size_t size)", + ), + ( + "__FORTIFY_INLINE void *memcpy(void *p, const void *q, __kernel_size_t size)", + "__FORTIFY_INLINE void *memcpy(void * const POS0 p, const void * const POS0 q, __kernel_size_t size)", + ), + ( + "__FORTIFY_INLINE void *memmove(void *p, const void *q, __kernel_size_t size)", + "__FORTIFY_INLINE void *memmove(void * const POS0 p, const void * const POS0 q, __kernel_size_t size)", + ), + ( + "__FORTIFY_INLINE void *memscan(void *p, int c, __kernel_size_t size)", + "__FORTIFY_INLINE void *memscan(void * const POS0 p, int c, __kernel_size_t size)", + ), + ( + "__FORTIFY_INLINE int memcmp(const void *p, const void *q, __kernel_size_t size)", + "__FORTIFY_INLINE int memcmp(const void * const POS0 p, const void * const POS0 q, __kernel_size_t size)", + ), + ( + "__FORTIFY_INLINE void *memchr(const void *p, int c, __kernel_size_t size)", + "__FORTIFY_INLINE void *memchr(const void * const POS0 p, int c, __kernel_size_t size)", + ), + ( + "__FORTIFY_INLINE void *memchr_inv(const void *p, int c, size_t size)", + "__FORTIFY_INLINE void *memchr_inv(const void * const POS0 p, int c, size_t size)", + ), + ( + "__FORTIFY_INLINE void *kmemdup(const void *p, size_t size, gfp_t gfp)", + "__FORTIFY_INLINE void *kmemdup(const void * const POS0 p, size_t size, gfp_t gfp)", + ), + ( + "__FORTIFY_INLINE char *strcpy(char *p, const char *q)", + "__FORTIFY_INLINE char *strcpy(char * const POS0 p, const char * const POS q)", + ), + ] + for a, b in replacements: + if a not in t: + raise SystemExit(f"missing fortify prototype:\n{a}") + t = t.replace(a, b, 1) + + # With Clang __pass_object_size, fortified strlen(q) sees a known object + # size and panics when the C string is not NUL-terminated within that + # bound. strlcpy/strcpy intentionally need the unbounded source length + # (same as the GCC path when bos was usually -1). Use the underlying + # strlen so enabling both wrappers does not brick boot. + # LAB bisect 2026-09-28: strlen+strlcpy fails; strlen+strncpy boots. + old_strlcpy_len = "\tret = strlen(q);\n" + new_strlcpy_len = ( + "\t/* AXP_Resurection: fortify-clang — do not nest fortified strlen */\n" + "\tret = __underlying_strlen(q);\n" + ) + if "ret = __underlying_strlen(q);" not in t: + if old_strlcpy_len not in t: + raise SystemExit("strlcpy strlen(q) probe not found") + t = t.replace(old_strlcpy_len, new_strlcpy_len, 1) + + old_strcpy_len = "\tmemcpy(p, q, strlen(q) + 1);\n" + new_strcpy_len = ( + "\tmemcpy(p, q, __underlying_strlen(q) + 1);\n" + ) + if "memcpy(p, q, __underlying_strlen(q) + 1);" not in t: + if old_strcpy_len not in t: + raise SystemExit("strcpy strlen(q) probe not found") + t = t.replace(old_strcpy_len, new_strcpy_len, 1) + + # Undef POS macros at end of fortify block (before #endif of FORTIFY_SOURCE) + end_marker = ( + "#undef __underlying_strncpy\n" + "#endif\n" + ) + end_repl = ( + "#undef __underlying_strncpy\n" + "#undef POS\n" + "#undef POS0\n" + "#endif\n" + ) + if end_marker not in t: + raise SystemExit("fortify #endif marker not found") + t = t.replace(end_marker, end_repl, 1) + + path.write_text(t) + print(f"patched {path}") + + +def main() -> int: + if len(sys.argv) != 2: + print(f"usage: {sys.argv[0]} /path/to/msm-4.14", file=sys.stderr) + return 2 + root = Path(sys.argv[1]) + patch_compiler_clang(root / "include/linux/compiler-clang.h") + patch_string_h(root / "include/linux/string.h") + patch_kconfig(root / "security/Kconfig") + print("fortify-clang apply OK") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/fortify-clang/apply_fortify_diag.py b/vendor/sunfish-a16/patches/009-kernel-hardening/fortify-clang/apply_fortify_diag.py new file mode 100755 index 0000000..54fecca --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/fortify-clang/apply_fortify_diag.py @@ -0,0 +1,597 @@ +#!/usr/bin/env python3 +"""Diagnostic overlays for FORTIFY / early boot capture (msm-4.14 sunfish LAB). + +v4 — docs/009-fortify-diag-v3-review-20260927.md: + + - Never map from the failure handler. + - Early map: early_ioremap (FIXMAP_PAGE_IO) before setup_arch + parse_early_param — same device attrs as permanent/access-ramoops. + - Keep early map until after mm_init; ordinary ioremap only then + (needs slab/vmalloc). Clear VA before retiring early map. + - First-failure at offset 0; milestones at offset 2048 (no shared slots). + - Adopt prior failure only if a complete record (header + \\n + mirror). + - Atomic claim for first-failure; milestones never touch failure zone. + +Readable: dd if=/dev/access-ramoops | strings | grep AXPDIAG + +Idempotent via markers. Attempt id is bake-time only; wipe failure zone +before repeating the same image (see capture plan). +""" +from __future__ import annotations + +import re +import sys +import time +from pathlib import Path + +MARKER_PANIC = "/* AXP_Resurection: fortify-diag capture v4 */" +MARKER_MAIN_MM = "/* AXP_Resurection: axp-diag mm_init */" +MARKER_SETUP_EARLY = "/* AXP_Resurection: axp-diag early_map */" +MARKER_MAKEFILE = "AXP_Resurection axp_diag_capture" +ATTEMPT = time.strftime("%Y%m%dT%H%M%SZ", time.gmtime()) + +# Sunfish DT: alt_ramoops_region@A4C1F000 size 0x400000 (no-map). +SUNFISH_ALT_PHYS = "0xA4C1F000ULL" + +CAPTURE_C = r""" +/* AXP_Resurection: axp_diag_capture — LAB early plaintext alt ramoops (v4) */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AXP_ALT_PHYS __SUNFISH_ALT_PHYS__ +#define AXP_MAP_SIZE PAGE_SIZE +#define AXP_ATTEMPT "__ATTEMPT__" + +/* Layout within the first mapped page (no shared slots). */ +#define AXP_FAIL_OFF 0U +#define AXP_FAIL_MIRROR 128U +#define AXP_FAIL_SPAN 1024U /* primary + mirrors */ +#define AXP_MILE_OFF 2048U +#define AXP_REC_MAX 120U + +static void __iomem *axp_alt_va; +static bool axp_va_is_early; +static atomic_t axp_first_latch = ATOMIC_INIT(0); + +static void notrace axp_bytes_out(void __iomem *dst, const char *src, size_t n) +{ + size_t i; + + for (i = 0; i < n; i++) + writeb((u8)src[i], dst + i); +} + +static void notrace axp_bytes_in(char *dst, const void __iomem *src, size_t n) +{ + size_t i; + + for (i = 0; i < n; i++) + dst[i] = (char)readb(src + i); +} + +static void axp_hex_u64(char *dst, unsigned long v) +{ + static const char hex[] = "0123456789abcdef"; + int i; + + dst[0] = '0'; + dst[1] = 'x'; + for (i = 0; i < 16; i++) + dst[2 + i] = hex[(v >> (60 - 4 * i)) & 0xf]; + dst[18] = '\0'; +} + +/* + * Complete first-failure: AXPDIAG1,...\n at FAIL_OFF and matching mirror. + * A truncated header alone must NOT suppress later captures. + */ +static bool notrace axp_first_complete(void) +{ + char buf[AXP_REC_MAX]; + char mir[AXP_REC_MAX]; + size_t i, n; + + if (!axp_alt_va) + return false; + axp_bytes_in(buf, axp_alt_va + AXP_FAIL_OFF, AXP_REC_MAX); + if (buf[0] != 'A' || buf[1] != 'X' || buf[2] != 'P' || buf[3] != 'D' || + buf[4] != 'I' || buf[5] != 'A' || buf[6] != 'G' || buf[7] != '1' || + buf[8] != ',') + return false; + n = 0; + for (i = 9; i < AXP_REC_MAX; i++) { + if (buf[i] == '\n') { + n = i + 1; + break; + } + } + if (!n) + return false; + axp_bytes_in(mir, axp_alt_va + AXP_FAIL_MIRROR, n); + for (i = 0; i < n; i++) { + if (mir[i] != buf[i]) + return false; + } + return true; +} + +static void notrace axp_adopt_prior_first(void) +{ + if (axp_first_complete()) + atomic_set(&axp_first_latch, 1); +} + +/* Failure-zone write: mirrors first, primary last (commit). */ +static void notrace axp_fail_commit(const char *rec, size_t n) +{ + size_t i; + + if (!axp_alt_va || !rec || !n) + return; + if (n > AXP_REC_MAX) + n = AXP_REC_MAX; + for (i = AXP_FAIL_MIRROR; i + n <= AXP_FAIL_SPAN; i += AXP_FAIL_MIRROR) + axp_bytes_out(axp_alt_va + i, rec, n); + wmb(); + axp_bytes_out(axp_alt_va + AXP_FAIL_OFF, rec, n); + wmb(); + (void)readb(axp_alt_va + AXP_FAIL_OFF); +} + +static void notrace axp_mile_write(const char *rec, size_t n) +{ + if (!axp_alt_va || !rec || !n) + return; + if (n > AXP_REC_MAX) + n = AXP_REC_MAX; + if (AXP_MILE_OFF + n > AXP_MAP_SIZE) + return; + axp_bytes_out(axp_alt_va + AXP_MILE_OFF, rec, n); + wmb(); + (void)readb(axp_alt_va + AXP_MILE_OFF); +} + +/* + * First durable failure. Format: + * AXPDIAG1,,,,\n + * Never maps. Null VA => lost (blind / transition window). + */ +void notrace __attribute__((no_sanitize("cfi"))) +axp_diag_mark_event(char type, const char *token, void *caller) +{ + char rec[128]; + char hex[20]; + size_t n = 0; + size_t ti; + const char *tok; + void __iomem *va = READ_ONCE(axp_alt_va); + + if (!va) + return; + if (atomic_read(&axp_first_latch)) + return; + if (axp_first_complete()) { + atomic_set(&axp_first_latch, 1); + return; + } + if (atomic_cmpxchg(&axp_first_latch, 0, 1) != 0) + return; + /* Re-check after claim (prior complete may have raced). */ + if (axp_first_complete()) + return; + + axp_hex_u64(hex, (unsigned long)caller); + tok = token ? token : "?"; + + { + static const char pfx[] = "AXPDIAG1,"; + size_t i; + + for (i = 0; i < sizeof(pfx) - 1; i++) + rec[n++] = pfx[i]; + } + rec[n++] = type; + rec[n++] = ','; + { + size_t i; + + for (i = 0; AXP_ATTEMPT[i] && n + 1 < sizeof(rec); i++) + rec[n++] = AXP_ATTEMPT[i]; + } + rec[n++] = ','; + { + size_t i; + + for (i = 0; i < 18 && n + 1 < sizeof(rec); i++) + rec[n++] = hex[i]; + } + rec[n++] = ','; + for (ti = 0; tok[ti] && n + 1 < sizeof(rec); ti++) + rec[n++] = tok[ti]; + rec[n++] = '\n'; + + { + int k; + + for (k = 0; k < 4; k++) + axp_fail_commit(rec, n); + } +} +EXPORT_SYMBOL_GPL(axp_diag_mark_event); + +void notrace __attribute__((no_sanitize("cfi"))) +axp_diag_mark_panic(const char *why) +{ + axp_diag_mark_event('P', why, __builtin_return_address(0)); +} +EXPORT_SYMBOL_GPL(axp_diag_mark_panic); + +/* Milestones: separate offset; never touch failure zone. */ +void notrace __attribute__((no_sanitize("cfi"))) +axp_diag_milestone(const char *name) +{ + char rec[96]; + size_t n = 0; + size_t i; + static const char pfx[] = "AXPDIAG0,M,"; + void __iomem *va = READ_ONCE(axp_alt_va); + + if (!va) + return; + if (atomic_read(&axp_first_latch) || axp_first_complete()) { + axp_adopt_prior_first(); + return; + } + + for (i = 0; i < sizeof(pfx) - 1; i++) + rec[n++] = pfx[i]; + for (i = 0; AXP_ATTEMPT[i] && n + 1 < sizeof(rec); i++) + rec[n++] = AXP_ATTEMPT[i]; + rec[n++] = ','; + if (!name) + name = "?"; + for (i = 0; name[i] && n + 1 < sizeof(rec); i++) + rec[n++] = name[i]; + rec[n++] = '\n'; + + /* Abort if a first-failure claimed while we composed. */ + if (atomic_read(&axp_first_latch) || axp_first_complete()) { + axp_adopt_prior_first(); + return; + } + axp_mile_write(rec, n); +} +EXPORT_SYMBOL_GPL(axp_diag_milestone); + +/* + * Early: early_ioremap (device/IO attrs), before parse_early_param. + * Kept across early_ioremap_reset until mm_init retires it. + * Permanent: ordinary ioremap ONLY after mm_init (slab + vmalloc ready). + * Failure handlers never call these. + */ +void __init axp_diag_map_early(void) +{ + void __iomem *va; + + if (axp_alt_va) + return; + /* FIXMAP_PAGE_IO — matches permanent ioremap / access-ramoops attrs. */ + va = early_ioremap(AXP_ALT_PHYS, AXP_MAP_SIZE); + if (!va) + return; + WRITE_ONCE(axp_alt_va, va); + axp_va_is_early = true; + axp_adopt_prior_first(); + if (!atomic_read(&axp_first_latch)) + axp_diag_milestone("early_map"); +} + +void __init axp_diag_map_permanent(void) +{ + void __iomem *va; + void __iomem *old; + + /* + * Ordinary ioremap needs get_vm_area → kzalloc / vmalloc. + * Call only after mm_init(). Never from setup_arch/paging_init. + */ + va = ioremap(AXP_ALT_PHYS, AXP_MAP_SIZE); + if (!va) + return; + + old = READ_ONCE(axp_alt_va); + /* Publish permanent first so writers never see a stale early VA. */ + WRITE_ONCE(axp_alt_va, va); + wmb(); + + if (axp_va_is_early && old) { + early_iounmap(old, AXP_MAP_SIZE); + axp_va_is_early = false; + } else if (old && old != va) { + iounmap(old); + } + + axp_adopt_prior_first(); + if (!atomic_read(&axp_first_latch)) + axp_diag_milestone("perm_map"); +} + +void __init axp_diag_after_mm_init(void) +{ + axp_diag_map_permanent(); + if (!atomic_read(&axp_first_latch)) + axp_diag_milestone("mm_init"); +} + +static int __init axp_diag_pure_init(void) +{ + if (!READ_ONCE(axp_alt_va)) + axp_diag_map_permanent(); + if (!atomic_read(&axp_first_latch)) + axp_diag_milestone("pure_init"); + return 0; +} +pure_initcall(axp_diag_pure_init); + +static int __init axp_diag_core_init(void) +{ + if (!atomic_read(&axp_first_latch)) + axp_diag_milestone("core_init"); + return 0; +} +core_initcall(axp_diag_core_init); + +static int notrace axp_panic_notifier(struct notifier_block *nb, + unsigned long action, void *data) +{ + axp_diag_mark_event('P', data ? (const char *)data : "notifier", + __builtin_return_address(0)); + return NOTIFY_OK; +} + +static struct notifier_block axp_panic_nb = { + .notifier_call = axp_panic_notifier, + .priority = INT_MAX, +}; + +static int __init axp_diag_panic_reg(void) +{ + atomic_notifier_chain_register(&panic_notifier_list, &axp_panic_nb); + if (!atomic_read(&axp_first_latch)) + axp_diag_milestone("panic_reg"); + return 0; +} +postcore_initcall(axp_diag_panic_reg); +""" + + +def write_capture_c(root: Path) -> None: + path = root / "kernel" / "axp_diag_capture.c" + body = ( + CAPTURE_C.replace("__SUNFISH_ALT_PHYS__", SUNFISH_ALT_PHYS) + .replace("__ATTEMPT__", ATTEMPT) + ) + if body.startswith("\n"): + body = body[1:] + path.write_text(body) + print(f"wrote {path} attempt={ATTEMPT}") + + +def patch_makefile(path: Path) -> None: + t = path.read_text() + if "axp_diag_capture.o" in t: + print(f"skip {path} (axp_diag_capture already listed)") + return + old = "obj-y = fork.o exec_domain.o panic.o \\" + new = f"obj-y = fork.o exec_domain.o panic.o axp_diag_capture.o \\" # {MARKER_MAKEFILE} + if old not in t: + raise SystemExit(f"kernel/Makefile obj-y panic.o line not found in {path}") + path.write_text(t.replace(old, new, 1)) + print(f"patched {path}") + + +def patch_main_mm(path: Path) -> None: + t = path.read_text() + if "axp_diag_after_mm_init" in t: + print(f"skip {path} (already patched)") + return + old = "\tmm_init();\n" + if t.count(old) < 1: + raise SystemExit(f"mm_init(); not found in {path}") + new = f"""\tmm_init(); +{MARKER_MAIN_MM} + {{ + extern void axp_diag_after_mm_init(void); + axp_diag_after_mm_init(); + }} +""" + path.write_text(t.replace(old, new, 1)) + print(f"patched mm_init hook in {path}") + + +def patch_arm64_setup(path: Path) -> None: + """Early IO map only — no ioremap before mm_init.""" + t = path.read_text() + + # Strip obsolete v3 permanent hook after paging_init if present. + perm_block = re.compile( + r"\tpaging_init\(\);\n" + r"/\* AXP_Resurection: axp-diag perm_map \*/\n" + r"\t\{\n" + r"\t\textern void axp_diag_map_permanent\(void\);\n" + r"\t\taxp_diag_map_permanent\(\);\n" + r"\t\}\n", + ) + t2, n = perm_block.subn("\tpaging_init();\n", t, count=1) + if n: + t = t2 + print(f"removed obsolete paging_init ioremap hook from {path}") + + if "axp_diag_map_early" in t: + path.write_text(t) + print(f"skip early hook in {path} (already present)") + return + + early_old = "\tjump_label_init();\n\tparse_early_param();\n" + early_new = f"""\tjump_label_init(); +{MARKER_SETUP_EARLY} + {{ + extern void axp_diag_map_early(void); + axp_diag_map_early(); + }} + parse_early_param(); +""" + if early_old not in t: + raise SystemExit(f"jump_label_init/parse_early_param block not found in {path}") + path.write_text(t.replace(early_old, early_new, 1)) + print(f"patched arm64 setup early_ioremap in {path}") + + +def _replace_fortify_panic(t: str) -> str: + if "fortify-diag capture v4" in t: + return t + + new = f"""{MARKER_PANIC} +extern void axp_diag_mark_event(char type, const char *token, void *caller); +void fortify_panic(const char *name) +{{ + void *caller = __builtin_return_address(0); + + /* Durable record FIRST — before printk/stack (may fault). Never maps. */ + axp_diag_mark_event('F', name, caller); + pr_emerg("FORTIFY_DIAG: overflow in %s caller=%pS attempt=%s\\n", + name, caller, "{ATTEMPT}"); + dump_stack(); + BUG(); +}} +""" + + stock = """void fortify_panic(const char *name) +{ + pr_emerg("detected buffer overflow in %s\\n", name); + BUG(); +} +""" + if "AXP_Resurection: fortify-diag capture" in t: + pat = re.compile( + r"/\* AXP_Resurection: fortify-diag capture(?: v[0-9]+)? \*/.*?^void fortify_panic\(const char \*name\)\n\{.*?\n\}\n", + re.S | re.M, + ) + m = pat.search(t) + if m: + return t[: m.start()] + new + t[m.end() :] + if stock in t: + return t.replace(stock, new, 1) + raise SystemExit("fortify_panic body not found / unrecognized") + + +def patch_fortify_panic(path: Path) -> None: + t = path.read_text() + if "fortify-diag capture v4" in t: + print(f"skip {path} (already v4)") + return + path.write_text(_replace_fortify_panic(t)) + print(f"patched fortify_panic v4 in {path}") + + +def patch_sysrq(path: Path) -> None: + t = path.read_text() + if "axp-diag-sysrq-v4" in t: + print(f"skip {path} (already v4)") + return + if "sysrq_handle_crash" not in t: + raise SystemExit(f"sysrq_handle_crash missing in {path}") + + new_crash = """/* AXP_Resurection: axp-diag-sysrq-v4 */ +extern void axp_diag_mark_event(char type, const char *token, void *caller); +static void sysrq_handle_crash(int key) +{ + rcu_read_unlock(); + axp_diag_mark_event('C', "sysrq-c", __builtin_return_address(0)); + panic("sysrq triggered crash\\n"); +} + +static void sysrq_handle_axp_mark(int key) +{ + axp_diag_mark_event('X', "sysrq-x", __builtin_return_address(0)); +} +static struct sysrq_key_op sysrq_axp_mark_op = { + .handler = sysrq_handle_axp_mark, + .help_msg = "axp-mark(x)", + .action_msg = "AXP alt diag mark", + .enable_mask = SYSRQ_ENABLE_DUMP, +}; +""" + + if "AXP_Resurection: axp-diag-sysrq" in t or "pstore-alt-plain-sysrq" in t: + pat = re.compile( + r"/\* AXP_Resurection: (?:axp-diag-sysrq-v[0-9]+|pstore-alt-plain-sysrq) \*/.*?" + r"(?:static struct sysrq_key_op sysrq_axp_mark_op = \{.*?\};\n|" + r"panic\(\"sysrq triggered crash\\n\"\);\n\})", + re.S, + ) + m = pat.search(t) + if m: + t = t[: m.start()] + new_crash + t[m.end() :] + else: + raise SystemExit(f"could not replace prior sysrq axp block in {path}") + else: + stock = """static void sysrq_handle_crash(int key) +{ + /* release the RCU read lock before crashing */ + rcu_read_unlock(); + + panic("sysrq triggered crash\\n"); +} +""" + if stock not in t: + raise SystemExit(f"unrecognized sysrq_handle_crash form in {path}") + t = t.replace(stock, new_crash, 1) + + if "axp_sysrq_mark_init" not in t: + t += """ +/* AXP_Resurection: axp-diag-sysrq-v4-reg */ +static int __init axp_sysrq_mark_init(void) +{ + register_sysrq_key('x', &sysrq_axp_mark_op); + return 0; +} +device_initcall(axp_sysrq_mark_init); +""" + else: + t = re.sub( + r"axp-diag-sysrq-v[0-9]+-reg", + "axp-diag-sysrq-v4-reg", + t, + count=1, + ) + + path.write_text(t) + print(f"patched sysrq v4 in {path}") + + +def main() -> int: + if len(sys.argv) != 2: + print(f"usage: {sys.argv[0]} /path/to/msm-4.14", file=sys.stderr) + return 2 + root = Path(sys.argv[1]) + write_capture_c(root) + patch_makefile(root / "kernel" / "Makefile") + patch_arm64_setup(root / "arch" / "arm64" / "kernel" / "setup.c") + patch_main_mm(root / "init" / "main.c") + patch_fortify_panic(root / "lib" / "string.c") + patch_sysrq(root / "drivers" / "tty" / "sysrq.c") + print(f"fortify-diag v4 apply OK attempt={ATTEMPT}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/stage1.list b/vendor/sunfish-a16/patches/009-kernel-hardening/stage1.list new file mode 100644 index 0000000..7263f2b --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/stage1.list @@ -0,0 +1,33 @@ +# Stage 1 — AXP Graphene/AH patches that apply clean on LOS msm-4.14 @ 28f9290ae067 +# Paths relative to /srv/rom/references/axp/kernel_patches +# Source attribution: AXP/Divest kernel_patches @ df3cab2155b3 (GrapheneOS-derived series) +0005-Graphene-Deny_USB/4.14/0003.patch +0008-Graphene-Kernel_Hardening-allocsize/4.14/0002.patch +0008-Graphene-Kernel_Hardening-allocsize/4.14/0011.patch +0008-Graphene-Kernel_Hardening-allocsize/4.14/0016.patch +0008-Graphene-Kernel_Hardening-allocsize/4.14/0021.patch +0008-Graphene-Kernel_Hardening-bugon/4.14/0010.patch +0008-Graphene-Kernel_Hardening-fortify/4.14/0004.patch +0008-Graphene-Kernel_Hardening-misc/4.14/0001.patch +0008-Graphene-Kernel_Hardening-misc/4.14/0005.patch +0008-Graphene-Kernel_Hardening-misc/4.14/0010.patch +0008-Graphene-Kernel_Hardening-misc/4.14/0018.patch +0008-Graphene-Kernel_Hardening-random/4.14/0002.patch +0008-Graphene-Kernel_Hardening-random/4.14/0007.patch +0008-Graphene-Kernel_Hardening-random/4.14/0012.patch +0008-Graphene-Kernel_Hardening-random/4.14/0017.patch +0008-Graphene-Kernel_Hardening-ro/4.14/0002.patch +0008-Graphene-Kernel_Hardening-ro/4.14/0012.patch +0008-Graphene-Kernel_Hardening-ro/4.14/0017.patch +0008-Graphene-Kernel_Hardening-ro/4.14/0028.patch +0008-Graphene-Kernel_Hardening-ro/4.14/0030.patch +0008-Graphene-Kernel_Hardening-ro/4.14/0032.patch +0008-Graphene-Kernel_Hardening-ro/4.14/0038.patch +0008-Graphene-Kernel_Hardening-sanitize/4.14/0005.patch +0008-Graphene-Kernel_Hardening-sanitize/4.14/0009.patch +0008-Graphene-Kernel_Hardening-sanitize/4.14/0015.patch +0008-Graphene-Kernel_Hardening-sanitize/4.14/0017.patch +0008-Graphene-Kernel_Hardening-slab/4.14/0006.patch +0008-Graphene-Kernel_Hardening-slab/4.14/0014.patch +0008-Graphene-Kernel_Hardening-unused/4.14/0001.patch +0008-Graphene-Kernel_Hardening-unused/4.14/0002.patch diff --git a/vendor/sunfish-a16/patches/009-kernel-hardening/uss5-1-README.md b/vendor/sunfish-a16/patches/009-kernel-hardening/uss5-1-README.md new file mode 100644 index 0000000..2fe5807 --- /dev/null +++ b/vendor/sunfish-a16/patches/009-kernel-hardening/uss5-1-README.md @@ -0,0 +1,42 @@ +# US-S5-1 — Yama + SLAB freelist random (defconfig) + +**Track**: AXP Resurection Pro Magisk, unlocked sunfish. +**On top of**: Stage1 + combo4 + FORTIFY + CVE clean-429 + hi-batch1–3. + +## Why + +High-offset KEEP CVEs are already on the ship pack. Remaining ge200 KEPT +items were **nf_tables** (`CVE-2023-3777`, `CVE-2024-26643`) — skipped on +purpose in batch3. Next attributable kernel depth without reopening CVE +quarantine: + +| Knob | Before | After | Attribution | +|------|--------|-------|-------------| +| `CONFIG_SECURITY_YAMA` | unset (but `CONFIG_LSM` listed yama) | `=y` | Graphene/AXP LSM stack; ptrace scope | +| `CONFIG_SLAB_FREELIST_RANDOM` | unset | `=y` | Graphene/AH slab hardening companion to existing `SLAB_FREELIST_HARDENED` | + +## Apply + +```bash +bash vendor/sunfish-a16/patches/009-kernel-hardening/apply_uss5_1_defconfig.sh \ + kernel/google/msm-4.14 +``` + +Wired into `scripts/009-bacon-axp-stage1-combo4-cve-hi-releasekeys.sh` after +Stage1+combo4+CVE apply. + +## LAB verify + +```text +zcat /proc/config.gz | grep CONFIG_SECURITY_YAMA=y +zcat /proc/config.gz | grep CONFIG_SLAB_FREELIST_RANDOM=y +cat /proc/sys/kernel/yama/ptrace_scope # expect 1 (default) +pidof magiskd # still up +``` + +## Out of scope here + +- `CVE-2022-49980` lock-scope port (still denylist) +- nf_tables high-offset CVEs +- Stage1 slab FAIL patches (`0010`/`0018` still reject on this tree) +- `hardened_malloc` / bootloader lock diff --git a/vendor/sunfish-a16/signing.mk b/vendor/sunfish-a16/signing.mk new file mode 100644 index 0000000..2b0eca6 --- /dev/null +++ b/vendor/sunfish-a16/signing.mk @@ -0,0 +1,17 @@ +# US-S2 — project release keys (Gate G). +# Soong requires paths inside ANDROID_BUILD_TOP (absolute $HOME/.android-certs panics). +# Host: copy keys into vendor/sunfish-a16/certs/ (gitignored). See docs/009-hardening-signing-checklist.md + +_AXP_CERT_DIR := vendor/sunfish-a16/certs + +ifneq ($(wildcard $(_AXP_CERT_DIR)/releasekey.pk8),) + PRODUCT_DEFAULT_DEV_CERTIFICATE := $(_AXP_CERT_DIR)/releasekey + PRODUCT_OTA_PUBLIC_KEYS := $(_AXP_CERT_DIR)/releasekey.x509.pem + # Without this, non-Google BT apex keeps AOSP security/bluetooth.x509.pem in + # plat_mac_permissions while apps sign with $(_AXP_CERT_DIR)/bluetooth → + # seinfo=default → zygote setcontext fails → Bluetooth crash loop (LAB 2026-10-02). + PRODUCT_MAINLINE_BLUETOOTH_SEPOLICY_DEV_CERTIFICATES := $(_AXP_CERT_DIR) +endif + +# Host setup: also symlink certs/testkey.{pk8,x509.pem} -> releasekey.* +# (system/sepolicy keys.conf @RELEASE still references testkey.x509.pem in this dir).