Commit graph

19 commits

Author SHA1 Message Date
okhsunrog
e2d41dea13 style: add clang-format, ktlint, editorconfig and format all code
- Add .editorconfig with ktlint config (disable wildcard-import rule,
  allow PascalCase for @Composable functions)
- Add kmod/.clang-format from upstream kernel tree
- Run clang-format on vpnhide_kmod.c (kernel coding style)
- Run ktlint --format on all Kotlin files (lsposed + test-app)
2026-04-12 23:26:36 +03:00
okhsunrog
e12c58cace fix: shell injection guard, use named constants, bypass own hooks for /proc/self/maps
- WebUI: validate package names against [a-zA-Z0-9_.\-]+ before
  interpolating into shell commands (both kmod and zygisk copies)
- zygisk hooks.rs: use RTM_NEWLINK/RTM_NEWADDR from filter.rs instead
  of magic constants 16/20
- zygisk lib.rs: read /proc/self/maps via raw libc::open in
  scrub_shadowhook_maps to bypass our own hooked_openat
- kmod: add comment explaining why seq->buf access without seq->lock
  is safe in fib_route_ret (seq_read holds the mutex around ->show())
- kmod: add comment clarifying MODULE_LICENSE("GPL") vs MIT SPDX
2026-04-12 23:12:45 +03:00
okhsunrog
33faf8f8aa fix: address race conditions, UB, and correctness issues across all components
kmod:
- Add explicit rcu_read_lock() around ifa->idev->dev->name dereferences
  in inet6_fill_entry, inet_fill_entry, and rtnl_fill_entry
- Remove racy READ_ONCE fast-path in is_target_uid; uncontended spin_lock
  is ~5ns on ARMv8 and the optimization had incorrect TOCTOU semantics
- Fix dev_ifconf_ret: return immediately on copy_from_user/copy_to_user
  failure instead of breaking the loop and writing back a wrong ifc_len
- Fail module load if zero kretprobes register; warn on partial registration

lsposed:
- Fix isSystemServer check-then-set race: use AtomicBoolean.compareAndSet
  to prevent duplicate hook installation from concurrent handleLoadPackage
- Fix NC hook partial state corruption: save all values before mutating,
  restore on exception, only set ThreadLocals after all mutations succeed
- Fix NI/LP hooks: replace param.result=null (which skips writeToParcel
  and corrupts the Parcel stream) with save-mutate-restore pattern
- Synchronize loadTargetUids() with double-checked locking; always cache
  result (even empty) to avoid file I/O on every Binder call
- Fix suExec: drain stderr on background thread, destroy process in finally

zygisk:
- Use std::sync::Once for shadowhook initialization instead of AtomicBool
- Handle write() return value on memfd: loop on short writes, return error
- Make netlink parsers (read_u32_ne/read_u16_ne) return Option instead of
  panicking on out-of-bounds access
2026-04-12 23:06:48 +03:00
okhsunrog
7b867c8b64 chore: add VERSION file and update-version.sh, bump to v0.4.0
Single VERSION file in repo root as the source of truth. The script
update-version.sh propagates it to all 5 locations: kmod module.prop,
zygisk module.prop, zygisk Cargo.toml, lsposed build.gradle.kts,
test-app build.gradle.kts. versionCode = major*10000 + minor*100 + patch.
2026-04-12 03:23:16 +03:00
okhsunrog
1ee26e1de8 docs: add VPN Hide app as primary target management method
The lsposed APK now includes a Compose target picker UI that works
with both kmod and zygisk on any root solution. Update all READMEs
to recommend the app over WebUI (which is KernelSU-only).
2026-04-12 03:17:59 +03:00
okhsunrog
c52a6711ff fix: UID resolution in save commands used printf \n escapes instead of real newlines
The shell variable $UIDS accumulated UIDs with literal \n (two chars)
instead of actual newlines. printf "$UIDS" wrote garbage to
/proc/vpnhide_targets and vpnhide_uids.txt. The empty-targets case
used bare > redirect which never triggers the proc write handler.

Fix: accumulate UIDs with real newlines (like service.sh does), use
echo "$UIDS" for output, and echo (writes \n) for the empty case so
the kmod write handler fires and clears the UID list.

Affects: APK target picker, kmod WebUI, zygisk WebUI.
2026-04-12 03:14:59 +03:00
okhsunrog
a8bed7e044 security: restrict target list visibility from apps
- /proc/vpnhide_targets: change from 0644 to 0600 (root only).
  Apps could read the UID list and discover which apps are targeted.
- Remove /data/local/tmp/vpnhide_targets.txt copies from service.sh
  and WebUI (no longer needed after get_module_dir() fix).
2026-04-12 02:06:39 +03:00
okhsunrog
a9a76b840c docs: remove incorrect vermagic bypass claims 2026-04-12 01:18:32 +03:00
okhsunrog
de958af450 docs: add architecture notes for all 6 kmod hooks 2026-04-11 23:34:20 +03:00
okhsunrog
21ba266a80 docs: update component READMEs to reflect current architecture 2026-04-11 23:24:25 +03:00
okhsunrog
c8ab6933e8 docs: fix Pixel GKI generation info 2026-04-11 23:20:58 +03:00
okhsunrog
32e78292c6 docs: simplify BUILDING.md, add DDK Docker build as primary method 2026-04-11 23:16:56 +03:00
okhsunrog
5eaebd0a12 license: unify entire project under MIT 2026-04-11 21:58:07 +03:00
okhsunrog
5ee50935c4 ci: use AOSP clang in Docker image, fix kmod build
- Add Google's AOSP clang (clang-r487747c, same as Pixel kernel build)
  to the CI Docker image via sparse checkout. Distro clang caused ABI
  mismatches leading to bootloops on device.
- Update kmod workflow to use the Docker image + AOSP clang instead of
  system clang from apt.
- Replace symvers with real vmlinux.symvers from Pixel kernel build
  (8050 symbols vs 4060 from device .ko extraction).
- Add kmod build deps (bc, kmod, cpio, binutils-aarch64) to Docker image.
2026-04-11 20:53:20 +03:00
okhsunrog
c391d90432 feat: add dev_ifconf, inet6/inet_fill_ifaddr hooks for full VPN hiding
Kernel module:
- Add dev_ifconf hook to filter SIOCGIFCONF interface enumeration
  (goes through sock_ioctl -> dev_ifconf, not dev_ioctl)
- Add inet6_fill_ifaddr and inet_fill_ifaddr hooks to filter RTM_GETADDR
  netlink responses. getifaddrs() was leaking tun0 via the address dump
  even though RTM_GETLINK was filtered. Uses skb_trim to undo the fill
  and return 0 (not -EMSGSIZE which causes infinite retry on empty skb).
- All 6 kretprobes now cover: ioctl, SIOCGIFCONF, netlink link dumps,
  netlink address dumps (IPv4+IPv6), and /proc/net/route.

Test app:
- Treat SELinux EACCES/EPERM as PASS — if the app can't access the
  resource, it can't detect VPN through it either.
- Test results: 14/14 passed with VPN active.
2026-04-11 19:09:00 +03:00
okhsunrog
e35cf1a6b9 refactor: overhaul kmod build system, fix kernel module bugs
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
2026-04-11 18:50:18 +03:00
okhsunrog
60b3235dc0 docs: redesign README hierarchy for monorepo
Root README is now the single source for shared content (verified
against, split tunneling, threat model, component overview). Sub-READMEs
focus on component-specific technical details and link back to root.

- Remove ~700 lines of duplicated content across sub-READMEs
- Update all cross-references to use monorepo relative paths
- Add test-app to components table
- Update zygisk README: mark openat/recvmsg/SIOCGIFCONF as implemented
- Fix stale links to archived repos
2026-04-11 16:20:33 +03:00
okhsunrog
ca23630e57 refactor: remove commercial app names, rewrite test app in Compose
- 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+.
2026-04-11 16:09:31 +03:00
okhsunrog
12daca5c1a monorepo: combine vpnhide-zygisk, vpnhide (lsposed), and vpnhide-kmod
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.
2026-04-11 15:01:49 +03:00