Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 94d9067

Browse files
WhatAmISupposedToPutHerenrabulinski
andcommittedMar 14, 2025··
Pass through the current working directory
Aside from just being better UX, some commands are sensitive to it and will not work correctly without it. Co-authored-by: Nikodem Rabuliński <[email protected]> Signed-off-by: Nikodem Rabuliński <[email protected]>
1 parent b16a542 commit 94d9067

File tree

5 files changed

+35
-7
lines changed

5 files changed

+35
-7
lines changed
 

‎crates/muvm/src/bin/muvm.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,13 @@ fn main() -> Result<ExitCode> {
9393
unreachable!("`launch_vm` never returns");
9494
}
9595

96+
let cwd = env::current_dir()?;
9697
let inherit_env = !options.no_inherit_env;
97-
let (lock_file, command, command_args, env) = match launch_or_lock(
98+
let (lock_file, command, command_args, env, cwd) = match launch_or_lock(
9899
options.command,
99100
options.command_args,
100101
options.env,
102+
cwd,
101103
options.no_tty,
102104
options.privileged,
103105
inherit_env,
@@ -112,7 +114,8 @@ fn main() -> Result<ExitCode> {
112114
command,
113115
command_args,
114116
env,
115-
} => (lock_file, command, command_args, env),
117+
cwd,
118+
} => (lock_file, command, command_args, env, cwd),
116119
};
117120

118121
// Make it lose CLOEXEC
@@ -125,6 +128,7 @@ fn main() -> Result<ExitCode> {
125128
command,
126129
command_args,
127130
env,
131+
cwd,
128132
options.no_tty,
129133
options.privileged,
130134
inherit_env,

‎crates/muvm/src/guest/server_worker.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,9 @@ async fn handle_connection(mut stream: BufStream<UnixStream>) -> Result<ConnRequ
200200
vsock_port,
201201
tty,
202202
privileged,
203+
cwd,
203204
} = read_request(&mut stream).await?;
204-
debug!(command:?, command_args:?, env:?; "received launch request");
205+
debug!(command:?, command_args:?, env:?, cwd:?; "received launch request");
205206

206207
if command == Path::new("/muvmdropcaches") {
207208
// SAFETY: everything below should be async signal safe
@@ -274,7 +275,19 @@ async fn handle_connection(mut stream: BufStream<UnixStream>) -> Result<ConnRequ
274275
.envs(envs)
275276
.stdin(stdin)
276277
.stdout(stdout)
277-
.stderr(stderr);
278+
.stderr(stderr)
279+
// The documentation says that if `command` is a relative path,
280+
// it's ambiguous whether it should be interpreted relative
281+
// to the parent's working directory or relative to `current_dir`.[0]
282+
// Luckily for us, on UNIX in case of `Command::spawn`,
283+
// it's implemented by calling `posix_spawn_file_actions_add_chdir`.[1]
284+
// This is exactly what we want, as the user may want to run `muvm ./foo`
285+
// in which case we need `./foo` to be interpreted relative to `current_dir`,
286+
// not relative to cwd of the server worker.
287+
//
288+
// [0]: https://doc.rust-lang.org/stable/std/process/struct.Command.html#platform-specific-behavior-1
289+
// [1]: https://github.com/rust-lang/rust/blob/cb50d4d8566b1ee97e9a5ef95a37a40936a62c30/library/std/src/sys/pal/unix/process/process_unix.rs#L705-L707
290+
.current_dir(cwd);
278291
if tty {
279292
unsafe {
280293
cmd.pre_exec(|| {

‎crates/muvm/src/launch.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub enum LaunchResult {
2828
command: PathBuf,
2929
command_args: Vec<String>,
3030
env: Vec<(String, Option<String>)>,
31+
cwd: PathBuf,
3132
},
3233
}
3334

@@ -89,6 +90,7 @@ fn wrapped_launch(
8990
command: PathBuf,
9091
command_args: Vec<String>,
9192
env: HashMap<String, String>,
93+
cwd: PathBuf,
9294
no_tty: bool,
9395
privileged: bool,
9496
) -> Result<ExitCode> {
@@ -100,7 +102,7 @@ fn wrapped_launch(
100102
_ = unlink(&path);
101103
let listener = UnixListener::bind(path).context("Failed to listen on vm socket")?;
102104
let tty = !no_tty && stdout_is_tty();
103-
request_launch(command, command_args, env, vsock_port, tty, privileged)?;
105+
request_launch(command, command_args, env, cwd, vsock_port, tty, privileged)?;
104106
let raw_tty = tty.then(|| RawTerminal::set().expect("Stdout should be a tty"));
105107
let code = run_io_host(listener, tty)?;
106108
drop(raw_tty);
@@ -111,6 +113,7 @@ pub fn launch_or_lock(
111113
command: PathBuf,
112114
command_args: Vec<String>,
113115
env: Vec<(String, Option<String>)>,
116+
cwd: PathBuf,
114117
no_tty: bool,
115118
privileged: bool,
116119
inherit_env: bool,
@@ -122,6 +125,7 @@ pub fn launch_or_lock(
122125
command,
123126
command_args,
124127
env,
128+
cwd,
125129
}),
126130
None => {
127131
let env = prepare_env_vars(env, inherit_env)?;
@@ -131,6 +135,7 @@ pub fn launch_or_lock(
131135
command.clone(),
132136
command_args.clone(),
133137
env.clone(),
138+
cwd.clone(),
134139
no_tty,
135140
privileged,
136141
) {
@@ -182,6 +187,7 @@ pub fn request_launch(
182187
command: PathBuf,
183188
command_args: Vec<String>,
184189
env: HashMap<String, String>,
190+
cwd: PathBuf,
185191
vsock_port: u32,
186192
tty: bool,
187193
privileged: bool,
@@ -195,6 +201,7 @@ pub fn request_launch(
195201
command,
196202
command_args,
197203
env,
204+
cwd,
198205
vsock_port,
199206
tty,
200207
privileged,

‎crates/muvm/src/monitor.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::collections::HashMap;
2+
use std::env::current_dir;
23
use std::path::PathBuf;
34
use std::thread;
45
use std::time;
@@ -43,7 +44,8 @@ fn set_guest_pressure(pressure: GuestPressure) -> Result<()> {
4344
let command = PathBuf::from("/muvmdropcaches");
4445
let command_args = vec![];
4546
let env = HashMap::new();
46-
request_launch(command, command_args, env, 0, false, true)?;
47+
let cwd = current_dir()?;
48+
request_launch(command, command_args, env, cwd, 0, false, true)?;
4749
}
4850

4951
let wsf: u32 = pressure.into();
@@ -52,7 +54,8 @@ fn set_guest_pressure(pressure: GuestPressure) -> Result<()> {
5254
let command = PathBuf::from("/sbin/sysctl");
5355
let command_args = vec![format!("vm.watermark_scale_factor={}", wsf)];
5456
let env = HashMap::new();
55-
request_launch(command, command_args, env, 0, false, true)
57+
let cwd = current_dir()?;
58+
request_launch(command, command_args, env, cwd, 0, false, true)
5659
}
5760

5861
fn run() {

‎crates/muvm/src/utils/launch.rs

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ pub struct Launch {
1212
pub vsock_port: u32,
1313
pub tty: bool,
1414
pub privileged: bool,
15+
pub cwd: PathBuf,
1516
}
1617

1718
#[derive(Clone, Eq, PartialEq, Debug, Deserialize, Serialize)]

0 commit comments

Comments
 (0)
Please sign in to comment.