at 21.11-pre 4.2 kB view raw
1import ./make-test-python.nix ({ pkgs, latestKernel ? false, ... } : { 2 name = "hardened"; 3 meta = with pkgs.lib.maintainers; { 4 maintainers = [ joachifm ]; 5 }; 6 7 machine = 8 { lib, pkgs, config, ... }: 9 with lib; 10 { users.users.alice = { isNormalUser = true; extraGroups = [ "proc" ]; }; 11 users.users.sybil = { isNormalUser = true; group = "wheel"; }; 12 imports = [ ../modules/profiles/hardened.nix ]; 13 boot.kernelPackages = 14 lib.mkIf latestKernel pkgs.linuxPackages_latest_hardened; 15 environment.memoryAllocator.provider = "graphene-hardened"; 16 nix.useSandbox = false; 17 virtualisation.emptyDiskImages = [ 4096 ]; 18 boot.initrd.postDeviceCommands = '' 19 ${pkgs.dosfstools}/bin/mkfs.vfat -n EFISYS /dev/vdb 20 ''; 21 virtualisation.fileSystems = { 22 "/efi" = { 23 device = "/dev/disk/by-label/EFISYS"; 24 fsType = "vfat"; 25 options = [ "noauto" ]; 26 }; 27 }; 28 boot.extraModulePackages = 29 optional (versionOlder config.boot.kernelPackages.kernel.version "5.6") 30 config.boot.kernelPackages.wireguard; 31 boot.kernelModules = [ "wireguard" ]; 32 }; 33 34 testScript = 35 let 36 hardened-malloc-tests = pkgs.stdenv.mkDerivation { 37 name = "hardened-malloc-tests-${pkgs.graphene-hardened-malloc.version}"; 38 src = pkgs.graphene-hardened-malloc.src; 39 buildPhase = '' 40 cd test/simple-memory-corruption 41 make -j4 42 ''; 43 44 installPhase = '' 45 find . -type f -executable -exec install -Dt $out/bin '{}' + 46 ''; 47 }; 48 in 49 '' 50 machine.wait_for_unit("multi-user.target") 51 52 53 with subtest("AppArmor profiles are loaded"): 54 machine.succeed("systemctl status apparmor.service") 55 56 57 # AppArmor securityfs 58 with subtest("AppArmor securityfs is mounted"): 59 machine.succeed("mountpoint -q /sys/kernel/security") 60 machine.succeed("cat /sys/kernel/security/apparmor/profiles") 61 62 63 # Test loading out-of-tree modules 64 with subtest("Out-of-tree modules can be loaded"): 65 machine.succeed("grep -Fq wireguard /proc/modules") 66 67 68 # Test kernel module hardening 69 with subtest("No more kernel modules can be loaded"): 70 # note: this better a be module we normally wouldn't load ... 71 machine.fail("modprobe dccp") 72 73 74 # Test userns 75 with subtest("User namespaces are restricted"): 76 machine.succeed("unshare --user true") 77 machine.fail("su -l alice -c 'unshare --user true'") 78 79 80 # Test dmesg restriction 81 with subtest("Regular users cannot access dmesg"): 82 machine.fail("su -l alice -c dmesg") 83 84 85 # Test access to kcore 86 with subtest("Kcore is inaccessible as root"): 87 machine.fail("cat /proc/kcore") 88 89 90 # Test deferred mount 91 with subtest("Deferred mounts work"): 92 machine.fail("mountpoint -q /efi") # was deferred 93 machine.execute("mkdir -p /efi") 94 machine.succeed("mount /dev/disk/by-label/EFISYS /efi") 95 machine.succeed("mountpoint -q /efi") # now mounted 96 97 98 # Test Nix dæmon usage 99 with subtest("nix-daemon cannot be used by all users"): 100 machine.fail("su -l nobody -s /bin/sh -c 'nix ping-store'") 101 machine.succeed("su -l alice -c 'nix ping-store'") 102 103 104 # Test kernel image protection 105 with subtest("The kernel image is protected"): 106 machine.fail("systemctl hibernate") 107 machine.fail("systemctl kexec") 108 109 110 # Test hardened memory allocator 111 def runMallocTestProg(prog_name, error_text): 112 text = "fatal allocator error: " + error_text 113 if not text in machine.fail( 114 "${hardened-malloc-tests}/bin/" 115 + prog_name 116 + " 2>&1" 117 ): 118 raise Exception("Hardened malloc does not work for {}".format(error_text)) 119 120 121 with subtest("The hardened memory allocator works"): 122 runMallocTestProg("double_free_large", "invalid free") 123 runMallocTestProg("unaligned_free_small", "invalid unaligned free") 124 runMallocTestProg("write_after_free_small", "detected write after free") 125 ''; 126})