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.
This commit is contained in:
sunfish-admin committed 2026-10-05 10:42:00 +02:00
1 parent fd793b9471
commit deaaf42caa
129 files changed
+11769 -141

No files matched your search

+248
View File
@@ -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.