test: make boot mode work in unprivileged containers
In a mount namespace owned by a non-initial user namespace, the kernel only allows mounting a fresh proc or sysfs if the namespace already contains a fully visible mount of the same filesystem type (mount_too_revealing()). systemd-nspawn's pivoted root contains no such mount, so booting the test container inside an unprivileged container (e.g. a containerized CI runner) fails with EPERM when mounting /proc. When running in a non-initial user namespace, satisfy the check by binding a read-only instance of each into the container under /work. Skipping the binds on regular privileged runs keeps the container isolated from the host's proc and sysfs. Binding non-recursively keeps foreign submounts (e.g. lxcfs overmounts) out, which would spoil full visibility where they end up locked, and which read-only would not cover. Signed-off-by: Paul Meyer <katexochen0@gmail.com>
This commit is contained in:
@@ -365,6 +365,15 @@ def process_coverage(args: argparse.Namespace, summary: Summary, name: str, jour
|
||||
print(f'Wrote coverage report for {name} to {output}', file=sys.stderr)
|
||||
|
||||
|
||||
def in_userns() -> bool:
|
||||
# The initial user namespace has a well-known inode number (USER_NS_INIT_INO, linux/nsfs.h).
|
||||
# Without kernel support for user namespaces, ours can only be the initial one.
|
||||
try:
|
||||
return os.stat('/proc/self/ns/user').st_ino != 0xEFFFFFFD
|
||||
except OSError:
|
||||
return False
|
||||
|
||||
|
||||
def coco_host_type() -> Optional[str]:
|
||||
try:
|
||||
if Path('/sys/module/kvm_intel/parameters/tdx').read_text().strip() == 'Y':
|
||||
@@ -706,7 +715,26 @@ def main() -> None:
|
||||
*(['--runtime-build-sources=no', '--register=no'] if not sys.stdin.isatty() else []),
|
||||
'vm' if vm else 'boot',
|
||||
*(
|
||||
['--', '--capability=CAP_BPF', f'--suppress-sync={"yes" if args.suppress_sync else "no"}', *vm_images_args, *coco_boot_args]
|
||||
[
|
||||
'--',
|
||||
'--capability=CAP_BPF',
|
||||
f'--suppress-sync={"yes" if args.suppress_sync else "no"}',
|
||||
# In a non-initial user namespace the kernel only allows mounting a fresh proc or
|
||||
# sysfs if the mount namespace already contains a fully visible mount of the same
|
||||
# filesystem type (mount_too_revealing()), which nspawn's pivoted root doesn't.
|
||||
# Satisfy the check with read-only binds, but only when actually confined, as
|
||||
# they expose the outer proc and sysfs to the container. Bind non-recursively:
|
||||
# carried-along submounts (e.g. lxcfs overmounts of container runtimes) would
|
||||
# spoil full visibility wherever they end up locked, and --bind-ro wouldn't make
|
||||
# them read-only either.
|
||||
*(
|
||||
['--bind-ro=/proc:/work/proc:norbind', '--bind-ro=/sys:/work/sys:norbind']
|
||||
if in_userns()
|
||||
else []
|
||||
),
|
||||
*vm_images_args,
|
||||
*coco_boot_args,
|
||||
]
|
||||
if not vm
|
||||
else []
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user