Repository navigation
Let the sandbox override uname fields - #335
Merged
Merged
Conversation
congwang-mk
force-pushed
the
uname-override
branch
from
October 29, 2026 21:48
cd93768 to
b3921ec
Compare
The sandbox name replaces the host name in uname() and /etc/hostname, but /proc/sys/kernel/hostname still returned the real host name, so a plain cat undid the virtualization. Serve it from the same virtual file as /etc/hostname so every channel reports one name. Signed-off-by: Cong Wang <cwang@multikernel.io>
congwang-mk
force-pushed
the
uname-override
branch
from
October 30, 2026 17:15
b3921ec to
a7857ef
Compare
Uname lets a sandbox report its own kernel identity (release, version, sysname, machine, domainname) in place of the host's, for hiding host details and for reproducible builds. One fact reaches a process through several channels, so each override also answers the procfs file that repeats it (/proc/sys/kernel/*, /proc/version); patching uname() alone would be contradicted by a plain cat. /proc/version is built from the fields alone, without the host's compiler banner, which names the build host and would keep the file differing across machines. Signed-off-by: Cong Wang <cwang@multikernel.io>
Expose the uname override on the command line as a repeatable FIELD=VALUE flag, matching --env. It needs the supervisor to answer uname() and the procfs files, so --no-supervisor rejects it like the other supervisor-mediated options. Signed-off-by: Cong Wang <cwang@multikernel.io>
Python callers declare the override as a field-to-value mapping,
uname={"release": "8.0.0"}, the same shape as env. Each entry crosses
the FFI through a new sandlock_sandbox_builder_uname setter, so field
names and lengths are checked once, in the core builder.
Signed-off-by: Cong Wang <cwang@multikernel.io>
Profiles describe the same policy as the builder, so the uname override gets a [uname] table keyed by utsname field. Unknown keys are rejected by serde and lengths by the builder, which now checks Uname on every build so a profile cannot bypass the per-field setter. A CLI --uname still overrides a profile value field by field. Signed-off-by: Cong Wang <cwang@multikernel.io>
Go callers get the uname override as a field-to-value map, the shape Env and the Python SDK already use, and ParseProfile carries a profile's [uname] table through instead of refusing it as a field Go cannot express. Field names and lengths stay checked in the core. Signed-off-by: Cong Wang <cwang@multikernel.io>
congwang-mk
force-pushed
the
uname-override
branch
from
October 30, 2026 17:31
a7857ef to
4134b47
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Let a sandbox report its own kernel identity in place of the host's:
Fields are
sysname,release,version,machineanddomainname; unset fields pass the host's value through.nodenamestays the sandbox name.Use cases
Reproducible builds. Builds that record the build kernel produce different artifacts on CI runners with different kernels. Common examples are configure logs and generated headers that capture
uname -a, Perl'sConfig.pm(osvers) and build-info stamps. reprotest, the Debian Reproducible Builds checker, treats this as a variation source: itskernelvariation changes the reported uname (viasetarch --uname-2.6) to catch builds that leak it. Pinningreleaseandversionremoves that variation. Together with features sandlock already has, a sandbox now covers several of reprotest's variations:kerneluname(this PR)domain_hostname(hostname) +unamedomainnametimetime_startfileorderingdeterministic_dirsnum_cpusnum_cpusHiding host details. A multi-tenant or agent sandbox no longer reveals the host's exact kernel build string through
uname.This is not an exploit mitigation. Kernel behavior (which syscalls exist, the Landlock ABI, the vDSO) still reveals the real kernel, and reducing attack surface through seccomp remains the actual defense.
Design
One fact reaches a process through several channels, so each override also answers the procfs file that repeats it:
/proc/sys/kernel/{ostype,osrelease,version,arch,domainname}and/proc/version. Otherwise a plaincatwould contradictuname()./proc/versionis built from the fields alone, without the host's compiler banner: the banner names the build host and differs across machines, so keeping it would defeat reproducibility.This is a policy field rather than something users build with
run_with_handlers. Built-in handlers run first and cannot be overridden, and the built-inunamehandler always answers (it supplies the nodename), so a user handler onunamenever runs. Under chroot/COW the built-in path handler answers every open first, so a useropenathandler could not serve the procfs files either. The field is implemented as built-in handlers in the same dispatch table, which also makes it available from the CLI, profiles and Go, none of which have the handler API.Validation lives in the core builder: unknown fields,
nodename, values over 64 bytes (utsnamefields arechar[65]) and NULs are rejected, and--no-supervisorrefuses the option.While probing this,
/proc/sys/kernel/hostnameturned out to leak the real host name even thoughuname -nand/etc/hostnameshow the sandbox name. The first commit fixes that on its own.Test plan
Unamevalidation,/proc/versionrendering,utsnamefield truncation, profile round trip and rejectiontest_uname_overridechecksuname -r/-v/-magainst/proc/sys/kernel/{osrelease,version,arch}and/proc/version;test_hostname_virtualizationcovers/proc/sys/kernel/hostnameTestUname(override plus unknown field rejection)TestUnameOverride,TestParseProfileMapsFieldswith[uname][uname]merged with a field-wise--unameoverride;--no-supervisorrejection🤖 Generated with Claude Code