Stop the LSPosed hooks' debug flag from depending on inotify - #317
Merged
Conversation
Found on a live Pixel 8 Pro: system_server was writing VpnHide-NC/NI lines to logcat — the ones that name the exact UIDs we hook — at ~3/s, five days after Debug logging had been turned off. The canonical config on disk said debug:false and had said so since the day after that boot. HookLog.enabled was assigned in exactly one place, HookLog.reload(), reachable only from install() at boot and from the FileObserver callback. That observer had stopped delivering: an atomic rename over the config produced no callback at all, confirmed on the device. So the flag was frozen at whatever the config said at boot, and no amount of toggling in the app could move it — only a reboot. The irony is that SystemServerConfigCache sits right beside it re-reading the same file every second by fingerprint, and was current the whole time. The hooks' targeting was right; only the logging flag was stale. So give the flag to the component that already polls: the cache sets HookLog.enabled whenever it installs a fresh config. The watcher stays, as latency rather than correctness — it makes a flip land immediately instead of within a second — and the comments now say so, because the next person to add state here will be tempted to hang it off the same callback. Not a leak: nothing an app can read. It is a toggle that silently did nothing, plus a stream of Binder-hot-path log calls the user asked us to stop making.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Found while investigating an unrelated report on a live Pixel 8 Pro: system_server was writing
VpnHide-NC/VpnHide-NIlines — the ones that name the exact UIDs we hook — at roughly 3/s, five days after Debug logging had been switched off. The canonical config on disk saiddebug: falseand had said so since the day after that boot.HookLog.enabledwas assigned in exactly one place,HookLog.reload(), reachable only frominstall()at boot and from theFileObservercallback. That observer had stopped delivering — an atomic rename over the config produced no callback at all, confirmed on the device — so the flag was frozen at its boot value and no amount of toggling in the app could move it. Only a reboot could.SystemServerConfigCachesits right beside it re-reading the same file every second by fingerprint, and was current the whole time: the hooks' targeting was correct, only the logging flag was stale. So the flag now belongs to the component that already polls.SystemServerConfigCachesetsHookLog.enabledwhenever it installs a freshly-read configHookLog.install()primes through that same path;reload()is goneNot a leak — nothing an app can read. It is a toggle that silently did nothing, plus a stream of log calls on a Binder hot path that the user had asked us to stop making.
Testing: the stale-flag state was reproduced and confirmed on hardware (atomic rename over the config produced no observer callback while the cache stayed current). End-to-end verification of the fix needs the module reloaded into system_server, i.e. a reboot on a test device.