vpnhide/zygisk/src
okhsunrog ebe0e3676e fix(zygisk): grow /proc/net read buffer past 64 KiB instead of truncating
`open_filtered_proc_net` used a fixed 65 536-byte stack array as the
read buffer. On devices with several hundred concurrent TCP sockets
(p2p clients, browsers with many tabs, dev devices with tethering),
`/proc/net/tcp6` exceeds 64 KiB — the previous code silently dropped
the tail and handed the truncated content back to the caller via
memfd. An app reading its own socket list could miss real entries,
which is a correctness bug, not a security one (the truncated tail
might contain non-VPN sockets the app needs).

Replace the stack array with a thread-local growable Vec<u8>:

* Initial capacity 64 KiB matches the previous fixed buffer, so the
  first call (and most subsequent ones) does no reallocation.
* When the read fills capacity, `Vec::reserve(8 * 1024)` triggers
  amortised doubling — large files cost O(log size) reallocations.
* `clear()` between calls keeps capacity intact: the second and later
  calls in the same thread are zero-allocation.
* Bounded memory: per-thread overhead is `max-observed-size`. On
  Android only one or two threads ever open /proc/net/* (network-
  info worker, diagnostics probe), so the steady state is well under
  a megabyte of RAM.

Trade-off: had to drop the `const { ... }` block on the thread_local
because `Vec::with_capacity` is not const fn. The per-`with()` lazy-
init flag check is negligible relative to the syscalls we're about
to issue.

Empirically: on the device used for testing /proc/net/tcp6 stays at
~15 KiB (no truncation triggered with the old buffer either). The
fix is preventive for power-user scenarios where the limit is
actually reached. SELinux on stock Android blocks /proc/net/* for
untrusted_app domain entirely, so the new path is exercised only on
permissive ROMs or by privileged callers — testing was therefore
limited to verifying no regression on the happy path.
2026-04-26 17:46:13 +03:00
..
generated chore(codegen): drop unused suffix forms digits_optional / any 2026-04-26 05:16:18 +03:00
filter.rs chore(zygisk): drop redundant allow(dead_code) on is_vpn_iface_cstr 2026-04-26 16:04:43 +03:00
hooks.rs fix(zygisk): grow /proc/net read buffer past 64 KiB instead of truncating 2026-04-26 17:46:13 +03:00
lib.rs docs(zygisk): document module lifecycle and per-fork state 2026-04-26 15:08:09 +03:00
shadowhook.rs fix: address race conditions, UB, and correctness issues across all components 2026-04-12 23:06:48 +03:00