From: Daan De Meyer Date: Fri, 14 Apr 2023 08:36:22 +0000 (+0200) Subject: Mount over passwd and related files from host X-Git-Tag: v15~251^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F1432%2Fhead;p=thirdparty%2Fmkosi.git Mount over passwd and related files from host Package managers have the annoying quirk that they use the user and group information from the host system instead of the user and group information from the chroot. As a workaround, in run_with_apivfs(), let's overmount the files from the host with the ones from the root if they exist. Let's also always install a distribution in 2 steps. First, we install the package that provides passwd. Then, we install the rest of the packages, during which passwd and related files will be overmounted. --- diff --git a/mkosi/__init__.py b/mkosi/__init__.py index 90c249301..1337ca78a 100644 --- a/mkosi/__init__.py +++ b/mkosi/__init__.py @@ -283,6 +283,8 @@ def install_distribution(state: MkosiState, cached: bool) -> None: else: with complete_step(f"Installing {str(state.config.distribution).capitalize()}"): state.installer.install(state) + if state.config.packages: + state.installer.install_packages(state, state.config.packages) def install_build_packages(state: MkosiState, cached: bool) -> None: diff --git a/mkosi/distributions/arch.py b/mkosi/distributions/arch.py index 865e2651c..ce9610ab4 100644 --- a/mkosi/distributions/arch.py +++ b/mkosi/distributions/arch.py @@ -16,7 +16,7 @@ class ArchInstaller(DistributionInstaller): @classmethod def install(cls, state: MkosiState) -> None: - cls.install_packages(state, ["filesystem", *state.config.packages]) + cls.install_packages(state, ["filesystem"]) @classmethod def install_packages(cls, state: MkosiState, packages: Sequence[str]) -> None: diff --git a/mkosi/distributions/centos.py b/mkosi/distributions/centos.py index 962839e0e..61bf509bd 100644 --- a/mkosi/distributions/centos.py +++ b/mkosi/distributions/centos.py @@ -75,7 +75,7 @@ class CentosInstaller(DistributionInstaller): @classmethod def install(cls, state: MkosiState) -> None: - cls.install_packages(state, ["filesystem", *state.config.packages]) + cls.install_packages(state, ["setup"]) # On Fedora, the default rpmdb has moved to /usr/lib/sysimage/rpm so if that's the case we need to # move it back to /var/lib/rpm on CentOS. diff --git a/mkosi/distributions/debian.py b/mkosi/distributions/debian.py index 9e40cd972..5fb431364 100644 --- a/mkosi/distributions/debian.py +++ b/mkosi/distributions/debian.py @@ -72,7 +72,7 @@ class DebianInstaller(DistributionInstaller): install_skeleton_trees(state, False, late=True) - cls.install_packages(state, ["base-files", *state.config.packages]) + cls.install_packages(state, ["base-passwd"]) # Ensure /efi exists so that the ESP is mounted there, and we never run dpkg -i on vfat state.root.joinpath("efi").mkdir(mode=0o755, exist_ok=True) diff --git a/mkosi/distributions/fedora.py b/mkosi/distributions/fedora.py index 66a282912..bb54cd55d 100644 --- a/mkosi/distributions/fedora.py +++ b/mkosi/distributions/fedora.py @@ -29,7 +29,7 @@ class FedoraInstaller(DistributionInstaller): @classmethod def install(cls, state: MkosiState) -> None: - cls.install_packages(state, ["filesystem", *state.config.packages]) + cls.install_packages(state, ["setup"]) @classmethod def install_packages(cls, state: MkosiState, packages: Sequence[str]) -> None: diff --git a/mkosi/distributions/gentoo.py b/mkosi/distributions/gentoo.py index c7009bcd0..3a389b536 100644 --- a/mkosi/distributions/gentoo.py +++ b/mkosi/distributions/gentoo.py @@ -25,12 +25,34 @@ ARCHITECTURES = { } +def invoke_emerge( + state: MkosiState, + pkgs: Sequence[str] = (), + actions: Sequence[str] = (), + opts: Sequence[str] = (), +) -> None: + jobs = os.cpu_count() or 1 + emerge_default_opts = [ + "--buildpkg=y", + "--usepkg=y", + "--keep-going=y", + f"--jobs={jobs}", + f"--load-average={jobs+1}", + "--nospinner", + ] + if "build-script" in ARG_DEBUG: + emerge_default_opts += ["--verbose", "--quiet=n", "--quiet-fail=n"] + else: + emerge_default_opts += ["--quiet-build", "--quiet"] + cmd = ["emerge", *pkgs, *emerge_default_opts, *opts, *actions] + run_workspace_command(state, cmd, network=True) + + class Gentoo: arch_profile: Path arch: str custom_profile_path: Path ebuild_sh_env_dir: Path - emerge_default_opts: list[str] emerge_vars: dict[str, str] portage_cfg_dir: Path profile_path: Path @@ -150,20 +172,6 @@ class Gentoo: self.portage_cfg_dir.mkdir(parents=True, exist_ok=True) - jobs = os.cpu_count() or 1 - self.emerge_default_opts = [ - "--buildpkg=y", - "--usepkg=y", - "--keep-going=y", - f"--jobs={jobs}", - f"--load-average={jobs+1}", - "--nospinner", - ] - if "build-script" in ARG_DEBUG: - self.emerge_default_opts += ["--verbose", "--quiet=n", "--quiet-fail=n"] - else: - self.emerge_default_opts += ["--quiet-build", "--quiet"] - self.arch, _ = ARCHITECTURES[state.config.architecture or "x86_64"] self.arch_profile = Path(f"default/linux/{self.arch}/{state.config.release}/no-multilib/systemd/merged-usr") self.pkgs['sys'] = ["@world"] @@ -184,7 +192,6 @@ class Gentoo: self.get_snapshot_of_portage_tree() self.update_stage3() self.depclean() - self.merge_user_pkgs() def fetch_fix_stage3(self) -> None: """usrmerge tracker bug: https://bugs.gentoo.org/690294""" @@ -293,25 +300,12 @@ class Gentoo: run_workspace_command(self.state, ["/usr/bin/emerge-webrsync"], network=True) def update_stage3(self) -> None: - self.invoke_emerge(opts=self.EMERGE_UPDATE_OPTS, pkgs=self.pkgs['boot']) - self.invoke_emerge(opts=["--config"], pkgs=["sys-kernel/gentoo-kernel-bin"]) - self.invoke_emerge(opts=self.EMERGE_UPDATE_OPTS, pkgs=self.pkgs['sys']) + invoke_emerge(self.state, opts=self.EMERGE_UPDATE_OPTS, pkgs=self.pkgs['boot']) + invoke_emerge(self.state, opts=["--config"], pkgs=["sys-kernel/gentoo-kernel-bin"]) + invoke_emerge(self.state, opts=self.EMERGE_UPDATE_OPTS, pkgs=self.pkgs['sys']) def depclean(self) -> None: - self.invoke_emerge(actions=["--depclean"]) - - def merge_user_pkgs(self) -> None: - if self.state.config.packages: - self.invoke_emerge(pkgs=self.state.config.packages) - - def invoke_emerge( - self, - pkgs: Sequence[str] = (), - actions: Sequence[str] = (), - opts: Sequence[str] = (), - ) -> None: - cmd = ["emerge", *pkgs, *self.emerge_default_opts, *opts, *actions] - run_workspace_command(self.state, cmd, network=True) + invoke_emerge(self.state, actions=["--depclean"]) class GentooInstaller(DistributionInstaller): @@ -327,3 +321,7 @@ class GentooInstaller(DistributionInstaller): @classmethod def install(cls, state: MkosiState) -> None: Gentoo(state) + + @classmethod + def install_packages(cls, state: MkosiState, packages: Sequence[str]) -> None: + invoke_emerge(state, packages) diff --git a/mkosi/distributions/mageia.py b/mkosi/distributions/mageia.py index 77750258b..03712ee03 100644 --- a/mkosi/distributions/mageia.py +++ b/mkosi/distributions/mageia.py @@ -15,7 +15,7 @@ class MageiaInstaller(DistributionInstaller): @classmethod def install(cls, state: MkosiState) -> None: - return cls.install_packages(state, ["filesystem", *state.config.packages]) + cls.install_packages(state, ["setup"]) @classmethod def install_packages(cls, state: MkosiState, packages: Sequence[str]) -> None: diff --git a/mkosi/distributions/openmandriva.py b/mkosi/distributions/openmandriva.py index 1727284ce..b55054f4b 100644 --- a/mkosi/distributions/openmandriva.py +++ b/mkosi/distributions/openmandriva.py @@ -15,7 +15,7 @@ class OpenmandrivaInstaller(DistributionInstaller): @classmethod def install(cls, state: MkosiState) -> None: - return cls.install_packages(state, ["filesystem", *state.config.packages]) + cls.install_packages(state, ["setup"]) @classmethod def install_packages(cls, state: MkosiState, packages: Sequence[str]) -> None: diff --git a/mkosi/distributions/opensuse.py b/mkosi/distributions/opensuse.py index dc8fa6245..33641f56d 100644 --- a/mkosi/distributions/opensuse.py +++ b/mkosi/distributions/opensuse.py @@ -17,7 +17,7 @@ class OpensuseInstaller(DistributionInstaller): @classmethod def install(cls, state: MkosiState) -> None: - cls.install_packages(state, ["filesystem", *state.config.packages]) + cls.install_packages(state, ["filesystem", "system-user-root"]) @classmethod def install_packages(cls, state: MkosiState, packages: Sequence[str]) -> None: diff --git a/mkosi/run.py b/mkosi/run.py index ade636ffe..a64cae359 100644 --- a/mkosi/run.py +++ b/mkosi/run.py @@ -266,6 +266,19 @@ def run_with_apivfs( "--ro-bind", "/sys", state.root / "sys", "--bind", state.var_tmp, state.root / "var/tmp", "--die-with-parent", + ] + + # If passwd or a related file exists in the root 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 root instead + # of from the host. If the file doesn't exist yet, mount over /dev/null instead. + for f in ("passwd", "group", "shadow", "gshadow"): + p = state.root / "etc" / f + if p.exists(): + cmdline += ["--bind", p, f"/etc/{f}"] + else: + cmdline += ["--bind", "/dev/null", f"/etc/{f}"] + + cmdline += [ *bwrap_params, "sh", "-c", ]