Skip to content

Commit 570f8e0

Browse files
fix: proper shell quoting in vz run and auto-create /dev/kvm, /dev/net/tun
- Replace hand-rolled shell_escape() with shell_words::quote() so that `vz run -- sh -c 'echo hello'` correctly preserves multi-word arguments when passed through /bin/sh -c. - Auto-create /dev/kvm and /dev/net/tun in the init script when the kernel supports them but devtmpfs doesn't populate the nodes. Applies to both initramfs-only and overlay rootfs (chroot) boot paths. Bump vz-cli to v0.3.2. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent e20843f commit 570f8e0

File tree

4 files changed

+31
-13
lines changed

4 files changed

+31
-13
lines changed

crates/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/vz-cli/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "vz-cli"
3-
version = "0.3.1"
3+
version = "0.3.2"
44
description = "CLI for managing containers and macOS VM sandboxes"
55
edition.workspace = true
66
rust-version.workspace = true

crates/vz-cli/src/commands/dev.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,14 @@ pub async fn cmd_run(args: DevRunArgs) -> anyhow::Result<()> {
258258
let container_id = resolve_container(&mut client, &sandbox_id).await?;
259259

260260
// Build the shell command with env vars and working directory.
261-
let shell_command = args.command.join(" ");
261+
// Each argument is shell-quoted so that multi-word args (e.g. `sh -c 'echo hello'`)
262+
// are preserved when the command string is passed through `/bin/sh -c`.
263+
let shell_command = args
264+
.command
265+
.iter()
266+
.map(|arg| shell_words::quote(arg).into_owned())
267+
.collect::<Vec<_>>()
268+
.join(" ");
262269
let mut env_map = config.env.clone();
263270

264271
// Ensure HOME is always set — many tools (rustup, npm, etc.) depend on it.
@@ -283,7 +290,7 @@ pub async fn cmd_run(args: DevRunArgs) -> anyhow::Result<()> {
283290

284291
let env_prefix: String = env_map
285292
.iter()
286-
.map(|(k, v)| format!("export {}={}", k, shell_escape(v)))
293+
.map(|(k, v)| format!("export {}={}", k, shell_words::quote(v)))
287294
.collect::<Vec<_>>()
288295
.join("; ");
289296

@@ -866,12 +873,3 @@ fn parse_memory(raw: Option<&str>) -> anyhow::Result<u64> {
866873
}
867874
}
868875

869-
fn shell_escape(s: &str) -> String {
870-
if s.chars()
871-
.all(|c| c.is_alphanumeric() || c == '_' || c == '-' || c == '/' || c == '.' || c == ':')
872-
{
873-
s.to_string()
874-
} else {
875-
format!("'{}'", s.replace('\'', "'\\''"))
876-
}
877-
}

linux/initramfs/init

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,17 @@ mount -t tmpfs tmpfs /tmp
1111

1212
mkdir -p /run /mnt/rootfs /mnt/merged
1313

14+
# Create device nodes that devtmpfs may not auto-populate.
15+
# /dev/kvm: needed for nested virtualization (Firecracker, QEMU).
16+
# /dev/net/tun: needed for tap networking (Firecracker guest NICs).
17+
if [ -e /sys/devices/virtual/misc/kvm ] && [ ! -e /dev/kvm ]; then
18+
/bin/busybox mknod /dev/kvm c 10 232 2>/dev/null || true
19+
fi
20+
if [ -e /sys/class/misc/tun ] && [ ! -e /dev/net/tun ]; then
21+
mkdir -p /dev/net
22+
/bin/busybox mknod /dev/net/tun c 10 200 2>/dev/null || true
23+
fi
24+
1425
# Optional runtime binary share (host-provided youki artifact).
1526
mkdir -p /mnt/oci-runtime-bin
1627

@@ -58,6 +69,15 @@ switch_root_into_overlay_rootfs() {
5869
mount -t devtmpfs devtmpfs "$ROOTFS/dev" || true
5970
mount -t tmpfs tmpfs "$ROOTFS/tmp" || return 1
6071

72+
# Create device nodes that devtmpfs may not auto-populate in the chroot.
73+
if [ -e /sys/devices/virtual/misc/kvm ] && [ ! -e "$ROOTFS/dev/kvm" ]; then
74+
/bin/busybox mknod "$ROOTFS/dev/kvm" c 10 232 2>/dev/null || true
75+
fi
76+
if [ -e /sys/class/misc/tun ] && [ ! -e "$ROOTFS/dev/net/tun" ]; then
77+
mkdir -p "$ROOTFS/dev/net"
78+
/bin/busybox mknod "$ROOTFS/dev/net/tun" c 10 200 2>/dev/null || true
79+
fi
80+
6181
# Mount cgroup2 for OCI container runtime (youki) support.
6282
mkdir -p "$ROOTFS/sys/fs/cgroup"
6383
mount -t cgroup2 none "$ROOTFS/sys/fs/cgroup" || true

0 commit comments

Comments
 (0)