# 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.