mirror of
https://github.com/hanzoai/lsp.git
synced 2026-09-30 22:52:48 +00:00
TypeScript and JavaScript were the two languages the new image could not serve. The daemon said why and kept going: `language server did not start … spawn EPERM`, once per root, while the other eight answered. socketpair was denied beside socket, on the reading that a served process must be able to obtain no socket fd at all. But libuv gives a child its stdio through a socketpair, so what that denied was not a network — it was Node starting a process, and typescript-language-server exists to run tsserver. A socketpair reaches nothing: both ends come back already connected to each other, in AF_UNIX, inside this jail's namespaces. It cannot be connect()ed elsewhere, and a peer that could pass a network fd over it would have to be outside the jail, where nothing is. socket() is still denied, so there is still no way to obtain a fd to a network. The filter now reads args[0] and admits AF_UNIX alone. Allowing it outright would have been equivalent today — the kernel implements socketpair for no other family — but that is a fact about the kernel, not a property of this program, and the claim in the header is worth keeping true by construction. The arithmetic is the risk: those two jump edges are hand-computed offsets over a list whose length changes with the phase, and an off-by-one reads as ALLOW. TestSocketpairIsDecidedByItsFamily interprets the program for AF_UNIX and for five families that must fail, in both phases, and pins that the carve-out did not widen to socket(). Co-authored-by: Hanzo Dev <[email protected]>