diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d9d35c1..45f5ce2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ## [Prerelease] - Unreleased +## [v0.21.0] + ### Added - `AppSandbox::snapshot_with_scratch_mb` takes a snapshot with another scratch size, which the sandbox continues on and a restore of the snapshot gets: boot with what unpacking the rootfs needs, then run guest function calls with what they need, less or more. The snapshot records the size (`snapshot_scratch_mb`), as do later snapshots of the sandbox. A size too small for the kernel makes the sandbox's next entry, the restore, and a boot from the snapshot fail (restoring a snapshot that fits recovers the sandbox). A guest function call that runs out of scratch ends with its process killed (status 137 with a single-process driver, such as python's) or the guest aborted, depending on what runs out first. A restore recovers the sandbox. @@ -12,10 +14,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ### Changed -- The host places the transport arena at a fixed address below the top of scratch, so a snapshot keeps it when restored with a different scratch size. Snapshots saved by an earlier release are refused: save them again. A native Unikraft kernel (`--kernel`, `SandboxBuilder::from_kernel`) built against an earlier `plat/hyperlight` can allocate over the arena: rebuild it against this kernel tree. +- Snapshots saved by v0.20.1 and earlier releases are refused (the kernel, the host's memory layout and the hyperlight-host dependency changed); save them again. +- The host places the transport arena at a fixed address below the top of scratch, so a snapshot keeps it when restored with a different scratch size. +- `hyperlight-host` and `hyperlight-common` move to 0.19. Hyperlight 0.19 gives the guest no heap region (hyperlight-dev/hyperlight#1968): the memory the guest allocates from is scratch. The kernel took its 1 MiB boot stack from that region, and now keeps it in its own image. The re-exported `hyperlight_host` is 0.19: its `SandboxConfiguration::set_heap_size`, `SandboxConfiguration::DEFAULT_HEAP_SIZE`, `SandboxBuilder::heap_size` and `SandboxBuilder::get_heap_size` (hyperlight's builder, not hluk's) are gone (size scratch instead), and `HostFunctions`, `Snapshot` (and what takes or returns one), `Error::Hyperlight`, and the interrupt handle `AppSandbox::interrupt_handle` returns and `SandboxBuilder::on_interrupt_handle` hands over are 0.19's types. For Hyperlight 0.19's other breaking changes (among them `PtRootFinder` gets a `SnapshotMemoryReader` and returns `Result>`, `Sandbox::snapshot` removes `map_region` and `map_file_cow` regions, snapshot ABI 9), see [its CHANGELOG](https://github.com/hyperlight-dev/hyperlight/blob/v0.19.0/CHANGELOG.md). A native Unikraft kernel (`--kernel`, `SandboxBuilder::from_kernel`) built against an earlier `plat/hyperlight` no longer boots: rebuild it against this kernel tree. `plat/hyperlight` now selects paging and refuses a build without a boot allocator, and the guest crashes if the canary word at the bottom of its 1 MiB boot stack (the init thread's, which also runs a native `main()` without `LIBUKBOOT_MAINTHREAD`) is found overwritten at the end of boot, at the start of an entry from the host, at the end of a call's entry, or at a shutdown. +- A `NetworkFilter`'s `allows` is asked at each send on a connected UDP socket rather than at its `connect()`, as it already was at an unconnected `sendto()`; a TCP connect is asked about as before. A `BlockList` looks its names up at those sends too, rather than at the UDP `connect()`. +- CI: on the Linux arm64 runner, a failure of the `http-express` demo or of the `smolagents` or `mcp` integration jobs no longer fails the run: under nested virtualization their guest's vCPU wedges (hyperlight-dev/hyperlight#2025), so the nightly is not red for that known cause. They still run and log; macOS, Windows and every other job stay strict. +- CI: a wedged HTTP demo fails once its five-minute wait for an answer runs out (60 tries, each a 3 s request and a 2 s pause), instead of holding its job until the timeout (the Linux arm64 nightly's demos job sat at its 90-minute ceiling): the demo harness captures the server's output to a file instead of a pipe it never drained, and stops the server with a bounded terminate, then kill. ### Fixed +- Under a restricted network policy (`AllowList`, `BlockList` or `Filter`), a name lookup with `AI_ADDRCONFIG`, as Node makes for a connection to a hostname, failed with `getaddrinfo EACCES` (#247): musl probes the address families it can use with a UDP `connect()`, to loopback among others, which the policy refused. A UDP `connect()` sends nothing, so it is no longer checked, and keeps the host's own errors; each send on a connected UDP socket is checked instead, against its peer, after a reconnect or an `AF_UNSPEC` disconnect too, as an unconnected `sendto()` already was. TCP is checked at its connect, as before. - The kernel allocated scratch pages the host reserves at the top of scratch. It now stops below them. - A guest that ran out of scratch during a copy-on-write fault crashed the VM (an unexpected exit) instead of aborting. - On x86, a page fault the kernel could not handle early in boot or in its fault handler ended the guest as if it had finished: a guest function call that hit one looked complete. The guest aborts. diff --git a/Cargo.lock b/Cargo.lock index 05210524..758e5578 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -548,7 +548,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -564,7 +564,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -778,8 +778,9 @@ dependencies = [ [[package]] name = "hyperlight-common" -version = "0.18.0" -source = "git+https://github.com/hyperlight-dev/hyperlight?rev=6c17f7cd4e78b03d77fadf4cfe749d7ede96b7ab#6c17f7cd4e78b03d77fadf4cfe749d7ede96b7ab" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8255ebc8f04272f64137e19f5c42cdcc1c92df56a63df964d258923c553add6" dependencies = [ "anyhow", "bitflags 2.13.1", @@ -797,8 +798,9 @@ dependencies = [ [[package]] name = "hyperlight-host" -version = "0.18.0" -source = "git+https://github.com/hyperlight-dev/hyperlight?rev=6c17f7cd4e78b03d77fadf4cfe749d7ede96b7ab#6c17f7cd4e78b03d77fadf4cfe749d7ede96b7ab" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48ed7feb4bdb2ea3fe07de299f9fb1cbc4246c91991d6ccc2a29eb387f7c7625" dependencies = [ "anyhow", "bindgen", @@ -845,7 +847,7 @@ dependencies = [ [[package]] name = "hyperlight-unikraft" -version = "0.20.1" +version = "0.21.0" dependencies = [ "anyhow", "bytes", @@ -1186,7 +1188,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1502,7 +1504,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -1783,7 +1785,7 @@ dependencies = [ "getrandom 0.4.3", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -2120,7 +2122,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index ab27425c..2b3f84a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hyperlight-unikraft" -version = "0.20.1" +version = "0.21.0" edition = "2024" description = "Run ordinary Linux programs inside Hyperlight micro-VMs using a Unikraft unikernel as the guest kernel — the hluk CLI and library." license = "Apache-2.0" @@ -38,7 +38,7 @@ mshv = ["hyperlight-host/mshv3"] cpio = ["dep:tar"] [dependencies] -hyperlight-common = "0.18" +hyperlight-common = "0.19" serde_json = "1" thiserror = "2" tracing = "0.1" @@ -85,12 +85,12 @@ sha2 = { version = "0.11", optional = true } # Windows — WHP, compiled in unconditionally for the target (no feature). # macOS — Hypervisor.framework via the default `hvf` feature. [target.'cfg(target_os = "linux")'.dependencies] -hyperlight-host = { version = "0.18", default-features = false, features = ["kvm", "build-metadata"] } +hyperlight-host = { version = "0.19", default-features = false, features = ["kvm", "build-metadata"] } # Non-Linux keeps hyperlight's defaults: HVF (macOS) is on, WHP (Windows) is # unconditional, and the Linux-only kvm/mshv3 features are inert here. [target.'cfg(not(target_os = "linux"))'.dependencies] -hyperlight-host = "0.18" +hyperlight-host = "0.19" [target.'cfg(windows)'.dependencies] # Private working set for the bench RSS line (already in the tree via clap). @@ -103,10 +103,3 @@ tracing-subscriber = { version = "0.3", default-features = false, features = ["r # The FlatBuffer decoder's external-value source, mirrored in the tests. anyhow = "1" bytes = "1" - -# hyperlight main, for scratch resize (#1947) and scratch_allocated_bytes -# (#2019). crates.io takes no git dependency, so hyperlight-unikraft is not -# published until a hyperlight release replaces this. -[patch.crates-io] -hyperlight-host = { git = "https://github.com/hyperlight-dev/hyperlight", rev = "6c17f7cd4e78b03d77fadf4cfe749d7ede96b7ab" } -hyperlight-common = { git = "https://github.com/hyperlight-dev/hyperlight", rev = "6c17f7cd4e78b03d77fadf4cfe749d7ede96b7ab" } diff --git a/build.rs b/build.rs index 651caafa..030a8902 100644 --- a/build.rs +++ b/build.rs @@ -11,7 +11,7 @@ use std::path::{Path, PathBuf}; use sha2::{Digest, Sha256}; /// The host side of the guest contract: the host functions and their -/// meaning, the virtqueue pool sizes, the heap, scratch and initrd layout, +/// meaning, the virtqueue pool sizes, the scratch and initrd layout, /// the guest MSR list, and the hyperlight-host release that reads a /// snapshot. Bump it when any of those changes in a way a snapshot would /// notice; a kernel change rolls the key by itself. diff --git a/defconfig-elfloader b/defconfig-elfloader index d51c437c..106bc38c 100644 --- a/defconfig-elfloader +++ b/defconfig-elfloader @@ -1,8 +1,7 @@ CONFIG_UK_NAME="elfloader" CONFIG_PLAT_HYPERLIGHT=y -# Paging + vmem (must be explicit — elfloader's imply doesn't stick) -CONFIG_LIBUKPAGING=y -CONFIG_LIBUKFALLOC=y +# PLAT_HYPERLIGHT selects paging. +# vmem must be explicit (elfloader's imply doesn't stick). CONFIG_LIBUKVMEM=y CONFIG_LIBUKVMEM_DEFAULT_BASE=0x0000001000000000 CONFIG_LIBUKVMEM_DEMAND_PAGE_IN_SIZE=12 diff --git a/demos/pptx-gen/Cargo.lock b/demos/pptx-gen/Cargo.lock index 4d08ecf2..9c5492d5 100644 --- a/demos/pptx-gen/Cargo.lock +++ b/demos/pptx-gen/Cargo.lock @@ -623,7 +623,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -656,7 +656,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -1046,8 +1046,9 @@ dependencies = [ [[package]] name = "hyperlight-common" -version = "0.18.0" -source = "git+https://github.com/hyperlight-dev/hyperlight?rev=6c17f7cd4e78b03d77fadf4cfe749d7ede96b7ab#6c17f7cd4e78b03d77fadf4cfe749d7ede96b7ab" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8255ebc8f04272f64137e19f5c42cdcc1c92df56a63df964d258923c553add6" dependencies = [ "anyhow", "bitflags 2.13.1", @@ -1065,8 +1066,9 @@ dependencies = [ [[package]] name = "hyperlight-host" -version = "0.18.0" -source = "git+https://github.com/hyperlight-dev/hyperlight?rev=6c17f7cd4e78b03d77fadf4cfe749d7ede96b7ab#6c17f7cd4e78b03d77fadf4cfe749d7ede96b7ab" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48ed7feb4bdb2ea3fe07de299f9fb1cbc4246c91991d6ccc2a29eb387f7c7625" dependencies = [ "anyhow", "bindgen", @@ -1127,7 +1129,7 @@ dependencies = [ [[package]] name = "hyperlight-unikraft" -version = "0.20.1" +version = "0.21.0" dependencies = [ "cap-fs-ext", "cap-std", @@ -1309,7 +1311,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20fd6de4ccfcc187e38bc21cfa543cb5a302cb86a8b114eb7f0bf0dc9f8ac00f" dependencies = [ "io-lifetimes 3.0.1", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1601,7 +1603,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1828,7 +1830,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -2094,7 +2096,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -2494,7 +2496,7 @@ dependencies = [ "getrandom 0.4.3", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -3060,7 +3062,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] diff --git a/demos/pptx-gen/Cargo.toml b/demos/pptx-gen/Cargo.toml index 1e240380..f4d33fc3 100644 --- a/demos/pptx-gen/Cargo.toml +++ b/demos/pptx-gen/Cargo.toml @@ -15,10 +15,3 @@ dotenvy = "0.15" anyhow = "1" tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } - -# hyperlight main, for scratch resize (#1947) and scratch_allocated_bytes -# (#2019). crates.io takes no git dependency, so hyperlight-unikraft is not -# published until a hyperlight release replaces this. -[patch.crates-io] -hyperlight-host = { git = "https://github.com/hyperlight-dev/hyperlight", rev = "6c17f7cd4e78b03d77fadf4cfe749d7ede96b7ab" } -hyperlight-common = { git = "https://github.com/hyperlight-dev/hyperlight", rev = "6c17f7cd4e78b03d77fadf4cfe749d7ede96b7ab" } diff --git a/docs/manifest.md b/docs/manifest.md index 9313e1ea..02e15967 100644 --- a/docs/manifest.md +++ b/docs/manifest.md @@ -27,18 +27,18 @@ Where the rootfs comes from decides the next step: ## The published images and the cache -Every release publishes each runtime's rootfs to `ghcr.io/hyperlight-dev/hyperlight-unikraft/` in two forms (see [RELEASE.md](RELEASE.md)): `:initrd-v` is the runnable CPIO, `:v` the filesystem image a Dockerfile builds `FROM`. A rootfs is tied to the release of `hluk` it was built with, because the two share the driver protocol, so `hluk init` pins both tags to its own version: a project made by `hluk` 0.20.1 names `python:initrd-v0.20.1` and `python-shell:v0.20.1`, and keeps working when a newer `hluk` is installed until you choose to move it. A build of an unreleased `hluk` has no published rootfs; the error says so and points at `just build-rootfs` and `[rootfs] path`. A dev build of `hluk` (the `dev` pre-release, see [RELEASE.md](RELEASE.md#dev-builds)) pins the images of its own commit, `:initrd-dev-` and `:dev-`, which the channel keeps for its last two builds: a project made by an older one names images that are gone, and `hluk init` with the current one starts it afresh. +Every release publishes each runtime's rootfs to `ghcr.io/hyperlight-dev/hyperlight-unikraft/` in two forms (see [RELEASE.md](RELEASE.md)): `:initrd-v` is the runnable CPIO, `:v` the filesystem image a Dockerfile builds `FROM`. A rootfs is tied to the release of `hluk` it was built with, because the two share the driver protocol, so `hluk init` pins both tags to its own version: a project made by `hluk` 0.21.0 names `python:initrd-v0.21.0` and `python-shell:v0.21.0`, and keeps working when a newer `hluk` is installed until you choose to move it. A build of an unreleased `hluk` has no published rootfs; the error says so and points at `just build-rootfs` and `[rootfs] path`. A dev build of `hluk` (the `dev` pre-release, see [RELEASE.md](RELEASE.md#dev-builds)) pins the images of its own commit, `:initrd-dev-` and `:dev-`, which the channel keeps for its last two builds: a project made by an older one names images that are gone, and `hluk init` with the current one starts it afresh. -`hluk` pulls the image itself: the anonymous token, the manifest and the one layer, checked against its digest and unpacked, with no Docker on the host. So a project runs wherever `hluk` does, Windows and macOS included. Pulled images land in a cache shared by every project, `$HLUK_CACHE_DIR` if set, else `$XDG_CACHE_HOME/hluk` or `~/.cache/hluk` on Unix and `%LOCALAPPDATA%\hluk\cache` on Windows, laid out by reference: `rootfs/ghcr.io/hyperlight-dev/hyperlight-unikraft/python/initrd-v0.20.1.cpio`. `hluk pull` asks the registry again and re-downloads a tag whose layer changed; `hluk run` takes what is cached. +`hluk` pulls the image itself: the anonymous token, the manifest and the one layer, checked against its digest and unpacked, with no Docker on the host. So a project runs wherever `hluk` does, Windows and macOS included. Pulled images land in a cache shared by every project, `$HLUK_CACHE_DIR` if set, else `$XDG_CACHE_HOME/hluk` or `~/.cache/hluk` on Unix and `%LOCALAPPDATA%\hluk\cache` on Windows, laid out by reference: `rootfs/ghcr.io/hyperlight-dev/hyperlight-unikraft/python/initrd-v0.21.0.cpio`. `hluk pull` asks the registry again and re-downloads a tag whose layer changed; `hluk run` takes what is cached. -`--registry` (or `HLUK_REGISTRY`) points `init` at another registry laid out the same way, such as a fork's; the image references it writes are complete, so `run` and `pull` need no flag. `--image-version` (or `HLUK_IMAGE_VERSION`) pins another release's images instead of this build's, which is how a build between releases, with no published images of its own, starts a project: `hluk init --image-version 0.20.1` works for as long as the driver protocol has not changed since that release. +`--registry` (or `HLUK_REGISTRY`) points `init` at another registry laid out the same way, such as a fork's; the image references it writes are complete, so `run` and `pull` need no flag. `--image-version` (or `HLUK_IMAGE_VERSION`) pins another release's images instead of this build's, which is how a build between releases, with no published images of its own, starts a project: `hluk init --image-version 0.21.0` works for as long as the driver protocol has not changed since that release. ## Extending a rootfs The published images are minimal on purpose: the interpreter, its standard library, the driver. A project that needs packages says so in a Dockerfile that starts `FROM` the published base and adds them; `hluk build` builds it with Docker, exports the image's filesystem and converts it to the CPIO the kernel takes, with the `/etc` files `docker export` empties (`hosts`, `nsswitch.conf`, `resolv.conf`) put back. The `http-python` template is the pattern for pip: ```dockerfile -FROM ghcr.io/hyperlight-dev/hyperlight-unikraft/python-shell:v0.20.1 AS base +FROM ghcr.io/hyperlight-dev/hyperlight-unikraft/python-shell:v0.21.0 AS base # pip runs in a real Linux stage; the rootfs is FROM scratch and has no shell. FROM python:3.12-slim-bookworm AS installer @@ -72,7 +72,7 @@ manifest_version = 1 # the format; this hluk reads 1 name = "hello" # letters, digits, `-`, `_` [rootfs] # exactly one of: -image = "ghcr.io/hyperlight-dev/hyperlight-unikraft/python:initrd-v0.20.1" +image = "ghcr.io/hyperlight-dev/hyperlight-unikraft/python:initrd-v0.21.0" # dockerfile = "Dockerfile" # built by `hluk build` into .hluk/rootfs.cpio # path = "build-elfloader/python-rootfs.cpio" @@ -105,7 +105,7 @@ The guest is Linux on the host's CPU, so what `[build]` compiles must be a Linux ### Memory -A guest's memory is `scratch_mb` when the manifest sets it. Otherwise it is the size the runtime's image is tested and benchmarked with, which `hluk` carries as a table (the justfile's `scratch_*`): c, rust and quickjs 64 MiB, go and php 128, bash, python, python-shell, dotnet-aot and wasmtime 256, node and java 512, dotnet-jit 768, powershell 1024, agent 1536. The runtime is read from the image's name when `[rootfs] image` is a published one (`…/agent:initrd-v0.20.1`), and otherwise from the runtime the rootfs names in `etc/hluk-runtime` (the `agent` image writes it, so a rootfs `FROM` agent gets 1536), else from the driver found in the rootfs (a Dockerfile rootfs `FROM` the python-shell base carries `hl_pywarmdriver`, so it gets python-shell's 256); an image with no driver `hluk` knows gets 256. `hluk run` without `--scratch-mb` does the same by marker and driver, and so does a `SandboxBuilder` that never called `scratch_mb`; `default_scratch_mb`, `runtime_scratch_mb` and `RUNTIME_SCRATCH_MB` are the library's. The rootfs is unpacked into that memory, so a rootfs that packages have grown past it fails to unpack: `hluk build` and `hluk run` say so, with a size to set, whenever the rootfs takes more than half of the memory it would get. +A guest's memory is `scratch_mb` when the manifest sets it. Otherwise it is the size the runtime's image is tested and benchmarked with, which `hluk` carries as a table (the justfile's `scratch_*`): c, rust and quickjs 64 MiB, go and php 128, bash, python, python-shell, dotnet-aot and wasmtime 256, node and java 512, dotnet-jit 768, powershell 1024, agent 1536. The runtime is read from the image's name when `[rootfs] image` is a published one (`…/agent:initrd-v0.21.0`), and otherwise from the runtime the rootfs names in `etc/hluk-runtime` (the `agent` image writes it, so a rootfs `FROM` agent gets 1536), else from the driver found in the rootfs (a Dockerfile rootfs `FROM` the python-shell base carries `hl_pywarmdriver`, so it gets python-shell's 256); an image with no driver `hluk` knows gets 256. `hluk run` without `--scratch-mb` does the same by marker and driver, and so does a `SandboxBuilder` that never called `scratch_mb`; `default_scratch_mb`, `runtime_scratch_mb` and `RUNTIME_SCRATCH_MB` are the library's. The rootfs is unpacked into that memory, so a rootfs that packages have grown past it fails to unpack: `hluk build` and `hluk run` say so, with a size to set, whenever the rootfs takes more than half of the memory it would get. Under a memory limit (a pod's or a container's, or a systemd slice's `MemoryMax`), `--scratch-mb max`, or `scratch_mb = "max"` in the manifest, gives the guest what the limit leaves once `hluk` has 64 MiB for itself, with a note, so a pod that runs `hluk run` in its image names the size once, as its limit. Every other size, the manifest's, the flag's or the tested default, stands as before, since the guest's memory is backed as it is touched: a guest sized past the limit runs until it uses more than the limit leaves, and `hluk run`, `hluk snapshot save` and `hluk snapshot run` say so with a note, as the host's kernel kills it then without a word. A run that saves a snapshot, `--warm` or `hluk snapshot save`, is told instead when the limit holds the guest but may not hold its snapshot too, as the save builds it in memory, about as much again as the guest has used; `max` on such a run is that case, so a pod that warms its guest wants a limit of twice what the guest will use. `--scratch-mb max` is an error with no limit to take it from; a manifest's `max`, written for the pod, falls back to the tested size elsewhere with a note, as `hluk build` does. The limit is the memory cgroup's (`memory.max`, or `memory.limit_in_bytes` under cgroup v1, whose hierarchy may be mounted under all its controllers' names), the tightest in sight: the process's own cgroup's, and its ancestors' up to where the hierarchy is mounted (`/proc/self/mountinfo` says where, and from which of its directories): the whole of it on a host, a container's own cgroup inside one, where a cgroup made for a child counts first. A snapshot records its guest's size, which the note on `hluk snapshot run` goes by. `cgroup_memory_limit_mb`, `scratch_mb_within`, `CONTAINER_SCRATCH_HEADROOM_MB` and `snapshot_scratch_mb` are the library's; a `SandboxBuilder` is not sized by the limit. diff --git a/docs/templates.md b/docs/templates.md index 00879777..b59552d5 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -42,9 +42,9 @@ Five strings are replaced in every file, and nothing else is touched, so `{{` th | Placeholder | Becomes | |---|---| | `{{name}}` | the project name (`hluk init myapp` → `myapp`) | -| `{{image}}` | the runnable rootfs of `runtime`: `ghcr.io/hyperlight-dev/hyperlight-unikraft/python:initrd-v0.20.1` | -| `{{base}}` | the same rootfs as a filesystem image to build `FROM`: `…/python:v0.20.1` | -| `{{version}}` | the release those images are pinned to: `0.20.1`, or `dev-44ee170` for a dev build | +| `{{image}}` | the runnable rootfs of `runtime`: `ghcr.io/hyperlight-dev/hyperlight-unikraft/python:initrd-v0.21.0` | +| `{{base}}` | the same rootfs as a filesystem image to build `FROM`: `…/python:v0.21.0` | +| `{{version}}` | the release those images are pinned to: `0.21.0`, or `dev-44ee170` for a dev build | | `{{registry}}` | the registry they come from: `ghcr.io/hyperlight-dev/hyperlight-unikraft` | The version is the `hluk` that ran `init` (or its `--image-version`), not the one the template was written for, because a rootfs has to match the `hluk` that runs it. Write `image = "{{image}}"` in the manifest and `FROM {{base}}` in a Dockerfile rather than a fixed tag, and the template keeps working as `hluk` moves on. diff --git a/install.ps1 b/install.ps1 index 521bd64d..a7470325 100644 --- a/install.ps1 +++ b/install.ps1 @@ -2,7 +2,7 @@ # # irm https://raw.githubusercontent.com/hyperlight-dev/hyperlight-unikraft/main/install.ps1 | iex # -# $env:HLUK_VERSION = 'v0.20.1' a release instead of the latest +# $env:HLUK_VERSION = 'v0.21.0' a release instead of the latest # $env:HLUK_VERSION = 'dev' the dev build: main's latest push that passed CI # $env:HLUK_INSTALL_DIR = 'DIR' where hluk.exe goes (default %LOCALAPPDATA%\hluk\bin) # diff --git a/install.sh b/install.sh index f2520f4b..e3dd935e 100755 --- a/install.sh +++ b/install.sh @@ -3,7 +3,7 @@ # # curl -fsSL https://raw.githubusercontent.com/hyperlight-dev/hyperlight-unikraft/main/install.sh | sh # -# HLUK_VERSION=v0.20.1 a release instead of the latest +# HLUK_VERSION=v0.21.0 a release instead of the latest # HLUK_VERSION=dev the dev build: main's latest push that passed CI # HLUK_INSTALL_DIR=DIR where the binary goes (default ~/.local/bin) # diff --git a/integrations/clickhouse/Cargo.lock b/integrations/clickhouse/Cargo.lock index 453c3745..fb0285f3 100644 --- a/integrations/clickhouse/Cargo.lock +++ b/integrations/clickhouse/Cargo.lock @@ -436,7 +436,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -446,7 +446,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -606,8 +606,9 @@ dependencies = [ [[package]] name = "hyperlight-common" -version = "0.18.0" -source = "git+https://github.com/hyperlight-dev/hyperlight?rev=6c17f7cd4e78b03d77fadf4cfe749d7ede96b7ab#6c17f7cd4e78b03d77fadf4cfe749d7ede96b7ab" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8255ebc8f04272f64137e19f5c42cdcc1c92df56a63df964d258923c553add6" dependencies = [ "anyhow", "bitflags 2.13.2", @@ -625,8 +626,9 @@ dependencies = [ [[package]] name = "hyperlight-host" -version = "0.18.0" -source = "git+https://github.com/hyperlight-dev/hyperlight?rev=6c17f7cd4e78b03d77fadf4cfe749d7ede96b7ab#6c17f7cd4e78b03d77fadf4cfe749d7ede96b7ab" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48ed7feb4bdb2ea3fe07de299f9fb1cbc4246c91991d6ccc2a29eb387f7c7625" dependencies = [ "anyhow", "bindgen", @@ -673,7 +675,7 @@ dependencies = [ [[package]] name = "hyperlight-unikraft" -version = "0.20.1" +version = "0.21.0" dependencies = [ "cap-fs-ext", "cap-std", @@ -1249,7 +1251,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1455,7 +1457,7 @@ dependencies = [ "getrandom", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1654,7 +1656,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] diff --git a/integrations/clickhouse/Cargo.toml b/integrations/clickhouse/Cargo.toml index 212fc466..f17f82bc 100644 --- a/integrations/clickhouse/Cargo.toml +++ b/integrations/clickhouse/Cargo.toml @@ -27,10 +27,3 @@ thiserror = "2" [dev-dependencies] tempfile = "3" - -# hyperlight main, for scratch resize (#1947) and scratch_allocated_bytes -# (#2019). crates.io takes no git dependency, so hyperlight-unikraft is not -# published until a hyperlight release replaces this. -[patch.crates-io] -hyperlight-host = { git = "https://github.com/hyperlight-dev/hyperlight", rev = "6c17f7cd4e78b03d77fadf4cfe749d7ede96b7ab" } -hyperlight-common = { git = "https://github.com/hyperlight-dev/hyperlight", rev = "6c17f7cd4e78b03d77fadf4cfe749d7ede96b7ab" } diff --git a/justfile b/justfile index ba0d7529..75097842 100644 --- a/justfile +++ b/justfile @@ -471,12 +471,21 @@ changelog-notes version: grab { print } ' "{{root_dir}}/CHANGELOG.md" | sed -e '/./,$!d' | sed -e :strip -e '/^\n*$/{$d;N;bstrip}' # Plus GitHub's auto-generated PR list, stripped of its own heading. From - # the last release's tag, named outright: left to choose, GitHub could - # take the `dev` pre-release's, which points at main too. + # the release before this one, named outright: left to choose, GitHub could + # take the `dev` pre-release's, which points at main too. hluk's releases + # are the `vX.Y.Z` tags; the Python packages tag `-v`, + # and `v*` would take `verl-hyperlight-v0.1.1` for one. Sorted field by + # field with `sort -t. -k1,1n -k2,2n -k3,3n` rather than `sort -V`, which + # older macOS lacks. if [ "{{version}}" != "Prerelease" ] && command -v gh >/dev/null 2>&1; then - prev="$(git -C "{{root_dir}}" tag -l 'v*' --sort=-v:refname | grep -vx "{{version}}" | head -1)" || true + ver="{{trim_start_match(version, "v")}}" + tag="v$ver" + prev="$(git -C "{{root_dir}}" tag -l 'v[0-9]*' | sed 's/^v//' \ + | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' | grep -Fvx "$ver" \ + | { cat; echo "$ver"; } | sort -t. -k1,1n -k2,2n -k3,3n \ + | grep -Fx -B1 "$ver" | grep -Fvx "$ver" | sed 's/^/v/')" || true prs="$(gh api "repos/{owner}/{repo}/releases/generate-notes" \ - -f tag_name="{{version}}" ${prev:+-f previous_tag_name="$prev"} \ + -f tag_name="$tag" ${prev:+-f previous_tag_name="$prev"} \ --jq '.body' 2>/dev/null | sed '1{/^## /d;}')" || true if [ -n "${prs:-}" ]; then printf '\n## Pull requests\n\n%s\n' "$prs" diff --git a/kernel/elfloader_hyperlight-arm64 b/kernel/elfloader_hyperlight-arm64 index bae5f69c..a9e1f0b1 100755 Binary files a/kernel/elfloader_hyperlight-arm64 and b/kernel/elfloader_hyperlight-arm64 differ diff --git a/kernel/elfloader_hyperlight-x86_64 b/kernel/elfloader_hyperlight-x86_64 index a6fc4313..ed860344 100755 Binary files a/kernel/elfloader_hyperlight-x86_64 and b/kernel/elfloader_hyperlight-x86_64 differ diff --git a/kernel/unikraft b/kernel/unikraft index 9f414729..3b7cba88 160000 --- a/kernel/unikraft +++ b/kernel/unikraft @@ -1 +1 @@ -Subproject commit 9f41472980edd6a93d2ec5f2a0e5f8f445d786d3 +Subproject commit 3b7cba8816c02a497e7b5aa9c901655784a01000 diff --git a/src/lib.rs b/src/lib.rs index 215f547f..5fcf088d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -598,13 +598,6 @@ impl GuestOutput { } } -/// PEB heap size. -/// -/// Only needed for the boot stack (allocated before `ukplat_mem_init`). -/// Can be dropped to 0 once the guest allocates the boot stack from -/// scratch instead. -const HEAP_SIZE: u64 = 0x10_0000; // 1 MiB - /// What a snapshot depends on, as a tag suffix `k-c`: /// the embedded kernel's SHA-256 (its first 16 hex digits; the kernel's /// code and host-call protocol are in the snapshot's memory) and the host @@ -2155,7 +2148,6 @@ fn assemble_sandbox( info!(scratch_mb, "guest memory"); let mut cfg = SandboxConfiguration::default(); cfg.set_scratch_size(scratch_size); - cfg.set_heap_size(HEAP_SIZE); apply_transport(&mut cfg); if let Some(level) = guest_log_level { cfg.set_max_guest_log_level(level); @@ -3448,7 +3440,6 @@ fn restore_snapshot( // it override scratch. let mut sbcfg = SandboxConfiguration::default(); apply_transport(&mut sbcfg); - sbcfg.set_heap_size(HEAP_SIZE); apply_guest_msrs(&mut sbcfg)?; if let Some(level) = guest_log_level { sbcfg.set_max_guest_log_level(level); diff --git a/tests/fixtures/native-kernel/README.md b/tests/fixtures/native-kernel/README.md index d9241bdd..0de0d056 100644 --- a/tests/fixtures/native-kernel/README.md +++ b/tests/fixtures/native-kernel/README.md @@ -27,5 +27,5 @@ The build invokes `make -C kernel/unikraft A=` directly (no per-app `Makefi - `helloworld.c` — the native app (`main()` prints a greeting, and a line to stderr) - `Makefile.uk` — Unikraft app build rules (registers `helloworld.c`) -- `defconfig` — native Hyperlight config (paging + vmem + posix-environ, no elfloader app) +- `defconfig` — native Hyperlight config (vmem + posix-environ, no elfloader app; `plat/hyperlight` selects paging) - `helloworld-native_hyperlight-x86_64` — the prebuilt kernel the test loads diff --git a/tests/fixtures/native-kernel/defconfig b/tests/fixtures/native-kernel/defconfig index a6372895..66f01c69 100644 --- a/tests/fixtures/native-kernel/defconfig +++ b/tests/fixtures/native-kernel/defconfig @@ -1,7 +1,5 @@ CONFIG_UK_NAME="helloworld-native" CONFIG_PLAT_HYPERLIGHT=y -CONFIG_LIBUKPAGING=y -CONFIG_LIBUKFALLOC=y CONFIG_LIBUKVMEM=y CONFIG_LIBUKVMEM_DEFAULT_BASE=0x0000001000000000 CONFIG_LIBUKVMEM_DEMAND_PAGE_IN_SIZE=12 diff --git a/tests/fixtures/native-kernel/helloworld-native_hyperlight-x86_64 b/tests/fixtures/native-kernel/helloworld-native_hyperlight-x86_64 index 7094853b..89d146b0 100755 Binary files a/tests/fixtures/native-kernel/helloworld-native_hyperlight-x86_64 and b/tests/fixtures/native-kernel/helloworld-native_hyperlight-x86_64 differ