diff --git a/nixos/modules/system/boot/binfmt.nix b/nixos/modules/system/boot/binfmt.nix index cbdf581d73a7f..fb51c3900146d 100644 --- a/nixos/modules/system/boot/binfmt.nix +++ b/nixos/modules/system/boot/binfmt.nix @@ -20,11 +20,13 @@ let optionalString fixBinary "F"; in ":${name}:${type}:${offset'}:${magicOrExtension}:${mask'}:${interpreter}:${flags}"; - activationSnippet = name: { interpreter, ... }: '' + activationSnippet = name: { interpreter, preserveArgvZero, ... }: '' rm -f /run/binfmt/${name} cat > /run/binfmt/${name} << 'EOF' #!${pkgs.bash}/bin/sh - exec -- ${interpreter} "$@" + ${if preserveArgvZero && interpreter == getEmulator name + then ''exec -- ${interpreter} -0 "$2" "$1" "''${@:3}"'' # Correctly handle argv0 for the default QEMU emulator. + else ''exec -- ${interpreter} "$@"''} EOF chmod +x /run/binfmt/${name} ''; diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 58b2ba7fa514a..5a9a0c4570b44 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -389,6 +389,7 @@ in systemd = handleTest ./systemd.nix {}; systemd-analyze = handleTest ./systemd-analyze.nix {}; systemd-binfmt = handleTestOn ["x86_64-linux"] ./systemd-binfmt.nix {}; + systemd-binfmt-argv0 = handleTestOn ["x86_64-linux"] ./systemd-binfmt-argv0.nix {}; systemd-boot = handleTest ./systemd-boot.nix {}; systemd-confinement = handleTest ./systemd-confinement.nix {}; systemd-journal = handleTest ./systemd-journal.nix {}; diff --git a/nixos/tests/systemd-binfmt-argv0.nix b/nixos/tests/systemd-binfmt-argv0.nix new file mode 100644 index 0000000000000..306cf0b053930 --- /dev/null +++ b/nixos/tests/systemd-binfmt-argv0.nix @@ -0,0 +1,32 @@ +# Test the default interpreter script correctly handle argv0 +# when `preserveArgvZero` is enabled. +import ./make-test-python.nix ({ pkgs, ... }: { + name = "systemd-binfmt-argv0"; + machine = { + boot.binfmt.emulatedSystems = [ "aarch64-linux" ]; + boot.binfmt.registrations."aarch64-linux".preserveArgvZero = true; + }; + + testScript = let + echoArgs = pkgs.pkgsCross.aarch64-multiplatform.runCommandCC "echo-args" {} '' + cat >echo.c < + int main(int argc, char **argv) { + printf("<"); + for (int i = 0; i < argc; ++i) + printf("%s-", argv[i]); + puts(">"); + return 0; + } + EOF + mkdir -p $out/bin + $CC echo.c -o $out/bin/echo -O2 + ''; + in '' + machine.start() + ret = machine.succeed( + "exec -a hello ${echoArgs}/bin/echo world" + ) + assert "" in ret, "Got: " + ret + ''; +})