Two related changes that ship together because they touch the same
build-script + docs surface and were verified together on-device.
16 KiB alignment
- zygisk/build.rs: pass `-Wl,-z,max-page-size=16384` to lld so the
cdylib's LOAD segments line up on 16 KiB pages. NDK r28+ already
does this by default, but the flag keeps r27 builds compatible.
- lsposed/native/build.rs: new file, same flag, for libvpnhide_checks.so.
- docs/development.md: bumped the NDK requirement to r28+ and noted
the 16 KiB rationale.
Verified via `llvm-readelf -l`: both libvpnhide_zygisk.so and
libvpnhide_checks.so now show `Align 0x4000` on every LOAD segment.
Unified build entry points
- kmod/build.py replaces kmod/build-zip.py. Single script that
auto-detects whether to build natively (we're inside the DDK image
or `--kdir` was passed) or to spawn `ghcr.io/ylarod/ddk-min` via
podman/docker. CI uses the same script with `--inside-container`.
- zygisk/build-zip.py renamed to zygisk/build.py for symmetry; logic
unchanged.
- kmod/BUILDING.md rewritten — local build is now one command:
`./kmod/build.py --kmi android14-6.1` (or `--all`). The old
hand-rolled podman/docker recipes are gone.
- .github/workflows/ci.yml updated to call the new entry points.
The DDK image tag in CI now has a comment pointing at
`DDK_IMAGE_TAG` in kmod/build.py as the source of truth.
- README.{md,en.md}, kmod/README.md, zygisk/README.md, docs/releasing.md,
scripts/build_lib.py: reference updates.
- README.en.md: also fixes a "bacame" typo and tightens the Windows
zygisk-build note (the aux.rs / libgit2 issue is still real).
Verified end-to-end on Pixel 8 Pro (husky, android14-6.1, Android 16):
APK installs, kmod + zygisk modules load, all 26 self-checks PASS in
Enforcing, 22/26 PASS in Permissive (the same 4 by-design FAILs as
before — kmod doesn't cover those paths in Permissive).
Split the contributor-facing knowledge that used to live in the local
CLAUDE.md into versioned, public docs:
- CONTRIBUTING.md — PR process, commit conventions, required changelog
entry for user-visible changes, code-style checks.
- docs/development.md — prereqs, keystore setup, per-module build
commands, device install, CI lints.
- docs/releasing.md — VERSION bump → update-version.py → tag → CI →
update-json.sh flow, with the rationale for why update-json is a
separate post-release commit.
- docs/changelog.md — changelog.json as source of truth, how the two
generated markdowns are regenerated, when to add an entry.
Extended kmod/BUILDING.md with a Podman variant of the DDK command,
covering rootless + SELinux (Fedora) where --userns=keep-id and :Z are
required. Kept the kmod build docs next to the code since the GKI /
DDK complexity is kmod-specific.
Component READMEs untouched — they document each module's architecture
and belong next to the code.
The VPN Hide app is now the sole UI for target management. WebUI was
KernelSU-Next-only and redundant since the app works on both KSU and
Magisk. Remove webroot/, action.sh, and all references across docs,
install scripts, module descriptions, and code comments.
Build system:
- Replace hardcoded paths in Makefile with env vars (KERNEL_SRC, CLANG_DIR)
- Add .env.example and .envrc for direnv-based config
- Simplify build-zip.sh to delegate to make instead of duplicating build command
- Rewrite BUILDING.md: 5-step happy path with direnv, standalone prep as appendix
- Remove redundant quick-reference script and step 7 (manual module.lds hack)
Kernel module (vpnhide_kmod.c):
- Fix fib_route_seq_show hook: save seq_file pointer and buffer position in entry
handler instead of reading regs->regs[0] in return handler (which holds the
return value on arm64, not the original argument). Rewrite buffer scanning as
clean forward iteration with memmove compaction.
- Remove dead SIOCGIFCONF case from dev_ioctl hook (confirmed in kernel source:
SIOCGIFCONF goes through sock_ioctl -> dev_ifconf, not dev_ioctl on GKI 6.1)
- Fix header comment: remove false tcp4_seq_show claim, correct rtnl symbol name
Test app:
- Auto-run checks on launch (LaunchedEffect) for easier adb-driven testing
- Remove specific commercial app/bank names from all READMEs, comments,
and log messages to avoid legal issues. Open-source detection tools
(RKNHardering, YourVPNDead) are kept with links.
- Rewrite test-app in Jetpack Compose with Material3 dynamic colors,
edge-to-edge, system dark/light theme support.
- Make test UI more verbose with detailed result cards.
- Add full logcat output for all checks (tag: VPNHideTest) for
automated testing by AI agents.
- Fix 16KB page alignment for Android 15+.
Unified repository for the complete Android VPN-hiding stack:
- zygisk/ — Rust Zygisk module (inline libc hooks via shadowhook)
- lsposed/ — Kotlin LSPosed module (Java API + system_server hooks)
- kmod/ — C kernel module (kretprobe hooks, invisible to anti-tamper)
CI workflows use path filters to build only the changed component.