Skip to content

Commit

Permalink
test: closes #1099 jailer mount propagation by creating mounts for th…
Browse files Browse the repository at this point in the history
…e guest kernel and rootfs and mounting them to the jailer root as mentioned in #1089 Signed-off-by: Anthony Corletti <[email protected]>
  • Loading branch information
anthonycorletti committed Feb 11, 2025
1 parent 3ca2fab commit 6940c7f
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ test_results/*
/resources/linux
/resources/x86_64
/resources/aarch64
.venv
24 changes: 24 additions & 0 deletions tests/framework/microvm.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import select
import shutil
import signal
import subprocess
import time
import uuid
from collections import namedtuple
Expand Down Expand Up @@ -1115,13 +1116,36 @@ def build_from_snapshot(self, snapshot: Snapshot):
vm.restore_from_snapshot(snapshot, resume=True)
return vm

def unmount(self, path: str) -> None:
"""Unmounts a path with `umount` in a subprocess"""
try:
subprocess.run(["umount", path], check=True)
except subprocess.CalledProcessError:
print(f"Failed to unmount {path}")

def get_mounts_at_path(self, path: str) -> list:
"""Get all mounts for a given path. Returns a list of mount points."""
try:
with open("/proc/mounts", "r", encoding="utf-8") as f:
return [
line.split()[1]
for line in f
if line.split()[1].startswith(os.path.abspath(path))
]
except FileNotFoundError:
return False # /proc/mounts may not exist on some systems

def kill(self):
"""Clean up all built VMs"""
for vm in self.vms:
vm.kill()
vm.jailer.cleanup()
chroot_base_with_id = vm.jailer.chroot_base_with_id()
if len(vm.jailer.jailer_id) > 0 and chroot_base_with_id.exists():
mounts = self.get_mounts_at_path(chroot_base_with_id)
if mounts:
for mounted_path in mounts:
self.unmount(mounted_path)
shutil.rmtree(chroot_base_with_id)
vm.netns.cleanup()

Expand Down
73 changes: 73 additions & 0 deletions tests/integration_tests/security/test_jail.py
Original file line number Diff line number Diff line change
Expand Up @@ -664,3 +664,76 @@ def test_cgroupsv2_written_only_once(uvm_plain, cgroups_info):
assert len(write_lines) == 1
assert len(mkdir_lines) != len(cgroups), "mkdir equal to number of cgroups"
assert len(mkdir_lines) == 1


def test_mount_proagation_to_root(uvm_plain, tmp_path, guest_kernel, rootfs_rw):
"""
Test that the jailer mounts are propagated to the root mount namespace.
This is a test for
https://github.com/firecracker-microvm/firecracker/pull/#1093
"""

test_microvm = uvm_plain

# make a directory to hold the original content
original_content_dir = tmp_path / "original"
original_content_dir.mkdir(parents=True)

# make a directory to hold the jailed content
jailed_content_dir = tmp_path / "firecracker" / "testbindmount" / "root"
jailed_content_dir.mkdir(parents=True)

test_microvm.jailer.jailer_id = "testbindmount"
test_microvm.jailer.chroot_base = tmp_path
test_microvm.jailer.daemonize = True
test_microvm.jailer.gid = 0
test_microvm.jailer.uid = 0
test_microvm.extra_args = {"seccomp-level": 0}

# assert that the directory was created
assert jailed_content_dir.exists()

# Create the guest kernel and rootfs in the jailed content directory
# and mount them in the jailed content directory
os.system(f"cp {guest_kernel} {original_content_dir}")
os.system(f"cp {rootfs_rw} {original_content_dir}")
guest_kernel_mount_path = jailed_content_dir / os.path.basename(guest_kernel)
rootfs_mount_path = jailed_content_dir / os.path.basename(rootfs_rw)
guest_kernel_mount_path.touch()
rootfs_mount_path.touch()

# assert that the files were created
assert guest_kernel_mount_path.exists()
assert rootfs_mount_path.exists()

# mount the rootfs
subprocess.run(
[
"mount",
"--bind",
original_content_dir / os.path.basename(guest_kernel),
guest_kernel_mount_path,
],
check=True,
)
subprocess.run(
[
"mount",
"--bind",
original_content_dir / os.path.basename(rootfs_rw),
rootfs_mount_path,
],
check=True,
)

# assert that the mounts are present
assert guest_kernel_mount_path.exists()
assert rootfs_mount_path.exists()

# run
test_microvm.spawn()

# assert that the mounts are present
assert guest_kernel_mount_path.exists()
assert rootfs_mount_path.exists()

0 comments on commit 6940c7f

Please sign in to comment.