]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Mount over passwd and related files from host 1432/head
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Fri, 14 Apr 2023 08:36:22 +0000 (10:36 +0200)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Sat, 15 Apr 2023 17:37:41 +0000 (19:37 +0200)
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.

mkosi/__init__.py
mkosi/distributions/arch.py
mkosi/distributions/centos.py
mkosi/distributions/debian.py
mkosi/distributions/fedora.py
mkosi/distributions/gentoo.py
mkosi/distributions/mageia.py
mkosi/distributions/openmandriva.py
mkosi/distributions/opensuse.py
mkosi/run.py

index 90c249301337a71405f8b1b7e8b663526ebea3f4..1337ca78afc42b63ccc7eae0a2f49e4967268c0e 100644 (file)
@@ -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:
index 865e2651cdf572776dd7c67b1827b829b4d0c721..ce9610ab4b59b8f51e942a4f251e4b9e86e6e077 100644 (file)
@@ -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:
index 962839e0e277942718a77a7ca03f58291f9ebdf5..61bf509bdb13e1b0cc6c4285c2ed23086263f976 100644 (file)
@@ -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.
index 9e40cd972095b2b2ebc2695ffa0722ee8313164f..5fb4313644550641d7af9ee26a4457ee753eb309 100644 (file)
@@ -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)
index 66a282912712e383c4af24b6f05b43290c590568..bb54cd55d5f4c62eccffa14a740c4ae7fa35a40d 100644 (file)
@@ -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:
index c7009bcd08bbd67f0f65a4247adc9a08d712fd6b..3a389b536d69a5c512db735865080f6586ea6517 100644 (file)
@@ -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)
index 77750258b369cc94116d22336d1d1ccd8c2f5de1..03712ee035317230e6baaf7986f14f26339629ee 100644 (file)
@@ -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:
index 1727284ce13a806670f62a774abfcd4669c6c595..b55054f4bd863baefd7f0faefe5e8f0bd6b36e4a 100644 (file)
@@ -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:
index dc8fa6245db5df0a6b493a5cb59b40a837857e66..33641f56d17382164fa3ad621fa0ee291d139a7a 100644 (file)
@@ -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:
index ade636ffeadabd3e7e9dca7c161decb40d5a417b..a64cae359b7118c032cb5c66627cf1e386e8eeab 100644 (file)
@@ -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",
     ]