nixos/systemd-stage-1: Do not run code from stage 2 until it's actually time to switch-root. (#355166)

This commit is contained in:
Florian Klink 2024-11-12 12:04:54 +01:00 committed by GitHub
commit cb88cda0d4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 72 additions and 12 deletions

View File

@ -482,6 +482,9 @@ in {
# so NSS can look up usernames
"${pkgs.glibc}/lib/libnss_files.so.2"
# Resolving sysroot symlinks without code exec
"${pkgs.chroot-realpath}/bin/chroot-realpath"
] ++ optionals cfg.package.withCryptsetup [
# fido2 support
"${cfg.package}/lib/cryptsetup/libcryptsetup-token-systemd-fido2.so"
@ -522,7 +525,7 @@ in {
script = /* bash */ ''
set -uo pipefail
export PATH="/bin:${cfg.package.util-linux}/bin"
export PATH="/bin:${cfg.package.util-linux}/bin:${pkgs.chroot-realpath}/bin"
# Figure out what closure to boot
closure=
@ -543,7 +546,7 @@ in {
# Resolve symlinks in the init parameter. We need this for some boot loaders
# (e.g. boot.loader.generationsDir).
closure="$(chroot /sysroot ${pkgs.coreutils}/bin/realpath "$closure")"
closure="$(chroot-realpath /sysroot "$closure")"
# Assume the directory containing the init script is the closure.
closure="$(dirname "$closure")"
@ -578,14 +581,10 @@ in {
];
services.initrd-nixos-activation = {
requires = [
config.boot.initrd.systemd.services.initrd-find-nixos-closure.name
];
after = [
"initrd-fs.target"
config.boot.initrd.systemd.services.initrd-find-nixos-closure.name
];
requiredBy = [ "initrd.target" ];
after = [ "initrd-switch-root.target" ];
requiredBy = [ "initrd-switch-root.service" ];
before = [ "initrd-switch-root.service" ];
unitConfig.DefaultDependencies = false;
unitConfig = {
AssertPathExists = "/etc/initrd-release";
RequiresMountsFor = [

View File

@ -139,10 +139,10 @@
closure="$(realpath /nixos-closure)"
metadata_image="$(chroot /sysroot ${lib.getExe' pkgs.coreutils "realpath"} "$closure/etc-metadata-image")"
metadata_image="$(${pkgs.chroot-realpath}/bin/chroot-realpath /sysroot "$closure/etc-metadata-image")"
ln -s "/sysroot$metadata_image" /etc-metadata-image
basedir="$(chroot /sysroot ${lib.getExe' pkgs.coreutils "realpath"} "$closure/etc-basedir")"
basedir="$(${pkgs.chroot-realpath}/bin/chroot-realpath /sysroot "$closure/etc-basedir")"
ln -s "/sysroot$basedir" /etc-basedir
'';
};

View File

@ -0,0 +1,21 @@
{
lib,
rustPlatform,
}:
let
cargo = lib.importTOML ./src/Cargo.toml;
in
rustPlatform.buildRustPackage {
pname = cargo.package.name;
version = cargo.package.version;
src = ./src;
cargoLock.lockFile = ./src/Cargo.lock;
meta = {
description = "Output a path's realpath within a chroot.";
maintainers = [ lib.maintainers.elvishjerricco ];
};
}

View File

@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "chroot-realpath"
version = "0.1.0"

View File

@ -0,0 +1,9 @@
[package]
name = "chroot-realpath"
version = "0.1.0"
edition = "2021"
[dependencies]
[profile.release]
opt-level = "z"

View File

@ -0,0 +1,24 @@
use std::env;
use std::io::{stdout, Error, ErrorKind, Write};
use std::os::unix::ffi::OsStrExt;
use std::os::unix::fs;
fn main() -> std::io::Result<()> {
let args: Vec<String> = env::args().collect();
if args.len() != 3 {
return Err(Error::new(
ErrorKind::InvalidInput,
format!("Usage: {} <chroot> <path>", args[0]),
));
}
fs::chroot(&args[1])?;
std::env::set_current_dir("/")?;
let path = std::fs::canonicalize(&args[2])?;
stdout().write_all(path.into_os_string().as_bytes())?;
Ok(())
}