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 An allocator designed to mitigate memory corruption attacks, such as
13 those caused by use-after-free bugs.
14 '';
15 };
16
17 jemalloc = {
18 libPath = "${pkgs.jemalloc}/lib/libjemalloc.so";
19 description = ''
20 A general purpose allocator that emphasizes fragmentation avoidance
21 and scalable concurrency support.
22 '';
23 };
24
25 scudo = {
26 libPath = "${pkgs.llvmPackages_latest.compiler-rt}/lib/linux/libclang_rt.scudo-x86_64.so";
27 description = ''
28 A user-mode allocator based on LLVM Sanitizer’s CombinedAllocator,
29 which aims at providing additional mitigations against heap based
30 vulnerabilities, while maintaining good performance.
31 '';
32 };
33 };
34
35 providerConf = providers.${cfg.provider};
36
37 # An output that contains only the shared library, to avoid
38 # needlessly bloating the system closure
39 mallocLib = pkgs.runCommand "malloc-provider-${cfg.provider}"
40 rec {
41 preferLocalBuild = true;
42 allowSubstitutes = false;
43 origLibPath = providerConf.libPath;
44 libName = baseNameOf origLibPath;
45 }
46 ''
47 mkdir -p $out/lib
48 cp -L $origLibPath $out/lib/$libName
49 '';
50
51 # The full path to the selected provider shlib.
52 providerLibPath = "${mallocLib}/lib/${mallocLib.libName}";
53in
54
55{
56 meta = {
57 maintainers = [ maintainers.joachifm ];
58 };
59
60 options = {
61 environment.memoryAllocator.provider = mkOption {
62 type = types.enum ([ "libc" ] ++ attrNames providers);
63 default = "libc";
64 description = ''
65 The system-wide memory allocator.
66
67 Briefly, the system-wide memory allocator providers are:
68 <itemizedlist>
69 <listitem><para><literal>libc</literal>: the standard allocator provided by libc</para></listitem>
70 ${toString (mapAttrsToList
71 (name: value: "<listitem><para><literal>${name}</literal>: ${value.description}</para></listitem>")
72 providers)}
73 </itemizedlist>
74
75 <warning>
76 <para>
77 Selecting an alternative allocator (i.e., anything other than
78 <literal>libc</literal>) may result in instability, data loss,
79 and/or service failure.
80 </para>
81 </warning>
82 '';
83 };
84 };
85
86 config = mkIf (cfg.provider != "libc") {
87 environment.etc."ld-nix.so.preload".text = ''
88 ${providerLibPath}
89 '';
90 security.apparmor.includes = {
91 "abstractions/base" = ''
92 r /etc/ld-nix.so.preload,
93 r ${config.environment.etc."ld-nix.so.preload".source},
94 mr ${providerLibPath},
95 '';
96 };
97 };
98}