summary refs log tree commit diff
path: root/pkgs/build-support/grsecurity/default.nix
blob: 3bf40a2e8d6b2a5917393cbc2ff92f32efa0bcae (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
{ grsecOptions, lib, pkgs }:

with lib;

let
  cfg = {
    stable  = grsecOptions.stable  or false;
    testing = grsecOptions.testing or false;
    config = {
      mode = "auto";
      sysctl = false;
      denyChrootChmod = false;
      denyUSB = false;
      restrictProc = false;
      restrictProcWithGroup = true;
      unrestrictProcGid = 121; # Ugh, an awful hack. See grsecurity NixOS gid
      disableRBAC = false;
      verboseVersion = false;
      kernelExtraConfig = "";
    } // grsecOptions.config;
  };

  vals = rec {

    mkKernel = kernel: patch:
      assert patch.kversion == kernel.version;
        { inherit kernel patch;
          inherit (patch) grversion revision;
        };

    test-patch = with pkgs.kernelPatches; grsecurity_unstable;
    stable-patch = with pkgs.kernelPatches; grsecurity_stable;

    grKernel = if cfg.stable
               then mkKernel pkgs.linux_3_14 stable-patch
               else mkKernel pkgs.linux_4_2 test-patch;

    ## -- grsecurity configuration ---------------------------------------------

    grsecPrioCfg =
      if cfg.config.priority == "security" then
        "GRKERNSEC_CONFIG_PRIORITY_SECURITY y"
      else
        "GRKERNSEC_CONFIG_PRIORITY_PERF y";

    grsecSystemCfg =
      if cfg.config.system == "desktop" then
        "GRKERNSEC_CONFIG_DESKTOP y"
      else
        "GRKERNSEC_CONFIG_SERVER y";

    grsecVirtCfg =
      if cfg.config.virtualisationConfig == null then
        "GRKERNSEC_CONFIG_VIRT_NONE y"
      else if cfg.config.virtualisationConfig == "host" then
        "GRKERNSEC_CONFIG_VIRT_HOST y"
      else
        "GRKERNSEC_CONFIG_VIRT_GUEST y";

    grsecHwvirtCfg = if cfg.config.virtualisationConfig == null then "" else
      if cfg.config.hardwareVirtualisation == true then
        "GRKERNSEC_CONFIG_VIRT_EPT y"
      else
        "GRKERNSEC_CONFIG_VIRT_SOFT y";

    grsecVirtswCfg =
      let virtCfg = opt: "GRKERNSEC_CONFIG_VIRT_"+opt+" y";
      in
        if cfg.config.virtualisationConfig == null then ""
        else if cfg.config.virtualisationSoftware == "xen"    then virtCfg "XEN"
        else if cfg.config.virtualisationSoftware == "kvm"    then virtCfg "KVM"
        else if cfg.config.virtualisationSoftware == "vmware" then virtCfg "VMWARE"
        else                                                       virtCfg "VIRTUALBOX";

    grsecMainConfig = if cfg.config.mode == "custom" then "" else ''
      GRKERNSEC_CONFIG_AUTO y
      ${grsecPrioCfg}
      ${grsecSystemCfg}
      ${grsecVirtCfg}
      ${grsecHwvirtCfg}
      ${grsecVirtswCfg}
    '';

    grsecConfig =
      let boolToKernOpt = b: if b then "y" else "n";
          # Disable RANDSTRUCT under virtualbox, as it has some kind of
          # breakage with the vbox guest drivers
          #randstruct = optionalString config.virtualisation.virtualbox.guest.enable
          #  "GRKERNSEC_RANDSTRUCT n";

          # Disable restricting links under the testing kernel, as something
          # has changed causing it to fail miserably during boot.
          restrictLinks = optionalString cfg.testing
            "GRKERNSEC_LINK n";
      in ''
        GRKERNSEC y
        ${grsecMainConfig}

        ${if cfg.config.restrictProc then
            "GRKERNSEC_PROC_USER y"
          else
            optionalString cfg.config.restrictProcWithGroup ''
              GRKERNSEC_PROC_USERGROUP y
              GRKERNSEC_PROC_GID ${toString cfg.config.unrestrictProcGid}
            ''
        }

        GRKERNSEC_SYSCTL ${boolToKernOpt cfg.config.sysctl}
        GRKERNSEC_CHROOT_CHMOD ${boolToKernOpt cfg.config.denyChrootChmod}
        GRKERNSEC_DENYUSB ${boolToKernOpt cfg.config.denyUSB}
        GRKERNSEC_NO_RBAC ${boolToKernOpt cfg.config.disableRBAC}
        ${restrictLinks}

        ${cfg.config.kernelExtraConfig}
      '';

    ## -- grsecurity kernel packages -------------------------------------------

    localver = grkern:
      "-grsec" + optionalString cfg.config.verboseVersion
         "-${grkern.grversion}-${grkern.revision}";

    grsecurityOverrider = args: grkern: {
      # Apparently as of gcc 4.6, gcc-plugin headers (which are needed by PaX plugins)
      # include libgmp headers, so we need these extra tweaks
      buildInputs = args.buildInputs ++ [ pkgs.gmp ];
      preConfigure = ''
        ${args.preConfigure or ""}
        sed -i 's|-I|-I${pkgs.gmp}/include -I|' scripts/gcc-plugin.sh
        sed -i 's|HOST_EXTRACFLAGS +=|HOST_EXTRACFLAGS += -I${pkgs.gmp}/include|' tools/gcc/Makefile
        sed -i 's|HOST_EXTRACXXFLAGS +=|HOST_EXTRACXXFLAGS += -I${pkgs.gmp}/include|' tools/gcc/Makefile
        rm localversion-grsec
        echo ${localver grkern} > localversion-grsec
      '';
    };

    mkGrsecKern = grkern:
      lowPrio (overrideDerivation (grkern.kernel.override (args: {
        kernelPatches = args.kernelPatches ++ [ grkern.patch pkgs.kernelPatches.grsec_fix_path ];
        argsOverride = {
          modDirVersion = "${grkern.kernel.modDirVersion}${localver grkern}";
        };
        extraConfig = grsecConfig;
        features.grsecurity = true;
      })) (args: grsecurityOverrider args grkern));

    mkGrsecPkg = grkern: pkgs.linuxPackagesFor grkern (mkGrsecPkg grkern);

    ## -- Kernel packages ------------------------------------------------------

    grsecKernel  = mkGrsecKern grKernel;
    grsecPackage = mkGrsecPkg grsecKernel;
  };
in vals