Files
AXP-Resurection/docs/009-kernel-hardening-map.md

17 KiB
Raw Permalink Blame History

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. 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 SLAB_FREELIST_RANDOM (Yama off like GOLDEN) Graphene/AXP class Y Y apply apply_uss5_1_defconfig.sh; Yama scope 2 broke PairIP, reverted 2026-10-10

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-10-16 cgroup and dirty-source audit

The 20261016 GOLDEN build reports a cgroup v2 mount, but the kernel exposes no v2 controllers at the root. /proc/cgroups also lacks memory and pids, and the log contains:

Activation of cgroup controller +memory failed ... Invalid argument

The source Kconfig has independent MEMCG and CGROUP_PIDS options, but the ship defconfig does not enable either. This is a real kernel configuration gap, not an Android app issue. lmkd still works through the legacy low-memory path, so it is not an immediate boot blocker, but Android 16 UID memory isolation is incomplete.

Do not flip these options directly in the current ship tree. A candidate must be built in a disposable clean worktree, retain SLAB_FREELIST_RANDOM=y, Yama unset, USERFAULTFD off and all existing ship patches, then be checked for:

  1. boot and USB/ADB recovery;
  2. cgroup v2 memory/pids controller availability and UID activation;
  3. lmkd behavior, memory pressure, camera, media, radio, Wi-Fi and Bluetooth;
  4. kernel module ABI and vendor SPL compatibility.

The current host kernel is also intentionally patched in place: 503 modified paths contain the Stage1/CVE/hardening result, and 13 untracked *.orig patch backups remain. That is why uname ends in -dirty. Do not delete or reset those files in the canonical tree. A future final bacon should use a disposable worktree with patch provenance recorded and no .orig residue, or explicitly document why the generated kernel is accepted as dirty. The current 20261016 artifact remains the rollback/reference build until that decision is made.

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.