Randomize the CLI socket to remove a /proc/net/unix fingerprint - #892
Randomize the CLI socket to remove a /proc/net/unix fingerprint#892JingMatrix wants to merge 1 commit into
Conversation
The daemon bound its CLI socket to a fixed filesystem path, /data/adb/lspd/.cli_sock. A filesystem socket's bind address is copied verbatim into /proc/net/unix, which is world-readable across Android's single global network namespace, so any unprivileged app reads the full path regardless of the 0700 directory guarding the node on disk. That constant string was a stable, version-independent signature: a scanner only had to grep for it, even with every other surface clean (#891). Permissions were never the leak, so the fix changes the address itself. The socket now binds in the abstract namespace under a name minted from 128 random bits at each daemon start, appearing as @<hex> - no path, nothing framework-specific, different every boot. Since the daemon and CLI are separate processes, they can no longer share the name through a compile-time constant. The daemon writes the current name to a root-only file (/data/adb/lspd/.sock) and the CLI reads it at connect time; that file is not a socket, so it never appears in /proc/net/unix. Both auth layers are unchanged - the compiled-in CLI_TOKEN still gates every connection and the CLI still requires root - so the abstract namespace's lack of a filesystem-permission gate costs nothing exploitable. The bind carries no file, so the startup delete and shutdown unlink are gone.
|
TODO before megre: add docs of using the cli in the |
|
Closing this. The premise is wrong. The change rests on "any unprivileged app reads the full path" from I also ran the scanner from #891 on a device where So there is no app-visible fingerprint to remove here, and the justification in the body and the two code comments is incorrect. If we still want the CLI socket randomized for consistency with the Dex2Oat abstract socket, that's a separate, honestly-scoped change against a root/shell-context reader — not this. |
The daemon bound its CLI socket to a fixed filesystem path,
/data/adb/lspd/.cli_sock. A filesystem socket's bind address is copied verbatim into/proc/net/unix, which is world-readable across Android's single global network namespace — so any unprivileged app reads the full path, regardless of the0700directory guarding the node on disk. That constant string was a stable, version-independent signature: an integrity scanner only had to grep for it, even with every other surface clean (#891).Permissions were never the leak, so the fix changes the address itself. The socket now binds in the abstract namespace under a name minted from 128 random bits at each daemon start, appearing as
@<hex>— no path, nothing framework-specific, different every boot.Since the daemon and CLI are separate processes, they can no longer share the name through a compile-time constant. The daemon writes the current name to a root-only file (
/data/adb/lspd/.sock) and the CLI reads it at connect time; that file is not a socket, so it never appears in/proc/net/unix.Both auth layers are unchanged — the compiled-in
CLI_TOKENstill gates every connection and the CLI still requires root — so the abstract namespace's lack of a filesystem-permission gate costs nothing exploitable. The bind carries no file, so the startup delete and shutdown unlink are gone.Verified on-device: the socket binds as
@<hex>, the old constant is absent from/proc/net/unix,cli statusround-trips, and there is no SELinuxconnecttodenial.Closes #891.