Skip to content

Commit

Permalink
Use passwd symlinks instead of bind mounts
Browse files Browse the repository at this point in the history
Bind mounts don't reflect changes to the original files if they're
replaced instead of modified. Let's use symlinks instead so that
changes to the original files are always reflected.

Fixes systemd#3189
  • Loading branch information
DaanDeMeyer committed Nov 15, 2024
1 parent 10d36a2 commit c85c9de
Show file tree
Hide file tree
Showing 4 changed files with 13 additions and 15 deletions.
7 changes: 3 additions & 4 deletions mkosi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@
chroot_cmd,
chroot_options,
finalize_interpreter,
finalize_passwd_mounts,
finalize_passwd_symlinks,
fork_and_wait,
run,
workdir,
Expand Down Expand Up @@ -2822,9 +2822,8 @@ def run_tmpfiles(context: Context) -> None:
options=[
"--bind", context.root, "/buildroot",
# systemd uses acl.h to parse ACLs in tmpfiles snippets which uses the host's
# passwd so we have to mount the image's passwd over it to make ACL parsing
# work.
*finalize_passwd_mounts(context.root),
# passwd so we have to symlink the image's passwd to make ACL parsing work.
*finalize_passwd_symlinks("/buildroot"),
# Sometimes directories are configured to be owned by root in tmpfiles snippets
# so we want to make sure those chown()'s succeed by making ourselves the root
# user so that the root user exists.
Expand Down
8 changes: 4 additions & 4 deletions mkosi/archive.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from typing import Optional

from mkosi.log import log_step
from mkosi.run import SandboxProtocol, finalize_passwd_mounts, nosandbox, run, workdir
from mkosi.run import SandboxProtocol, finalize_passwd_symlinks, nosandbox, run, workdir
from mkosi.sandbox import umask
from mkosi.types import PathString
from mkosi.util import chdir
Expand Down Expand Up @@ -51,7 +51,7 @@ def make_tar(src: Path, dst: Path, *, sandbox: SandboxProtocol = nosandbox) -> N
# Make sure tar uses user/group information from the root directory instead of the host.
sandbox=sandbox(
binary="tar",
options=["--ro-bind", src, workdir(src), *finalize_passwd_mounts(src)],
options=["--ro-bind", src, workdir(src), *finalize_passwd_symlinks(workdir(src))],
),
) # fmt: skip

Expand Down Expand Up @@ -98,7 +98,7 @@ def extract_tar(
options=[
"--ro-bind", src, workdir(src),
"--bind", dst, workdir(dst),
*finalize_passwd_mounts(dst),
*finalize_passwd_symlinks(workdir(dst)),
],
),
) # fmt: skip
Expand Down Expand Up @@ -136,6 +136,6 @@ def make_cpio(
stdout=f,
sandbox=sandbox(
binary="cpio",
options=["--ro-bind", src, workdir(src), *finalize_passwd_mounts(src)],
options=["--ro-bind", src, workdir(src), *finalize_passwd_symlinks(workdir(src))],
),
) # fmt: skip
9 changes: 4 additions & 5 deletions mkosi/installer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from mkosi.config import Config, ConfigFeature, OutputFormat
from mkosi.context import Context
from mkosi.mounts import finalize_crypto_mounts
from mkosi.run import apivfs_options, finalize_interpreter, finalize_passwd_mounts, find_binary
from mkosi.run import apivfs_options, finalize_interpreter, finalize_passwd_symlinks, find_binary
from mkosi.tree import rmtree
from mkosi.types import PathString
from mkosi.util import flatten, startswith
Expand Down Expand Up @@ -109,10 +109,9 @@ def options(cls, *, root: PathString, apivfs: bool = True) -> list[PathString]:
"--suppress-chown",
# Make sure /etc/machine-id is not overwritten by any package manager post install scripts.
"--ro-bind-try", Path(root) / "etc/machine-id", "/buildroot/etc/machine-id",
# If we're already in the sandbox, we want to pick up use the passwd files from /buildroot since
# the original root won't be available anymore. If we're not in the sandbox yet, we want to pick
# up the passwd files from the original root.
*finalize_passwd_mounts(root),
# Some package managers (e.g. dpkg) read from the host's /etc/passwd instead of the buildroot's
# /etc/passwd so we symlink /etc/passwd from the buildroot to make sure it gets used.
*(finalize_passwd_symlinks("/buildroot") if apivfs else []),
] # fmt: skip

@classmethod
Expand Down
4 changes: 2 additions & 2 deletions mkosi/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -415,14 +415,14 @@ def workdir(path: Path, sandbox: Optional[SandboxProtocol] = None) -> str:
return joinpath(subdir, str(path))


def finalize_passwd_mounts(root: PathString) -> list[PathString]:
def finalize_passwd_symlinks(root: PathString) -> list[PathString]:
"""
If passwd or a related file exists in the apivfs directory, bind mount it over the host files while we
run the command, to make sure that the command we run uses user/group information from the apivfs
directory instead of from the host.
"""
return flatten(
("--ro-bind-try", Path(root) / "etc" / f, f"/etc/{f}")
("--symlink", Path(root) / "etc" / f, f"/etc/{f}")
for f in ("passwd", "group", "shadow", "gshadow")
)

Expand Down

0 comments on commit c85c9de

Please sign in to comment.