From 3055d28d112343d9e60f1830bdb1b183da93689a Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Fri, 20 Dec 2024 11:39:37 +0100 Subject: [PATCH] sandbox: Make sure we use pacman keyring and crypto policies from tools tree If ToolsTreeCertificates=yes, we still need to make sure we use the crypto policies and pacman keyring from the tools tree if one is used. --- mkosi/__init__.py | 33 +++++++++++++-------------------- mkosi/mounts.py | 36 ++++++++++++++++++++---------------- 2 files changed, 33 insertions(+), 36 deletions(-) diff --git a/mkosi/__init__.py b/mkosi/__init__.py index 9a86514fe..6ca7c30f3 100644 --- a/mkosi/__init__.py +++ b/mkosi/__init__.py @@ -3750,25 +3750,18 @@ def build_image(context: Context) -> None: def run_sandbox(args: Args, config: Config) -> None: cmdline = args.cmdline or [os.getenv("SHELL", "bash")] - options: list[PathString] = ["--same-dir"] - - # If we're not using tools tree certificates we don't have to do anything since the relaxed sandbox will - # already have /etc and /var from the host so we don't need to do anything extra. - if config.tools_tree_certificates: - mounts = finalize_crypto_mounts(config) - - # Since we reuse almost every top level directory from the host except /usr, the crypto mountpoints - # have to exist already in these directories or we'll fail with a permission error. Let's check this - # early and show a better error and a suggestion on how users can fix this issue. We use slice - # notation to get every 3rd item from the mounts list which is the destination path. - for dst in mounts[2::3]: - if not Path(dst).exists(): - die( - f"Missing mountpoint {dst}", - hint=f"Create an empty directory at {dst} using 'mkdir -p {dst}' as root and try again", - ) - - options += mounts + mounts = finalize_crypto_mounts(config, relaxed=True) + + # Since we reuse almost every top level directory from the host except /usr, the crypto mountpoints + # have to exist already in these directories or we'll fail with a permission error. Let's check this + # early and show a better error and a suggestion on how users can fix this issue. We use slice + # notation to get every 3rd item from the mounts list which is the destination path. + for dst in mounts[2::3]: + if not Path(dst).exists(): + die( + f"Missing mountpoint {dst}", + hint=f"Create an empty directory at {dst} using 'mkdir -p {dst}' as root and try again", + ) run( cmdline, @@ -3780,7 +3773,7 @@ def run_sandbox(args: Args, config: Config) -> None: devices=True, network=True, relaxed=True, - options=options, + options=["--same-dir", *mounts], ), ) diff --git a/mkosi/mounts.py b/mkosi/mounts.py index 09ea674b3..a04d7f4b9 100644 --- a/mkosi/mounts.py +++ b/mkosi/mounts.py @@ -86,25 +86,29 @@ def finalize_source_mounts(config: Config, *, ephemeral: bool) -> Iterator[list[ yield options -def finalize_crypto_mounts(config: Config) -> list[PathString]: +def finalize_crypto_mounts(config: Config, relaxed: bool = False) -> list[PathString]: + mounts = [] root = config.tools() if config.tools_tree_certificates else Path("/") - mounts = [ - (root / subdir, Path("/") / subdir) - for subdir in ( - Path("etc/pki"), - Path("etc/ssl"), - Path("etc/ca-certificates"), - Path("var/lib/ca-certificates"), - ) - if (root / subdir).exists() and any(p for p in (root / subdir).rglob("*") if not p.is_dir()) - ] + if not relaxed or root != Path("/"): + mounts += [ + (root / subdir, Path("/") / subdir) + for subdir in ( + Path("etc/pki"), + Path("etc/ssl"), + Path("etc/ca-certificates"), + Path("var/lib/ca-certificates"), + ) + if (root / subdir).exists() and any(p for p in (root / subdir).rglob("*") if not p.is_dir()) + ] - # This contains the Arch Linux keyring, which isn't certificates so ToolsTreeCertificates= doesn't apply. - if (config.tools() / "etc/pacman.d/gnupg").exists(): - mounts += [(config.tools() / "etc/pacman.d/gnupg", Path("/etc/pacman.d/gnupg"))] + if not relaxed or config.tools() != Path("/"): + # This contains the Arch Linux keyring, which isn't certificates so ToolsTreeCertificates= doesn't + # apply. + if (config.tools() / "etc/pacman.d/gnupg").exists(): + mounts += [(config.tools() / "etc/pacman.d/gnupg", Path("/etc/pacman.d/gnupg"))] - if (config.tools() / "etc/crypto-policies").exists(): - mounts += [(config.tools() / "etc/crypto-policies", Path("/etc/crypto-policies"))] + if (config.tools() / "etc/crypto-policies").exists(): + mounts += [(config.tools() / "etc/crypto-policies", Path("/etc/crypto-policies"))] return flatten(("--ro-bind", src, target) for src, target in sorted(set(mounts), key=lambda s: s[1]))