at 24.11-pre 4.2 kB view raw
1{ config, lib, pkgs, ... }: 2with lib; 3 4let 5 cfg = config.environment.memoryAllocator; 6 7 # The set of alternative malloc(3) providers. 8 providers = { 9 graphene-hardened = { 10 libPath = "${pkgs.graphene-hardened-malloc}/lib/libhardened_malloc.so"; 11 description = '' 12 Hardened memory allocator coming from GrapheneOS project. 13 The default configuration template has all normal optional security 14 features enabled and is quite aggressive in terms of sacrificing 15 performance and memory usage for security. 16 ''; 17 }; 18 19 graphene-hardened-light = { 20 libPath = "${pkgs.graphene-hardened-malloc}/lib/libhardened_malloc-light.so"; 21 description = '' 22 Hardened memory allocator coming from GrapheneOS project. 23 The light configuration template disables the slab quarantines, 24 write after free check, slot randomization and raises the guard 25 slab interval from 1 to 8 but leaves zero-on-free and slab canaries enabled. 26 The light configuration has solid performance and memory usage while still 27 being far more secure than mainstream allocators with much better security 28 properties. 29 ''; 30 }; 31 32 jemalloc = { 33 libPath = "${pkgs.jemalloc}/lib/libjemalloc.so"; 34 description = '' 35 A general purpose allocator that emphasizes fragmentation avoidance 36 and scalable concurrency support. 37 ''; 38 }; 39 40 scudo = let 41 platformMap = { 42 aarch64-linux = "aarch64"; 43 x86_64-linux = "x86_64"; 44 }; 45 46 systemPlatform = platformMap.${pkgs.stdenv.hostPlatform.system} or (throw "scudo not supported on ${pkgs.stdenv.hostPlatform.system}"); 47 in { 48 libPath = "${pkgs.llvmPackages_14.compiler-rt}/lib/linux/libclang_rt.scudo-${systemPlatform}.so"; 49 description = '' 50 A user-mode allocator based on LLVM Sanitizers CombinedAllocator, 51 which aims at providing additional mitigations against heap based 52 vulnerabilities, while maintaining good performance. 53 ''; 54 }; 55 56 mimalloc = { 57 libPath = "${pkgs.mimalloc}/lib/libmimalloc.so"; 58 description = '' 59 A compact and fast general purpose allocator, which may 60 optionally be built with mitigations against various heap 61 vulnerabilities. 62 ''; 63 }; 64 }; 65 66 providerConf = providers.${cfg.provider}; 67 68 # An output that contains only the shared library, to avoid 69 # needlessly bloating the system closure 70 mallocLib = pkgs.runCommand "malloc-provider-${cfg.provider}" 71 rec { 72 preferLocalBuild = true; 73 allowSubstitutes = false; 74 origLibPath = providerConf.libPath; 75 libName = baseNameOf origLibPath; 76 } 77 '' 78 mkdir -p $out/lib 79 cp -L $origLibPath $out/lib/$libName 80 ''; 81 82 # The full path to the selected provider shlib. 83 providerLibPath = "${mallocLib}/lib/${mallocLib.libName}"; 84in 85 86{ 87 meta = { 88 maintainers = [ maintainers.joachifm ]; 89 }; 90 91 options = { 92 environment.memoryAllocator.provider = mkOption { 93 type = types.enum ([ "libc" ] ++ attrNames providers); 94 default = "libc"; 95 description = '' 96 The system-wide memory allocator. 97 98 Briefly, the system-wide memory allocator providers are: 99 100 - `libc`: the standard allocator provided by libc 101 ${concatStringsSep "\n" (mapAttrsToList 102 (name: value: "- `${name}`: ${replaceStrings [ "\n" ] [ " " ] value.description}") 103 providers)} 104 105 ::: {.warning} 106 Selecting an alternative allocator (i.e., anything other than 107 `libc`) may result in instability, data loss, 108 and/or service failure. 109 ::: 110 ''; 111 }; 112 }; 113 114 config = mkIf (cfg.provider != "libc") { 115 environment.etc."ld-nix.so.preload".text = '' 116 ${providerLibPath} 117 ''; 118 security.apparmor.includes = { 119 "abstractions/base" = '' 120 r /etc/ld-nix.so.preload, 121 r ${config.environment.etc."ld-nix.so.preload".source}, 122 include "${pkgs.apparmorRulesFromClosure { 123 name = "mallocLib"; 124 baseRules = ["mr $path/lib/**.so*"]; 125 } [ mallocLib ] }" 126 ''; 127 }; 128 }; 129}