yield state.root
-def finalize_mounts(config: MkosiConfig) -> list[PathString]:
- sources = [
- (source, target)
- for source, target
- in [(Path.cwd(), Path.cwd())] + [t.with_prefix(Path.cwd()) for t in config.build_sources]
- ]
+@contextlib.contextmanager
+def finalize_mounts(config: MkosiConfig) -> Iterator[list[PathString]]:
+ with contextlib.ExitStack() as stack:
+ sources = [
+ (stack.enter_context(mount_overlay([source])), target)
+ for source, target
+ in [(Path.cwd(), Path.cwd())] + [t.with_prefix(Path.cwd()) for t in config.build_sources]
+ ]
- # bwrap() mounts /home and /var read-only during execution. So let's add the bind mount options for the
- # directories that could be in /home or /var that we do need to be writable.
- sources += [(d, d) for d in (config.workspace_dir, config.cache_dir, config.output_dir, config.build_dir) if d]
+ # bwrap() mounts /home and /var read-only during execution. So let's add the bind mount options for the
+ # directories that could be in /home or /var that we do need to be writable.
+ sources += [
+ (d, d)
+ for d in (config.workspace_dir_or_default(), config.cache_dir, config.output_dir, config.build_dir)
+ if d
+ ]
- return flatten(["--bind", src, target] for src, target in sorted(set(sources), key=lambda s: s[1]))
+ yield flatten(["--bind", src, target] for src, target in sorted(set(sources), key=lambda s: s[1]))
def script_maybe_chroot(script: Path, mountpoint: str) -> list[str]:
step_msg = "Running prepare script {}…"
arg = "final"
+ mounts = stack.enter_context(finalize_mounts(state.config))
cd = stack.enter_context(finalize_chroot_scripts(state))
for script in state.config.prepare_scripts:
script_maybe_chroot(script, "/work/prepare") + [arg],
network=True,
readonly=True,
- options=finalize_mounts(state.config),
+ options=mounts,
scripts=hd,
env=env | state.config.environment,
stdin=sys.stdin,
with (
mount_build_overlay(state, volatile=True),
finalize_chroot_scripts(state) as cd,
+ finalize_mounts(state.config) as mounts,
):
for script in state.config.build_scripts:
helpers = {
script_maybe_chroot(script, "/work/build-script") + cmdline,
network=state.config.with_network,
readonly=True,
- options=finalize_mounts(state.config),
+ options=mounts,
scripts=hd,
env=env | state.config.environment,
stdin=sys.stdin,
SRCDIR=str(Path.cwd()),
)
- with finalize_chroot_scripts(state) as cd:
+ with (
+ finalize_chroot_scripts(state) as cd,
+ finalize_mounts(state.config) as mounts,
+ ):
for script in state.config.postinst_scripts:
helpers = {
"mkosi-chroot": chroot_cmd(
script_maybe_chroot(script, "/work/postinst") + ["final"],
network=state.config.with_network,
readonly=True,
- options=finalize_mounts(state.config),
+ options=mounts,
scripts=hd,
env=env | state.config.environment,
stdin=sys.stdin,
SRCDIR=str(Path.cwd()),
)
- with finalize_chroot_scripts(state) as cd:
+ with (
+ finalize_chroot_scripts(state) as cd,
+ finalize_mounts(state.config) as mounts,
+ ):
for script in state.config.finalize_scripts:
helpers = {
"mkosi-chroot": chroot_cmd(
script_maybe_chroot(script, "/work/finalize"),
network=state.config.with_network,
readonly=True,
- options=finalize_mounts(state.config),
+ options=mounts,
scripts=hd,
env=env | state.config.environment,
stdin=sys.stdin,
die(f"The workspace directory ({wd}) cannot be located in the current working directory ({Path.cwd()})",
hint="Use WorkspaceDirectory= to configure a different workspace directory")
- for src, _ in config.build_sources:
- if wd.is_relative_to(src):
- die(f"The workspace directory ({wd}) cannot be a subdirectory of any source directory ({src})",
+ for tree in config.build_sources:
+ if wd.is_relative_to(tree.source):
+ die(f"The workspace directory ({wd}) cannot be a subdirectory of any source directory ({tree.source})",
hint="Use WorkspaceDirectory= to configure a different workspace directory")
```
When scripts are executed, any directories that are still writable are
-also made read-only (`/home`, `/var`, `/root`, ...) and only the minimal set
-of directories that need to be writable remain writable. This is to
+also made read-only (`/home`, `/var`, `/root`, ...) and only the minimal
+set of directories that need to be writable remain writable. This is to
ensure that scripts can't mess with the host system when mkosi is
running as root.
+Note that when executing scripts, all source directories are made
+ephemeral which means all changes made to source directories while
+running scripts are thrown away after the scripts finish executing. Use
+the output, build or cache directories if you need to persist data
+between builds.
+
# Files
To make it easy to build images for development versions of your