From 57a30e4cbded50ed364361353a918345dc42ae3d Mon Sep 17 00:00:00 2001 From: r-vdp Date: Sun, 11 Aug 2024 19:03:05 +0200 Subject: [PATCH 1/2] specialisation: limit the allowed characters in specialisation names Since the systemd boot counting PR was merged, dashes in specialisation names cause issues when installing the boot loader entries, since dashes are also used as separator for the different components of the file name of the boot loader entries on disk. The assertion avoids this footgun which is pretty annoying to recover from. --- .../system/activation/specialisation.nix | 19 ++++++++++- nixos/tests/nixos-rebuild-specialisations.nix | 33 +++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/nixos/modules/system/activation/specialisation.nix b/nixos/modules/system/activation/specialisation.nix index fdab287802fa5..fc348ad94c03a 100644 --- a/nixos/modules/system/activation/specialisation.nix +++ b/nixos/modules/system/activation/specialisation.nix @@ -1,10 +1,14 @@ -{ config, lib, pkgs, extendModules, noUserModules, ... }: +{ config, lib, extendModules, noUserModules, ... }: let inherit (lib) + attrNames concatStringsSep + filter + length mapAttrs mapAttrsToList + match mkOption types ; @@ -73,6 +77,19 @@ in }; config = { + assertions = [( + let + invalidNames = filter (name: match "[[:alnum:]_]+" name == null) (attrNames config.specialisation); + in + { + assertion = length invalidNames == 0; + message = '' + Specialisation names can only contain alphanumeric characters and underscores + Invalid specialisation names: ${concatStringsSep ", " invalidNames} + ''; + } + )]; + system.systemBuilderCommands = '' mkdir $out/specialisation ${concatStringsSep "\n" diff --git a/nixos/tests/nixos-rebuild-specialisations.nix b/nixos/tests/nixos-rebuild-specialisations.nix index 9192b8a8a030b..a5b916f7d7e90 100644 --- a/nixos/tests/nixos-rebuild-specialisations.nix +++ b/nixos/tests/nixos-rebuild-specialisations.nix @@ -71,6 +71,32 @@ import ./make-test-python.nix ({ pkgs, ... }: { } ''; + wrongConfigFile = pkgs.writeText "configuration.nix" '' + { lib, pkgs, ... }: { + imports = [ + ./hardware-configuration.nix + + ]; + + boot.loader.grub = { + enable = true; + device = "/dev/vda"; + forceInstall = true; + }; + + documentation.enable = false; + + environment.systemPackages = [ + (pkgs.writeShellScriptBin "parent" "") + ]; + + specialisation.foo-bar = { + inheritParentConfig = true; + + configuration = { ... }: { }; + }; + } + ''; in '' machine.start() @@ -116,5 +142,12 @@ import ./make-test-python.nix ({ pkgs, ... }: { with subtest("Make sure nonsense command combinations are forbidden"): machine.fail("nixos-rebuild boot --specialisation foo") machine.fail("nixos-rebuild boot -c foo") + + machine.copy_from_host( + "${wrongConfigFile}", + "/etc/nixos/configuration.nix", + ) + with subtest("Make sure that invalid specialisation names are rejected"): + machine.fail("nixos-rebuild switch") ''; }) From d38257b024216705d8cbb055aea4714be19f1c13 Mon Sep 17 00:00:00 2001 From: r-vdp Date: Sun, 11 Aug 2024 23:33:18 +0200 Subject: [PATCH 2/2] systemd-boot-builder: allow underscores in the specialisation name --- .../system/boot/loader/systemd-boot/systemd-boot-builder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py index 846787985ceab..c4324a8eae5bc 100644 --- a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py +++ b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py @@ -65,7 +65,7 @@ def from_path(cls: Type["Entry"], path: Path) -> "Entry": # Matching nixos*-generation-$number*.conf rex_generation = re.compile(r"^nixos.*-generation-([0-9]+).*\.conf$") # Matching nixos*-generation-$number-specialisation-$specialisation_name*.conf - rex_specialisation = re.compile(r"^nixos.*-generation-([0-9]+)-specialisation-([a-zA-Z0-9]+).*\.conf$") + rex_specialisation = re.compile(r"^nixos.*-generation-([0-9]+)-specialisation-([a-zA-Z0-9_]+).*\.conf$") profile = rex_profile.sub(r"\1", filename) if rex_profile.match(filename) else None specialisation = rex_specialisation.sub(r"\2", filename) if rex_specialisation.match(filename) else None try: