Skip to content

fix(net): prevent gvproxy socket path collision between concurrent boxes#219

Merged
DorianZheng merged 2 commits intomainfrom
fix/gvproxy-socket-path-collision
Feb 9, 2026
Merged

fix(net): prevent gvproxy socket path collision between concurrent boxes#219
DorianZheng merged 2 commits intomainfrom
fix/gvproxy-socket-path-collision

Conversation

@DorianZheng
Copy link
Copy Markdown
Member

Summary

  • Bug: Two concurrent BoxLite instances collide on /tmp/gvproxy-1.sock because Go's nextID counter starts at 1 per process. Each shim generates the same socket path, breaking instance A's networking when instance B starts.
  • Fix: Caller provides the socket path instead of Go generating it. Each box gets ~/.boxlite/boxes/{box_id}/sockets/net.sock — unique by design.
  • Deleted: Entire gvproxy_get_socket_path FFI chain (Go export → C extern → Rust wrapper) — no longer needed since the caller already knows the path.

Changes

File Change
gvproxy-bridge/main.go Add SocketPath to Go config, use caller's path, delete gvproxy_get_socket_path
libgvproxy-sys/src/lib.rs Remove gvproxy_get_socket_path extern
net/gvproxy/config.rs Add socket_path: PathBuf field, update constructor
net/gvproxy/ffi.rs Delete get_socket_path() wrapper
net/gvproxy/instance.rs Store socket_path, replace FFI getter with accessor
net/gvproxy/mod.rs Pass socket_path through GvisorTapBackend
net/mod.rs Add socket_path to NetworkBackendConfig
runtime/layout.rs Add net_backend_socket_path()
litebox/init/tasks/vmm_spawn.rs Wire layout path into NetworkBackendConfig
bin/shim.rs Use net_config.socket_path instead of FFI call

Test plan

  • 4 regression tests that would fail on old code (compile errors — fields/methods didn't exist) and pass on new code:
    • test_different_boxes_get_different_net_backend_socket_paths (layout uniqueness)
    • test_socket_path_survives_json_serialization (JSON reaches Go FFI)
    • test_two_configs_have_different_socket_paths_in_json (collision prevention)
    • test_network_config_carries_unique_socket_paths (serde across process boundary)
  • cargo test -p boxlite — all tests pass
  • cargo fmt — clean
  • cargo clippy -D warnings — clean

Two concurrent BoxLite instances would collide on /tmp/gvproxy-1.sock
because Go's nextID counter starts at 1 per process. Each shim process
generated the same socket path, causing instance A's networking to break
when instance B started.

The fix makes the caller provide the socket path instead of letting
the Go library generate it. Each box now gets a unique path derived
from its layout: ~/.boxlite/boxes/{box_id}/sockets/net.sock.

Changes:
- Add socket_path field to GvproxyConfig (Rust) and GvproxyConfig (Go)
- Add net_backend_socket_path() to BoxFilesystemLayout
- Add socket_path to NetworkBackendConfig
- Delete gvproxy_get_socket_path FFI chain (Go export, C extern, Rust wrapper)
- Update shim.rs to use config-provided socket path
- Add 4 regression tests covering layout uniqueness, JSON serialization,
  config differentiation, and cross-process serde
All 4 -sys build scripts had guards that skipped rebuilding when the
output artifact already existed. This defeated cargo's rerun-if-changed
mechanism: cargo correctly re-ran the build script when sources changed,
but the script exited early because the stale artifact was still present.

This caused the gvproxy socket path fix to silently fail at runtime —
the Go library was never recompiled despite source changes.
@DorianZheng DorianZheng merged commit d4840bf into main Feb 9, 2026
13 checks passed
@DorianZheng DorianZheng deleted the fix/gvproxy-socket-path-collision branch February 9, 2026 06:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant