Skip to content

Fix guest file, console and call bugs; kernel messages as Hyperlight's guest log - #180

Merged
danbugs merged 9 commits into
mainfrom
exec-fixes
Oct 22, 2026
Merged

danbugs merged 9 commits into
mainfrom
exec-fixes

Conversation

@danbugs

@danbugs danbugs commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Fixes to the guest's files, console and calls, found running hluk once per command and reading what comes back. The kernel side is on plat-hyperlight-v2; its generic fixes (vfscore, ukconsole, ukprint, posix-tty) were reproduced and checked on stock QEMU/KVM, where the console changes leave the output unchanged.

  • Mounted files: stat gives the host's mode bits and times, and os.utime sets times. An FsBackend reports times through FileStat::times and sets them through set_times, ignored by default.
  • Paths: mkdir -p, the working directory at a mount's root, and mount paths with trailing slashes work.
  • The kernel's messages are Hyperlight's guest log (target hyperlight_guest, with library, file and line) instead of the program's stderr, so a failed exec no longer adds ERR: lines to its output. SandboxBuilder::guest_log_level sets the level, --log-level shows them, and the CLI still prints them when hluk itself fails.
  • The console is a terminal only where the output reaches one, so isatty, prompts and echo behave as on Linux; drivers keep stdout line-buffered.
  • Guest function calls carry up to 1 MiB, from about 72 KB; a larger one fails with Error::CallTooLarge before it is sent.
  • The exec driver says why it cannot run a program, and dispatch callback failed is printed only for the driver's own failure.

Copilot AI balanced review requested due to automatic review settings October 21, 2026 21:27
@danbugs danbugs added the ci/arm64 Run the arm64 guest tests (self-hosted KVM and HVF runners) label Oct 21, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The cross-platform host–kernel protocol, transport, and snapshot-sensitive console changes warrant human review of companion-kernel integration results.

No open issues 🎉

What changed in this PR

Updates Hyperlight–Unikraft’s host support and runtime drivers to improve mounted-file behavior, console handling, guest logging, and call capacity alongside the companion kernel changes.

Changes:

  • Adds mounted-file timestamps and host permission bits, strips setuid/setgid from chmod requests, and normalizes mount paths.
  • Separates kernel logs from program output, adjusts terminal detection and buffering, and improves execution diagnostics.
  • Expands guest calls to roughly 1 MiB with early size checks, updates snapshot compatibility, and adds regression coverage.
File Description
tests/​quickjs.rs Updates oversized-result test limits.
tests/​python.rs Covers filesystem, console, large-call, and failure-output behavior.
tests/​project.rs Clarifies piped REPL behavior in comments.
tests/​compiled.rs Tests diagnostics for unexecutable files.
tests/​common/​mod.rs Adds a guest-log capture helper.
tests/​bash.rs Tests guest logging, encoding, and disabled logging.
templates/​bash-repl/​repl.sh Shows prompts only for terminal input.
src/​main.rs Configures guest logging, retains failure diagnostics, and explains oversized scripts.
src/​lib.rs Expands transport capacity and adds console and logging controls.
src/​hostfs.rs Exposes host metadata and supports safe permission and timestamp updates.
src/​cli/​mod.rs Configures terminal behavior around warm snapshots.
src/​cli/​cpio.rs Checks kernel diagnostics through guest logs.
integrations/​smolagents/​src/​smolagents_hyperlight/​executor.py Clarifies legacy console behavior in comments.
integrations/​clickhouse/​src/​function.rs Clarifies legacy driver diagnostics in comments.
integrations/​clickhouse/​Cargo.lock Locks the filesystem extension dependency.
drivers/​hl_py.h Keeps Python stdout line-buffered.
drivers/​hl_execdriver.c Reports execution errors with appropriate status codes.
drivers/​hl_driver.h Enables line buffering and limits driver-failure messages.
docs/​fs.md Documents metadata and timestamp support.
docs/​driver.md Updates the documented call-buffer capacity.
docs/​calls.md Documents console, logging, and transport behavior.
CHANGELOG.md Records behavior changes and compatibility implications.
Cargo.toml Adds filesystem extensions and test logging support.
Cargo.lock Locks the new filesystem dependency.
build.rs Bumps the snapshot compatibility contract.
.github/​actions/​arm64-host/​action.yml Restores executable permissions on downloaded test binaries.

Review effort: Balanced

@danbugs
danbugs force-pushed the exec-fixes branch 3 times, most recently from e38aa73 to 80b5546 Compare October 21, 2026 23:52
…through fs_set_times

A host directory's files all read mode 755 (555 read-only) and the
epoch for every time.  The directory backend now gives the host's
mode bits (on Windows, from the read-only flag as before) and its
access, modification and status change times, which FileStat carries
(FileStat::times; the epoch for a backend that sets none), and fs_stat
sends them, as seconds and nanoseconds.

FsBackend::set_times sets the access and modification times, ignored by
default like chmod, and the directory backend sets them on the host.
fs_set_times serves it, so the guest's utime family sets a mounted
file's times; it did nothing.  Times before 1970 fail with EINVAL.

Signed-off-by: danbugs <danilochiarlone@gmail.com>
A mount given as `--mount=/h:/g/` reached the kernel as "/g/", which a
restore then did not match against the kernel's own table, which keeps
mount points without them.  Write each mount point without its trailing
slashes (but "/").

Signed-off-by: danbugs <danilochiarlone@gmail.com>
…ror::CallTooLarge

A guest function call carried about 72 KB, so a script any larger
failed in the transport (`H2G capacity cannot provide N buffers`).
Post Hyperlight's default 32 receive buffers at 32 KiB each, so a call
carries up to 1 MiB (`GUEST_CALL_MAX`, and `CALL_PAYLOAD_MAX` of its
strings), and refuse a larger one before it is sent, with
`Error::CallTooLarge`.  `hluk run` says how to run a script past it.

Signed-off-by: danbugs <danilochiarlone@gmail.com>
…utput reaches one

The guest's console was always a terminal, so a program whose output
an embedder captures, or `hluk run` pipes, prompted, coloured its
output and echoed its piped input as on one.  The new kernel asks
ConsoleIsTerminal: standard input and output are a terminal where this
process's stdin and stdout are, standard error where its stderr is,
only while the output is echoed, and only once the embedder allows it
(`AppSandbox::console_terminal`, `SandboxBuilder::console_terminal`),
so what a runtime decides at boot, and keeps in a snapshot, does not
depend on the process that booted it.  `hluk run` allows it for the
workload, and from boot unless the boot ends in a warm snapshot.

Off a terminal, libc and Python buffer standard output whole, so a
call's standard error would come out before what it printed earlier:
the drivers keep standard output line-buffered either way.  The
`bash-repl` template prompts only on a terminal.

Signed-off-by: danbugs <danilochiarlone@gmail.com>
…callback failed" only for the driver's own failure

A program the exec driver could not start (not executable, not a
program) failed the call with nothing said: the kernel's message about
it no longer reaches the output.  Say which and why, as a shell does
(`hl: cannot execute <path>: <reason>`), and fail with 126, or 127 for
a missing file.

The drivers also printed `hl_driver: dispatch callback failed` after a
call that exited with a status of its own, which the program has
explained if it meant to.  Print it only when the driver fails.

Signed-off-by: danbugs <danilochiarlone@gmail.com>
…ght_guest, the CLI's kernel tail

The new kernel sends its messages as Hyperlight's guest log, which the
host logs through `tracing` as target `hyperlight_guest`, rather than
on the guest's standard error.  `SandboxBuilder::guest_log_level` sets
the most verbose level it sends, on a fresh guest and on a restored
one; unset, a fresh guest takes Hyperlight's default and a restored one
its snapshot's.

`hluk --log-level <level>` shows them, and the CLI always passes a
level, so a restored guest does not keep its saver's.  Without
`--log-level`, the CLI keeps the latest 16 KiB of them and prints them
when hluk itself fails, or an entry point writes nothing, so one that
cannot start still says why; not after a workload's own failure,
whose output says what it has to.

Signed-off-by: danbugs <danilochiarlone@gmail.com>
An artifact keeps no file modes, and a mount now gives the guest the
host's, so the test binaries the rootfs-arm64 job built reached the
guest without an execute bit, and the exec driver refused them.

Signed-off-by: danbugs <danilochiarlone@gmail.com>
…APSHOT_CONTRACT 7

The kernel fixes mkdir and rmdir with trailing slashes, the working
directory at a mount's root, mount points with trailing slashes and
umount2's error; hostfs's stat times and utime; the console is a
terminal only where ConsoleIsTerminal says, and behaves as a pipe off
one; and its messages are Hyperlight guest log messages, at the level
the host asks for.  The hostfs reply and the host functions changed, so
snapshots of earlier builds are refused.

Tests for each: mounted files' modes and times, trailing slashes, a
captured console, a large script, failed programs' own words, and the
kernel's messages in the guest log.

Signed-off-by: danbugs <danilochiarlone@gmail.com>
Signed-off-by: danbugs <danilochiarlone@gmail.com>
@danbugs
danbugs merged commit 51a085f into main Oct 22, 2026
151 of 154 checks passed
@danbugs
danbugs deleted the exec-fixes branch October 22, 2026 15:51
cmainas pushed a commit to cmainas/hyperlight-unikraft that referenced this pull request Oct 26, 2026
Bump the crate to 0.19.0 and add the changelog's entries under
[v0.19.0], keeping an empty Unreleased section, with a note that
snapshots saved by 0.18 are refused and locally built images need
rebuilding.  0.19.0 rather than 0.18.1: NetworkPolicy and Mount changed
in ways that break code that matches or builds them, and the guest's
console and kernel messages behave differently.  The snapshot contract
was already bumped with hyperlight-dev#180.  The docs' and install scripts' examples
name the new release; pptx-gen's lock gains cap-fs-ext, which it had
lacked since hyperlight-dev#180.

Signed-off-by: danbugs <danilochiarlone@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/arm64 Run the arm64 guest tests (self-hosted KVM and HVF runners)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants