Skip to content

Install KPM hooks on CFI/LTO kernels, and explain a partial install when they don't - #308

Merged
okhsunrog merged 3 commits into
mainfrom
fix/kpm-partial-hooks-diagnostics
Aug 24, 2026
Merged

Install KPM hooks on CFI/LTO kernels, and explain a partial install when they don't#308
okhsunrog merged 3 commits into
mainfrom
fix/kpm-partial-hooks-diagnostics

Conversation

@okhsunrog

Copy link
Copy Markdown
Owner

From a bug report on a POCO M3 Pro 5G (MediaTek 4.14, HyperOS): the KPM was loaded and green on the dashboard while Diagnostics showed a red ioctl SIOCGIFCONF leak, with nothing connecting the two. The backend was reporting PARTIAL_HOOKS with mask 0x20003bc — sock_ioctl, fib_route_seq_show and ipv6_route_seq_show never installed, because that kernel's kallsyms carries them as name$<hex> (Clang CFI + full LTO promoting a local symbol) and the suffix matcher only accepted .isra.N / .constprop.N / .llvm.N. The kernel image the reporter sent confirms the build: CONFIG_CFI_CLANG=y, CONFIG_LTO_CLANG=y, CONFIG_THINLTO=y. Correlation is 3/3 missing and 0/9 installed.

  • accept $<hex> as a clone suffix, requiring the hex run to end the string so the neighbouring name$<hex>.cfi_jt jump-table alias is rejected — hooking a trampoline would patch the wrong instructions
  • move the matcher to shared/vpnhide_logic.h where it is freestanding and host-testable, with every observed form pinned in test_vpnhide_logic.c
  • skip module-owned symbols in the kallsyms walk; hook targets are vmlinux functions
  • missingBackendHooks(): the gap between a kernel backend's family set and the mask it actually reported. An unread status stays "unknown" rather than "nothing installed"; Zygisk is out of scope, its mask is per-process
  • dashboard warning naming the count and the unresolved symbols, and the leaking check now says which hook is missing when expanded — "your kernel does not expose sock_ioctl" instead of an unexplained leak
  • classifyKpmProblem gains NeedsSuperkey: APatch answered but refused the module control call while no SuperKey is saved. That case previously fell to the generic branch, which suggested collecting a log or reinstalling the zip; the actual fix is one field in Settings → Security. This is what the same reporter hit first
  • the activator's failure detail now names the credential it used (auth: saved superkey / auth: trusted su), which is what made the first bundle ambiguous

Not yet confirmed on the device: whether hook_wrap succeeds once the symbol resolves. A test KPM build is going to the reporter — hooks 0x20003ff with error 0x0 closes it.

Note for whichever of this and #307 merges second: both touch the serialized report, so the golden file there needs refreshing. missingHooks is an added field, so no schema bump.

A bug report from a MediaTek 4.14 device (POCO M3 Pro 5G, HyperOS) came
back with the KPM loaded but reporting PARTIAL_HOOKS and mask 0x20003bc —
sock_ioctl, fib_route_seq_show and ipv6_route_seq_show missing, so
ioctl(SIOCGIFCONF) still enumerated tun0 for targeted apps.

kallsyms on that build carries exactly those three as
`name$<hex>` (Clang CFI + full LTO promoting a local symbol), while every
target that did install is either global or `name.llvm.<decimal>`. The
suffix matcher only accepted `.isra.N` / `.constprop.N` / `.llvm.N`, so
lookup_fn returned 0 and install_hook silently skipped them.

- accept `$<hex>` as a clone suffix, requiring the hex run to end the
  string so the neighbouring `name$<hex>.cfi_jt` jump-table alias is
  rejected — hooking a trampoline would patch the wrong instructions
- move the matcher to shared/vpnhide_logic.h where it is freestanding and
  host-testable, with the observed forms (including the .cfi_jt alias)
  pinned in test_vpnhide_logic.c
- skip module-owned symbols in the kallsyms walk; hook targets are
  vmlinux functions and a same-named module symbol is a different one

The kallsyms correlation is 3/3 missing and 0/9 installed, but this is
not yet confirmed on the device — the reporter is sending a kernel-image
export next, which will show whether the hook then installs.
A report came in with the KPM active and green on the dashboard, and a red
`ioctl SIOCGIFCONF` leak in Diagnostics — no way for the user (or for me)
to connect the two. The backend was reporting PARTIAL_HOOKS with three
kernel hooks missing, and nothing rendered that: hook ownership was
derived from the backend family alone, so a vector whose hook never
installed still counted as covered and read as an ordinary leak.

- missingBackendHooks(): the gap between the family set and the mask the
  kernel backend actually reported. Empty for an unread status (that is
  "unknown", not "nothing installed") and for Zygisk, whose mask is
  per-process
- dashboard warning naming the count and the unresolved symbols, so the
  green card is no longer the whole story. Not an error: what installed
  still works, and no reinstall fixes a renamed kernel symbol
- the leaking check now carries its missing hooks and says so when
  expanded, turning "leak" into "your kernel does not expose sock_ioctl"
- classifyKpmProblem gains NeedsSuperkey: APatch answered but refused the
  module control call while no SuperKey is saved. Previously this fell to
  the generic branch, which told the user to collect a log or reinstall
  the zip; the actual fix is one field in Settings → Security
`kpm list supercall failed with rc=-1` was the whole diagnosis in a bug
report — the same message whether the saved SuperKey was rejected, or the
activator only ever had KernelPatch's trusted-`su` grant (enough for the
hello ping it authenticates with, not necessarily for module management).
Telling those apart took reading the activator source alongside a second
capture of superkey_saved.

The failure detail now carries `(auth: saved superkey)` / `(auth: trusted
su)`, so the next bundle answers it by itself.
@okhsunrog
okhsunrog merged commit 1675d2b into main Aug 24, 2026
35 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant