buildroot: mask /proc/cmdline
Since we bind `/proc` inside the container, we leak certain information that comes with it. One of this is the kernel command line. None of the decisions done by software running inside the container should depend on the kernel command line on the host, so overwrite the kernel command line by creating a temporary directory and mapping it inside the build- root. For now we default to a simple `root=/dev/osbuild` fake kernel command line. Add a simple check for it as well.
This commit is contained in:
parent
4c54f7e4a6
commit
36356342b0
2 changed files with 52 additions and 0 deletions
|
|
@ -45,6 +45,25 @@ class CompletedBuild:
|
|||
return self.output
|
||||
|
||||
|
||||
class ProcOverrides:
|
||||
"""Overrides for /proc inside the buildroot"""
|
||||
|
||||
def __init__(self, path) -> None:
|
||||
self.path = path
|
||||
self.overrides = set()
|
||||
|
||||
@property
|
||||
def cmdline(self) -> str:
|
||||
with open(os.path.join(self.path, "cmdline"), "r") as f:
|
||||
return f.read().strip()
|
||||
|
||||
@cmdline.setter
|
||||
def cmdline(self, value) -> None:
|
||||
with open(os.path.join(self.path, "cmdline"), "w") as f:
|
||||
f.write(value + "\n")
|
||||
self.overrides.add("cmdline")
|
||||
|
||||
|
||||
# pylint: disable=too-many-instance-attributes
|
||||
class BuildRoot(contextlib.AbstractContextManager):
|
||||
"""Build Root
|
||||
|
|
@ -69,6 +88,7 @@ class BuildRoot(contextlib.AbstractContextManager):
|
|||
self._apis = []
|
||||
self.dev = None
|
||||
self.var = None
|
||||
self.proc = None
|
||||
self.tmp = None
|
||||
self.mount_boot = True
|
||||
|
||||
|
|
@ -108,6 +128,11 @@ class BuildRoot(contextlib.AbstractContextManager):
|
|||
self.var = os.path.join(self.tmp, "var")
|
||||
os.makedirs(self.var, exist_ok=True)
|
||||
|
||||
proc = os.path.join(self.tmp, "proc")
|
||||
os.makedirs(proc)
|
||||
self.proc = ProcOverrides(proc)
|
||||
self.proc.cmdline = "root=/dev/osbuild"
|
||||
|
||||
subprocess.run(["mount", "-t", "tmpfs", "-o", "nosuid", "none", self.dev], check=True)
|
||||
self._exitstack.callback(lambda: subprocess.run(["umount", "--lazy", self.dev], check=True))
|
||||
|
||||
|
|
@ -209,6 +234,14 @@ class BuildRoot(contextlib.AbstractContextManager):
|
|||
modpath = os.path.dirname(modorigin)
|
||||
mounts += ["--ro-bind", f"{modpath}", "/run/osbuild/lib/osbuild"]
|
||||
|
||||
# Setup /proc overrides
|
||||
for override in self.proc.overrides:
|
||||
mounts += [
|
||||
"--ro-bind",
|
||||
os.path.join(self.proc.path, override),
|
||||
os.path.join("/proc", override)
|
||||
]
|
||||
|
||||
# Make caller-provided mounts available as well.
|
||||
for b in binds or []:
|
||||
mounts += ["--bind"] + b.split(":")
|
||||
|
|
|
|||
|
|
@ -145,3 +145,22 @@ def test_selinuxfs_ro(tempdir):
|
|||
|
||||
r = root.run(cmd, monitor, readonly_binds=ro_binds)
|
||||
assert r.returncode == 0
|
||||
|
||||
|
||||
@pytest.mark.skipif(not TestBase.can_bind_mount(), reason="root only")
|
||||
def test_proc_overrides(tempdir):
|
||||
runner = detect_host_runner()
|
||||
libdir = os.path.abspath(os.curdir)
|
||||
var = pathlib.Path(tempdir, "var")
|
||||
var.mkdir()
|
||||
|
||||
cmdline = "is-this-the-real-world"
|
||||
|
||||
monitor = NullMonitor(sys.stderr.fileno())
|
||||
with BuildRoot("/", runner, libdir, var) as root:
|
||||
|
||||
root.proc.cmdline = cmdline
|
||||
|
||||
r = root.run(["cat", "/proc/cmdline"], monitor)
|
||||
assert r.returncode == 0
|
||||
assert cmdline in r.output.strip()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue