ch-runner: run CH in bwrap

Albeit rather relaxed
This commit is contained in:
Else Someone 2026-02-23 06:35:32 +02:00
parent a3ed9cb4ea
commit 04befb6328
3 changed files with 87 additions and 52 deletions

View file

@ -30,6 +30,8 @@ stdenv.mkDerivation {
rustc
];
buildInputs = [ ch-proxy ];
meta.mainProgram = "taps";
}
# { lib, rustPlatform }:
#

View file

@ -278,6 +278,7 @@ in
(lib.getBin package)
(lib.getBin pkgs.virtiofsd)
(lib.getBin pkgs.bubblewrap)
(lib.getBin pkgs.strace)
uvmsPkgs.taps
];
@ -403,7 +404,6 @@ in
**kwargs,
)
@contextmanager
def bwrap(
self,
*bwrap_args,
@ -420,20 +420,26 @@ in
unshare_uts=None,
unshare_cgroup_try=True,
bind=(),
dev_bind=("/dev/kvm", "/dev/vfio"),
dev_bind=(),
dev_bind_implicit=("/dev/kvm", "/dev/vfio"),
dev="/dev",
proc="/proc",
ro_bind=(
ro_bind_implicit=(
"/etc",
"/sys",
"/proc/sys",
"/dev/null",
"/proc/kallsyms",
*CLOSURE),
ro_bind_extra=(),
ro_bind=(),
remount_ro=("/proc/fs", "/proc/irq"),
tmpfs=("/dev/shm", "/tmp", "/var/tmp", "/proc/fs", "/proc/irq"),
tmpfs_extra=(),
tmpfs_implicit=(
"/dev/shm",
"/tmp",
"/var/tmp",
"/proc/fs",
"/proc/irq"),
tmpfs=(),
pass_fds=(2,),
**popen_kwargs):
@ -455,23 +461,29 @@ in
print_arg("--unshare-pid")
if unshare_net:
print_arg("--unshare-net")
elif unshare_net is False:
print_arg("--share-net")
if unshare_uts:
print_arg("--unshare-uts")
if unshare_cgroup_try:
print_arg("--unshare-cgroup-try")
if die_with_parent:
print_arg("--die-with-parent")
if dev:
print_arg("--dev", dev)
if proc:
print_arg("--proc", proc)
for p in bind:
p1, p2 = (p, p) if isinstance(p, str) else p
print_arg("--bind", p1, p2)
for p in (*ro_bind, *ro_bind_extra):
for p in (*ro_bind, *ro_bind_implicit):
p1, p2 = (p, p) if isinstance(p, str) else p
print_arg("--ro-bind", p1, p2)
for p in dev_bind:
for p in (*dev_bind, *dev_bind_implicit):
p1, p2 = (p, p) if isinstance(p, str) else p
print_arg("--dev-bind", p1, p2)
for p in (*tmpfs, *tmpfs_extra):
for p in (*tmpfs, *tmpfs_implicit):
print_arg("--tmpfs", p)
# Hunch: order might matter...
for p in remount_ro:
@ -487,44 +499,48 @@ in
pass_fds=(*pass_fds, remote.fileno()),
)
with proc as p:
try:
yield p
finally:
try:
p.poll()
except: # noqa: E722
pass
if p.returncode is None:
p.terminate()
p.wait()
return proc
@contextmanager
def run_ch(self):
args = [
SOCKETBINDER_PATH,
"-B",
self.prefix + "/vmm.sock",
CH_PATH,
"--api-socket",
"fd=0",
]
p = self.popen(
*args,
shell=False,
stdin=subprocess.DEVNULL,
stdout=subprocess.DEVNULL,
pass_fds=())
try:
p.wait(0.125)
needs_cleanup = False
except subprocess.TimeoutExpired:
needs_cleanup = True
if not os.path.exists(self.prefix + "/vmm.sock"):
raise RuntimeError(f"{self.prefix}/vmm.sock should exist by now")
if p.returncode is not None:
raise RuntimeError("CH exited early")
try:
# s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0)
# s.set_inheritable(True)
# s.setblocking(True)
# s.bind(self.prefix + "/vmm.sock")
args = [
SOCKETBINDER_PATH,
"-B",
self.prefix + "/vmm.sock",
# "${lib.getExe pkgs.strace}", # noqa: E501
# "-Z",
# "-ff",
CH_PATH,
"--api-socket",
"fd=0",
# f"fd={s.fileno()}"
]
p = self.bwrap(
*args,
bind=[self.prefix],
# Probably just need the path to vmlinux
ro_bind=("/nix/store",), # A give up
unshare_net=False,
shell=False,
stderr=None,
# pass_fds=(s.fileno(),)
)
# s.close()
try:
p.wait(0.125)
needs_cleanup = False
except subprocess.TimeoutExpired:
needs_cleanup = True
if not os.path.exists(self.prefix + "/vmm.sock"):
raise RuntimeError(
f"{self.prefix}/vmm.sock should exist by now")
if p.returncode is not None:
raise RuntimeError("CH exited early")
yield p
finally:
try:
@ -598,7 +614,7 @@ in
kwargs = {
# If bwrap():
# "bind": [],
# ("ro_bind_extra" if ro else "bind"):
# ("ro_bind" if ro else "bind"):
# [*subdirs]
# if subdirs is not None
# else [root_dir],

View file

@ -1,13 +1,30 @@
with import <nixpkgs> { };
let
uvmPkgs = callPackage ./pkgs { };
in
mkShell.override { stdenv = stdenvNoCC; } {
packages = map lib.getBin [
cloud-hypervisor
virtiofsd
crosvm # virtio-gpu
npins
] ++ [
man-pages
linux-manual
inputsFrom = with uvmPkgs; [
ch-proxy
taps
writeErofsLayers
request-usb
];
packages =
map lib.getBin [
cloud-hypervisor
virtiofsd
crosvm # virtio-gpu
npins
strace
python3
execline
s6
wayland-proxy-virtwl
uvmPkgs.taps
]
++ [
man-pages
linux-manual
];
}