From 60e4ffd5b3b5eb61edf3b0ca6adb68fcb158b3b7 Mon Sep 17 00:00:00 2001 From: Sasha Finkelstein Date: Thu, 13 Mar 2025 18:24:33 +0100 Subject: [PATCH 1/6] Always use interactive mode. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is always what you want if running via binfmt Signed-off-by: Nikodem Rabuliński --- crates/muvm/src/bin/muvm.rs | 1 - crates/muvm/src/cli_options.rs | 6 ------ crates/muvm/src/launch.rs | 7 ------- 3 files changed, 14 deletions(-) diff --git a/crates/muvm/src/bin/muvm.rs b/crates/muvm/src/bin/muvm.rs index 3d1c699e..e60347b6 100644 --- a/crates/muvm/src/bin/muvm.rs +++ b/crates/muvm/src/bin/muvm.rs @@ -78,7 +78,6 @@ fn main() -> Result { options.command, options.command_args, options.env, - options.interactive, options.tty, options.privileged, )? { diff --git a/crates/muvm/src/cli_options.rs b/crates/muvm/src/cli_options.rs index 9dd01f36..b8aa0f0f 100644 --- a/crates/muvm/src/cli_options.rs +++ b/crates/muvm/src/cli_options.rs @@ -16,7 +16,6 @@ pub struct Options { pub passt_socket: Option, pub fex_images: Vec, pub merged_rootfs: bool, - pub interactive: bool, pub tty: bool, pub privileged: bool, pub publish_ports: Vec, @@ -109,10 +108,6 @@ pub fn options() -> OptionParser { .help("Instead of starting passt, connect to passt socket at PATH") .argument("PATH") .optional(); - let interactive = long("interactive") - .short('i') - .help("Attach to the command's stdin/out after starting it") - .switch(); let tty = long("tty") .short('t') .help("Allocate a tty for the command") @@ -147,7 +142,6 @@ pub fn options() -> OptionParser { passt_socket, fex_images, merged_rootfs, - interactive, tty, privileged, publish_ports, diff --git a/crates/muvm/src/launch.rs b/crates/muvm/src/launch.rs index bc507905..db57dc28 100644 --- a/crates/muvm/src/launch.rs +++ b/crates/muvm/src/launch.rs @@ -87,14 +87,9 @@ fn wrapped_launch( command: PathBuf, command_args: Vec, env: HashMap, - interactive: bool, tty: bool, privileged: bool, ) -> Result { - if !interactive { - request_launch(command, command_args, env, 0, false, privileged)?; - return Ok(ExitCode::from(0)); - } let run_path = env::var("XDG_RUNTIME_DIR") .map_err(|e| anyhow!("unable to get XDG_RUNTIME_DIR: {:?}", e))?; let socket_dir = Path::new(&run_path).join("krun/socket"); @@ -120,7 +115,6 @@ pub fn launch_or_lock( command: PathBuf, command_args: Vec, env: Vec<(String, Option)>, - interactive: bool, tty: bool, privileged: bool, ) -> Result { @@ -140,7 +134,6 @@ pub fn launch_or_lock( command.clone(), command_args.clone(), env.clone(), - interactive, tty, privileged, ) { From c72c9aa796bdd9a24332001f1797facf07b637f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikodem=20Rabuli=C5=84ski?= Date: Thu, 13 Mar 2025 22:18:47 +0100 Subject: [PATCH 2/6] Update usage in README MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nikodem Rabuliński --- README.md | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index e5b42445..7b4500ef 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,9 @@ ## Using ``` sh -Usage: muvm [-c=CPU_LIST]... [-e=ENV]... [--mem=MEM] [--vram=VRAM] [--passt-socket=PATH] [-p= -SERVER_PORT] [-f=FEX_IMAGE]... COMMAND [COMMAND_ARGS]... +Usage: muvm [-c=CPU_LIST]... [-e=ENV]... [--mem=MEM] [--vram=VRAM] [--passt-socket=PATH] [-f= +FEX_IMAGE]... [-m] [-i] [-t] [--privileged] [-p=<[[IP:][HOST_PORT]:]GUEST_PORT[/PROTOCOL]>]... [ +--emu=EMU] COMMAND [COMMAND_ARGS]... Available positional items: COMMAND the command you want to execute in the vm @@ -34,19 +35,26 @@ Available options: Machine Monitor) will attempt to return as many pages as possible to the host. [default: 80% of total RAM] - --vram=VRAM The amount of Video RAM, in MiB, that will be available to this - microVM. - The memory configured for the microVM will not be reserved - immediately. Instead, it will be provided as the guest demands - it, and will be returned to the host once the guest releases - the underlying resources. - [default: same as the total amount of RAM in the system] + --vram=VRAM The amount of Video RAM, in MiB, that will reported by userspace in + this microVM. + The userspace drivers will report this amount as heap size + to the clients running in the microVM. + [default: 50% of total RAM] --passt-socket=PATH Instead of starting passt, connect to passt socket at PATH - -p, --server-port=SERVER_PORT Set the port to be used in server mode - [default: 3334] -f, --fex-image=FEX_IMAGE Adds an erofs file to be mounted as a FEX rootfs. May be specified multiple times. First the base image, then overlays in order. + -m, --merged-rootfs Use merged rootfs for FEX (experimental) + -t, --tty Allocate a tty for the command + --privileged Run the command as root inside the vm. + This notably does not allow root access to the host fs. + -p, --publish=<[[IP:][HOST_PORT]:]GUEST_PORT[/PROTOCOL]> + Publish a guest’s port, or range of ports, to the host. + The syntax is similar to podman/docker. + --emu=EMU Which emulator to use for running x86_64 binaries. + Valid options are "box" and "fex". If this argument is not + present, muvm will try to use FEX, falling back to Box if it + can't be found. -h, --help Prints help information ``` From 2ff7d90f81ad06b06555c0861efe1b2dd45e2d27 Mon Sep 17 00:00:00 2001 From: Sasha Finkelstein Date: Fri, 14 Mar 2025 12:06:17 +0100 Subject: [PATCH 3/6] Daemonize the vm process MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Launches the initial command via the server too. Server is set to linger for 10 seconds after last command finishes. Co-authored-by: Nikodem Rabuliński Signed-off-by: Nikodem Rabuliński --- Cargo.lock | 435 ++++++++++++++---------- crates/muvm/Cargo.toml | 2 +- crates/muvm/src/bin/muvm.rs | 84 +++-- crates/muvm/src/guest/bin/muvm-guest.rs | 2 +- crates/muvm/src/guest/server.rs | 71 ++-- crates/muvm/src/launch.rs | 21 +- crates/muvm/src/utils/launch.rs | 1 - 7 files changed, 361 insertions(+), 255 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cb44bcd9..e46b4700 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,18 +4,18 @@ version = 3 [[package]] name = "addr2line" -version = "0.22.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "aho-corasick" @@ -28,9 +28,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.14" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -43,43 +43,44 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.7" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.3" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.3" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "once_cell", + "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.91" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8" +checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" [[package]] name = "autocfg" @@ -89,24 +90,24 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.72" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17c6a35df3749d2e8bb1b7b21a976d82b15548788d2735b9d82f329268f71a11" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] name = "bindgen" -version = "0.69.4" +version = "0.69.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" dependencies = [ "bitflags", "cexpr", @@ -124,15 +125,15 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.5.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" [[package]] name = "bpaf" -version = "0.9.12" +version = "0.9.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3280efcf6d66bc77c2cf9b67dc8acee47a217d9be67dd590b3230dffe663724d" +checksum = "4848ed5727d39a7573551c205bcb1ccd88c8cad4ed2c80f62e2316f208196b8d" [[package]] name = "byteorder" @@ -142,15 +143,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" - -[[package]] -name = "cc" -version = "1.0.99" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cexpr" @@ -175,9 +170,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "clang-sys" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", @@ -185,88 +180,89 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "either" -version = "1.11.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "env_filter" -version = "0.1.0" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" dependencies = [ "log", ] [[package]] name = "env_logger" -version = "0.11.3" +version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9" +checksum = "c3716d7a920fb4fac5d84e9d4bce8ceb321e9414b4409da61b07b75c1e3d0697" dependencies = [ "anstream", "anstyle", "env_filter", - "humantime", + "jiff", "log", ] [[package]] name = "errno" -version = "0.3.8" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "fastrand" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "getrandom" -version = "0.2.15" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.13.3+wasi-0.2.2", + "windows-targets 0.52.6", ] [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "glob" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "hermit-abi" @@ -280,12 +276,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - [[package]] name = "input-linux" version = "0.7.1" @@ -319,9 +309,9 @@ dependencies = [ [[package]] name = "is_terminal_polyfill" -version = "1.70.0" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itertools" @@ -334,9 +324,33 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "jiff" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d699bc6dfc879fb1bf9bdff0d4c56f0884fc6f0d0eb0fba397a6d00cd9a6b85e" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", +] + +[[package]] +name = "jiff-static" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d16e75759ee0aa64c57a56acbf43916987b20c77373cb7e808979e02b93c9f9" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "krun-sys" @@ -348,9 +362,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "lazycell" @@ -360,9 +374,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.161" +version = "0.2.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" [[package]] name = "libudev-sys" @@ -376,21 +390,27 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413" [[package]] name = "log" -version = "0.4.21" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memoffset" @@ -409,22 +429,22 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" +checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" dependencies = [ - "adler", + "adler2", ] [[package]] name = "mio" -version = "0.8.11" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", - "wasi", - "windows-sys 0.48.0", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.52.0", ] [[package]] @@ -441,7 +461,7 @@ dependencies = [ "log", "nix", "procfs", - "rustix", + "rustix 0.38.44", "serde", "serde_json", "tempfile", @@ -475,41 +495,52 @@ dependencies = [ ] [[package]] -name = "num_cpus" -version = "1.16.0" +name = "object" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ - "hermit-abi", - "libc", + "memchr", ] [[package]] -name = "object" -version = "0.35.0" +name = "once_cell" +version = "1.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e" -dependencies = [ - "memchr", -] +checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pkg-config" -version = "0.3.31" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "portable-atomic" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" +checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] [[package]] name = "proc-macro2" -version = "1.0.82" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" dependencies = [ "unicode-ident", ] @@ -523,7 +554,7 @@ dependencies = [ "bitflags", "hex", "procfs-core", - "rustix", + "rustix 0.38.44", ] [[package]] @@ -538,18 +569,18 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] [[package]] name = "regex" -version = "1.10.4" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -559,9 +590,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -570,9 +601,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rustc-demangle" @@ -588,38 +619,51 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ "bitflags", "errno", "itoa", "libc", - "linux-raw-sys", - "windows-sys 0.52.0", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7178faa4b75a30e269c71e61c353ce2748cf3d76f0c44c393f4e60abf49b825" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys 0.9.3", + "windows-sys 0.59.0", ] [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "serde" -version = "1.0.203" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.203" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", @@ -628,11 +672,12 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -654,9 +699,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", @@ -664,9 +709,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.61" +version = "2.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c993ed8ccba56ae856363b1845da7266a7cb78e1d146c8a32d54b45a8b831fc9" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" dependencies = [ "proc-macro2", "quote", @@ -675,39 +720,38 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.10.1" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "488960f40a3fd53d72c2a29a58722561dee8afdd175bd88e3db4677d7b2ba600" dependencies = [ - "cfg-if", "fastrand", - "rustix", - "windows-sys 0.52.0", + "once_cell", + "rustix 1.0.2", + "windows-sys 0.59.0", ] [[package]] name = "tokio" -version = "1.38.0" +version = "1.44.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "2.3.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", @@ -716,9 +760,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.15" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ "futures-core", "pin-project-lite", @@ -728,9 +772,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034" dependencies = [ "bytes", "futures-core", @@ -741,9 +785,9 @@ dependencies = [ [[package]] name = "udev" -version = "0.9.1" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d5c197b95f1769931c89f85c33c407801d1fb7a311113bc0b39ad036f1bd81" +checksum = "af4e37e9ea4401fc841ff54b9ddfc9be1079b1e89434c1a6a865dd68980f7e9f" dependencies = [ "io-lifetimes", "libc", @@ -753,21 +797,21 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.10.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" dependencies = [ "getrandom", "serde", @@ -779,6 +823,15 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.13.3+wasi-0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -794,7 +847,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -814,18 +876,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -836,9 +898,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -848,9 +910,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -860,15 +922,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -878,9 +940,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -890,9 +952,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -902,9 +964,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -914,6 +976,15 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags", +] diff --git a/crates/muvm/Cargo.toml b/crates/muvm/Cargo.toml index 855968a5..ab430e1d 100644 --- a/crates/muvm/Cargo.toml +++ b/crates/muvm/Cargo.toml @@ -23,7 +23,7 @@ rustix = { version = "0.38.34", default-features = false, features = ["fs", "mou serde = { version = "1.0.203", default-features = false, features = ["derive"] } serde_json = { version = "1.0.117", default-features = false, features = ["std"] } tempfile = { version = "3.10.1", default-features = false, features = [] } -tokio = { version = "1.38.0", default-features = false, features = ["io-util", "macros", "net", "process", "rt-multi-thread", "sync"] } +tokio = { version = "1.38.0", default-features = false, features = ["io-util", "macros", "net", "process", "rt-multi-thread", "sync", "time"] } tokio-stream = { version = "0.1.15", default-features = false, features = ["net", "sync"] } udev = { version = "0.9.0", default-features = false, features = [] } uuid = { version = "1.10.0", default-features = false, features = ["serde", "std", "v7"] } diff --git a/crates/muvm/src/bin/muvm.rs b/crates/muvm/src/bin/muvm.rs index e60347b6..ca365012 100644 --- a/crates/muvm/src/bin/muvm.rs +++ b/crates/muvm/src/bin/muvm.rs @@ -1,20 +1,22 @@ -use std::collections::HashMap; +use std::convert::Infallible; +use std::env; use std::ffi::{c_char, CString}; +use std::fs::{self, File}; use std::io::Write; -use std::os::fd::{IntoRawFd, OwnedFd}; +use std::os::fd::{FromRawFd, IntoRawFd, OwnedFd}; use std::path::Path; -use std::process::ExitCode; -use std::{env, fs}; +use std::process::{Command, ExitCode}; use anyhow::{anyhow, Context, Result}; use krun_sys::{ krun_add_disk, krun_add_virtiofs2, krun_add_vsock_port, krun_add_vsock_port2, krun_create_ctx, - krun_set_env, krun_set_gpu_options2, krun_set_log_level, krun_set_passt_fd, krun_set_root, - krun_set_vm_config, krun_set_workdir, krun_start_enter, VIRGLRENDERER_DRM, - VIRGLRENDERER_THREAD_SYNC, VIRGLRENDERER_USE_ASYNC_FENCE_CB, VIRGLRENDERER_USE_EGL, + krun_set_console_output, krun_set_env, krun_set_gpu_options2, krun_set_log_level, + krun_set_passt_fd, krun_set_root, krun_set_vm_config, krun_set_workdir, krun_start_enter, + VIRGLRENDERER_DRM, VIRGLRENDERER_THREAD_SYNC, VIRGLRENDERER_USE_ASYNC_FENCE_CB, + VIRGLRENDERER_USE_EGL, }; use log::debug; -use muvm::cli_options::options; +use muvm::cli_options::{options, Options}; use muvm::cpu::{get_fallback_cores, get_performance_cores}; use muvm::env::{find_muvm_exec, prepare_env_vars}; use muvm::hidpipe_server::spawn_hidpipe_server; @@ -22,17 +24,19 @@ use muvm::launch::{launch_or_lock, LaunchResult, DYNAMIC_PORT_RANGE}; use muvm::monitor::spawn_monitor; use muvm::net::{connect_to_passt, start_passt}; use muvm::types::MiB; -use muvm::utils::launch::{ - GuestConfiguration, Launch, HIDPIPE_SOCKET, MUVM_GUEST_SOCKET, PULSE_SOCKET, -}; +use muvm::utils::launch::{GuestConfiguration, HIDPIPE_SOCKET, MUVM_GUEST_SOCKET, PULSE_SOCKET}; +use nix::fcntl::{fcntl, FcntlArg}; use nix::sys::sysinfo::sysinfo; use nix::unistd::User; -use rustix::io::Errno; +use rustix::io::{dup, Errno}; use rustix::process::{ geteuid, getgid, getrlimit, getuid, sched_setaffinity, setrlimit, CpuSet, Resource, }; use serde::Serialize; use tempfile::NamedTempFile; +use uuid::Uuid; + +const LOCK_FD_ENV_VAR: &str = "__MUVM_DO_LAUNCH_VM_LOCK__"; #[derive(Serialize)] pub struct KrunConfig { @@ -73,8 +77,19 @@ fn main() -> Result { } let options = options().fallback_to_usage().run(); + if let Ok(lock_fd) = env::var(LOCK_FD_ENV_VAR) { + let lock_fd = lock_fd.parse()?; + fcntl(lock_fd, FcntlArg::F_GETFD).context("Lockfile fd is not open")?; + // SAFETY: We verify that the file descriptor is valid. + // The file will not be read from/written to, + // so worse case if it's not a file nothing bad will happen, + // as we only care about calling `close` on Drop. + let _lock_file = unsafe { File::from_raw_fd(lock_fd) }; + launch_vm(options)?; + unreachable!("`launch_vm` never returns"); + } - let (_lock_file, command, command_args, env) = match launch_or_lock( + let (lock_file, command, command_args, env) = match launch_or_lock( options.command, options.command_args, options.env, @@ -94,8 +109,21 @@ fn main() -> Result { } => (lock_file, command, command_args, env), }; - let mut env = prepare_env_vars(env).context("Failed to prepare environment variables")?; + // Make it lose CLOEXEC + let lock_fd = dup(lock_file)?; + Command::new(env::current_exe()?) + .args(env::args()) + .env(LOCK_FD_ENV_VAR, lock_fd.into_raw_fd().to_string()) + .spawn()?; + match launch_or_lock(command, command_args, env, options.tty, options.privileged)? { + LaunchResult::LockAcquired { .. } => Err(anyhow!("VM did not start")), + LaunchResult::LaunchRequested(code) => Ok(code), + } +} +fn launch_vm(options: Options) -> Result { + let mut env = + prepare_env_vars(Vec::new()).context("Failed to prepare environment variables")?; { // Set the log level to "off". // @@ -276,6 +304,7 @@ fn main() -> Result { } } + let console_base; if let Ok(run_path) = env::var("XDG_RUNTIME_DIR") { let pulse_path = Path::new(&run_path).join("pulse/native"); if pulse_path.exists() { @@ -343,6 +372,9 @@ fn main() -> Result { let err = Errno::from_raw_os_error(-err); return Err(err).context("Failed to configure vsock for guest server socket"); } + console_base = run_path; + } else { + console_base = "/tmp".to_string(); } let username = env::var("USER").context("Failed to get username from environment")?; @@ -380,14 +412,6 @@ fn main() -> Result { let display = env::var("DISPLAY").ok(); let guest_config = GuestConfiguration { - command: Launch { - command, - command_args, - env: HashMap::new(), - vsock_port: 0, - tty: false, - privileged: false, - }, username, uid: getuid().as_raw(), gid: getgid().as_raw(), @@ -462,6 +486,22 @@ fn main() -> Result { } } + { + let uuid = Uuid::now_v7(); + let path = Path::new(&console_base).join(format!("muvm-{uuid}.console")); + let console_path = CString::new( + path.to_str() + .expect("console_path should not contain invalid UTF-8"), + ) + .expect("console_path should not contain NUL character"); + // SAFETY: `console_path` is a CString that outlives this call + let err = unsafe { krun_set_console_output(ctx_id, console_path.as_ptr()) }; + if err < 0 { + let err = Errno::from_raw_os_error(-err); + return Err(err).context("Failed to configure console"); + } + } + spawn_monitor(); { diff --git a/crates/muvm/src/guest/bin/muvm-guest.rs b/crates/muvm/src/guest/bin/muvm-guest.rs index 0a4eb3f7..46cfea6f 100644 --- a/crates/muvm/src/guest/bin/muvm-guest.rs +++ b/crates/muvm/src/guest/bin/muvm-guest.rs @@ -129,5 +129,5 @@ fn main() -> Result<()> { }); let rt = tokio::runtime::Runtime::new().unwrap(); - rt.block_on(async { server_main(options.command.command, options.command.command_args).await }) + rt.block_on(async { server_main().await }) } diff --git a/crates/muvm/src/guest/server.rs b/crates/muvm/src/guest/server.rs index 2f343842..a8d76fb5 100644 --- a/crates/muvm/src/guest/server.rs +++ b/crates/muvm/src/guest/server.rs @@ -8,15 +8,13 @@ use nix::sys::socket::{ }; use std::os::fd::AsRawFd; use std::os::unix::net::UnixListener as StdUnixListener; -use std::os::unix::process::ExitStatusExt as _; -use std::path::PathBuf; use tokio::net::UnixListener; -use tokio::process::Command; use tokio::sync::watch; +use tokio::time::{self, Duration, Instant}; use tokio_stream::wrappers::WatchStream; use tokio_stream::StreamExt as _; -pub async fn server_main(command: PathBuf, command_args: Vec) -> Result<()> { +pub async fn server_main() -> Result<()> { let sock_fd = socket( AddressFamily::Vsock, SockType::Stream, @@ -38,16 +36,16 @@ pub async fn server_main(command: PathBuf, command_args: Vec) -> Result< let mut worker = Worker::new(listener, state_tx); worker.run().await; }); - let command_status = Command::new(&command).args(command_args).status(); - tokio::pin!(command_status); let mut state_rx = WatchStream::new(state_rx); + let far_future = Duration::from_secs(3600 * 24 * 365); + let linger_timer = time::sleep(far_future); + tokio::pin!(linger_timer); - let mut server_died = false; - let mut command_exited = false; + let mut all_exited = false; loop { tokio::select! { - res = &mut worker_handle, if !server_died => { + res = &mut worker_handle => { // If an error is received here, accepting connections from the // TCP listener failed due to non-transient errors and the // server is giving up and shutting down. @@ -56,49 +54,28 @@ pub async fn server_main(command: PathBuf, command_args: Vec) -> Result< // not bubble up to this point. if let Err(err) = res { error!(err:% = err; "server task failed"); - server_died = true; - } - }, - res = &mut command_status, if !command_exited => { - match res { - Ok(status) => { - if !status.success() { - if let Some(code) = status.code() { - eprintln!( - "{command:?} process exited with status code: {code}" - ); - } else { - eprintln!( - "{:?} process terminated by signal: {}", - command, - status - .signal() - .expect("either one of status code or signal should be set") - ); - } - } - }, - Err(err) => { - eprintln!( - "Failed to execute {command:?} as child process: {err}" - ); - }, + return Ok(()); } - command_exited = true; }, - Some(state) = state_rx.next(), if command_exited => { + Some(state) = state_rx.next() => { if state.connection_idle() && state.child_processes() == 0 { - // Server is idle (not currently handling an accepted - // incoming connection) and no more child processes. - // We're done. - return Ok(()); + linger_timer.as_mut().reset(Instant::now() + Duration::from_secs(10)); + all_exited = true; + } else { + linger_timer.as_mut().reset(Instant::now() + far_future); + println!( + "Waiting for {} other commands launched through this muvm server to exit...", + state.child_processes() + ); + all_exited = false; } - println!( - "Waiting for {} other commands launched through this muvm server to exit...", - state.child_processes() - ); - println!("Press Ctrl+C to force quit"); }, + _tick = &mut linger_timer, if all_exited => { + // Server is idle (not currently handling an accepted + // incoming connection) and no more child processes. + // We're done. + return Ok(()); + } } } } diff --git a/crates/muvm/src/launch.rs b/crates/muvm/src/launch.rs index db57dc28..f9adb8d7 100644 --- a/crates/muvm/src/launch.rs +++ b/crates/muvm/src/launch.rs @@ -5,6 +5,8 @@ use std::fmt::{Display, Formatter}; use std::fs::File; use std::io::{BufRead, BufReader, Write}; use std::path::{Path, PathBuf}; +use std::thread; +use std::time::Duration; use anyhow::{anyhow, Context, Result}; use rustix::fs::{flock, FlockOperation}; @@ -192,7 +194,7 @@ pub fn request_launch( let run_path = env::var("XDG_RUNTIME_DIR") .map_err(|e| anyhow!("unable to get XDG_RUNTIME_DIR: {:?}", e))?; let socket_path = Path::new(&run_path).join("krun/server"); - let mut stream = UnixStream::connect(socket_path).map_err(LaunchError::Connection)?; + let mut stream = connect_to_socket(socket_path)?; let launch = Launch { command, @@ -227,3 +229,20 @@ pub fn request_launch( Err(LaunchError::Server(resp).into()) } } + +fn connect_to_socket(socket_path: PathBuf) -> Result { + let mut tries = 0; + loop { + match UnixStream::connect(&socket_path).map_err(LaunchError::Connection) { + Ok(stream) => return Ok(stream), + Err(err) => { + if tries == 5 { + return Err(err.into()); + } else { + thread::sleep(Duration::from_millis(500)); + tries += 1; + } + }, + } + } +} diff --git a/crates/muvm/src/utils/launch.rs b/crates/muvm/src/utils/launch.rs index 01400c91..16056861 100644 --- a/crates/muvm/src/utils/launch.rs +++ b/crates/muvm/src/utils/launch.rs @@ -37,7 +37,6 @@ impl FromStr for Emulator { #[derive(Clone, Eq, PartialEq, Debug, Deserialize, Serialize)] pub struct GuestConfiguration { - pub command: Launch, pub username: String, pub uid: u32, pub gid: u32, From b924227b700fd1a99ccd1c7d58e2f684d93498dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikodem=20Rabuli=C5=84ski?= Date: Fri, 14 Mar 2025 19:43:49 +0100 Subject: [PATCH 4/6] Pass through most environment variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the approach to environment variables to delete ones that are likely to cause problems, instead of only passing through a pre-approved list. Co-authored-by: Sasha Finkelstein Signed-off-by: Nikodem Rabuliński --- README.md | 6 ++- crates/muvm/src/bin/muvm.rs | 13 ++++- crates/muvm/src/cli_options.rs | 8 ++++ crates/muvm/src/env.rs | 87 +++++++++++++++++++++++----------- crates/muvm/src/launch.rs | 3 +- 5 files changed, 84 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 7b4500ef..36182006 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,8 @@ ``` sh Usage: muvm [-c=CPU_LIST]... [-e=ENV]... [--mem=MEM] [--vram=VRAM] [--passt-socket=PATH] [-f= -FEX_IMAGE]... [-m] [-i] [-t] [--privileged] [-p=<[[IP:][HOST_PORT]:]GUEST_PORT[/PROTOCOL]>]... [ ---emu=EMU] COMMAND [COMMAND_ARGS]... +FEX_IMAGE]... [-m] [-t] [--privileged] [-p=<[[IP:][HOST_PORT]:]GUEST_PORT[/PROTOCOL]>]... [--emu=EMU +] [--no-inherit-env] COMMAND [COMMAND_ARGS]... Available positional items: COMMAND the command you want to execute in the vm @@ -55,6 +55,8 @@ Available options: Valid options are "box" and "fex". If this argument is not present, muvm will try to use FEX, falling back to Box if it can't be found. + --no-inherit-env Run the command with as little of the environment variables + passed in as possible, instead of inheriting most of them. -h, --help Prints help information ``` diff --git a/crates/muvm/src/bin/muvm.rs b/crates/muvm/src/bin/muvm.rs index ca365012..736ba0ce 100644 --- a/crates/muvm/src/bin/muvm.rs +++ b/crates/muvm/src/bin/muvm.rs @@ -89,12 +89,14 @@ fn main() -> Result { unreachable!("`launch_vm` never returns"); } + let inherit_env = !options.no_inherit_env; let (lock_file, command, command_args, env) = match launch_or_lock( options.command, options.command_args, options.env, options.tty, options.privileged, + inherit_env, )? { LaunchResult::LaunchRequested(code) => { // There was a muvm instance already running and we've requested it @@ -115,7 +117,14 @@ fn main() -> Result { .args(env::args()) .env(LOCK_FD_ENV_VAR, lock_fd.into_raw_fd().to_string()) .spawn()?; - match launch_or_lock(command, command_args, env, options.tty, options.privileged)? { + match launch_or_lock( + command, + command_args, + env, + options.tty, + options.privileged, + inherit_env, + )? { LaunchResult::LockAcquired { .. } => Err(anyhow!("VM did not start")), LaunchResult::LaunchRequested(code) => Ok(code), } @@ -123,7 +132,7 @@ fn main() -> Result { fn launch_vm(options: Options) -> Result { let mut env = - prepare_env_vars(Vec::new()).context("Failed to prepare environment variables")?; + prepare_env_vars(Vec::new(), false).context("Failed to prepare environment variables")?; { // Set the log level to "off". // diff --git a/crates/muvm/src/cli_options.rs b/crates/muvm/src/cli_options.rs index b8aa0f0f..5067836f 100644 --- a/crates/muvm/src/cli_options.rs +++ b/crates/muvm/src/cli_options.rs @@ -20,6 +20,7 @@ pub struct Options { pub privileged: bool, pub publish_ports: Vec, pub emulator: Option, + pub no_inherit_env: bool, pub command: PathBuf, pub command_args: Vec, } @@ -127,6 +128,12 @@ pub fn options() -> OptionParser { ) .argument::("[[IP:][HOST_PORT]:]GUEST_PORT[/PROTOCOL]") .many(); + let no_inherit_env = long("no-inherit-env") + .help( + "Run the command with as little of the environment variables + passed in as possible, instead of inheriting most of them.", + ) + .switch(); let command = positional("COMMAND").help("the command you want to execute in the vm"); let command_args = any::("COMMAND_ARGS", |arg| { (!["--help", "-h"].contains(&&*arg)).then_some(arg) @@ -146,6 +153,7 @@ pub fn options() -> OptionParser { privileged, publish_ports, emulator, + no_inherit_env, // positionals command, command_args, diff --git a/crates/muvm/src/env.rs b/crates/muvm/src/env.rs index 89f73e15..1e083fb1 100644 --- a/crates/muvm/src/env.rs +++ b/crates/muvm/src/env.rs @@ -35,42 +35,69 @@ const WELL_KNOWN_ENV_VARS: [&str; 20] = [ "XMODIFIERS", ]; +/// Variables to drop if we're inheriting the environment from the host. +const DROP_ENV_VARS: [&str; 17] = [ + "DBUS_SESSION_BUS_ADDRESS", + "DISPLAY", + "ICEAUTHORITY", + "KONSOLE_DBUS_SERVICE", + "KONSOLE_DBUS_SESSION", + "KONSOLE_DBUS_WINDOW", + "MANAGERPID", + "PAM_KWALLET5_LOGIN", + "SESSION_MANAGER", + "SYSTEMD_EXEC_PID", + "WAYLAND_DISPLAY", + "XAUTHORITY", + "XDG_RUNTIME_DIR", + "XDG_SEAT", + "XDG_SEAT_PATH", + "XDG_SESSION_PATH", + "XDG_VTNR", +]; + /// See https://github.com/AsahiLinux/docs/wiki/Devices const ASAHI_SOC_COMPAT_IDS: [&str; 1] = ["apple,arm-platform"]; -pub fn prepare_env_vars(env: Vec<(String, Option)>) -> Result> { +pub fn prepare_env_vars( + env: Vec<(String, Option)>, + inherit_env: bool, +) -> Result> { let mut env_map = HashMap::new(); - for key in WELL_KNOWN_ENV_VARS { - let value = match env::var(key) { - Ok(value) => value, - Err(VarError::NotPresent) => { - if key == "MESA_LOADER_DRIVER_OVERRIDE" { - match fs::read_to_string("/proc/device-tree/compatible") { - Ok(compatible) => { - for compat_id in compatible.split('\0') { - if ASAHI_SOC_COMPAT_IDS.iter().any(|&s| s == compat_id) { - env_map.insert( - "MESA_LOADER_DRIVER_OVERRIDE".to_owned(), - "asahi".to_owned(), - ); - break; - } - } - }, - Err(err) if err.kind() == ErrorKind::NotFound => { - continue; - }, - Err(err) => { - Err(err).context("Failed to read `/proc/device-tree/compatible`")? - }, + if inherit_env { + for (key, value) in env::vars() { + env_map.insert(key, value); + } + + for key in DROP_ENV_VARS { + env_map.remove(key); + } + } else { + for key in WELL_KNOWN_ENV_VARS { + let value = match env::var(key) { + Ok(value) => value, + Err(VarError::NotPresent) => continue, + Err(err) => Err(err).with_context(|| format!("Failed to get `{key}` env var"))?, + }; + env_map.insert(key.to_owned(), value); + } + } + + if !env_map.contains_key("MESA_LOADER_DRIVER_OVERRIDE") { + match fs::read_to_string("/proc/device-tree/compatible") { + Ok(compatible) => { + for compat_id in compatible.split('\0') { + if ASAHI_SOC_COMPAT_IDS.iter().any(|&s| s == compat_id) { + env_map + .insert("MESA_LOADER_DRIVER_OVERRIDE".to_owned(), "asahi".to_owned()); + break; } } - continue; }, - Err(err) => Err(err).with_context(|| format!("Failed to get `{key}` env var"))?, - }; - env_map.insert(key.to_owned(), value); + Err(err) if err.kind() == ErrorKind::NotFound => (), + Err(err) => return Err(err).context("Failed to read `/proc/device-tree/compatible`"), + } } if !(env_map.contains_key("LANG") @@ -111,6 +138,10 @@ pub fn prepare_env_vars(env: Vec<(String, Option)>) -> Result)>, tty: bool, privileged: bool, + inherit_env: bool, ) -> Result { let lock_file = lock_file()?; match lock_file { @@ -129,7 +130,7 @@ pub fn launch_or_lock( env, }), None => { - let env = prepare_env_vars(env)?; + let env = prepare_env_vars(env, inherit_env)?; let mut tries = 0; loop { match wrapped_launch( From af98f630cc2305c6e7fbea6bdf43285abf26fba9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikodem=20Rabuli=C5=84ski?= Date: Fri, 14 Mar 2025 19:46:25 +0100 Subject: [PATCH 5/6] Default to allocating a tty MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of requiring a user to ask for tty allocation, which usually is what you want anyway, default to allocating one if stdin is a tty unless the user specifically doesn't want to. Signed-off-by: Nikodem Rabuliński --- README.md | 6 +++--- crates/muvm/src/bin/muvm.rs | 4 ++-- crates/muvm/src/cli_options.rs | 9 ++++----- crates/muvm/src/launch.rs | 18 ++++++------------ crates/muvm/src/tty.rs | 8 ++++++-- 5 files changed, 21 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 36182006..013ee54b 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,8 @@ ``` sh Usage: muvm [-c=CPU_LIST]... [-e=ENV]... [--mem=MEM] [--vram=VRAM] [--passt-socket=PATH] [-f= -FEX_IMAGE]... [-m] [-t] [--privileged] [-p=<[[IP:][HOST_PORT]:]GUEST_PORT[/PROTOCOL]>]... [--emu=EMU -] [--no-inherit-env] COMMAND [COMMAND_ARGS]... +FEX_IMAGE]... [-m] [--no-tty] [--privileged] [-p=<[[IP:][HOST_PORT]:]GUEST_PORT[/PROTOCOL]>]... [ +--emu=EMU] [--no-inherit-env] COMMAND [COMMAND_ARGS]... Available positional items: COMMAND the command you want to execute in the vm @@ -45,7 +45,7 @@ Available options: May be specified multiple times. First the base image, then overlays in order. -m, --merged-rootfs Use merged rootfs for FEX (experimental) - -t, --tty Allocate a tty for the command + --no-tty Force not allocating a tty for the command --privileged Run the command as root inside the vm. This notably does not allow root access to the host fs. -p, --publish=<[[IP:][HOST_PORT]:]GUEST_PORT[/PROTOCOL]> diff --git a/crates/muvm/src/bin/muvm.rs b/crates/muvm/src/bin/muvm.rs index 736ba0ce..606118fd 100644 --- a/crates/muvm/src/bin/muvm.rs +++ b/crates/muvm/src/bin/muvm.rs @@ -94,7 +94,7 @@ fn main() -> Result { options.command, options.command_args, options.env, - options.tty, + options.no_tty, options.privileged, inherit_env, )? { @@ -121,7 +121,7 @@ fn main() -> Result { command, command_args, env, - options.tty, + options.no_tty, options.privileged, inherit_env, )? { diff --git a/crates/muvm/src/cli_options.rs b/crates/muvm/src/cli_options.rs index 5067836f..cac3cefa 100644 --- a/crates/muvm/src/cli_options.rs +++ b/crates/muvm/src/cli_options.rs @@ -16,7 +16,7 @@ pub struct Options { pub passt_socket: Option, pub fex_images: Vec, pub merged_rootfs: bool, - pub tty: bool, + pub no_tty: bool, pub privileged: bool, pub publish_ports: Vec, pub emulator: Option, @@ -109,9 +109,8 @@ pub fn options() -> OptionParser { .help("Instead of starting passt, connect to passt socket at PATH") .argument("PATH") .optional(); - let tty = long("tty") - .short('t') - .help("Allocate a tty for the command") + let no_tty = long("no-tty") + .help("Force not allocating a tty for the command") .switch(); let privileged = long("privileged") .help( @@ -149,7 +148,7 @@ pub fn options() -> OptionParser { passt_socket, fex_images, merged_rootfs, - tty, + no_tty, privileged, publish_ports, emulator, diff --git a/crates/muvm/src/launch.rs b/crates/muvm/src/launch.rs index 3a600efc..96570c71 100644 --- a/crates/muvm/src/launch.rs +++ b/crates/muvm/src/launch.rs @@ -12,7 +12,7 @@ use anyhow::{anyhow, Context, Result}; use rustix::fs::{flock, FlockOperation}; use crate::env::prepare_env_vars; -use crate::tty::{run_io_host, RawTerminal}; +use crate::tty::{run_io_host, stdout_is_tty, RawTerminal}; use crate::utils::launch::Launch; use nix::unistd::unlink; use std::ops::Range; @@ -89,7 +89,7 @@ fn wrapped_launch( command: PathBuf, command_args: Vec, env: HashMap, - tty: bool, + no_tty: bool, privileged: bool, ) -> Result { let run_path = env::var("XDG_RUNTIME_DIR") @@ -99,15 +99,9 @@ fn wrapped_launch( let path = socket_dir.join(format!("port-{vsock_port}")); _ = unlink(&path); let listener = UnixListener::bind(path).context("Failed to listen on vm socket")?; - let raw_tty = if tty { - Some( - RawTerminal::set() - .context("Asked to allocate a tty for the command, but stdin is not a tty")?, - ) - } else { - None - }; + let tty = !no_tty && stdout_is_tty(); request_launch(command, command_args, env, vsock_port, tty, privileged)?; + let raw_tty = tty.then(|| RawTerminal::set().expect("Stdout should be a tty")); let code = run_io_host(listener, tty)?; drop(raw_tty); Ok(ExitCode::from(code)) @@ -117,7 +111,7 @@ pub fn launch_or_lock( command: PathBuf, command_args: Vec, env: Vec<(String, Option)>, - tty: bool, + no_tty: bool, privileged: bool, inherit_env: bool, ) -> Result { @@ -137,7 +131,7 @@ pub fn launch_or_lock( command.clone(), command_args.clone(), env.clone(), - tty, + no_tty, privileged, ) { Err(err) => match err.downcast_ref::() { diff --git a/crates/muvm/src/tty.rs b/crates/muvm/src/tty.rs index 7c53d5bc..3cbade59 100644 --- a/crates/muvm/src/tty.rs +++ b/crates/muvm/src/tty.rs @@ -11,8 +11,8 @@ use nix::sys::epoll::{Epoll, EpollCreateFlags, EpollEvent, EpollFlags, EpollTime use nix::sys::signal::{sigprocmask, SigSet, SigmaskHow, Signal}; use nix::sys::signalfd::SignalFd; use rustix::termios::{ - tcgetattr, tcgetwinsize, tcsetattr, ControlModes, InputModes, LocalModes, OptionalActions, - OutputModes, SpecialCodeIndex, Termios, + isatty, tcgetattr, tcgetwinsize, tcsetattr, ControlModes, InputModes, LocalModes, + OptionalActions, OutputModes, SpecialCodeIndex, Termios, }; fn process_remote_msg( @@ -152,3 +152,7 @@ pub fn run_io_host(listener: UnixListener, is_tty: bool) -> Result { } } } + +pub fn stdout_is_tty() -> bool { + isatty(stdout()) +} From 1edd91dc863db32c42052a62730bc7733fc59d86 Mon Sep 17 00:00:00 2001 From: Sasha Finkelstein Date: Fri, 14 Mar 2025 21:26:49 +0100 Subject: [PATCH 6/6] Pass through the current working directory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Nikodem Rabuliński --- crates/muvm/src/bin/muvm.rs | 8 ++++++-- crates/muvm/src/guest/server_worker.rs | 17 +++++++++++++++-- crates/muvm/src/launch.rs | 9 ++++++++- crates/muvm/src/monitor.rs | 7 +++++-- crates/muvm/src/utils/launch.rs | 1 + 5 files changed, 35 insertions(+), 7 deletions(-) diff --git a/crates/muvm/src/bin/muvm.rs b/crates/muvm/src/bin/muvm.rs index 606118fd..096aa05a 100644 --- a/crates/muvm/src/bin/muvm.rs +++ b/crates/muvm/src/bin/muvm.rs @@ -89,11 +89,13 @@ fn main() -> Result { unreachable!("`launch_vm` never returns"); } + let cwd = env::current_dir()?; let inherit_env = !options.no_inherit_env; - let (lock_file, command, command_args, env) = match launch_or_lock( + let (lock_file, command, command_args, env, cwd) = match launch_or_lock( options.command, options.command_args, options.env, + cwd, options.no_tty, options.privileged, inherit_env, @@ -108,7 +110,8 @@ fn main() -> Result { command, command_args, env, - } => (lock_file, command, command_args, env), + cwd, + } => (lock_file, command, command_args, env, cwd), }; // Make it lose CLOEXEC @@ -121,6 +124,7 @@ fn main() -> Result { command, command_args, env, + cwd, options.no_tty, options.privileged, inherit_env, diff --git a/crates/muvm/src/guest/server_worker.rs b/crates/muvm/src/guest/server_worker.rs index c7c5459d..a93807d4 100644 --- a/crates/muvm/src/guest/server_worker.rs +++ b/crates/muvm/src/guest/server_worker.rs @@ -200,8 +200,9 @@ async fn handle_connection(mut stream: BufStream) -> Result) -> Result, env: Vec<(String, Option)>, + cwd: PathBuf, }, } @@ -89,6 +90,7 @@ fn wrapped_launch( command: PathBuf, command_args: Vec, env: HashMap, + cwd: PathBuf, no_tty: bool, privileged: bool, ) -> Result { @@ -100,7 +102,7 @@ fn wrapped_launch( _ = unlink(&path); let listener = UnixListener::bind(path).context("Failed to listen on vm socket")?; let tty = !no_tty && stdout_is_tty(); - request_launch(command, command_args, env, vsock_port, tty, privileged)?; + request_launch(command, command_args, env, cwd, vsock_port, tty, privileged)?; let raw_tty = tty.then(|| RawTerminal::set().expect("Stdout should be a tty")); let code = run_io_host(listener, tty)?; drop(raw_tty); @@ -111,6 +113,7 @@ pub fn launch_or_lock( command: PathBuf, command_args: Vec, env: Vec<(String, Option)>, + cwd: PathBuf, no_tty: bool, privileged: bool, inherit_env: bool, @@ -122,6 +125,7 @@ pub fn launch_or_lock( command, command_args, env, + cwd, }), None => { let env = prepare_env_vars(env, inherit_env)?; @@ -131,6 +135,7 @@ pub fn launch_or_lock( command.clone(), command_args.clone(), env.clone(), + cwd.clone(), no_tty, privileged, ) { @@ -182,6 +187,7 @@ pub fn request_launch( command: PathBuf, command_args: Vec, env: HashMap, + cwd: PathBuf, vsock_port: u32, tty: bool, privileged: bool, @@ -195,6 +201,7 @@ pub fn request_launch( command, command_args, env, + cwd, vsock_port, tty, privileged, diff --git a/crates/muvm/src/monitor.rs b/crates/muvm/src/monitor.rs index 836acd5f..f0173249 100644 --- a/crates/muvm/src/monitor.rs +++ b/crates/muvm/src/monitor.rs @@ -1,4 +1,5 @@ use std::collections::HashMap; +use std::env::current_dir; use std::path::PathBuf; use std::thread; use std::time; @@ -43,7 +44,8 @@ fn set_guest_pressure(pressure: GuestPressure) -> Result<()> { let command = PathBuf::from("/muvmdropcaches"); let command_args = vec![]; let env = HashMap::new(); - request_launch(command, command_args, env, 0, false, true)?; + let cwd = current_dir()?; + request_launch(command, command_args, env, cwd, 0, false, true)?; } let wsf: u32 = pressure.into(); @@ -52,7 +54,8 @@ fn set_guest_pressure(pressure: GuestPressure) -> Result<()> { let command = PathBuf::from("/sbin/sysctl"); let command_args = vec![format!("vm.watermark_scale_factor={}", wsf)]; let env = HashMap::new(); - request_launch(command, command_args, env, 0, false, true) + let cwd = current_dir()?; + request_launch(command, command_args, env, cwd, 0, false, true) } fn run() { diff --git a/crates/muvm/src/utils/launch.rs b/crates/muvm/src/utils/launch.rs index 16056861..59b692c1 100644 --- a/crates/muvm/src/utils/launch.rs +++ b/crates/muvm/src/utils/launch.rs @@ -12,6 +12,7 @@ pub struct Launch { pub vsock_port: u32, pub tty: bool, pub privileged: bool, + pub cwd: PathBuf, } #[derive(Clone, Eq, PartialEq, Debug, Deserialize, Serialize)]