diff --git a/mkosi/__init__.py b/mkosi/__init__.py index 0646890f8..58edc7681 100644 --- a/mkosi/__init__.py +++ b/mkosi/__init__.py @@ -1511,15 +1511,15 @@ def run_ukify( "build", *arguments, "--efi-arch", arch, - "--stub", stub, + "--stub", workdir(stub), "--output", workdir(output), - *(["--cmdline", f"@{context.workspace / 'cmdline'}"] if cmdline else []), + *(["--cmdline", f"@{workdir(context.workspace / 'cmdline')}"] if cmdline else []), ] # fmt: skip opt: list[PathString] = [ - "--ro-bind", stub, stub, + "--ro-bind", stub, workdir(stub), "--bind", output.parent, workdir(output.parent), - "--ro-bind", context.workspace / "cmdline", context.workspace / "cmdline", + "--ro-bind", context.workspace / "cmdline", workdir(context.workspace / "cmdline"), ] # fmt: skip if sign and context.config.secure_boot: @@ -1529,27 +1529,27 @@ def run_ukify( if context.config.secure_boot_sign_tool != SecureBootSignTool.pesign: cmd += [ "--signtool", "sbsign", - "--secureboot-private-key", context.config.secure_boot_key, - "--secureboot-certificate", context.config.secure_boot_certificate, + "--secureboot-certificate", workdir(context.config.secure_boot_certificate), ] # fmt: skip opt += [ - "--ro-bind", context.config.secure_boot_certificate, context.config.secure_boot_certificate, + "--ro-bind", context.config.secure_boot_certificate, workdir(context.config.secure_boot_certificate), # noqa ] # fmt: skip if context.config.secure_boot_key_source.type == KeySourceType.engine: cmd += ["--signing-engine", context.config.secure_boot_key_source.source] opt += ["--bind-try", "/run/pcscd", "/run/pcscd"] if context.config.secure_boot_key.exists(): - opt += ["--ro-bind", context.config.secure_boot_key, context.config.secure_boot_key] + cmd += ["--secureboot-private-key", workdir(context.config.secure_boot_key)] + opt += ["--ro-bind", context.config.secure_boot_key, workdir(context.config.secure_boot_key)] + else: + cmd += ["--secureboot-private-key", context.config.secure_boot_key] else: pesign_prepare(context) cmd += [ "--signtool", "pesign", - "--secureboot-certificate-dir", - context.workspace / "pesign", - "--secureboot-certificate-name", - certificate_common_name(context, context.config.secure_boot_certificate), + "--secureboot-certificate-dir", workdir(context.workspace / "pesign"), + "--secureboot-certificate-name", certificate_common_name(context, context.config.secure_boot_certificate), # noqa ] # fmt: skip - opt += ["--ro-bind", context.workspace / "pesign", context.workspace / "pesign"] + opt += ["--ro-bind", context.workspace / "pesign", workdir(context.workspace / "pesign")] run( cmd, @@ -1576,17 +1576,16 @@ def build_uki( die("Could not find ukify") arguments: list[PathString] = [ - "--os-release", f"@{context.root / 'usr/lib/os-release'}", + "--os-release", f"@{workdir(context.root / 'usr/lib/os-release')}", "--uname", kver, - "--linux", kimg, - *flatten(["--join-profile", os.fspath(profile)] for profile in profiles), + "--linux", workdir(kimg), + *flatten(["--join-profile", os.fspath(workdir(profile))] for profile in profiles), ] # fmt: skip options: list[PathString] = [ - "--ro-bind", context.workspace / "cmdline", context.workspace / "cmdline", - "--ro-bind", context.root / "usr/lib/os-release", context.root / "usr/lib/os-release", - "--ro-bind", kimg, kimg, - *flatten(["--ro-bind", os.fspath(profile), os.fspath(profile)] for profile in profiles), + "--ro-bind", context.root / "usr/lib/os-release", workdir(context.root / "usr/lib/os-release"), + "--ro-bind", kimg, workdir(kimg), + *flatten(["--ro-bind", os.fspath(profile), os.fspath(workdir(profile))] for profile in profiles), ] # fmt: skip if context.config.secure_boot: @@ -1598,26 +1597,31 @@ def build_uki( if want_signed_pcrs(context.config): assert context.config.sign_expected_pcr_key assert context.config.sign_expected_pcr_certificate + arguments += [ - "--pcr-private-key", context.config.sign_expected_pcr_key, # SHA1 might be disabled in OpenSSL depending on the distro so we opt to not sign # for SHA1 to avoid having to manage a bunch of configuration to re-enable SHA1. "--pcr-banks", "sha256", ] # fmt: skip - if context.config.sign_expected_pcr_key.exists(): - options += ["--bind", context.config.sign_expected_pcr_key, context.config.sign_expected_pcr_key] + if context.config.sign_expected_pcr_key_source.type == KeySourceType.engine: arguments += [ "--signing-engine", context.config.sign_expected_pcr_key_source.source, - "--pcr-public-key", context.config.sign_expected_pcr_certificate, + "--pcr-public-key", workdir(context.config.sign_expected_pcr_certificate), ] # fmt: skip options += [ - "--ro-bind", - context.config.sign_expected_pcr_certificate, - context.config.sign_expected_pcr_certificate, + "--ro-bind", context.config.sign_expected_pcr_certificate, workdir(context.config.sign_expected_pcr_certificate), # noqa "--bind-try", "/run/pcscd", "/run/pcscd", ] # fmt: skip + if context.config.sign_expected_pcr_key.exists(): + arguments += ["--pcr-private-key", workdir(context.config.sign_expected_pcr_key)] + options += [ + "--ro-bind", context.config.sign_expected_pcr_key, workdir(context.config.sign_expected_pcr_key), # noqa + ] # fmt: skip + else: + arguments += ["--pcr-private-key", context.config.sign_expected_pcr_key] + if microcodes: # new .ucode section support? if ( @@ -1631,14 +1635,14 @@ def build_uki( and version >= "256" ): for microcode in microcodes: - arguments += ["--microcode", microcode] - options += ["--ro-bind", microcode, microcode] + arguments += ["--microcode", workdir(microcode)] + options += ["--ro-bind", microcode, workdir(microcode)] else: initrds = microcodes + initrds for initrd in initrds: - arguments += ["--initrd", initrd] - options += ["--ro-bind", initrd, initrd] + arguments += ["--initrd", workdir(initrd)] + options += ["--ro-bind", initrd, workdir(initrd)] with complete_step(f"Generating unified kernel image for kernel version {kver}"): run_ukify(context, stub, output, cmdline=" ".join(cmdline), arguments=arguments, options=options) @@ -1980,8 +1984,8 @@ def install_pe_addons(context: Context) -> None: context, stub, output, - arguments=["--config", addon], - options=["--ro-bind", addon, addon], + arguments=["--config", workdir(addon)], + options=["--ro-bind", addon, workdir(addon)], ) @@ -2021,8 +2025,8 @@ def build_uki_profiles(context: Context, cmdline: Sequence[str]) -> list[Path]: stub, output, cmdline=f"{' '.join(cmdline)} {profile_cmdline}", - arguments=["--config", profile], - options=["--ro-bind", profile, profile], + arguments=["--config", workdir(profile)], + options=["--ro-bind", profile, workdir(profile)], sign=False, ) @@ -2248,12 +2252,12 @@ def calculate_signature(context: Context) -> None: if not home.exists(): die(f"GPG home {home} not found") - env = dict(GNUPGHOME=os.fspath(home)) + env = dict(GNUPGHOME=os.fspath(workdir(home))) if sys.stderr.isatty(): env |= dict(GPG_TTY=os.ttyname(sys.stderr.fileno())) options: list[PathString] = [ - "--bind", home, home, + "--bind", home, workdir(home), "--bind", context.staging, workdir(context.staging), "--bind", "/run", "/run", ] # fmt: skip @@ -2880,13 +2884,13 @@ def have_cache(config: Config) -> bool: logging.info("Cache manifest mismatch, not reusing cached images") if ARG_DEBUG.get(): run( - ["diff", "--unified", manifest, "-"], + ["diff", "--unified", workdir(manifest), "-"], input=new, check=False, sandbox=config.sandbox( binary="diff", tools=False, - options=["--bind", manifest, manifest], + options=["--bind", manifest, workdir(manifest)], ), ) @@ -2999,7 +3003,7 @@ def make_image( "--ro-bind", context.config.verity_certificate, workdir(context.config.verity_certificate), - ] + ] # noqa if skip: cmdline += ["--defer-partitions", ",".join(skip)] if split: @@ -3274,7 +3278,7 @@ def make_extension_image(context: Context, output: Path) -> None: "--seed", str(context.config.seed) if context.config.seed else "random", "--empty=create", "--size=auto", - "--definitions", r, + "--definitions", workdir(r), workdir(output), ] # fmt: skip options: list[PathString] = [ @@ -3283,23 +3287,29 @@ def make_extension_image(context: Context, output: Path) -> None: "--become-root", "--bind", output.parent, workdir(output.parent), "--ro-bind", context.root, "/buildroot", - "--ro-bind", r, r, + "--ro-bind", r, workdir(r), ] # fmt: skip if not context.config.architecture.is_native(): cmdline += ["--architecture", str(context.config.architecture)] if context.config.passphrase: cmdline += ["--key-file", context.config.passphrase] - options += ["--ro-bind", context.config.passphrase, context.config.passphrase] + options += ["--ro-bind", context.config.passphrase, workdir(context.config.passphrase)] if context.config.verity_key: - cmdline += ["--private-key", context.config.verity_key] if context.config.verity_key_source.type != KeySourceType.file: cmdline += ["--private-key-source", str(context.config.verity_key_source)] if context.config.verity_key.exists(): - options += ["--ro-bind", context.config.verity_key, context.config.verity_key] + cmdline += ["--private-key", workdir(context.config.verity_key)] + options += ["--ro-bind", context.config.verity_key, workdir(context.config.verity_key)] + else: + cmdline += ["--private-key", context.config.verity_key] if context.config.verity_certificate: - cmdline += ["--certificate", context.config.verity_certificate] - options += ["--ro-bind", context.config.verity_certificate, context.config.verity_certificate] + cmdline += ["--certificate", workdir(context.config.verity_certificate)] + options += [ + "--ro-bind", + context.config.verity_certificate, + workdir(context.config.verity_certificate), + ] # noqa if context.config.sector_size: cmdline += ["--sector-size", str(context.config.sector_size)] if context.config.split_artifacts: @@ -3421,12 +3431,12 @@ def copy_repository_metadata(config: Config, dst: Path) -> None: exclude: list[PathString] if d == "cache": exclude = flatten( - ("--ro-bind", tmp, p) + ("--ro-bind", tmp, workdir(p)) for p in config.distribution.package_manager(config).cache_subdirs(src) ) else: exclude = flatten( - ("--ro-bind", tmp, p) + ("--ro-bind", tmp, workdir(p)) for p in config.distribution.package_manager(config).state_subdirs(src) ) @@ -3683,13 +3693,13 @@ def run_shell(args: Args, config: Config) -> None: run( [ "systemd-repart", - "--image", fname, + "--image", workdir(fname), *([f"--size={config.runtime_size}"] if config.runtime_size else []), "--no-pager", "--dry-run=no", "--offline=no", "--pretty=no", - fname, + workdir(fname), ], stdin=sys.stdin, env=config.environment, @@ -3697,7 +3707,7 @@ def run_shell(args: Args, config: Config) -> None: binary="systemd-repart", network=True, devices=True, - options=["--bind", fname, fname], + options=["--bind", fname, workdir(fname)], ), ) # fmt: skip @@ -4302,7 +4312,15 @@ def run_build( if not Path(d).exists(): continue - if config.output_dir_or_cwd().is_relative_to(d): + if any( + p and p.is_relative_to(d) + for p in ( + config.workspace_dir_or_default(), + config.package_cache_dir_or_default(), + config.cache_dir, + config.output_dir_or_cwd(), + ) + ): continue attrs = MOUNT_ATTR_RDONLY diff --git a/mkosi/archive.py b/mkosi/archive.py index 6ad8df48a..b735955bf 100644 --- a/mkosi/archive.py +++ b/mkosi/archive.py @@ -6,7 +6,7 @@ from typing import Optional from mkosi.log import log_step -from mkosi.run import SandboxProtocol, finalize_passwd_mounts, nosandbox, run +from mkosi.run import SandboxProtocol, finalize_passwd_mounts, nosandbox, run, workdir from mkosi.sandbox import umask from mkosi.types import PathString from mkosi.util import chdir @@ -32,7 +32,7 @@ def make_tar(src: Path, dst: Path, *, sandbox: SandboxProtocol = nosandbox) -> N "tar", "--create", "--file", "-", - "--directory", src, + "--directory", workdir(src), "--acls", "--selinux", # --xattrs implies --format=pax @@ -49,7 +49,10 @@ def make_tar(src: Path, dst: Path, *, sandbox: SandboxProtocol = nosandbox) -> N ], stdout=f, # Make sure tar uses user/group information from the root directory instead of the host. - sandbox=sandbox(binary="tar", options=["--ro-bind", src, src, *finalize_passwd_mounts(src)]), + sandbox=sandbox( + binary="tar", + options=["--ro-bind", src, workdir(src), *finalize_passwd_mounts(src)], + ), ) # fmt: skip @@ -75,8 +78,8 @@ def extract_tar( [ "tar", "--extract", - "--file", src, - "--directory", dst, + "--file", workdir(src), + "--directory", workdir(dst), "--keep-directory-symlink", "--no-overwrite-dir", "--same-permissions", @@ -92,7 +95,11 @@ def extract_tar( sandbox=sandbox( binary="tar", # Make sure tar uses user/group information from the root directory instead of the host. - options=["--ro-bind", src, src, "--bind", dst, dst, *finalize_passwd_mounts(dst)], + options=[ + "--ro-bind", src, workdir(src), + "--bind", dst, workdir(dst), + *finalize_passwd_mounts(dst), + ], ), ) # fmt: skip @@ -122,10 +129,13 @@ def make_cpio( "--null", "--format=newc", "--quiet", - "--directory", src, + "--directory", workdir(src), *(["--owner=0:0"] if os.getuid() != 0 else []), ], input="\0".join(os.fspath(f) for f in files), stdout=f, - sandbox=sandbox(binary="cpio", options=["--ro-bind", src, src, *finalize_passwd_mounts(src)]), + sandbox=sandbox( + binary="cpio", + options=["--ro-bind", src, workdir(src), *finalize_passwd_mounts(src)], + ), ) # fmt: skip diff --git a/mkosi/bootloader.py b/mkosi/bootloader.py index 2569a7d8c..2fc91691c 100644 --- a/mkosi/bootloader.py +++ b/mkosi/bootloader.py @@ -199,11 +199,11 @@ def grub_mkimage( [ mkimage, "--directory", "/grub", - "--config", earlyconfig.name, + "--config", workdir(Path(earlyconfig.name)), "--prefix", f"/{context.config.distribution.grub_prefix()}", - "--output", output or ("/grub/core.img"), + "--output", workdir(output) if output else "/grub/core.img", "--format", target, - *(["--sbat", str(sbat)] if sbat else []), + *(["--sbat", str(workdir(sbat))] if sbat else []), *(["--disable-shim-lock"] if context.config.shim_bootloader == ShimBootloader.none else []), "cat", "cmp", @@ -232,9 +232,9 @@ def grub_mkimage( binary=mkimage, options=[ "--bind", directory, "/grub", - "--ro-bind", earlyconfig.name, earlyconfig.name, - *(["--bind", str(output.parent), str(output.parent)] if output else []), - *(["--ro-bind", str(sbat), str(sbat)] if sbat else []), + "--ro-bind", earlyconfig.name, workdir(Path(earlyconfig.name)), + *(["--bind", str(output.parent), str(workdir(output.parent))] if output else []), + *(["--ro-bind", str(sbat), str(workdir(sbat))] if sbat else []), ], ), ) # fmt: skip @@ -284,7 +284,7 @@ def extract_pe_section(context: Context, binary: Path, section: str, output: Pat import pefile import sys from pathlib import Path - pe = pefile.PE("{binary}", fast_load=True) + pe = pefile.PE("{workdir(binary)}", fast_load=True) section = {{s.Name.decode().strip("\\0"): s for s in pe.sections}}.get("{section}") if not section: sys.exit(67) @@ -299,7 +299,7 @@ def extract_pe_section(context: Context, binary: Path, section: str, output: Pat stdout=f, sandbox=context.sandbox( binary=python_binary(context.config, binary=None), - options=["--ro-bind", binary, binary], + options=["--ro-bind", binary, workdir(binary)], ), success_exit_status=(0, 67), ) @@ -377,20 +377,22 @@ def grub_bios_setup(context: Context, partitions: Sequence[Partition]) -> None: # the bios boot partition. To make installation work unprivileged, we trick grub to think that the # root device is our image by mounting over its /proc/self/mountinfo file (where it gets its # information from) with our own file correlating the root directory to our image file. - mountinfo.write(f"1 0 1:1 / / - fat {context.staging / context.config.output_with_format}\n") + mountinfo.write( + f"1 0 1:1 / / - fat {workdir(context.staging / context.config.output_with_format)}\n" + ) mountinfo.flush() run( [ setup, "--directory", "/grub", - context.staging / context.config.output_with_format, + workdir(context.staging / context.config.output_with_format), ], sandbox=context.sandbox( binary=setup, options=[ "--bind", directory, "/grub", - "--bind", context.staging, context.staging, + "--bind", context.staging, workdir(context.staging), "--bind", mountinfo.name, "/proc/self/mountinfo", ], ), @@ -420,10 +422,10 @@ def certificate_common_name(context: Context, certificate: Path) -> str: "-noout", "-subject", "-nameopt", "multiline", - "-in", certificate, + "-in", workdir(certificate), ], stdout=subprocess.PIPE, - sandbox=context.sandbox(binary="openssl", options=["--ro-bind", certificate, certificate]), + sandbox=context.sandbox(binary="openssl", options=["--ro-bind", certificate, workdir(certificate)]), ).stdout # fmt: skip for line in output.splitlines(): @@ -462,15 +464,15 @@ def pesign_prepare(context: Context) -> None: "-certpbe", "NONE", "-nomaciter", "-passout", "pass:", - "-inkey", context.config.secure_boot_key, - "-in", context.config.secure_boot_certificate, + "-inkey", workdir(context.config.secure_boot_key), + "-in", workdir(context.config.secure_boot_certificate), ], stdout=f, sandbox=context.sandbox( binary="openssl", options=[ - "--ro-bind", context.config.secure_boot_key, context.config.secure_boot_key, - "--ro-bind", context.config.secure_boot_certificate, context.config.secure_boot_certificate, # noqa + "--ro-bind", context.config.secure_boot_key, workdir(context.config.secure_boot_key), + "--ro-bind", context.config.secure_boot_certificate, workdir(context.config.secure_boot_certificate), # noqa ], ), ) # fmt: skip @@ -482,14 +484,14 @@ def pesign_prepare(context: Context) -> None: "pk12util", "-K", "", "-W", "", - "-i", context.workspace / "secure-boot.p12", - "-d", context.workspace / "pesign", + "-i", workdir(context.workspace / "secure-boot.p12"), + "-d", workdir(context.workspace / "pesign"), ], sandbox=context.sandbox( binary="pk12util", options=[ - "--ro-bind", context.workspace / "secure-boot.p12", context.workspace / "secure-boot.p12", - "--ro-bind", context.workspace / "pesign", context.workspace / "pesign", + "--ro-bind", context.workspace / "secure-boot.p12", workdir(context.workspace / "secure-boot.p12"), # noqa + "--ro-bind", context.workspace / "pesign", workdir(context.workspace / "pesign"), ], ), ) # fmt: skip diff --git a/mkosi/config.py b/mkosi/config.py index 37782c40e..c7bed5374 100644 --- a/mkosi/config.py +++ b/mkosi/config.py @@ -33,7 +33,7 @@ from mkosi.distributions import Distribution, detect_distribution from mkosi.log import ARG_DEBUG, ARG_DEBUG_SHELL, Style, die from mkosi.pager import page -from mkosi.run import SandboxProtocol, find_binary, nosandbox, run, sandbox_cmd +from mkosi.run import SandboxProtocol, find_binary, nosandbox, run, sandbox_cmd, workdir from mkosi.sandbox import __version__ from mkosi.types import PathString, SupportsRead from mkosi.user import INVOKING_USER @@ -4732,8 +4732,8 @@ def want_selinux_relabel( return None policy = run( - ["sh", "-c", f". {selinux} && echo $SELINUXTYPE"], - sandbox=config.sandbox(binary="sh", options=["--ro-bind", selinux, selinux]), + ["sh", "-c", f". {workdir(selinux)} && echo $SELINUXTYPE"], + sandbox=config.sandbox(binary="sh", options=["--ro-bind", selinux, workdir(selinux)]), stdout=subprocess.PIPE, ).stdout.strip() if not policy: diff --git a/mkosi/curl.py b/mkosi/curl.py index 5d792af13..2aa91749a 100644 --- a/mkosi/curl.py +++ b/mkosi/curl.py @@ -4,7 +4,7 @@ from mkosi.config import Config from mkosi.mounts import finalize_crypto_mounts -from mkosi.run import run +from mkosi.run import run, workdir def curl(config: Config, url: str, output_dir: Path) -> None: @@ -12,7 +12,7 @@ def curl(config: Config, url: str, output_dir: Path) -> None: [ "curl", "--location", - "--output-dir", output_dir, + "--output-dir", workdir(output_dir), "--remote-name", "--no-progress-meter", "--fail", @@ -26,6 +26,6 @@ def curl(config: Config, url: str, output_dir: Path) -> None: sandbox=config.sandbox( binary="curl", network=True, - options=["--bind", output_dir, output_dir, *finalize_crypto_mounts(config)], + options=["--bind", output_dir, workdir(output_dir), *finalize_crypto_mounts(config)], ), ) # fmt: skip diff --git a/mkosi/distributions/debian.py b/mkosi/distributions/debian.py index 80875f85a..7720f583f 100644 --- a/mkosi/distributions/debian.py +++ b/mkosi/distributions/debian.py @@ -11,7 +11,7 @@ from mkosi.installer import PackageManager from mkosi.installer.apt import Apt, AptRepository from mkosi.log import die -from mkosi.run import run +from mkosi.run import run, workdir from mkosi.sandbox import umask @@ -140,12 +140,12 @@ def install(cls, context: Context) -> None: "install", [ "-oDebug::pkgDPkgPm=1", - f"-oDPkg::Pre-Install-Pkgs::=cat >{f.name}", + f"-oDPkg::Pre-Install-Pkgs::=cat >{workdir(Path(f.name))}", "?essential", "?exact-name(usr-is-merged)", "base-files", ], - options=["--bind", f.name, f.name], + options=["--bind", f.name, workdir(Path(f.name))], ) essential = f.read().strip().splitlines() diff --git a/mkosi/installer/apt.py b/mkosi/installer/apt.py index ab71473b6..c1dbec6fc 100644 --- a/mkosi/installer/apt.py +++ b/mkosi/installer/apt.py @@ -10,7 +10,7 @@ from mkosi.context import Context from mkosi.installer import PackageManager from mkosi.log import die -from mkosi.run import run +from mkosi.run import run, workdir from mkosi.sandbox import umask from mkosi.types import _FILE, CompletedProcess, PathString @@ -256,9 +256,12 @@ def createrepo(cls, context: Context) -> None: ], sandbox=context.sandbox( binary="reprepro", - options=["--bind", context.repository, context.repository, "--chdir", context.repository], + options=[ + "--bind", context.repository, workdir(context.repository), + "--chdir", workdir(context.repository), + ], ), - ) + ) # fmt: skip (context.sandbox_tree / "etc/apt/sources.list.d").mkdir(parents=True, exist_ok=True) (context.sandbox_tree / "etc/apt/sources.list.d/mkosi-local.sources").write_text( diff --git a/mkosi/installer/dnf.py b/mkosi/installer/dnf.py index 63f4db2a5..aa70f756e 100644 --- a/mkosi/installer/dnf.py +++ b/mkosi/installer/dnf.py @@ -8,7 +8,7 @@ from mkosi.installer import PackageManager from mkosi.installer.rpm import RpmRepository, rpm_cmd from mkosi.log import ARG_DEBUG -from mkosi.run import run +from mkosi.run import run, workdir from mkosi.types import _FILE, CompletedProcess, PathString @@ -217,9 +217,9 @@ def sync(cls, context: Context, force: bool, arguments: Sequence[str] = ()) -> N @classmethod def createrepo(cls, context: Context) -> None: run( - ["createrepo_c", context.repository], + ["createrepo_c", workdir(context.repository)], sandbox=context.sandbox( - binary="createrepo_c", options=["--bind", context.repository, context.repository] + binary="createrepo_c", options=["--bind", context.repository, workdir(context.repository)] ), ) diff --git a/mkosi/installer/pacman.py b/mkosi/installer/pacman.py index 729bbac8c..63d08a6c2 100644 --- a/mkosi/installer/pacman.py +++ b/mkosi/installer/pacman.py @@ -9,7 +9,7 @@ from mkosi.config import Config from mkosi.context import Context from mkosi.installer import PackageManager -from mkosi.run import run +from mkosi.run import run, workdir from mkosi.sandbox import umask from mkosi.types import _FILE, CompletedProcess, PathString from mkosi.versioncomp import GenericVersion @@ -181,11 +181,15 @@ def createrepo(cls, context: Context) -> None: [ "repo-add", "--quiet", - context.repository / "mkosi.db.tar", - *sorted(context.repository.glob("*.pkg.tar*"), key=lambda p: GenericVersion(Path(p).name)), + workdir(context.repository / "mkosi.db.tar"), + *sorted( + (workdir(p) for p in context.repository.glob("*.pkg.tar*")), + key=lambda p: GenericVersion(Path(p).name), + ), ], sandbox=context.sandbox( - binary="repo-add", options=["--bind", context.repository, context.repository] + binary="repo-add", + options=["--bind", context.repository, workdir(context.repository)], ), ) diff --git a/mkosi/installer/zypper.py b/mkosi/installer/zypper.py index 90f78a990..16ad76d49 100644 --- a/mkosi/installer/zypper.py +++ b/mkosi/installer/zypper.py @@ -8,7 +8,7 @@ from mkosi.context import Context from mkosi.installer import PackageManager from mkosi.installer.rpm import RpmRepository, rpm_cmd -from mkosi.run import run +from mkosi.run import run, workdir from mkosi.types import _FILE, CompletedProcess, PathString @@ -138,9 +138,10 @@ def sync(cls, context: Context, force: bool, arguments: Sequence[str] = ()) -> N @classmethod def createrepo(cls, context: Context) -> None: run( - ["createrepo_c", context.repository], + ["createrepo_c", workdir(context.repository)], sandbox=context.sandbox( - binary="createrepo_c", options=["--bind", context.repository, context.repository] + binary="createrepo_c", + options=["--bind", context.repository, workdir(context.repository)], ), ) diff --git a/mkosi/partition.py b/mkosi/partition.py index 58949216e..e6972de56 100644 --- a/mkosi/partition.py +++ b/mkosi/partition.py @@ -6,7 +6,7 @@ from typing import Any, Final, Optional from mkosi.log import die -from mkosi.run import SandboxProtocol, nosandbox, run +from mkosi.run import SandboxProtocol, nosandbox, run, workdir @dataclasses.dataclass(frozen=True) @@ -33,10 +33,10 @@ def from_dict(cls, dict: Mapping[str, Any]) -> "Partition": def find_partitions(image: Path, *, sandbox: SandboxProtocol = nosandbox) -> list[Partition]: output = json.loads( run( - ["systemd-repart", "--json=short", image], + ["systemd-repart", "--json=short", workdir(image)], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, - sandbox=sandbox(binary="systemd-repart", options=["--ro-bind", image, image]), + sandbox=sandbox(binary="systemd-repart", options=["--ro-bind", image, workdir(image)]), ).stdout ) return [Partition.from_dict(d) for d in output] diff --git a/mkosi/qemu.py b/mkosi/qemu.py index cdb6501c4..93ce6b247 100644 --- a/mkosi/qemu.py +++ b/mkosi/qemu.py @@ -158,9 +158,9 @@ def identify(cls, config: Config, path: Path) -> "KernelType": return KernelType.unknown type = run( - ["bootctl", "kernel-identify", path], + ["bootctl", "kernel-identify", workdir(path)], stdout=subprocess.PIPE, - sandbox=config.sandbox(binary="bootctl", options=["--ro-bind", path, path]), + sandbox=config.sandbox(binary="bootctl", options=["--ro-bind", path, workdir(path)]), ).stdout.strip() try: @@ -253,7 +253,7 @@ def start_swtpm(config: Config) -> Iterator[Path]: run( [ "swtpm_setup", - "--tpm-state", state, + "--tpm-state", workdir(Path(state)), "--tpm2", "--pcr-banks", "sha256", @@ -261,16 +261,12 @@ def start_swtpm(config: Config) -> Iterator[Path]: ], sandbox=config.sandbox( binary="swtpm_setup", - options=["--bind", state, state], - setup=scope_cmd( - name=f"mkosi-swtpm-{config.machine_or_name()}", - description=f"swtpm for {config.machine_or_name()}", - ), + options=["--bind", state, workdir(Path(state))], ), stdout=None if ARG_DEBUG.get() else subprocess.DEVNULL, ) # fmt: skip - cmdline = ["swtpm", "socket", "--tpm2", "--tpmstate", f"dir={state}"] + cmdline = ["swtpm", "socket", "--tpm2", "--tpmstate", f"dir={workdir(Path(state))}"] # We create the socket ourselves and pass the fd to swtpm to avoid race conditions where we start # qemu before swtpm has had the chance to create the socket (or where we try to chown it first). @@ -284,7 +280,14 @@ def start_swtpm(config: Config) -> Iterator[Path]: with spawn( cmdline, pass_fds=(sock.fileno(),), - sandbox=config.sandbox(binary="swtpm", options=["--bind", state, state]), + sandbox=config.sandbox( + binary="swtpm", + options=["--bind", state, workdir(Path(state))], + setup=scope_cmd( + name=f"mkosi-swtpm-{config.machine_or_name()}", + description=f"swtpm for {config.machine_or_name()}", + ), + ), ) as proc: yield path proc.terminate() @@ -575,16 +578,16 @@ def copy() -> None: become_root_in_subuid_range() elif config.output_format in (OutputFormat.disk, OutputFormat.esp): attr = run( - ["lsattr", "-l", src], - sandbox=config.sandbox(binary="lsattr", options=["--ro-bind", src, src]), + ["lsattr", "-l", workdir(src)], + sandbox=config.sandbox(binary="lsattr", options=["--ro-bind", src, workdir(src)]), stdout=subprocess.PIPE, ).stdout if "No_COW" in attr: tmp.touch() run( - ["chattr", "+C", tmp], - sandbox=config.sandbox(binary="chattr", options=["--bind", tmp, tmp]), + ["chattr", "+C", workdir(tmp)], + sandbox=config.sandbox(binary="chattr", options=["--bind", tmp, workdir(tmp)]), ) copy_tree( @@ -635,9 +638,12 @@ def generate_scratch_fs(config: Config) -> Iterator[Path]: fs = config.distribution.filesystem() extra = config.environment.get(f"SYSTEMD_REPART_MKFS_OPTIONS_{fs.upper()}", "") run( - [f"mkfs.{fs}", "-L", "scratch", *extra.split(), scratch.name], + [f"mkfs.{fs}", "-L", "scratch", *extra.split(), workdir(Path(scratch.name))], stdout=subprocess.DEVNULL, - sandbox=config.sandbox(binary=f"mkfs.{fs}", options=["--bind", scratch.name, scratch.name]), + sandbox=config.sandbox( + binary=f"mkfs.{fs}", + options=["--bind", scratch.name, workdir(Path(scratch.name))], + ), ) yield Path(scratch.name) @@ -683,10 +689,10 @@ def finalize_firmware_variables( run( [ "virt-fw-vars", - "--input", ovmf.vars, - "--output", ovmf_vars.name, - "--enroll-cert", config.secure_boot_certificate, - "--add-db", "OvmfEnrollDefaultKeys", config.secure_boot_certificate, + "--input", workdir(ovmf.vars), + "--output", workdir(Path(ovmf_vars.name)), + "--enroll-cert", workdir(config.secure_boot_certificate), + "--add-db", "OvmfEnrollDefaultKeys", workdir(config.secure_boot_certificate), "--no-microsoft", "--secure-boot", "--loglevel", "WARNING", @@ -694,8 +700,9 @@ def finalize_firmware_variables( sandbox=config.sandbox( binary=qemu, options=[ - "--bind", ovmf_vars.name, ovmf_vars.name, - "--ro-bind", config.secure_boot_certificate, config.secure_boot_certificate, + "--bind", ovmf_vars.name, workdir(Path(ovmf_vars.name)), + "--ro-bind", ovmf.vars, workdir(ovmf.vars), + "--ro-bind", config.secure_boot_certificate, workdir(config.secure_boot_certificate), ], ), ) # fmt: skip @@ -726,9 +733,9 @@ def apply_runtime_size(config: Config, image: Path) -> None: f"--size={round_up(config.runtime_size, resource.getpagesize())}", "--pretty=no", "--offline=yes", - image, + workdir(image), ], - sandbox=config.sandbox(binary="systemd-repart", options=["--bind", image, image]), + sandbox=config.sandbox(binary="systemd-repart", options=["--bind", image, workdir(image)]), ) # fmt: skip diff --git a/mkosi/run.py b/mkosi/run.py index ca39ce36a..6674118b7 100644 --- a/mkosi/run.py +++ b/mkosi/run.py @@ -562,7 +562,7 @@ def sandbox_cmd( if not overlay and not relaxed: tmp = stack.enter_context(vartmpdir()) - yield [*cmdline, "--bind", tmp, "/var/tmp", *options, "--"] + yield [*cmdline, "--bind", tmp, "/var/tmp", "--dir", "/tmp", "--dir", "/run", *options, "--"] return for d in ("etc", "opt"):