diff --git a/Cargo.lock b/Cargo.lock index 61b0a2616..3bf382a27 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -59,9 +59,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.18" +version = "0.6.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" dependencies = [ "anstyle", "anstyle-parse", @@ -74,33 +74,33 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" [[package]] name = "anstyle-parse" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" dependencies = [ "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.8" +version = "3.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6680de5231bd6ee4c6191b8a1325daa282b415391ec9d3a37bd34f2060dc73fa" +checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" dependencies = [ "anstyle", "once_cell_polyfill", @@ -124,6 +124,7 @@ dependencies = [ "smbios", "utils", "vm-memory", + "vmm-sys-util", ] [[package]] @@ -149,9 +150,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.74" +version = "0.3.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" dependencies = [ "addr2line", "cfg-if", @@ -184,7 +185,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" dependencies = [ "annotate-snippets", - "bitflags 2.9.0", + "bitflags 2.9.1", "cexpr", "clang-sys", "itertools 0.12.1", @@ -204,7 +205,7 @@ version = "0.71.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "cexpr", "clang-sys", "itertools 0.13.0", @@ -220,9 +221,23 @@ dependencies = [ [[package]] name = "bitfield" -version = "0.15.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c821a6e124197eb56d907ccc2188eab1038fb919c914f47976e64dd8dbc855d1" +checksum = "db1bcd90f88eabbf0cadbfb87a45bceeaebcd3b4bc9e43da379cd2ef0162590d" +dependencies = [ + "bitfield-macros", +] + +[[package]] +name = "bitfield-macros" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3787a07661997bfc05dd3431e379c0188573f78857080cf682e1393ab8e4d64c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "bitflags" @@ -232,15 +247,15 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "bumpalo" -version = "3.17.0" +version = "3.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" +checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" [[package]] name = "byteorder" @@ -279,9 +294,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.19" +version = "1.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e3a13707ac958681c13b39b458c073d0d9bc8a22cb1b2f4c8e55eb72c13f362" +checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac" dependencies = [ "jobserver", "libc", @@ -321,9 +336,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.40" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" +checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" dependencies = [ "android-tzdata", "iana-time-zone", @@ -352,9 +367,9 @@ checksum = "12170080f3533d6f09a19f81596f836854d0fa4867dc32c8172b8474b4e9de61" [[package]] name = "colorchoice" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "convert_case" @@ -462,7 +477,7 @@ dependencies = [ "nix 0.24.3", "pipewire", "polly", - "rand", + "rand 0.8.5", "rutabaga_gfx", "thiserror 1.0.69", "utils", @@ -475,23 +490,23 @@ dependencies = [ [[package]] name = "dirs" -version = "5.0.1" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -651,9 +666,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", @@ -662,9 +677,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "libc", @@ -686,9 +701,9 @@ checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" dependencies = [ "allocator-api2", "equivalent", @@ -838,7 +853,7 @@ version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" dependencies = [ - "getrandom 0.3.2", + "getrandom 0.3.3", "libc", ] @@ -875,20 +890,20 @@ dependencies = [ [[package]] name = "kvm-bindings" -version = "0.11.1" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b13baf7bdfda2e10bcb109fcb099ef40cff82374eb6b7cdcf4695bdec4e522c" +checksum = "d4b153a59bb3ca930ff8148655b2ef68c34259a623ae08cf2fb9b570b2e45363" dependencies = [ "vmm-sys-util", ] [[package]] name = "kvm-ioctls" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "083c460d5a272c2f22205973e319147b791d92a288d7d7a8d4c6194f95229440" +checksum = "b702df98508cb63ad89dd9beb9f6409761b30edca10d48e57941d3f11513a006" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "kvm-bindings", "libc", "vmm-sys-util", @@ -914,7 +929,7 @@ checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libkrun" -version = "1.13.0" +version = "1.14.0" dependencies = [ "crossbeam-channel", "devices", @@ -925,6 +940,8 @@ dependencies = [ "libc", "libloading", "log", + "nitro", + "nitro-enclaves", "once_cell", "polly", "utils", @@ -934,12 +951,12 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" +checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.52.6", + "windows-targets 0.53.0", ] [[package]] @@ -948,7 +965,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "libc", ] @@ -958,7 +975,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65f3a4b81b2a2d8c7f300643676202debd1b7c929dbf5c9bb89402ea11d19810" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "cc", "convert_case", "cookie-factory", @@ -1040,6 +1057,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -1055,6 +1081,29 @@ dependencies = [ "adler2", ] +[[package]] +name = "nitro" +version = "0.1.0" +dependencies = [ + "libc", + "nitro-enclaves", + "nix 0.26.4", + "vsock", +] + +[[package]] +name = "nitro-enclaves" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bc4f6ad5cab7056766551e23ffe2e80c445406d4719944a36816873deec109d" +dependencies = [ + "bitflags 2.9.1", + "libc", + "nix 0.26.4", + "rand 0.9.1", + "vsock", +] + [[package]] name = "nix" version = "0.24.3" @@ -1086,7 +1135,7 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "cfg-if", "libc", ] @@ -1097,10 +1146,11 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "cfg-if", "cfg_aliases", "libc", + "memoffset 0.9.1", ] [[package]] @@ -1145,11 +1195,11 @@ checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" [[package]] name = "openssl" -version = "0.10.72" +version = "0.10.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" +checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "cfg-if", "foreign-types", "libc", @@ -1175,14 +1225,24 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +[[package]] +name = "openssl-src" +version = "300.5.0+3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8ce546f549326b0e6052b649198487d91320875da901e7bd11a06d1ee3f9c2f" +dependencies = [ + "cc", +] + [[package]] name = "openssl-sys" -version = "0.9.107" +version = "0.9.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07" +checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" dependencies = [ "cc", "libc", + "openssl-src", "pkg-config", "vcpkg", ] @@ -1222,7 +1282,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08e645ba5c45109106d56610b3ee60eb13a6f2beb8b74f8dc8186cf261788dda" dependencies = [ "anyhow", - "bitflags 2.9.0", + "bitflags 2.9.1", "libc", "libspa", "libspa-sys", @@ -1259,9 +1319,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] name = "portable-atomic-util" @@ -1278,14 +1338,14 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy 0.8.24", + "zerocopy 0.8.25", ] [[package]] name = "prettyplease" -version = "0.2.32" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "664ec5419c51e34154eec046ebcba56312d5a2fc3b09a06da188e1ad21afadf6" +checksum = "9dee91521343f4c5c6a63edd65e54f31f5c92fe8978c40a4282f8372194c6a7d" dependencies = [ "proc-macro2", "syn", @@ -1337,8 +1397,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", ] [[package]] @@ -1348,7 +1418,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", ] [[package]] @@ -1357,7 +1437,16 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.3", ] [[package]] @@ -1366,18 +1455,18 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d92195228612ac8eed47adbc2ed0f04e513a4ccb98175b6f2bd04d963b533655" dependencies = [ - "rand_core", + "rand_core 0.6.4", ] [[package]] name = "redox_users" -version = "0.4.6" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", "libredox", - "thiserror 1.0.69", + "thiserror 2.0.12", ] [[package]] @@ -1449,9 +1538,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] name = "rutabaga_gfx" @@ -1465,6 +1554,7 @@ dependencies = [ "pkg-config", "remain", "thiserror 1.0.69", + "vmm-sys-util", "winapi", "zerocopy 0.6.6", ] @@ -1542,23 +1632,23 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] [[package]] name = "sev" -version = "6.0.0" +version = "6.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20ac277517d8fffdf3c41096323ed705b3a7c75e397129c072fb448339839d0f" +checksum = "1750ba11a6a6bba3c220da714caa0226aa34e417dce3975d2953062240717dea" dependencies = [ "base64", "bincode", "bitfield", - "bitflags 1.3.2", + "bitflags 2.9.1", "byteorder", "codicon", "dirs", @@ -1605,9 +1695,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", "windows-sys 0.52.0", @@ -1621,9 +1711,9 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "syn" -version = "2.0.100" +version = "2.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" dependencies = [ "proc-macro2", "quote", @@ -1691,9 +1781,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.44.2" +version = "1.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" +checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" dependencies = [ "backtrace", "pin-project-lite", @@ -1701,9 +1791,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.20" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", "serde_spanned", @@ -1713,18 +1803,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.8" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.24" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ "indexmap", "serde", @@ -1746,9 +1836,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662" dependencies = [ "proc-macro2", "quote", @@ -1757,9 +1847,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", ] @@ -1802,11 +1892,13 @@ dependencies = [ [[package]] name = "uuid" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" +checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" dependencies = [ + "js-sys", "serde", + "wasm-bindgen", ] [[package]] @@ -1838,9 +1930,9 @@ checksum = "7e21282841a059bb62627ce8441c491f09603622cd5a21c43bfedc85a2952f23" [[package]] name = "vm-memory" -version = "0.16.1" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1720e7240cdc739f935456eb77f370d7e9b2a3909204da1e2b47bef1137a013" +checksum = "1fd5e56d48353c5f54ef50bd158a0452fc82f5383da840f7b8efc31695dd3b9d" dependencies = [ "libc", "thiserror 1.0.69", @@ -1882,14 +1974,24 @@ dependencies = [ [[package]] name = "vmm-sys-util" -version = "0.12.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1435039746e20da4f8d507a72ee1b916f7b4b05af7a91c093d2c6561934ede" +checksum = "d21f366bf22bfba3e868349978766a965cbe628c323d58e026be80b8357ab789" dependencies = [ "bitflags 1.3.2", "libc", ] +[[package]] +name = "vsock" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e8b4d00e672f147fc86a09738fadb1445bd1c0a40542378dfb82909deeee688" +dependencies = [ + "libc", + "nix 0.29.0", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -1987,9 +2089,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.61.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement", "windows-interface", @@ -2028,31 +2130,22 @@ checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" [[package]] name = "windows-result" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ "windows-link", ] [[package]] name = "windows-strings" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ "windows-link", ] -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-sys" version = "0.52.0" @@ -2071,21 +2164,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - [[package]] name = "windows-targets" version = "0.52.6" @@ -2095,7 +2173,7 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", @@ -2103,10 +2181,20 @@ dependencies = [ ] [[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" +name = "windows-targets" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] [[package]] name = "windows_aarch64_gnullvm" @@ -2115,10 +2203,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" +name = "windows_aarch64_gnullvm" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" [[package]] name = "windows_aarch64_msvc" @@ -2127,10 +2215,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] -name = "windows_i686_gnu" -version = "0.48.5" +name = "windows_aarch64_msvc" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" [[package]] name = "windows_i686_gnu" @@ -2138,6 +2226,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" @@ -2145,10 +2239,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] -name = "windows_i686_msvc" -version = "0.48.5" +name = "windows_i686_gnullvm" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" [[package]] name = "windows_i686_msvc" @@ -2157,10 +2251,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" +name = "windows_i686_msvc" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" [[package]] name = "windows_x86_64_gnu" @@ -2169,10 +2263,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" +name = "windows_x86_64_gnu" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" [[package]] name = "windows_x86_64_gnullvm" @@ -2181,10 +2275,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" +name = "windows_x86_64_gnullvm" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" [[package]] name = "windows_x86_64_msvc" @@ -2192,11 +2286,17 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "winnow" -version = "0.7.6" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10" +checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" dependencies = [ "memchr", ] @@ -2207,7 +2307,7 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", ] [[package]] @@ -2231,11 +2331,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.24" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" +checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" dependencies = [ - "zerocopy-derive 0.8.24", + "zerocopy-derive 0.8.25", ] [[package]] @@ -2251,9 +2351,9 @@ dependencies = [ [[package]] name = "zerocopy-derive" -version = "0.8.24" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" +checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" dependencies = [ "proc-macro2", "quote", diff --git a/Makefile b/Makefile index 7e9c59416..ce70aee16 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ LIBRARY_HEADER = include/libkrun.h ABI_VERSION=1 -FULL_VERSION=1.13.0 +FULL_VERSION=1.14.0 INIT_SRC = init/init.c KBS_INIT_SRC = init/tee/kbs/kbs.h \ @@ -27,9 +27,6 @@ ifeq ($(SEV),1) INIT_SRC += $(SNP_INIT_SRC) BUILD_INIT = 0 endif -ifeq ($(GPU),1) - FEATURE_FLAGS += --features gpu -endif ifeq ($(VIRGL_RESOURCE_MAP2),1) FEATURE_FLAGS += --features virgl_resource_map2 endif @@ -39,12 +36,20 @@ endif ifeq ($(NET),1) FEATURE_FLAGS += --features net endif +ifeq ($(EFI),1) + VARIANT = -efi + FEATURE_FLAGS := --features efi # EFI Implies blk and net + BUILD_INIT = 0 +endif +ifeq ($(GPU),1) + FEATURE_FLAGS += --features gpu +endif ifeq ($(SND),1) FEATURE_FLAGS += --features snd endif -ifeq ($(EFI),1) - VARIANT = -efi - FEATURE_FLAGS := --features efi,gpu +ifeq ($(NITRO),1) + VARIANT = -nitro + FEATURE_FLAGS := --features nitro BUILD_INIT = 0 endif @@ -91,9 +96,12 @@ $(LIBRARY_RELEASE_$(OS)): $(INIT_BINARY) ifeq ($(SEV),1) mv target/release/libkrun.so target/release/$(KRUN_BASE_$(OS)) endif +ifeq ($(NITRO),1) + mv target/release/libkrun.so target/release/$(KRUN_BASE_$(OS)) +endif ifeq ($(OS),Darwin) ifeq ($(EFI),1) - install_name_tool -id libkrun-efi.dylib target/release/libkrun.dylib + install_name_tool -id $(PREFIX)/$(LIBDIR_$(OS))/$(KRUN_SONAME_$(OS)) target/release/libkrun.dylib endif mv target/release/libkrun.dylib target/release/$(KRUN_BASE_$(OS)) endif diff --git a/examples/Makefile b/examples/Makefile index 3eedfa471..c1ce8a24e 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -5,6 +5,7 @@ LDFLAGS_aarch64_Linux = -lkrun LDFLAGS_arm64_Darwin = -L/opt/homebrew/lib -lkrun LDFLAGS_sev = -lkrun-sev LDFLAGS_efi = -L/opt/homebrew/lib -lkrun-efi +LDFLAGS_nitro = -lkrun-nitro CFLAGS = -O2 -g -I../include ROOTFS_DISTRO := fedora ROOTFS_DIR = rootfs_$(ROOTFS_DISTRO) @@ -42,6 +43,9 @@ ifeq ($(OS),Darwin) codesign --entitlements chroot_vm.entitlements --force -s - $@ endif +nitro: nitro.c + gcc -o $@ $< $(CFLAGS) $(LDFLAGS_nitro) + # Build the rootfs to be used with chroot_vm. rootfs: mkdir -p $(ROOTFS_DIR) @@ -50,4 +54,4 @@ rootfs: podman rm libkrun_chroot_vm clean: - rm -rf chroot_vm $(ROOTFS_DIR) launch-tee boot_efi external_kernel + rm -rf chroot_vm $(ROOTFS_DIR) launch-tee boot_efi external_kernel nitro diff --git a/examples/nitro.c b/examples/nitro.c new file mode 100644 index 000000000..43332c49c --- /dev/null +++ b/examples/nitro.c @@ -0,0 +1,224 @@ +/* + * This is an example implementing running an example AWS nitro enclave with + * libkrun. + * + * Given a nitro enclave image, run the image in a nitro enclave with 1 vCPU and + * 256 MiB of memory allocated. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_ARGS_LEN 4096 +#ifndef MAX_PATH +#define MAX_PATH 4096 +#endif + +#define IPC_SOCK_PATH "/tmp/krun_nitro_example_ipc.sock" + +static void print_help(char *const name) +{ + fprintf(stderr, + "Usage: %s EIF_FILE [COMMAND_ARGS...]\n" + "OPTIONS: \n" + " -h --help Show help\n" + "\n" + "ENCLAVE_IMAGE: The enclave image to run\n", + name + ); +} + +static const struct option long_options[] = { + { "help", no_argument, NULL, 'h' }, + { NULL, 0, NULL, 0 } +}; + +struct cmdline { + bool show_help; + const char *eif_path; +}; + +bool parse_cmdline(int argc, char *const argv[], struct cmdline *cmdline) +{ + int c, option_index = 0; + + assert(cmdline != NULL); + + // set the defaults + *cmdline = (struct cmdline){ + .show_help = false, + .eif_path = NULL, + }; + + // the '+' in optstring is a GNU extension that disables permutating argv + while ((c = getopt_long(argc, argv, "+h", long_options, &option_index)) != -1) { + switch (c) { + case 'h': + cmdline->show_help = true; + return true; + case '?': + return false; + default: + fprintf(stderr, "internal argument parsing error (returned character code 0x%x)\n", c); + return false; + } + } + + if (optind < argc) { + cmdline->eif_path = argv[optind]; + return true; + } else + fprintf(stderr, "Missing EIF_FILE argument"); + + return false; +} + +void *listen_enclave_output(void *opaque) +{ + int ret, fd = (int) opaque, sock, len; + char buf[512]; + struct sockaddr_un client_sockaddr; + + sock = accept(fd, (struct sockaddr *) &client_sockaddr, &len); + if (sock < 1) + return (void *) -1; + + for (;;) { + ret = read(sock, &buf, 512); + if (ret <= 0) + break; + else if (ret < 512) { + buf[ret] = '\0'; + } + + printf("%s", buf); + } +} + +int main(int argc, char *const argv[]) +{ + int ret, ctx_id, err, i, sock_fd, enable = 1; + struct cmdline cmdline; + struct sockaddr_un addr; + pthread_t thread; + + if (!parse_cmdline(argc, argv, &cmdline)) { + putchar('\n'); + print_help(argv[0]); + return -1; + } + + if (cmdline.show_help){ + print_help(argv[0]); + return 0; + } + + // Set the log level to "off". + err = krun_set_log_level(0); + if (err) { + errno = -err; + perror("Error configuring log level"); + return -1; + } + + // Create the configuration context. + ctx_id = krun_create_ctx(); + if (ctx_id < 0) { + errno = -ctx_id; + perror("Error creating configuration context"); + return -1; + } + + // Configure the number of vCPUs (1) and the amount of RAM (512 MiB). + if (err = krun_set_vm_config(ctx_id, 1, 512)) { + errno = -err; + perror("Error configuring the number of vCPUs and/or the amount of RAM"); + return -1; + } + + // Set the nitro enclave image specified on the command line. + if (err = krun_nitro_set_image(ctx_id, cmdline.eif_path, + KRUN_NITRO_IMG_TYPE_EIF)) { + errno = -err; + perror("Error configuring nitro enclave image"); + return -1; + + } + + // Configure the nitro enclave to run in debug mode. + if (err = krun_nitro_set_start_flags(ctx_id, KRUN_NITRO_START_FLAG_DEBUG)) { + errno = -err; + perror("Error configuring nitro enclave start flags"); + return -1; + } + + // Create and initialize UNIX IPC socket for reading enclave output. + sock_fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (sock_fd < 0) { + perror("Error creating UNIX IPC socket for enclave communication"); + return -1; + } + memset(&addr, 0, sizeof(struct sockaddr_un)); + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, IPC_SOCK_PATH); + + // Listen on the socket for enclave output. + unlink(IPC_SOCK_PATH); + ret = bind(sock_fd, (struct sockaddr *) &addr, sizeof(addr)); + if (ret < 0) { + perror("Error binding socket"); + close(sock_fd); + exit(1); + } + + ret = listen(sock_fd, 1); + if (ret < 0) { + perror("Error listening on socket"); + close(sock_fd); + exit(1); + } + + // Configure the IPC socket to read output from the enclave. The "port" + // argument is ignored. + if (err = krun_add_vsock_port(ctx_id, 0, IPC_SOCK_PATH)) { + close(sock_fd); + errno = -err; + perror("Error configuring enclave vsock"); + return -1; + } + + ret = pthread_create(&thread, NULL, listen_enclave_output, + (void *) sock_fd); + if (ret < 0) { + perror("unable to create new listener thread"); + close(sock_fd); + exit(1); + } + + // Start and enter the microVM. Unless there is some error while creating the microVM + // this function never returns. + if (err = krun_start_enter(ctx_id)) { + close(sock_fd); + errno = -err; + perror("Error creating the microVM"); + return -1; + } + + ret = pthread_join(thread, NULL); + if (ret < 0) { + perror("unable to join listener thread"); + close(sock_fd); + exit(1); + } + + return 0; +} diff --git a/examples/test_data/hello.eif b/examples/test_data/hello.eif new file mode 100644 index 000000000..ebc68dac7 Binary files /dev/null and b/examples/test_data/hello.eif differ diff --git a/include/libkrun.h b/include/libkrun.h index ffd12135c..cd80ab3f9 100644 --- a/include/libkrun.h +++ b/include/libkrun.h @@ -623,6 +623,29 @@ int32_t krun_check_nested_virt(void); */ int32_t krun_split_irqchip(uint32_t ctx_id, bool enable); +#define KRUN_NITRO_IMG_TYPE_EIF 1 +/** + * Configure a Nitro Enclaves image. + * + * Arguments: + * "ctx_id" - the configuration context ID. + * "image_path" - a null-terminated string representing the path of the image + * in the host. + * "image_type" - the type of enclave image being provided. + */ +int32_t krun_nitro_set_image(uint32_t ctx_id, const char *image_path, + uint32_t image_type); + +#define KRUN_NITRO_START_FLAG_DEBUG (1 << 0) +/** + * Configure a Nitro Enclave's start flags. + * + * Arguments: + * "ctx_id" - the configuration context ID. + * "start_flags" - Start flags. + */ +int32_t krun_nitro_set_start_flags(uint32_t ctx_id, uint64_t start_flags); + /** * Starts and enters the microVM with the configured parameters. The VMM will attempt to take over * stdin/stdout to manage them on behalf of the process running inside the isolated environment, diff --git a/src/arch/Cargo.toml b/src/arch/Cargo.toml index 63357ebd1..562f39dc2 100644 --- a/src/arch/Cargo.toml +++ b/src/arch/Cargo.toml @@ -12,6 +12,7 @@ efi = [] [dependencies] libc = ">=0.2.39" vm-memory = { version = ">=0.13", features = ["backend-mmap"] } +vmm-sys-util = ">= 0.14" arch_gen = { path = "../arch_gen" } smbios = { path = "../smbios" } diff --git a/src/arch/src/aarch64/linux/regs.rs b/src/arch/src/aarch64/linux/regs.rs index d60f0318c..b932c9cc4 100644 --- a/src/arch/src/aarch64/linux/regs.rs +++ b/src/arch/src/aarch64/linux/regs.rs @@ -153,7 +153,7 @@ mod tests { let kvm = Kvm::new().unwrap(); let vm = kvm.create_vm().unwrap(); let vcpu = vm.create_vcpu(0).unwrap(); - let (_mem_info, regions) = arch_memory_regions(layout::FDT_MAX_SIZE + 0x1000); + let (_mem_info, regions) = arch_memory_regions(layout::FDT_MAX_SIZE + 0x1000, 0); let mem = GuestMemoryMmap::from_ranges(®ions).expect("Cannot initialize memory"); match setup_regs(&vcpu, 0, 0x0, &mem).unwrap_err() { diff --git a/src/arch/src/aarch64/mod.rs b/src/arch/src/aarch64/mod.rs index ed11c75ab..162fde117 100644 --- a/src/arch/src/aarch64/mod.rs +++ b/src/arch/src/aarch64/mod.rs @@ -17,8 +17,9 @@ pub use self::macos::*; use std::fmt::Debug; -use crate::{round_up, ArchMemoryInfo}; +use crate::ArchMemoryInfo; use vm_memory::{Address, GuestAddress, GuestMemory, GuestMemoryMmap}; +use vmm_sys_util::align_upwards; #[cfg(feature = "efi")] use smbios; @@ -44,7 +45,7 @@ pub fn arch_memory_regions( initrd_size: u64, ) -> (ArchMemoryInfo, Vec<(GuestAddress, usize)>) { let page_size: usize = unsafe { libc::sysconf(libc::_SC_PAGESIZE).try_into().unwrap() }; - let dram_size = round_up(size, page_size); + let dram_size = align_upwards!(size, page_size); let ram_last_addr = layout::DRAM_MEM_START + (dram_size as u64); let shm_start_addr = ((ram_last_addr / 0x4000_0000) + 1) * 0x4000_0000; @@ -97,8 +98,9 @@ pub fn get_kernel_start() -> u64 { /// Returns the memory address where the initrd could be loaded. pub fn initrd_load_addr(guest_mem: &GuestMemoryMmap, initrd_size: usize) -> super::Result { - let round_to_pagesize = |size| (size + (super::PAGE_SIZE - 1)) & !(super::PAGE_SIZE - 1); - match GuestAddress(get_fdt_addr(guest_mem)).checked_sub(round_to_pagesize(initrd_size) as u64) { + match GuestAddress(get_fdt_addr(guest_mem)) + .checked_sub(align_upwards!(initrd_size, super::PAGE_SIZE) as u64) + { Some(offset) => { if guest_mem.address_in_range(offset) { Ok(offset.raw_value()) @@ -135,7 +137,7 @@ mod tests { #[test] fn test_regions_lt_1024gb() { - let (_mem_info, regions) = arch_memory_regions(1usize << 29); + let (_mem_info, regions) = arch_memory_regions(1usize << 29, 0); assert_eq!(1, regions.len()); assert_eq!(GuestAddress(super::layout::DRAM_MEM_START), regions[0].0); assert_eq!(1usize << 29, regions[0].1); @@ -143,7 +145,7 @@ mod tests { #[test] fn test_regions_gt_1024gb() { - let (_mem_info, regions) = arch_memory_regions(1usize << 41); + let (_mem_info, regions) = arch_memory_regions(1usize << 41, 0); assert_eq!(1, regions.len()); assert_eq!(GuestAddress(super::layout::DRAM_MEM_START), regions[0].0); assert_eq!(super::layout::DRAM_MEM_MAX_SIZE, regions[0].1 as u64); @@ -151,15 +153,15 @@ mod tests { #[test] fn test_get_fdt_addr() { - let (_mem_info, regions) = arch_memory_regions(layout::FDT_MAX_SIZE - 0x1000); + let (_mem_info, regions) = arch_memory_regions(layout::FDT_MAX_SIZE - 0x1000, 0); let mem = GuestMemoryMmap::from_ranges(®ions).expect("Cannot initialize memory"); assert_eq!(get_fdt_addr(&mem), layout::DRAM_MEM_START); - let (_mem_info, regions) = arch_memory_regions(layout::FDT_MAX_SIZE); + let (_mem_info, regions) = arch_memory_regions(layout::FDT_MAX_SIZE, 0); let mem = GuestMemoryMmap::from_ranges(®ions).expect("Cannot initialize memory"); assert_eq!(get_fdt_addr(&mem), layout::DRAM_MEM_START); - let (_mem_info, regions) = arch_memory_regions(layout::FDT_MAX_SIZE + 0x1000); + let (_mem_info, regions) = arch_memory_regions(layout::FDT_MAX_SIZE + 0x1000, 0); let mem = GuestMemoryMmap::from_ranges(®ions).expect("Cannot initialize memory"); assert_eq!(get_fdt_addr(&mem), 0x1000 + layout::DRAM_MEM_START); } diff --git a/src/arch/src/lib.rs b/src/arch/src/lib.rs index 453385ea5..d5e7e9475 100644 --- a/src/arch/src/lib.rs +++ b/src/arch/src/lib.rs @@ -48,12 +48,3 @@ pub struct InitrdConfig { /// Default (smallest) memory page size for the supported architectures. pub const PAGE_SIZE: usize = 4096; - -pub fn round_up(size: usize, align: usize) -> usize { - let page_mask = align - 1; - (size + page_mask) & !page_mask -} -pub fn round_down(size: usize, align: usize) -> usize { - let page_mask = !(align - 1); - size & page_mask -} diff --git a/src/arch/src/x86_64/mod.rs b/src/arch/src/x86_64/mod.rs index 4253554fc..e400bb6f3 100644 --- a/src/arch/src/x86_64/mod.rs +++ b/src/arch/src/x86_64/mod.rs @@ -17,12 +17,13 @@ pub mod msr; /// Logic for configuring x86_64 registers. pub mod regs; -use crate::{round_up, ArchMemoryInfo, InitrdConfig}; +use crate::{ArchMemoryInfo, InitrdConfig}; use arch_gen::x86::bootparam::{boot_params, E820_RAM}; use vm_memory::Bytes; use vm_memory::{ Address, ByteValued, GuestAddress, GuestMemory, GuestMemoryMmap, GuestMemoryRegion, }; +use vmm_sys_util::align_upwards; // This is a workaround to the Rust enforcement specifying that any implementation of a foreign // trait (in this case `ByteValued`) where: @@ -73,7 +74,7 @@ pub fn arch_memory_regions( ) -> (ArchMemoryInfo, Vec<(GuestAddress, usize)>) { let page_size: usize = unsafe { libc::sysconf(libc::_SC_PAGESIZE).try_into().unwrap() }; - let size = round_up(size, page_size); + let size = align_upwards!(size, page_size); // It's safe to cast MMIO_MEM_START to usize because it fits in a u32 variable // (It points to an address in the 32 bit space). @@ -155,7 +156,7 @@ pub fn arch_memory_regions( ) -> (ArchMemoryInfo, Vec<(GuestAddress, usize)>) { let page_size: usize = unsafe { libc::sysconf(libc::_SC_PAGESIZE).try_into().unwrap() }; - let size = round_up(size, page_size); + let size = align_upwards!(size, page_size); if let Some(kernel_load_addr) = kernel_load_addr { if size < (kernel_load_addr + kernel_size as u64) as usize { panic!("Kernel doesn't fit in RAM"); diff --git a/src/cpuid/Cargo.toml b/src/cpuid/Cargo.toml index 85e937720..8d9bbeeae 100644 --- a/src/cpuid/Cargo.toml +++ b/src/cpuid/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Amazon Firecracker team "] edition = "2021" [dependencies] -vmm-sys-util = "0.12.1" +vmm-sys-util = ">= 0.14" [target.'cfg(target_os = "linux")'.dependencies] kvm-bindings = { version = ">=0.11", features = ["fam-wrappers"] } diff --git a/src/devices/Cargo.toml b/src/devices/Cargo.toml index aaf2166de..3b818a8cd 100644 --- a/src/devices/Cargo.toml +++ b/src/devices/Cargo.toml @@ -13,6 +13,7 @@ efi = ["blk", "net"] gpu = ["rutabaga_gfx", "thiserror", "zerocopy", "zerocopy-derive"] snd = ["pw", "thiserror"] virgl_resource_map2 = [] +nitro = [] [dependencies] bitflags = "1.2.0" diff --git a/src/devices/src/legacy/ioapic.rs b/src/devices/src/legacy/ioapic.rs index ca4cf205c..71a30eaae 100644 --- a/src/devices/src/legacy/ioapic.rs +++ b/src/devices/src/legacy/ioapic.rs @@ -1,7 +1,7 @@ use crossbeam_channel::unbounded; use kvm_bindings::{ - kvm_enable_cap, kvm_irq_routing, kvm_irq_routing_entry, kvm_irq_routing_entry__bindgen_ty_1, - kvm_irq_routing_msi, KVM_CAP_SPLIT_IRQCHIP, KVM_IRQ_ROUTING_MSI, + kvm_enable_cap, kvm_irq_routing_entry, kvm_irq_routing_entry__bindgen_ty_1, + kvm_irq_routing_msi, KvmIrqRouting, KVM_CAP_SPLIT_IRQCHIP, KVM_IRQ_ROUTING_MSI, }; use kvm_ioctls::{Error, VmFd}; @@ -125,20 +125,10 @@ impl IoApic { (0..IOAPIC_NUM_PINS).for_each(|i| ioapic.add_msi_route(i)); - let mut irq_routing = utils::sized_vec::vec_with_array_field::< - kvm_irq_routing, - kvm_irq_routing_entry, - >(ioapic.irq_routes.len()); - irq_routing[0].nr = ioapic.irq_routes.len() as u32; - irq_routing[0].flags = 0; - - unsafe { - let entries_slice: &mut [kvm_irq_routing_entry] = - irq_routing[0].entries.as_mut_slice(ioapic.irq_routes.len()); - entries_slice.copy_from_slice(ioapic.irq_routes.as_slice()); - } - - vm.set_gsi_routing(&irq_routing[0])?; + let mut routing = KvmIrqRouting::new(ioapic.irq_routes.len()).unwrap(); + let routing_entires = routing.as_mut_slice(); + routing_entires.copy_from_slice(ioapic.irq_routes.as_slice()); + vm.set_gsi_routing(&routing)?; Ok(ioapic) } diff --git a/src/devices/src/virtio/mod.rs b/src/devices/src/virtio/mod.rs index b39ed1809..791925700 100644 --- a/src/devices/src/virtio/mod.rs +++ b/src/devices/src/virtio/mod.rs @@ -21,7 +21,7 @@ pub mod console; pub mod descriptor_utils; pub mod device; pub mod file_traits; -#[cfg(not(feature = "tee"))] +#[cfg(not(any(feature = "tee", feature = "nitro")))] pub mod fs; #[cfg(feature = "gpu")] pub mod gpu; @@ -42,7 +42,7 @@ pub use self::balloon::*; pub use self::block::{Block, CacheType}; pub use self::console::*; pub use self::device::*; -#[cfg(not(feature = "tee"))] +#[cfg(not(any(feature = "tee", feature = "nitro")))] pub use self::fs::*; #[cfg(feature = "gpu")] pub use self::gpu::*; diff --git a/src/libkrun/Cargo.toml b/src/libkrun/Cargo.toml index 1ab018fd2..195e45627 100644 --- a/src/libkrun/Cargo.toml +++ b/src/libkrun/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libkrun" -version = "1.13.0" +version = "1.14.0" authors = ["Sergio Lopez "] edition = "2021" build = "build.rs" @@ -14,6 +14,7 @@ efi = [ "blk", "net" ] gpu = [] snd = [] virgl_resource_map2 = [] +nitro = [ "dep:nitro", "dep:nitro-enclaves" ] [dependencies] crossbeam-channel = ">=0.5.15" @@ -34,6 +35,8 @@ hvf = { path = "../hvf" } [target.'cfg(target_os = "linux")'.dependencies] kvm-bindings = { version = ">=0.11", features = ["fam-wrappers"] } kvm-ioctls = ">=0.21" +nitro = { path = "../nitro", optional = true } +nitro-enclaves = { version = "0.2.0", optional = true } vm-memory = ">=0.13" [lib] diff --git a/src/libkrun/build.rs b/src/libkrun/build.rs index b9deece29..efc4886db 100644 --- a/src/libkrun/build.rs +++ b/src/libkrun/build.rs @@ -5,5 +5,11 @@ fn main() { std::env::var("CARGO_PKG_VERSION_MAJOR").unwrap() ); #[cfg(target_os = "macos")] + println!( + "cargo:rustc-cdylib-link-arg=-Wl,-install_name,libkrun.{}.dylib,-compatibility_version,{}.0.0,-current_version,{}.{}.0", + std::env::var("CARGO_PKG_VERSION_MAJOR").unwrap(), std::env::var("CARGO_PKG_VERSION_MAJOR").unwrap(), + std::env::var("CARGO_PKG_VERSION_MAJOR").unwrap(), std::env::var("CARGO_PKG_VERSION_MINOR").unwrap() + ); + #[cfg(target_os = "macos")] println!("cargo:rustc-link-lib=framework=Hypervisor"); } diff --git a/src/libkrun/src/lib.rs b/src/libkrun/src/lib.rs index a778db2fe..94d7d62bf 100644 --- a/src/libkrun/src/lib.rs +++ b/src/libkrun/src/lib.rs @@ -12,6 +12,8 @@ use std::fs::File; #[cfg(target_os = "linux")] use std::os::fd::AsRawFd; use std::os::fd::{FromRawFd, RawFd}; +#[cfg(feature = "nitro")] +use std::os::unix::net::UnixStream; use std::path::PathBuf; use std::slice; use std::sync::atomic::{AtomicI32, Ordering}; @@ -50,6 +52,12 @@ use vmm::vmm_config::machine_config::VmConfig; use vmm::vmm_config::net::NetworkInterfaceConfig; use vmm::vmm_config::vsock::VsockDeviceConfig; +#[cfg(feature = "nitro")] +use nitro::enclaves::NitroEnclave; + +#[cfg(feature = "nitro")] +use nitro_enclaves::launch::StartFlags; + // Value returned on success. We use libc's errors otherwise. const KRUN_SUCCESS: i32 = 0; // Maximum number of arguments/environment variables we allow @@ -151,6 +159,10 @@ struct ContextConfig { console_output: Option, vmm_uid: Option, vmm_gid: Option, + #[cfg(feature = "nitro")] + nitro_image_path: Option, + #[cfg(feature = "nitro")] + nitro_start_flags: StartFlags, } impl ContextConfig { @@ -295,6 +307,73 @@ impl ContextConfig { fn set_vmm_gid(&mut self, vmm_gid: libc::gid_t) { self.vmm_gid = Some(vmm_gid); } + + #[cfg(feature = "nitro")] + fn set_nitro_image(&mut self, image_path: PathBuf) { + self.nitro_image_path = Some(image_path); + } + + #[cfg(feature = "nitro")] + fn set_nitro_start_flags(&mut self, start_flags: StartFlags) { + self.nitro_start_flags = start_flags; + } +} + +#[cfg(feature = "nitro")] +impl TryFrom for NitroEnclave { + type Error = i32; + + fn try_from(ctx: ContextConfig) -> Result { + let vm_config = ctx.vmr.vm_config(); + + let Some(mem_size_mib) = vm_config.mem_size_mib else { + error!("memory size not configured"); + return Err(-libc::EINVAL); + }; + + let Some(vcpus) = vm_config.vcpu_count else { + error!("vCPU count not configured"); + return Err(-libc::EINVAL); + }; + + let Some(image_path) = ctx.nitro_image_path else { + error!("nitro image not configured"); + return Err(-libc::EINVAL); + }; + + let Ok(image) = File::open(&image_path) else { + error!("unable to open {}", image_path.display()); + return Err(-libc::EINVAL); + }; + + let Some(port_map) = ctx.unix_ipc_port_map else { + error!("enclave vsock not configured"); + return Err(-libc::EINVAL); + }; + + if port_map.len() > 1 { + error!("too many nitro vsocks detected (max 1)"); + return Err(-libc::EINVAL); + } + + let ipc_stream = { + let mut vec = Vec::from_iter(port_map.values()); + let Some((path, _)) = vec.pop() else { + error!("enclave vsock path not found"); + return Err(-libc::EINVAL); + }; + + UnixStream::connect(path).unwrap() + }; + + Ok(Self { + image, + mem_size_mib, + vcpus, + ipc_stream, + start_flags: ctx.nitro_start_flags, + }) + } } static CTX_MAP: Lazy>> = Lazy::new(|| Mutex::new(HashMap::new())); @@ -983,6 +1062,11 @@ pub unsafe extern "C" fn krun_add_vsock_port2( c_filepath: *const c_char, listen: bool, ) -> i32 { + #[cfg(feature = "nitro")] + if listen { + return -libc::EINVAL; + } + let filepath = match CStr::from_ptr(c_filepath).to_str() { Ok(f) => PathBuf::from(f.to_string()), Err(_) => return -libc::EINVAL, @@ -1399,7 +1483,52 @@ pub extern "C" fn krun_setgid(ctx_id: u32, gid: libc::gid_t) -> i32 { KRUN_SUCCESS } +#[cfg(feature = "nitro")] +#[allow(clippy::missing_safety_doc)] +#[no_mangle] +pub unsafe extern "C" fn krun_nitro_set_image(ctx_id: u32, c_image_filepath: *const c_char) -> i32 { + let filepath = match CStr::from_ptr(c_image_filepath).to_str() { + Ok(f) => PathBuf::from(f.to_string()), + Err(_) => return -libc::EINVAL, + }; + + match CTX_MAP.lock().unwrap().entry(ctx_id) { + Entry::Occupied(mut ctx_cfg) => { + let cfg = ctx_cfg.get_mut(); + cfg.set_nitro_image(filepath); + } + Entry::Vacant(_) => return -libc::ENOENT, + } + + KRUN_SUCCESS +} + +#[cfg(feature = "nitro")] +#[allow(clippy::missing_safety_doc)] #[no_mangle] +pub unsafe extern "C" fn krun_nitro_set_start_flags(ctx_id: u32, start_flags: u64) -> i32 { + let mut flags = StartFlags::empty(); + + // Only debug mode is supported at the moment. To avoid doing conversion and + // checking if the "start_flags" argument is valid, set the flags to debug mode + // if the "start_flags" argument is greater than zero. + if start_flags > 0 { + flags |= StartFlags::DEBUG; + } + + match CTX_MAP.lock().unwrap().entry(ctx_id) { + Entry::Occupied(mut ctx_cfg) => { + let cfg = ctx_cfg.get_mut(); + cfg.set_nitro_start_flags(flags); + } + Entry::Vacant(_) => return -libc::ENOENT, + } + + KRUN_SUCCESS +} + +#[no_mangle] +#[allow(unreachable_code)] pub extern "C" fn krun_start_enter(ctx_id: u32) -> i32 { #[cfg(target_os = "linux")] { @@ -1410,6 +1539,9 @@ pub extern "C" fn krun_start_enter(ctx_id: u32) -> i32 { unsafe { libc::prctl(libc::PR_SET_NAME, prname.as_ptr()) }; } + #[cfg(feature = "nitro")] + return krun_start_enter_nitro(ctx_id); + let mut event_manager = match EventManager::new() { Ok(em) => em, Err(e) => { @@ -1582,3 +1714,23 @@ pub extern "C" fn krun_start_enter(ctx_id: u32) -> i32 { } } } + +#[cfg(feature = "nitro")] +#[no_mangle] +fn krun_start_enter_nitro(ctx_id: u32) -> i32 { + let ctx_cfg = match CTX_MAP.lock().unwrap().remove(&ctx_id) { + Some(ctx_cfg) => ctx_cfg, + None => return -libc::ENOENT, + }; + + let Ok(mut enclave) = NitroEnclave::try_from(ctx_cfg) else { + return -libc::EINVAL; + }; + + if let Err(e) = enclave.run() { + error!("Error running nitro enclave: {e}"); + return -libc::EINVAL; + } + + KRUN_SUCCESS +} diff --git a/src/nitro/Cargo.toml b/src/nitro/Cargo.toml new file mode 100644 index 000000000..acb01f0b2 --- /dev/null +++ b/src/nitro/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "nitro" +version = "0.1.0" +edition = "2021" + +[features] +nitro = [] + +[dependencies] +libc = "0.2.171" +nix = { version = "0.26.0", features = ["ioctl", "poll"] } +vsock = "0.5.1" + +[target.'cfg(target_os = "linux")'.dependencies] +nitro-enclaves = "0.2.0" diff --git a/src/nitro/src/enclaves.rs b/src/nitro/src/enclaves.rs new file mode 100644 index 000000000..73a3ac00a --- /dev/null +++ b/src/nitro/src/enclaves.rs @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: Apache-2.0 + +use super::error::NitroError; +use nitro_enclaves::{ + launch::{ImageType, Launcher, MemoryInfo, PollTimeout, StartFlags}, + Device, +}; +use nix::{ + poll::{poll, PollFd, PollFlags}, + sys::{ + socket::{connect, socket, AddressFamily, SockFlag, SockType, VsockAddr as NixVsockAddr}, + time::{TimeVal, TimeValLike}, + }, + unistd::read, +}; +use std::{ + fs::File, + io::{Read, Write}, + os::{ + fd::{AsRawFd, RawFd}, + unix::net::UnixStream, + }, +}; +use vsock::{VsockAddr, VsockListener}; + +type Result = std::result::Result; + +const ENCLAVE_READY_VSOCK_PORT: u32 = 9000; +const CID_TO_CONSOLE_PORT_OFFSET: u32 = 10000; + +const VMADDR_CID_PARENT: u32 = 3; +const VMADDR_CID_HYPERVISOR: u32 = 0; + +const SO_VM_SOCKETS_CONNECT_TIMEOUT: i32 = 6; + +const HEART_BEAT: u8 = 0xb7; + +/// Nitro Enclave data. +pub struct NitroEnclave { + /// Enclave image. + pub image: File, + /// Amount of RAM (in MiB). + pub mem_size_mib: usize, + /// Number of vCPUs. + pub vcpus: u8, + /// Path of vsock for initial enclave communication. + pub ipc_stream: UnixStream, + /// Enclave start flags. + pub start_flags: StartFlags, +} + +impl NitroEnclave { + /// Run the enclave. + pub fn run(&mut self) -> Result<()> { + let device = Device::open().map_err(NitroError::DeviceOpen)?; + + let mut launcher = Launcher::new(&device).map_err(NitroError::VmCreate)?; + + let mem = MemoryInfo::new(ImageType::Eif(&mut self.image), self.mem_size_mib); + launcher.set_memory(mem).map_err(NitroError::VmMemorySet)?; + + for _ in 0..self.vcpus { + launcher.add_vcpu(None).map_err(NitroError::VcpuAdd)?; + } + + let sockaddr = VsockAddr::new(VMADDR_CID_PARENT, ENCLAVE_READY_VSOCK_PORT); + let listener = VsockListener::bind(&sockaddr).map_err(NitroError::HeartbeatBind)?; + + let cid = launcher + .start(self.start_flags, None) + .map_err(NitroError::VmStart)?; + + // Safe to unwrap. + let cid: u32 = cid.try_into().unwrap(); + + let poll_timeout = PollTimeout::try_from((&self.image, self.mem_size_mib << 20)) + .map_err(NitroError::PollTimeoutCalculate)?; + + enclave_check(listener, poll_timeout.into(), cid)?; + + self.listen(VMADDR_CID_HYPERVISOR, cid + CID_TO_CONSOLE_PORT_OFFSET)?; + + Ok(()) + } + + fn listen(&mut self, cid: u32, port: u32) -> Result<()> { + let socket_fd = socket( + AddressFamily::Vsock, + SockType::Stream, + SockFlag::empty(), + None, + ) + .map_err(|_| NitroError::VsockCreate)?; + + let sockaddr = NixVsockAddr::new(cid, port); + + vsock_timeout(socket_fd)?; + + connect(socket_fd, &sockaddr).map_err(|_| NitroError::VsockConnect)?; + + let mut buf = [0u8; 512]; + loop { + // Read debug output from vsock. + if let Ok(sz) = read(socket_fd, &mut buf) { + // If there is enclave debug output read, write it to the IPC socket. + if sz > 0 { + self.ipc_stream + .write_all(&buf[..sz]) + .map_err(NitroError::IpcWrite)?; + + continue; + } + } + + break; + } + + Ok(()) + } +} + +fn enclave_check(listener: VsockListener, poll_timeout_ms: libc::c_int, cid: u32) -> Result<()> { + let mut poll_fds = [PollFd::new(listener.as_raw_fd(), PollFlags::POLLIN)]; + let result = poll(&mut poll_fds, poll_timeout_ms); + if result == Ok(0) { + return Err(NitroError::PollNoSelectedEvents); + } else if result != Ok(1) { + return Err(NitroError::PollMoreThanOneSelectedEvent); + } + + let mut stream = listener.accept().map_err(NitroError::HeartbeatAccept)?; + + let mut buf = [0u8]; + let bytes = stream.0.read(&mut buf).map_err(NitroError::HeartbeatRead)?; + + if bytes != 1 || buf[0] != HEART_BEAT { + return Err(NitroError::EnclaveHeartbeatNotDetected); + } + + stream + .0 + .write_all(&buf) + .map_err(NitroError::HeartbeatWrite)?; + + if stream.1.cid() != cid { + return Err(NitroError::HeartbeatCidMismatch); + } + + Ok(()) +} + +fn vsock_timeout(socket_fd: RawFd) -> Result<()> { + // Set the timeout to 20 seconds. + let timeval = TimeVal::milliseconds(20000); + + let ret = unsafe { + libc::setsockopt( + socket_fd, + libc::AF_VSOCK, + SO_VM_SOCKETS_CONNECT_TIMEOUT, + &timeval as *const _ as *const libc::c_void, + size_of::() as u32, + ) + }; + + if ret != 0 { + return Err(NitroError::VsockSetTimeout); + } + + Ok(()) +} diff --git a/src/nitro/src/error.rs b/src/nitro/src/error.rs new file mode 100644 index 000000000..42a1b303e --- /dev/null +++ b/src/nitro/src/error.rs @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: Apache-2.0 + +use nitro_enclaves::launch::LaunchError; +use std::{fmt, io}; + +#[derive(Debug)] +pub enum NitroError { + DeviceOpen(io::Error), + VmCreate(LaunchError), + VmMemorySet(LaunchError), + VcpuAdd(LaunchError), + HeartbeatAccept(io::Error), + HeartbeatBind(io::Error), + HeartbeatRead(io::Error), + HeartbeatWrite(io::Error), + VmStart(LaunchError), + PollTimeoutCalculate(LaunchError), + PollNoSelectedEvents, + PollMoreThanOneSelectedEvent, + EnclaveHeartbeatNotDetected, + HeartbeatCidMismatch, + VsockCreate, + VsockSetTimeout, + VsockConnect, + IpcWrite(io::Error), +} + +impl fmt::Display for NitroError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let msg = match self { + NitroError::DeviceOpen(e) => format!("unable to open nitro enclaves device: {e}"), + NitroError::VmCreate(e) => format!("unable to create enclave VM: {e}"), + NitroError::VmMemorySet(e) => format!("unable to set enclave memory regions: {e}"), + NitroError::VcpuAdd(e) => format!("unable to add vCPU to enclave: {e}"), + NitroError::HeartbeatAccept(e) => { + format!("unable to accept enclave heartbeat vsock: {e}") + } + NitroError::HeartbeatBind(e) => { + format!("unable to bind to enclave hearbeat vsock: {e}") + } + NitroError::HeartbeatRead(e) => format!("unable to read enclave hearbeat vsock: {e}"), + NitroError::HeartbeatWrite(e) => { + format!("unable to write to enclave heartbeat vsock: {e}") + } + NitroError::VmStart(e) => format!("unable to start enclave: {e}"), + NitroError::PollTimeoutCalculate(e) => { + format!("unable to calculate vsock poll timeout: {e}") + } + NitroError::PollNoSelectedEvents => { + "no selected poll fds for heartbeat vsock found".to_string() + } + NitroError::PollMoreThanOneSelectedEvent => { + "more than one selected pollfd for heartbeat vsock found".to_string() + } + NitroError::EnclaveHeartbeatNotDetected => { + "enclave heartbeat message not detected".to_string() + } + NitroError::HeartbeatCidMismatch => "enclave heartbeat vsock CID mismatch".to_string(), + NitroError::VsockCreate => "unable to create enclave vsock".to_string(), + NitroError::VsockSetTimeout => { + "unable to set poll timeout for enclave vsock".to_string() + } + NitroError::VsockConnect => "unable to connect to enclave vsock".to_string(), + NitroError::IpcWrite(e) => { + format!("unable to write enclave vsock data to UNIX IPC socket: {e}") + } + }; + + write!(f, "{}", msg) + } +} diff --git a/src/nitro/src/lib.rs b/src/nitro/src/lib.rs new file mode 100644 index 000000000..b3e89ddb6 --- /dev/null +++ b/src/nitro/src/lib.rs @@ -0,0 +1,5 @@ +#[cfg(feature = "nitro")] +pub mod enclaves; + +#[cfg(feature = "nitro")] +mod error; diff --git a/src/rutabaga_gfx/Cargo.toml b/src/rutabaga_gfx/Cargo.toml index cabc55f64..7e35bb813 100644 --- a/src/rutabaga_gfx/Cargo.toml +++ b/src/rutabaga_gfx/Cargo.toml @@ -26,6 +26,7 @@ remain = "0.2" thiserror = "1.0.23" zerocopy = "0.6" log = "0.4" +vmm-sys-util = ">=0.14" [target.'cfg(unix)'.dependencies] nix = "0.26.1" diff --git a/src/rutabaga_gfx/src/rutabaga_os/sys/unix/shm.rs b/src/rutabaga_gfx/src/rutabaga_os/sys/unix/shm.rs index bcfdee842..c23366d21 100644 --- a/src/rutabaga_gfx/src/rutabaga_os/sys/unix/shm.rs +++ b/src/rutabaga_gfx/src/rutabaga_os/sys/unix/shm.rs @@ -14,6 +14,7 @@ use nix::sys::memfd::MemFdCreateFlag; use nix::unistd::ftruncate; use nix::unistd::sysconf; use nix::unistd::SysconfVar; +use vmm_sys_util::align_upwards; use crate::rutabaga_os::descriptor::AsRawDescriptor; use crate::rutabaga_os::descriptor::IntoRawDescriptor; @@ -72,8 +73,7 @@ impl IntoRawDescriptor for SharedMemory { pub fn round_up_to_page_size(v: u64) -> RutabagaResult { let page_size_opt = sysconf(SysconfVar::PAGE_SIZE)?; if let Some(page_size) = page_size_opt { - let page_mask = (page_size - 1) as u64; - let aligned_size = (v + page_mask) & !page_mask; + let aligned_size = align_upwards!(v, page_size as u64); Ok(aligned_size) } else { Err(RutabagaError::SpecViolation("no page size")) diff --git a/src/utils/Cargo.toml b/src/utils/Cargo.toml index 69e4f3c2f..7f8b56c10 100644 --- a/src/utils/Cargo.toml +++ b/src/utils/Cargo.toml @@ -8,7 +8,7 @@ edition = "2021" bitflags = "1.2.0" libc = ">=0.2.85" log = "0.4.0" -vmm-sys-util = "0.12.1" +vmm-sys-util = ">= 0.14" crossbeam-channel = ">=0.5.15" [target.'cfg(target_os = "linux")'.dependencies] diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index 7edd2f1c9..231c79a2e 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -12,6 +12,7 @@ blk = [] efi = [ "blk", "net" ] gpu = [] snd = [] +nitro = [] [dependencies] crossbeam-channel = ">=0.5.15" @@ -20,6 +21,7 @@ libc = ">=0.2.39" linux-loader = { version = "0.13.0", features = ["bzimage", "elf", "pe"] } log = "0.4.0" vm-memory = { version = ">=0.13", features = ["backend-mmap"] } +vmm-sys-util = ">=0.14" arch = { path = "../arch" } devices = { path = "../devices" } @@ -49,6 +51,3 @@ kvm-ioctls = ">=0.21" [target.'cfg(target_os = "macos")'.dependencies] hvf = { path = "../hvf" } - -[dev-dependencies] -vmm-sys-util = "0.12.1" diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index f32ccaa4d..35ffb85bf 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -55,7 +55,7 @@ use crate::terminal::term_set_raw_mode; #[cfg(feature = "blk")] use crate::vmm_config::block::BlockBuilder; use crate::vmm_config::boot_source::DEFAULT_KERNEL_CMDLINE; -#[cfg(not(feature = "tee"))] +#[cfg(not(any(feature = "tee", feature = "nitro")))] use crate::vmm_config::fs::FsDeviceConfig; #[cfg(target_os = "linux")] use crate::vstate::KvmContext; @@ -64,7 +64,7 @@ use crate::vstate::MeasuredRegion; use crate::vstate::{Error as VstateError, Vcpu, VcpuConfig, Vm}; use arch::{ArchMemoryInfo, InitrdConfig}; use device_manager::shm::ShmManager; -#[cfg(not(feature = "tee"))] +#[cfg(not(any(feature = "tee", feature = "nitro")))] use devices::virtio::{fs::ExportTable, VirtioShmRegion}; use flate2::read::GzDecoder; #[cfg(feature = "tee")] @@ -78,12 +78,14 @@ use utils::eventfd::EventFd; use utils::worker_message::WorkerMessage; #[cfg(all(target_arch = "x86_64", not(feature = "efi"), not(feature = "tee")))] use vm_memory::mmap::MmapRegion; -#[cfg(not(feature = "tee"))] +#[cfg(not(any(feature = "tee", feature = "nitro")))] use vm_memory::Address; use vm_memory::Bytes; +#[cfg(not(feature = "nitro"))] +use vm_memory::GuestMemory; #[cfg(all(target_arch = "x86_64", not(feature = "tee")))] use vm_memory::GuestRegionMmap; -use vm_memory::{GuestAddress, GuestMemory, GuestMemoryMmap}; +use vm_memory::{GuestAddress, GuestMemoryMmap}; #[cfg(feature = "efi")] static EDK2_BINARY: &[u8] = include_bytes!("../../../edk2/KRUN_EFI.silent.fd"); @@ -784,7 +786,7 @@ pub fn build_microvm( vm_resources.console_output.clone(), )?; - #[cfg(not(feature = "tee"))] + #[cfg(not(any(feature = "tee", feature = "nitro")))] let export_table: Option = if cfg!(feature = "gpu") { Some(Default::default()) } else { @@ -805,8 +807,7 @@ pub fn build_microvm( _sender.clone(), )?; } - - #[cfg(not(feature = "tee"))] + #[cfg(not(any(feature = "tee", feature = "nitro")))] attach_fs_devices( &mut vmm, &vm_resources.fs, @@ -1579,7 +1580,7 @@ fn attach_mmio_device( Ok(()) } -#[cfg(not(feature = "tee"))] +#[cfg(not(any(feature = "tee", feature = "nitro")))] fn attach_fs_devices( vmm: &mut Vmm, fs_devs: &[FsDeviceConfig], diff --git a/src/vmm/src/device_manager/shm.rs b/src/vmm/src/device_manager/shm.rs index 3fd944648..ef26905c9 100644 --- a/src/vmm/src/device_manager/shm.rs +++ b/src/vmm/src/device_manager/shm.rs @@ -1,7 +1,8 @@ use std::collections::BTreeMap; -use arch::{round_up, ArchMemoryInfo}; +use arch::ArchMemoryInfo; use vm_memory::GuestAddress; +use vmm_sys_util::align_upwards; #[derive(Debug)] pub enum Error { @@ -46,7 +47,7 @@ impl ShmManager { regions } - #[cfg(not(feature = "tee"))] + #[cfg(not(any(feature = "tee", feature = "nitro")))] pub fn fs_region(&self, index: usize) -> Option<&ShmRegion> { self.fs_regions.get(&index) } @@ -57,7 +58,7 @@ impl ShmManager { } fn create_region(&mut self, size: usize) -> Result { - let size = round_up(size, self.page_size); + let size = align_upwards!(size, self.page_size); let region = ShmRegion { guest_addr: GuestAddress(self.next_guest_addr), diff --git a/src/vmm/src/worker.rs b/src/vmm/src/worker.rs index fd18ffc18..e4cb121ba 100644 --- a/src/vmm/src/worker.rs +++ b/src/vmm/src/worker.rs @@ -15,7 +15,9 @@ use libc::{fallocate, madvise, FALLOC_FL_KEEP_SIZE, FALLOC_FL_PUNCH_HOLE, MADV_D #[cfg(feature = "tee")] use std::ffi::c_void; #[cfg(feature = "tee")] -use vm_memory::{guest_memory::GuestMemory, GuestAddress, GuestMemoryRegion, MemoryRegionAddress}; +use vm_memory::{ + guest_memory::GuestMemory, Address, GuestAddress, GuestMemoryRegion, MemoryRegionAddress, +}; pub fn start_worker_thread( vmm: Arc>, @@ -44,21 +46,11 @@ impl super::Vmm { WorkerMessage::GpuRemoveMapping(s, g, l) => self.remove_mapping(s, g, l), #[cfg(target_arch = "x86_64")] WorkerMessage::GsiRoute(sender, entries) => { - let mut irq_routing = utils::sized_vec::vec_with_array_field::< - kvm_bindings::kvm_irq_routing, - kvm_bindings::kvm_irq_routing_entry, - >(entries.len()); - irq_routing[0].nr = entries.len() as u32; - irq_routing[0].flags = 0; - - unsafe { - let entries_slice: &mut [kvm_bindings::kvm_irq_routing_entry] = - irq_routing[0].entries.as_mut_slice(entries.len()); - entries_slice.copy_from_slice(&entries); - } - + let mut routing = kvm_bindings::KvmIrqRouting::new(entries.len()).unwrap(); + let routing_entries = routing.as_mut_slice(); + routing_entries.copy_from_slice(&entries); sender - .send(self.vm.fd().set_gsi_routing(&irq_routing[0]).is_ok()) + .send(self.vm.fd().set_gsi_routing(&routing).is_ok()) .unwrap(); } #[cfg(target_arch = "x86_64")] @@ -77,15 +69,15 @@ impl super::Vmm { #[cfg(feature = "tee")] fn convert_memory(&self, sender: Sender, properties: MemoryProperties) { - let (guest_memfd, region_start) = self - .kvm_vm() - .guest_memfd_get(properties.gpa) - .unwrap_or_else(|| { - panic!( - "unable to find KVM guest_memfd for memory region corresponding to GPA 0x{:x}", - properties.gpa - ) - }); + let Some((guest_memfd, region_start)) = self.kvm_vm().guest_memfd_get(properties.gpa) + else { + error!( + "unable to find KVM guest_memfd for memory region corresponding to GPA 0x{:x}", + properties.gpa + ); + sender.send(false).unwrap(); + return; + }; let attributes: u64 = if properties.private { KVM_MEMORY_ATTRIBUTE_PRIVATE as u64 @@ -100,10 +92,11 @@ impl super::Vmm { flags: 0, }; - self.kvm_vm() - .fd() - .set_memory_attributes(attr) - .unwrap_or_else(|_| panic!("unable to set memory attributes for memory region corresponding to guest address 0x{:x}", properties.gpa)); + if self.kvm_vm().fd().set_memory_attributes(attr).is_err() { + error!("unable to set memory attributes for memory region corresponding to guest address 0x{:x}", properties.gpa); + sender.send(false).unwrap(); + return; + } let region = self .guest_memory() @@ -122,10 +115,14 @@ impl super::Vmm { if properties.private { let region_addr = MemoryRegionAddress(offset); - let host_startaddr = region - .unwrap() - .get_host_address(region_addr) - .expect("host address corresponding to memory region address 0x{:x} not found"); + let Ok(host_startaddr) = region.unwrap().get_host_address(region_addr) else { + error!( + "host address corresponding to memory region address 0x{:x} not found", + region_addr.raw_value() + ); + sender.send(false).unwrap(); + return; + }; let ret = unsafe { madvise(