Commit graph

16 commits

Author SHA1 Message Date
okhsunrog
bca81b80e7 fix: block socket binds to hidden VPN interfaces 2026-07-13 20:22:51 +03:00
Danila Gornushko
995f218f16
Fix FolkPatch KPM activation (#237)
* Fix FolkPatch KPM activation

* Keep APatch default supercall version
2026-07-04 20:10:02 +03:00
Danila Gornushko
589bd4cf0a
refactor(lsposed): canonical config is the single source of truth for debug logging (#229)
Some checks failed
CI / kmod (android15-6.6) (push) Has been cancelled
CI / kmod (android16-6.12) (push) Has been cancelled
CI / kmod-qemu (android12-5.10) (push) Has been cancelled
CI / kmod-qemu (android13-5.10) (push) Has been cancelled
CI / kmod-qemu (android13-5.15) (push) Has been cancelled
CI / kmod-qemu (android14-5.15) (push) Has been cancelled
CI / kmod-qemu (android14-6.1) (push) Has been cancelled
CI / kmod-qemu (android15-6.6) (push) Has been cancelled
CI / kmod-qemu (android16-6.12) (push) Has been cancelled
CI / kpm-qemu (android12-5.10) (push) Has been cancelled
CI / kpm-qemu (android13-5.10) (push) Has been cancelled
CI / kpm-qemu (android13-5.15) (push) Has been cancelled
CI / kpm-qemu (android14-5.15) (push) Has been cancelled
CI / kpm-qemu (android14-6.1) (push) Has been cancelled
CI / kpm-qemu (android15-6.6) (push) Has been cancelled
CI / kpm-qemu (android16-6.12) (push) Has been cancelled
CI / kpm-qemu-legacy (4.14) (push) Has been cancelled
CI / kpm-qemu-legacy (4.19) (push) Has been cancelled
CI / kpm-qemu-legacy (5.4) (push) Has been cancelled
CI / kpm (push) Has been cancelled
CI / zygisk (push) Has been cancelled
CI / lsposed (push) Has been cancelled
CI / portshide (push) Has been cancelled
CI / release (push) Has been cancelled
CI / kmod-activator (push) Has been cancelled
CI / kmod (android12-5.10) (push) Has been cancelled
CI / kmod (android13-5.10) (push) Has been cancelled
CI / kmod (android13-5.15) (push) Has been cancelled
CI / kmod (android14-5.15) (push) Has been cancelled
CI / kmod (android14-6.1) (push) Has been cancelled
* refactor(lsposed): canonical config is the single source of truth for debug logging

The debug flag lived in two stores — the app's SharedPreferences and the
canonical JSON — kept in sync by a startup reconcile plus a drift safety-net,
which was the source of a class of edge cases. Collapse it to one store: the
canonical JSON, with two distinct fields — `debug` (the effective flag every
sink gates on: app logger, system_server HookLog, native backends) and
`debugSwitch` (the user's toggle intent). The Settings toggle writes both; a
capture temporarily forces only `debug` and restores it to `debugSwitch` in a
finally; an interrupted capture self-heals on the next launch via a
`debug <- debugSwitch` reconcile within the same store — no cross-process drift,
no SharedPreferences.

- Add `debugSwitch` to the canonical config (migrates from `debug` when absent);
  serialize both. buildCanonicalConfig inherits `debugSwitch` from the existing
  config, so rebuild paths (Save / auto-hide / manual-hidden) never clobber the
  user's intent when it diverges from the effective flag during a capture.
- The app reads the effective `debug` from the canonical snapshot; the Settings
  toggle reflects `debugSwitch`.
- Captures force only `debug` via a targeted copy of the parsed canonical config
  (never a rebuild from the legacy targets snapshot), so settings/autoHiddenPackages
  are preserved, and restore to `debugSwitch`.
- Replace the prefs<->canonical reconcile and the drift safety-net with a single
  startup `debug <- debugSwitch` reconcile; delete SharedPreferences,
  runtimeReconcileCanonicalConfig, and reapplyDebugLoggingIfDrifted.
- VpnHideLog gains an always-on e() for errors; stray Log.e routed through it.
- Tests: debugSwitch migration/round-trip, capture session, and that the
  auto-hide rebuild preserves debugSwitch.

* refactor(lsposed): centralize log tags and gating, drop double-activator

- add LogTags registry so call sites, HookLog and the debug-capture
  logcat filter share one spelling instead of scattered literals
- extract the shared gate-and-level policy into GatedLogger; VpnHideLog
  and HookLog keep their own sinks and per-process flag sources
- startup debug reconcile no longer runs the native activator twice
  (the reconciled write already runs it; the no-op path runs it once)

* fix(lsposed): re-read canonical before writing the debug toggle

setDebugLoggingEnabled read the cached RootSnapshotCache StateFlow and
then invalidated it on success, with nothing on the Settings screen
repopulating it. A second toggle in the same visit read a null snapshot
and silently no-opped (no write; the switch snapped back). Read via
getOrLoad() so the write always sees fresh canonical state, matching the
capture and startup-reconcile sites.
2026-07-02 18:50:18 +03:00
Danila Gornushko
5902c0f86c
Upgrade diagnostic captures (#227)
Some checks are pending
CI / kmod-activator (push) Blocked by required conditions
CI / kmod (android12-5.10) (push) Blocked by required conditions
CI / kmod (android13-5.10) (push) Blocked by required conditions
CI / kmod (android13-5.15) (push) Blocked by required conditions
CI / kmod (android14-5.15) (push) Blocked by required conditions
CI / kmod (android14-6.1) (push) Blocked by required conditions
CI / kmod (android15-6.6) (push) Blocked by required conditions
CI / kmod (android16-6.12) (push) Blocked by required conditions
CI / kmod-qemu (android12-5.10) (push) Blocked by required conditions
CI / kmod-qemu (android13-5.10) (push) Blocked by required conditions
CI / kmod-qemu (android13-5.15) (push) Blocked by required conditions
CI / kmod-qemu (android14-5.15) (push) Blocked by required conditions
CI / kmod-qemu (android14-6.1) (push) Blocked by required conditions
CI / kmod-qemu (android15-6.6) (push) Blocked by required conditions
CI / kmod-qemu (android16-6.12) (push) Blocked by required conditions
CI / kpm-qemu (android12-5.10) (push) Blocked by required conditions
CI / kpm-qemu (android13-5.10) (push) Blocked by required conditions
CI / kpm-qemu (android13-5.15) (push) Blocked by required conditions
CI / kpm-qemu (android14-5.15) (push) Blocked by required conditions
CI / kpm-qemu (android14-6.1) (push) Blocked by required conditions
CI / kpm-qemu (android15-6.6) (push) Blocked by required conditions
CI / kpm-qemu (android16-6.12) (push) Blocked by required conditions
CI / kpm-qemu-legacy (4.14) (push) Blocked by required conditions
CI / kpm-qemu-legacy (4.19) (push) Blocked by required conditions
CI / kpm-qemu-legacy (5.4) (push) Blocked by required conditions
CI / kpm (push) Blocked by required conditions
CI / zygisk (push) Blocked by required conditions
CI / lsposed (push) Blocked by required conditions
CI / portshide (push) Blocked by required conditions
CI / release (push) Blocked by required conditions
* feat: upgrade diagnostic captures

Collect richer debug and full-logcat bundles with device, backend, hook, portshide, and kernel partition evidence.

Add an explicit kernel image export for maintainer-requested kernel analysis.

* fix: harden diagnostic capture sessions

* fix(lsposed): harden diagnostic export error paths from review

Address correctness findings from a review of the diagnostic-capture upgrade,
all validated on a Pixel 4a via the agent bridge (kernel/debug/logcat exports).

- Kernel image export: wrap exportKernelImagesZip so a zip/IO failure returns
  null (and cleans the parts dir) instead of escaping and stranding the export
  button disabled; add try/finally at the DiagnosticsScreen call site. Cap the
  per-partition dd (skip unknown/oversized partitions, bound with count=) so a
  mislabelled or huge partition can't fill /data.
- HookDiagnostics: drive counter deltas off an explicit "baseline captured"
  flag instead of baselineCounters.isEmpty(), so a fresh boot with an empty
  baseline no longer reports every delta as n/a. Add HookDiagnosticsTest.
- DebugShellSnapshot: raise the 20s snapshot timeout to 60s and preserve+flag a
  timeout-truncated section instead of silently dropping it and every later one.
- LogcatRecorder: delete the intermediate raw logcat file after zipping and on
  failed start, so repeated captures stop leaking multi-MB files into cache.
- DebugExport: rethrow CancellationException before the generic catch so
  navigating away mid-capture cancels cleanly instead of logging a false error.
- DebugCaptureLogging: when the on-disk canonical config is present but
  unparseable, refuse the targets-snapshot rebuild (which would reset settings
  and clear autoHiddenPackages); fall back to an app-process-only toggle.
- Dashboard: don't warn "ports rules not active" for a module the user disabled
  via their manager (new ports_disabled probe, mirrors the activator's guard).
- activator write_atomic: per-process temp name so a boot-time and app-triggered
  activation can't corrupt each other's load_status.
- Drop the wasted multi-user pm enumeration from the counter baseline command.
2026-07-02 16:25:53 +03:00
Danila Gornushko
1582efa067
docs: refresh installation/backend docs + 1.0.0 screenshots (#224)
* docs: refresh installation and backend docs

* docs: fix review findings and add KPM to update-json

Cross-checked the docs refresh against the code and corrected:
- protocol.md: config parser is vpnhide_parse_config (not the legacy
  vpnhide_parse_target_uids); path is kmod/shared/vpnhide_logic.h; drop the
  unverified 0x2026 KPatch-Next marker (activator drives it via the CLI).
- zygisk/README: module declares Zygisk API v2 (not v5); add the recv hook
  row and the if<N> renamed-netdev match.
- README (en/ru): live-check counts are 13 native / 12 Java; Diagnostics is
  under Settings, not a tab; mention the Statistics tab; note KPM beta parity.
- detection-vectors: KPM host-route helper is kpm_is_public_host_route{4,6};
  restore CONFIG_KPROBES and the Zygisk qualifiers; codegen renders four targets.
- storage.md: legacy files are no longer user-managed (migration inputs), not
  'gone'. CLAUDE.md: activator has four bins (kmod/kpm/zygisk/ports).
- development/ROADMAP/kmod/lsposed/portshide READMEs + AGENTS.md: assorted
  accuracy fixes (KPM needs a KernelPatch runtime, per-KMI kmod zip name, etc.).
- CONTRIBUTING.md: clang-format uses scripts/clang-format-c.sh (covers KPM src).
- portshide customize.sh: 'Hiding -> Ports' (renamed tab).
- update-json.sh: emit update-kpm.json so KPM gets Magisk/KSU update checks.

* docs: correct diagnostics check count (25, not 26 vectors)

* docs: refresh README screenshots for the 1.0.0 UI

Replace the v0.5.3-era screenshots (old per-tab Protection UI) with a
new 1.0.0 set: VPN-hidden dashboard, the unified Hiding list with
J/N/A/P, the Statistics tab + per-hook breakdown, per-app hook selection,
diagnostics, settings, and the community screen. Extra shots
(statistics-apps, settings-advanced, diagnostics-java, settings-developer)
are included for the release notes.

* docs: fix the how-it-works layer breakdown

The old 'Layer 3 — additional app-level controls' bucket was wrong:
interface hiding is what Layers 1+2 already do, app-hiding is done by the
LSPosed/Java layer (system_server PackageManager hooks), and ports is a
separate module. Fold app-hiding into Layer 1 (LSPosed) and make Layer 3
the standalone portshide module.

* docs: conceptual-coherence pass on the 5 core docs

Second review pass, this time for architectural coherence rather than
code-facts. Fixes:
- README (en/ru): 'What vpnhide hides' stopped reifying interface hiding
  as a standalone 'layer'/'role' and now ties the three hiding goals to
  the four J/N/A/P roles (interface = Java + Native, toggled independently)
- README (ru): add the KPM-beta hook-parity caveat (parity with the EN side)
- protocol.md: app-hiding is a normal lsposed mask bit, not a separate
  'package/observer records' entry in the §6 profile table
- detection-vectors.md: a complete install is two components (native + lsposed),
  not 'two roles'; name both lsposed jobs
- storage.md: scope the text protocol to the config wire (LSPosed reuses the
  format for its state file); 'by function' not 'by role'; note the Apps role
  shares the same resolver; heading no longer files ports under 'Native layer'
2026-07-02 00:03:17 +03:00
okhsunrog
52b137b78e Add backend-specific native hook selection 2026-06-29 19:24:03 +03:00
okhsunrog
0cfa16d331 feat(portshide): add configurable port ranges 2026-06-29 15:56:59 +03:00
okhsunrog
364ab53a74 feat(lsposed): add detailed diagnostics and java hook controls 2026-06-29 12:36:57 +03:00
okhsunrog
552762a246 Add LSPosed interception stats 2026-06-29 02:43:23 +03:00
okhsunrog
596a93f1f9 Add native interception stats 2026-06-29 01:47:12 +03:00
okhsunrog
bccdc324e7 docs(kpm): refresh runtime activation notes 2026-06-28 19:32:56 +03:00
okhsunrog
0f829e52bd fix(kpm): support APatch supercall activation 2026-06-28 19:28:12 +03:00
okhsunrog
69f0a92716 feat(storage): apply ports through activator 2026-06-28 19:01:44 +03:00
okhsunrog
c6cf8607d7 fix(storage): clean up legacy config leftovers 2026-06-28 18:51:47 +03:00
okhsunrog
05a3c0520f fix(storage): move boot wait into activator 2026-06-28 18:33:23 +03:00
okhsunrog
c593c6f9ea docs: storage & activation architecture (target design)
Capture the storage-layer design we converged on, above the wire protocol:

- docs/storage.md (new) — the authority. One JSON canonical
  (/data/system/vpnhide_config.json) as the single source of truth; the text
  protocol stays the runtime IPC for the native backends only; a Rust activator
  (workspace: protocol lib + zygisk cdylib + activator lib with three thin
  src/bin/{kmod,kpm,zygisk}.rs) projects JSON -> wire, each native module shipping
  only its own bin. LSPosed self-reads the canonical (it's an APK+hook, not a
  module, and the Java layer must work standalone), resolving uids via
  packages.list to avoid PM-hook re-entry. Stats stay kmod/KPM-only; zygisk
  per-hook stats deferred (no daemon-free cross-process aggregation). The APatch
  superkey gets an opt-in flag persisting it root-only at /data/adb/vpnhide/superkey
  (DE storage, boot-readable) to unlock APatch boot activation. SELinux layout,
  the file-count collapse, and migration are spelled out.

- protocol.md / state.md — pointers to storage.md and notes on the statements it
  supersedes (LSPosed reading the wire, APatch-can't-boot, the storage model). The
  frozen v1 wire format is unchanged.

- CLAUDE.md — index storage.md + protocol.md.

This is the target design; the current branch's code is the interim
protocol-on-every-backend step it converges toward.
2026-06-28 17:23:17 +03:00