diff --git a/osbuild/buildroot.py b/osbuild/buildroot.py index 59e91dd9..e25b988e 100644 --- a/osbuild/buildroot.py +++ b/osbuild/buildroot.py @@ -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(":") diff --git a/test/mod/test_buildroot.py b/test/mod/test_buildroot.py index 2ab3c0b9..67b51982 100644 --- a/test/mod/test_buildroot.py +++ b/test/mod/test_buildroot.py @@ -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()