diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 1263569e52ce..1eed27e00a54 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -236,6 +236,7 @@ in atuin = runTest ./atuin.nix; audiobookshelf = runTest ./audiobookshelf.nix; audit = runTest ./audit.nix; + audit-testsuite = runTest ./audit-testsuite.nix; auth-mysql = runTest ./auth-mysql.nix; authelia = runTest ./authelia.nix; auto-cpufreq = runTest ./auto-cpufreq.nix; diff --git a/nixos/tests/audit-testsuite.nix b/nixos/tests/audit-testsuite.nix new file mode 100644 index 000000000000..7c45de00544f --- /dev/null +++ b/nixos/tests/audit-testsuite.nix @@ -0,0 +1,45 @@ +{ lib, ... }: +{ + # https://github.com/linux-audit/audit-testsuite + # This test is meant to *only* run the audit regression testsuite. + # The test mutates the audit rules on the system it runs on, and can not run in the nix build sandbox. + # Thus a dedicated VM test makes sense. + + name = "audit-testsuite"; + + meta = { + maintainers = with lib.maintainers; [ grimmauld ]; + }; + + nodes.machine = + { pkgs, ... }: + { + # https://github.com/linux-audit/audit-testsuite/blob/5a10451642ac1ba2fa4b31c06a21cf9aa2d38b66/tests/amcast_joinpart/test#L86 + # tests use LC_TIME=en_DK.utf8 to force ISO 8601 date format + i18n.extraLocales = [ "en_DK.UTF-8/UTF-8" ]; + + security.polkit.enable = true; # needed for run0 + + security.audit.backlogLimit = 8192; + + security.auditd = { + enable = true; + plugins.af_unix.active = true; + settings = { + num_logs = 4; + disk_full_action = "rotate"; + }; + }; + + environment.systemPackages = [ pkgs.audit.testsuite.runner ]; + }; + + testScript = '' + start_all() + machine.wait_for_unit("auditd.service") + machine.wait_for_unit("network.target") # netfilter test requires network to be up + + # we need a valid session to which we can send commands, so we use run0 + machine.succeed("run0 --pty audit-testsuite-runner") + ''; +} diff --git a/pkgs/by-name/au/audit/package.nix b/pkgs/by-name/au/audit/package.nix index dbb8cd25ea56..197df3501597 100644 --- a/pkgs/by-name/au/audit/package.nix +++ b/pkgs/by-name/au/audit/package.nix @@ -26,6 +26,7 @@ nixosTests, pkgsStatic ? { }, # CI has allowVariants = false, in which case pkgsMusl would not be passed. So, instead add a default here. pkgsMusl ? { }, + callPackage, }: stdenv.mkDerivation (finalAttrs: { pname = "audit"; @@ -151,11 +152,12 @@ stdenv.mkDerivation (finalAttrs: { passthru = { updateScript = nix-update-script { }; + testsuite = callPackage ./testsuite.nix { }; tests = { musl = pkgsMusl.audit or null; static = pkgsStatic.audit or null; pkg-config = testers.testMetaPkgConfig finalAttrs.finalPackage; - audit = nixosTests.audit; + inherit (nixosTests) audit audit-testsuite; # Broken on a hardened kernel package = finalAttrs.finalPackage.overrideAttrs (previousAttrs: { pname = previousAttrs.pname + "-test"; diff --git a/pkgs/by-name/au/audit/testsuite.nix b/pkgs/by-name/au/audit/testsuite.nix new file mode 100644 index 000000000000..1acf9bbb523f --- /dev/null +++ b/pkgs/by-name/au/audit/testsuite.nix @@ -0,0 +1,150 @@ +{ + lib, + stdenv, + fetchFromGitHub, + fetchpatch, + unstableGitUpdater, + audit, + liburing, + nmap, + psmisc, + glibc, + perlPackages, + makeWrapper, + iptables, + coreutils, + writeShellApplication, + systemd, + iproute2, + inetutils, +}: +let + perlEnv = + with perlPackages; + makeFullPerlPath [ + FileWhich + TestMockTimeHiRes + SocketNetlink + ]; + testEnv = lib.makeBinPath [ + iptables + iproute2 # ip + inetutils # ping6 + ]; + + # syscall_socketcall: 32-bit tests are pain to build + # filter_exclude: relies on SELinux being enabled (`id -Z`) + # field_compare: weirdly flaky + disabledTests = [ + "syscall_socketcall" + "filter_exclude" + "field_compare" + ]; +in + +stdenv.mkDerivation (finalAttrs: { + pname = "audit-testsuite"; + version = "0-unstable-2025-08-30"; + + src = fetchFromGitHub { + owner = "linux-audit"; + repo = "audit-testsuite"; + rev = "25296c6623e95312437a58f76bb771ba31187bed"; + hash = "sha256-DeKcNOJVGhLSm7ZHYa6bOG2oSsbs3SH5UCLrbqzy+m4="; + }; + + patches = [ + # https://github.com/linux-audit/audit-testsuite/pull/125 + (fetchpatch { + url = "https://github.com/tweag/audit-testsuite/commit/bd3f8b612ce3290d86a82170e69ac510818d52e3.patch"; + hash = "sha256-rsSQ9uTjTEnDnB1Wlt2/Of2HmS+ajCIX7Iw/FRA4Fng="; + }) + ]; + + postPatch = '' + substituteInPlace tests/Makefile ${ + lib.concatMapStringsSep " " (t: "--replace-fail '${t}' ''") disabledTests + } + ''; + + passthru.updateScript = unstableGitUpdater { }; + + buildInputs = [ + perlPackages.perl + liburing + audit + nmap + psmisc + glibc + ]; + + nativeBuildInputs = [ + makeWrapper + ]; + + doCheck = false; # Can't run checks in the build sandbox, these checks are meant to run in a full VM + + installPhase = '' + runHook preInstall + + mkdir -p $out + pushd tests + find . -type f -executable -exec install -Dm755 "{}" $out/"{}" \; + popd + + rm -rf $out/{${lib.concatMapStringsSep "," lib.escapeShellArg disabledTests}} + + runHook postInstall + ''; + + # adapted from tests/Makefile + fixupPhase = '' + patchShebangs $out/runtests.pl + wrapProgram $out/runtests.pl \ + --set PERL5LIB ${perlEnv} \ + --set MODE ${toString stdenv.hostPlatform.parsed.cpu.bits} \ + --set ATS_DEBUG 1 \ + --set DISTRO nixos \ + --set TESTS "$(find $out -maxdepth 1 -mindepth 1 -type d -printf '%f\n' | sort | paste -sd' ')" \ + --prefix PATH : ${testEnv} + ''; + + passthru.runner = writeShellApplication { + name = "audit-testsuite-runner"; + runtimeInputs = [ + coreutils + systemd + ]; + text = '' + # log to journal for easier introspection in a VM test + exec &> >(tee >(systemd-cat -t audit-testsuite)) + testdir=$(mktemp -d) + export testdir + # test directory needs to be writable + cp -r ${finalAttrs.finalPackage}/* "$testdir" + cd "$testdir" + chmod +w -R . + + # exec_name test expects coreutils to be actual binaries in an absolute real path, + # no symlinks to /nix/store/-coreutils/bin/coreutils + # fix: copy coreutils to a temporary path where the actual binary can exist under that name + # https://github.com/linux-audit/audit-testsuite/blob/5a10451642ac1ba2fa4b31c06a21cf9aa2d38b66/tests/exec_name/test#L28-L47 + mkdir coreutils + for util in id echo ls ; do + cp "$(realpath "$(which "$util")")" coreutils/"$util" + done + sed -iE "s@/usr/bin/@$(pwd)/coreutils/@g" exec_name/test + + exec ./runtests.pl + ''; + }; + + meta = { + description = "A simple, self-contained regression test suite for the Linux Kernel's audit subsystem"; + homepage = "https://github.com/linux-audit/audit-testsuite"; + license = lib.licenses.gpl2Only; + maintainers = with lib.maintainers; [ grimmauld ]; + mainProgram = "audit-testsuite"; + platforms = lib.platforms.all; + }; +}) diff --git a/pkgs/top-level/perl-packages.nix b/pkgs/top-level/perl-packages.nix index 087c80b1bff1..66e94648bc2a 100644 --- a/pkgs/top-level/perl-packages.nix +++ b/pkgs/top-level/perl-packages.nix @@ -12628,6 +12628,23 @@ with self; }; }; + ExtUtilsH2PM = buildPerlPackage { + pname = "ExtUtils-H2PM"; + version = "0.11"; + src = fetchurl { + url = "mirror://cpan/authors/id/P/PE/PEVANS/ExtUtils-H2PM-0.11.tar.gz"; + hash = "sha256-RrSuyafSxXSSVtCdz3ukwtAM3dQRAUgkme2Ix2bp6No="; + }; + buildInputs = [ ModuleBuild ]; + meta = { + description = "Automatically generate perl modules to wrap C header files"; + license = with lib.licenses; [ + artistic1 + gpl1Plus + ]; + }; + }; + ExtUtilsInstall = buildPerlPackage { pname = "ExtUtils-Install"; version = "2.22"; @@ -30824,6 +30841,28 @@ with self; }; }; + SocketNetlink = buildPerlPackage { + pname = "Socket-Netlink"; + version = "0.05"; + src = fetchurl { + url = "mirror://cpan/authors/id/P/PE/PEVANS/Socket-Netlink-0.05.tar.gz"; + hash = "sha256-2EfbWbFI0I1A/gndoswlfvcvsetaDWgVX77csfWF2L0="; + }; + buildInputs = [ + ExtUtilsCChecker + ExtUtilsH2PM + TestHexString + ModuleBuild + ]; + meta = { + description = "Interface to Linux's C socket family"; + license = with lib.licenses; [ + artistic1 + gpl1Plus + ]; + }; + }; + SoftwareLicense = buildPerlPackage { pname = "Software-License"; version = "0.104004";