Skip to content

Commit b5977c6

Browse files
RoyLinRoyLin
authored andcommitted
fix(macos): restore bridge networking with shim-hosted netproxy
1 parent c754f53 commit b5977c6

16 files changed

Lines changed: 1176 additions & 51 deletions

File tree

src/Cargo.lock

Lines changed: 95 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ members = [
1212
resolver = "2"
1313

1414
[workspace.package]
15-
version = "0.8.9"
15+
version = "0.8.10"
1616
edition = "2021"
1717
authors = ["A3S Lab Team"]
1818
license = "MIT"

src/cli/src/health.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ pub fn spawn_health_checker(
4040

4141
#[cfg(not(windows))]
4242
async fn run_health_loop(box_id: String, exec_socket_path: PathBuf, hc: HealthCheck) {
43-
use std::path::Path;
4443
use std::time::Duration;
4544

4645
// Honour start_period before the first probe

src/core/src/vmm.rs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
//! - [`VmHandler`] — lifecycle operations on a running VM
1111
1212
use std::net::Ipv4Addr;
13+
#[cfg(target_os = "macos")]
14+
use std::os::fd::RawFd;
1315
use std::path::PathBuf;
1416

1517
use async_trait::async_trait;
@@ -51,11 +53,21 @@ pub struct TeeInstanceConfig {
5153
pub tee_type: String,
5254
}
5355

54-
/// Network instance configuration for passt-based networking.
56+
/// Network instance configuration for the network backend (passt on Linux, gvproxy on macOS).
5557
#[derive(Debug, Clone, Serialize, Deserialize)]
5658
pub struct NetworkInstanceConfig {
57-
/// Path to the passt Unix socket.
58-
pub passt_socket_path: PathBuf,
59+
/// Path to the network backend Unix socket (passt on Linux, gvproxy on macOS).
60+
pub net_socket_path: PathBuf,
61+
62+
/// Pre-opened Unix datagram socket fd inherited by the shim on macOS.
63+
#[cfg(target_os = "macos")]
64+
#[serde(default)]
65+
pub net_socket_fd: Option<RawFd>,
66+
67+
/// Proxy-side Unix datagram socket fd inherited by the shim on macOS.
68+
#[cfg(target_os = "macos")]
69+
#[serde(default)]
70+
pub net_proxy_fd: Option<RawFd>,
5971

6072
/// Assigned IPv4 address for this VM.
6173
pub ip_address: Ipv4Addr,
@@ -127,8 +139,8 @@ pub struct InstanceSpec {
127139
#[serde(default)]
128140
pub user: Option<String>,
129141

130-
/// Network configuration for passt-based networking.
131-
/// None = TSI mode (default), Some = passt virtio-net mode.
142+
/// Network configuration for virtio-net networking.
143+
/// None = TSI mode (default), Some = virtio-net mode (passt on Linux, gvproxy on macOS).
132144
#[serde(default)]
133145
pub network: Option<NetworkInstanceConfig>,
134146

@@ -371,7 +383,11 @@ mod tests {
371383
fn test_instance_spec_with_network() {
372384
let spec = InstanceSpec {
373385
network: Some(NetworkInstanceConfig {
374-
passt_socket_path: PathBuf::from("/tmp/passt.sock"),
386+
net_socket_path: PathBuf::from("/tmp/net.sock"),
387+
#[cfg(target_os = "macos")]
388+
net_socket_fd: Some(42),
389+
#[cfg(target_os = "macos")]
390+
net_proxy_fd: Some(43),
375391
ip_address: "10.0.0.2".parse().unwrap(),
376392
gateway: "10.0.0.1".parse().unwrap(),
377393
prefix_len: 24,
@@ -385,6 +401,10 @@ mod tests {
385401
let deserialized: InstanceSpec = serde_json::from_str(&json).unwrap();
386402

387403
let net = deserialized.network.unwrap();
404+
#[cfg(target_os = "macos")]
405+
assert_eq!(net.net_socket_fd, Some(42));
406+
#[cfg(target_os = "macos")]
407+
assert_eq!(net.net_proxy_fd, Some(43));
388408
assert_eq!(net.ip_address, "10.0.0.2".parse::<Ipv4Addr>().unwrap());
389409
assert_eq!(net.gateway, "10.0.0.1".parse::<Ipv4Addr>().unwrap());
390410
assert_eq!(net.prefix_len, 24);

src/guest/init/src/main.rs

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,34 @@ fn mount_virtio_fs_shares() -> Result<(), Box<dyn std::error::Error>> {
441441
std::fs::create_dir_all("/mnt/newroot/sys").ok();
442442
std::fs::create_dir_all("/mnt/newroot/dev").ok();
443443

444-
// Move mounts
444+
// Move mounts: MS_PRIVATE first to allow MS_MOVE on shared mounts (sysfs).
445+
let mut proc_moved = false;
446+
let mut sys_moved = false;
447+
let mut dev_moved = false;
448+
449+
// Make mounts private so MS_MOVE works
450+
let _ = mount(
451+
Some(""),
452+
"/proc",
453+
None::<&str>,
454+
MsFlags::MS_PRIVATE,
455+
None::<&str>,
456+
);
457+
let _ = mount(
458+
Some(""),
459+
"/sys",
460+
None::<&str>,
461+
MsFlags::MS_PRIVATE | MsFlags::MS_REC,
462+
None::<&str>,
463+
);
464+
let _ = mount(
465+
Some(""),
466+
"/dev",
467+
None::<&str>,
468+
MsFlags::MS_PRIVATE,
469+
None::<&str>,
470+
);
471+
445472
if let Err(e) = mount(
446473
Some("/proc"),
447474
"/mnt/newroot/proc",
@@ -450,6 +477,8 @@ fn mount_virtio_fs_shares() -> Result<(), Box<dyn std::error::Error>> {
450477
None::<&str>,
451478
) {
452479
warn!("Failed to move /proc: {}", e);
480+
} else {
481+
proc_moved = true;
453482
}
454483

455484
if let Err(e) = mount(
@@ -460,6 +489,8 @@ fn mount_virtio_fs_shares() -> Result<(), Box<dyn std::error::Error>> {
460489
None::<&str>,
461490
) {
462491
warn!("Failed to move /sys: {}", e);
492+
} else {
493+
sys_moved = true;
463494
}
464495

465496
if let Err(e) = mount(
@@ -470,16 +501,56 @@ fn mount_virtio_fs_shares() -> Result<(), Box<dyn std::error::Error>> {
470501
None::<&str>,
471502
) {
472503
warn!("Failed to move /dev: {}", e);
504+
} else {
505+
dev_moved = true;
473506
}
474507

475508
// Change directory to new root
476509
std::env::set_current_dir("/mnt/newroot")?;
477510

478-
// Pivot root
511+
// Pivot root via chroot
479512
use nix::unistd::{chdir, chroot};
480513
chroot("/mnt/newroot")?;
481514
chdir("/")?;
482515

516+
// Re-mount any filesystems that couldn't be moved (MS_MOVE failed).
517+
// This ensures /proc, /sys, /dev are available in the new rootfs.
518+
if !proc_moved {
519+
if let Err(e) = mount(
520+
Some("proc"),
521+
"/proc",
522+
Some("proc"),
523+
MsFlags::empty(),
524+
None::<&str>,
525+
) {
526+
warn!("Failed to remount /proc after chroot: {}", e);
527+
}
528+
}
529+
if !sys_moved {
530+
if let Err(e) = mount(
531+
Some("sysfs"),
532+
"/sys",
533+
Some("sysfs"),
534+
MsFlags::empty(),
535+
None::<&str>,
536+
) {
537+
warn!("Failed to remount /sys after chroot: {}", e);
538+
} else {
539+
info!("Remounted /sys after chroot (MS_MOVE failed)");
540+
}
541+
}
542+
if !dev_moved {
543+
if let Err(e) = mount(
544+
Some("devtmpfs"),
545+
"/dev",
546+
Some("devtmpfs"),
547+
MsFlags::empty(),
548+
None::<&str>,
549+
) {
550+
warn!("Failed to remount /dev after chroot: {}", e);
551+
}
552+
}
553+
483554
info!("Successfully pivoted to new root filesystem");
484555
}
485556
Err(e) => {

0 commit comments

Comments
 (0)