Repository navigation
network: resolve chroot named unix sockets on-behalf - #337
Closed
congwang-mk wants to merge 7 commits into
Closed
congwang-mk wants to merge 7 commits into
congwang-mk wants to merge 7 commits into
Conversation
Chroot mode never moves the child's real root or cwd, yet the named unix gate checked the raw sun_path lexically and returned Continue, leaving the kernel to resolve it on the host. An absolute virtual path therefore reached the host's socket of that name (an escape where Landlock cannot gate unix connect), and a relative one was checked as if anchored at / but resolved against the cwd the child was exec'ed in, so ./svc.sock from a granted cwd was refused while tmp/x.sock from an ungranted one passed. Serve chroot connect/sendto/sendmsg/sendmmsg on-behalf like non-chroot: build the virtual path against the tracked virtual cwd, pin the inode inside the root (mount aware), and check write access on where it really sits. The trap now stays on under chroot even with Landlock ABI v9. Signed-off-by: Cong Wang <cwang@multikernel.io>
congwang-mk
force-pushed
the
chroot-relative-unix-path
branch
from
October 31, 2026 20:51
55acccc to
7354bfd
Compare
A synchronous operation can outlive the future waiting for it. Using the caller's blocking pool lets stalled work consume its threads and delay runtime shutdown, while releasing admission on timeout would allow new work to accumulate behind calls that are still running. Add process-wide Tokio blocking pools with admission owned by each native closure until it returns. Reject saturation with EAGAIN and give filesystem work separate capacity so stalled external peers cannot take its workers. Dropping a waiter stops waiting only; it does not cancel the native call. Signed-off-by: Cong Wang <cwang@multikernel.io>
Unix and IP connects execute synchronously after policy approval. A slow peer can therefore hold up the notification loop and prevent unrelated trapped syscalls from making progress. Prepare a lazy blocking action for both connect paths and run it through the bounded pool once approved and admitted. The closure keeps the socket and pinned path alive until connect returns, and a rejected operation never starts the native call. Signed-off-by: Cong Wang <cwang@multikernel.io>
Awaiting an FFI callback inline still holds up notification intake even when the callback runs on a blocking thread. Terminal deferral cannot replace that wait because Continue must reach the remaining handlers. Add a suspended action that parks the notification and resumes its handler chain when the work finishes. Keep explicit deferral terminal, and use the bounded blocking pool for FFI callbacks. Retain the listener and callback owner in native work, and translate callback output there so a timed-out waiter cannot free userdata or strand an injected fd. Track native access to child memory so exec argument validation does not overlap it. Signed-off-by: Cong Wang <cwang@multikernel.io>
Chroot path lookup and COW filesystem operations perform synchronous I/O while dispatching a notification. Offloading only the copy leaves those lookups on the notification loop and can release COW state before a copy whose waiter was dropped has finished. Suspend these handlers on the isolated filesystem pool and keep the owned COW state lock through the whole operation, including copying and quota bookkeeping. Run copies directly on that worker and fail a write with EIO when copying fails. Route image helper work through the same pool. Signed-off-by: Cong Wang <cwang@multikernel.io>
Resuming the handler chain in a parked task lets it start native memory access while the notification loop validates exec arguments. Shared admission also lets stalled callbacks exclude filesystem work, and a fork slot reserved before suspension can leak when the request never resumes. Return suspended dispatch state to the notification loop before advancing the remaining handlers, keeping one deadline across suspensions. Track native memory access separately from admission and give filesystem waits their own capacity. Drain completed work during notification intake so a busy child cannot indefinitely postpone it. Reserve fork slots only after handlers and approval allow Continue, roll back failed responses, and refuse terminal deferral for fork-like calls because it bypasses accounting. Signed-off-by: Cong Wang <cwang@multikernel.io>
congwang-mk
force-pushed
the
chroot-relative-unix-path
branch
from
November 2, 2026 02:50
fc422d3 to
31366f2
Compare
A timed-out callback can keep running after its sandbox exits. Retaining the handler container does not protect caller-owned userdata, whose public lifetime ends when the FFI run returns. Keep a callback guard for each registered handler through the run. Wait for active callbacks before releasing their userdata and remove the callback so queued work cannot access it afterward. Preserve concurrent callback execution while keeping teardown outside the notification loop. Cover abandoned callbacks with borrowed userdata and queued callbacks that have not started. Document that a callback which never returns also prevents the FFI run from completing. Signed-off-by: Cong Wang <cwang@multikernel.io>
3 tasks done
Contributor
Author
|
Superseded by #340, which carries this PR's chroot named unix socket fix unchanged as its first commit and replaces the off-loop dispatch rework with a simpler design. |
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.
Follow-up to #328, which fixed relative named unix socket paths in non-chroot mode.
Chroot mode never moves the child's real root or cwd, yet the named unix gate checked the raw
sun_pathlexically and returnedContinue, leaving the kernel to resolve it on the host:/tmp/svc.sockreached the host socket of that name instead of the one in the rootfs. Where Landlock cannot gate unix connect (ABI < 9), that is an escape to host sockets under a granted prefix./but resolved against the cwd the child was exec'ed in, so./svc.sockfrom a granted cwd was refused whiletmp/x.sockfrom an ungranted one passed.This serves chroot
connect/sendto/sendmsg/sendmmsgon-behalf like non-chroot: build the virtual path against the tracked virtual cwd, pin the inode inside the root (mount aware) withopenat2(RESOLVE_IN_ROOT), and checkcan_writeon where the pinned inode really sits. The trap stays on under chroot even with Landlock ABI v9, since the kernel cannot resolve virtual paths. As in non-chroot pre-v9, the peer'sSO_PEERCREDthen names the supervisor.Tests: a new
unix-sendrootfs-helper command and three chroot integration tests (absolute and relative stream connects, relative datagram, relative path outside the grant, symlink out of the grant). All fail on main and pass here.