Skip to content

Commit cb88cda

Browse files
authored
nixos/systemd-stage-1: Do not run code from stage 2 until it's actually time to switch-root. (#355166)
2 parents 0af7aa2 + 6cfd95f commit cb88cda

File tree

6 files changed

+72
-12
lines changed

6 files changed

+72
-12
lines changed

nixos/modules/system/boot/systemd/initrd.nix

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,9 @@ in {
482482

483483
# so NSS can look up usernames
484484
"${pkgs.glibc}/lib/libnss_files.so.2"
485+
486+
# Resolving sysroot symlinks without code exec
487+
"${pkgs.chroot-realpath}/bin/chroot-realpath"
485488
] ++ optionals cfg.package.withCryptsetup [
486489
# fido2 support
487490
"${cfg.package}/lib/cryptsetup/libcryptsetup-token-systemd-fido2.so"
@@ -522,7 +525,7 @@ in {
522525

523526
script = /* bash */ ''
524527
set -uo pipefail
525-
export PATH="/bin:${cfg.package.util-linux}/bin"
528+
export PATH="/bin:${cfg.package.util-linux}/bin:${pkgs.chroot-realpath}/bin"
526529
527530
# Figure out what closure to boot
528531
closure=
@@ -543,7 +546,7 @@ in {
543546
544547
# Resolve symlinks in the init parameter. We need this for some boot loaders
545548
# (e.g. boot.loader.generationsDir).
546-
closure="$(chroot /sysroot ${pkgs.coreutils}/bin/realpath "$closure")"
549+
closure="$(chroot-realpath /sysroot "$closure")"
547550
548551
# Assume the directory containing the init script is the closure.
549552
closure="$(dirname "$closure")"
@@ -578,14 +581,10 @@ in {
578581
];
579582

580583
services.initrd-nixos-activation = {
581-
requires = [
582-
config.boot.initrd.systemd.services.initrd-find-nixos-closure.name
583-
];
584-
after = [
585-
"initrd-fs.target"
586-
config.boot.initrd.systemd.services.initrd-find-nixos-closure.name
587-
];
588-
requiredBy = [ "initrd.target" ];
584+
after = [ "initrd-switch-root.target" ];
585+
requiredBy = [ "initrd-switch-root.service" ];
586+
before = [ "initrd-switch-root.service" ];
587+
unitConfig.DefaultDependencies = false;
589588
unitConfig = {
590589
AssertPathExists = "/etc/initrd-release";
591590
RequiresMountsFor = [

nixos/modules/system/etc/etc-activation.nix

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,10 @@
139139
140140
closure="$(realpath /nixos-closure)"
141141
142-
metadata_image="$(chroot /sysroot ${lib.getExe' pkgs.coreutils "realpath"} "$closure/etc-metadata-image")"
142+
metadata_image="$(${pkgs.chroot-realpath}/bin/chroot-realpath /sysroot "$closure/etc-metadata-image")"
143143
ln -s "/sysroot$metadata_image" /etc-metadata-image
144144
145-
basedir="$(chroot /sysroot ${lib.getExe' pkgs.coreutils "realpath"} "$closure/etc-basedir")"
145+
basedir="$(${pkgs.chroot-realpath}/bin/chroot-realpath /sysroot "$closure/etc-basedir")"
146146
ln -s "/sysroot$basedir" /etc-basedir
147147
'';
148148
};
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
lib,
3+
rustPlatform,
4+
}:
5+
6+
let
7+
cargo = lib.importTOML ./src/Cargo.toml;
8+
in
9+
rustPlatform.buildRustPackage {
10+
pname = cargo.package.name;
11+
version = cargo.package.version;
12+
13+
src = ./src;
14+
15+
cargoLock.lockFile = ./src/Cargo.lock;
16+
17+
meta = {
18+
description = "Output a path's realpath within a chroot.";
19+
maintainers = [ lib.maintainers.elvishjerricco ];
20+
};
21+
}

pkgs/by-name/ch/chroot-realpath/src/Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "chroot-realpath"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
8+
[profile.release]
9+
opt-level = "z"
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
use std::env;
2+
use std::io::{stdout, Error, ErrorKind, Write};
3+
use std::os::unix::ffi::OsStrExt;
4+
use std::os::unix::fs;
5+
6+
fn main() -> std::io::Result<()> {
7+
let args: Vec<String> = env::args().collect();
8+
9+
if args.len() != 3 {
10+
return Err(Error::new(
11+
ErrorKind::InvalidInput,
12+
format!("Usage: {} <chroot> <path>", args[0]),
13+
));
14+
}
15+
16+
fs::chroot(&args[1])?;
17+
std::env::set_current_dir("/")?;
18+
19+
let path = std::fs::canonicalize(&args[2])?;
20+
21+
stdout().write_all(path.into_os_string().as_bytes())?;
22+
23+
Ok(())
24+
}

0 commit comments

Comments
 (0)