Skip to content

Commit 00bb4e6

Browse files
vadikabrianmcgillion
authored andcommitted
Memory wipe: use kernel config
- Enable PAGE_POISONING, INIT_ON_ALLOC_DEFAULT_ON, INIT_ON_FREE_DEFAULT_ON - Enable by default for all x86_64 platforms via hardware module - Update documentation to reflect build-time kernel configuration approach This provides runtime memory protection against information disclosure throughout system operation. Signed-off-by: vadik likholetov <[email protected]>
1 parent cd20eb7 commit 00bb4e6

File tree

7 files changed

+162
-46
lines changed

7 files changed

+162
-46
lines changed

docs/astro.config.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ export default defineConfig({
9494
"ghaf/dev/ref/idsvm-development",
9595
"ghaf/dev/ref/systemd-service-config",
9696
"ghaf/dev/ref/dynamic-hostname",
97+
"ghaf/dev/ref/memory-wipe",
9798
"ghaf/dev/ref/kill_switch",
9899
"ghaf/dev/ref/wireguard-gui",
99100
],
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
---
2+
title: Memory Wipe on Boot and Free
3+
description: Secure memory initialization and clearing using kernel configuration
4+
---
5+
6+
This module implements secure memory wiping by configuring the Linux kernel at build time to initialize memory on allocation and free operations.
7+
8+
## How it works
9+
10+
The module configures the kernel by applying kernel configuration patches:
11+
12+
- **`PAGE_POISONING`** - Enables page poisoning to overwrite freed pages
13+
- **`INIT_ON_ALLOC_DEFAULT_ON`** - Automatically zeroes memory when allocated from the page allocator
14+
- **`INIT_ON_FREE_DEFAULT_ON`** - Automatically zeroes memory when freed back to the page allocator
15+
16+
These settings are compiled into the kernel, ensuring:
17+
- Memory is wiped when freed, preventing data leakage between processes
18+
- Memory is zeroed on allocation, preventing information disclosure from previous allocations
19+
- The system maintains security throughout its runtime
20+
21+
## Default Behavior
22+
23+
This feature is **enabled by default** for the host kernel on all x86_64 platforms through the `hardware-x86_64-generic` module. Guest VMs do not have this feature enabled by default.
24+
25+
To disable it on x86_64 host platforms:
26+
27+
```nix
28+
{
29+
ghaf.host.kernel.memory-wipe.enable = false;
30+
}
31+
```
32+
33+
To enable it on other host platforms:
34+
35+
```nix
36+
{
37+
ghaf.host.kernel.memory-wipe.enable = true;
38+
}
39+
```
40+
41+
## Implementation Details
42+
43+
The module uses `boot.kernelPatches` to apply kernel configuration options at build time. This approach:
44+
- Integrates with the existing kernel build process
45+
- Works with any kernel package (doesn't force a specific kernel version)
46+
- Ensures security settings are part of the compiled kernel
47+
48+
## Security Benefits
49+
50+
- **Information Disclosure Prevention**: Prevents processes from reading sensitive data left in memory by previous processes
51+
- **Runtime Protection**: Active during the entire system operation
52+
- **Defense in Depth**: Multiple layers of memory clearing (page poisoning + init on free/alloc)
53+
- **Build-time Configuration**: Security settings are compiled into the kernel and cannot be disabled at runtime
54+
55+
## Performance Impact
56+
57+
Memory initialization on free and allocation operations adds a small performance overhead (typically 1-5%). This is a security vs. performance trade-off that prioritizes data protection. The overhead is generally acceptable for security-focused systems.
58+
59+
## Technical Requirements
60+
61+
- Linux kernel 5.3+ (for `init_on_free` and `init_on_alloc` support)
62+
- Kernel configuration support for `PAGE_POISONING`, `INIT_ON_ALLOC_DEFAULT_ON`, and `INIT_ON_FREE_DEFAULT_ON`
63+
- NixOS kernel build infrastructure
64+
65+
## Module Location
66+
67+
- **Module**: `modules/hardware/common/kernel.nix`
68+
- **Option**: `ghaf.host.kernel.memory-wipe.enable`
69+
- **Scope**: Host kernel only (guest VMs are not affected)
70+
- **Default enablement**: `modules/hardware/x86_64-generic/x86_64-linux.nix` (for x86_64 host platforms)

docs/src/content/docs/ghaf/dev/ref/modules.mdx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,18 @@ Ghaf provides 46 specialized NixOS modules that implement the secure edge comput
133133

134134
### Security and Isolation
135135

136+
#### kernel-memory-wipe
137+
**Location**: `modules/hardware/common/kernel.nix`
138+
**Option**: `ghaf.host.kernel.memory-wipe.enable`
139+
**Purpose**: Secure memory initialization and clearing via kernel configuration
140+
**Features**:
141+
- Build-time kernel configuration patches (`INIT_ON_ALLOC_DEFAULT_ON`, `INIT_ON_FREE_DEFAULT_ON`, `PAGE_POISONING`)
142+
- Enabled by default on x86_64 host platforms (not guest VMs)
143+
- Runtime memory protection against information disclosure
144+
- No boot parameters needed - compiled into kernel
145+
146+
See [Memory Wipe on Boot and Free](/ghaf/dev/ref/memory-wipe) for detailed documentation.
147+
136148
#### givc
137149
**Location**: `modules/givc/`
138150
**Purpose**: Guest-to-guest inter-VM communication

modules/hardware/common/kernel.nix

Lines changed: 71 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -41,59 +41,85 @@ in
4141
};
4242
};
4343

44-
config = {
45-
# Host kernel configuration
46-
boot = optionalAttrs fullVirtualization {
47-
initrd = {
48-
inherit (config.ghaf.hardware.definition.host.kernelConfig.stage1) kernelModules;
44+
options.ghaf.host.kernel.memory-wipe = {
45+
enable = lib.mkEnableOption "Memory wipe on boot and free using kernel configuration (host only)";
46+
};
47+
48+
config = lib.mkMerge [
49+
# Memory wipe kernel patches (applies to host only)
50+
{
51+
boot.kernelPatches = lib.optionals config.ghaf.host.kernel.memory-wipe.enable [
52+
{
53+
name = "memory-wipe-config";
54+
patch = null;
55+
structuredExtraConfig = with lib.kernel; {
56+
# Enable page poisoning for additional security
57+
PAGE_POISONING = yes;
58+
59+
# Enable init-on-alloc and init-on-free support
60+
INIT_ON_ALLOC_DEFAULT_ON = option yes;
61+
INIT_ON_FREE_DEFAULT_ON = option yes;
62+
};
63+
}
64+
];
65+
}
66+
67+
# Host kernel configuration (only for full virtualization)
68+
{
69+
boot = optionalAttrs fullVirtualization {
70+
initrd = {
71+
inherit (config.ghaf.hardware.definition.host.kernelConfig.stage1) kernelModules;
72+
};
73+
inherit (config.ghaf.hardware.definition.host.kernelConfig.stage2) kernelModules;
74+
kernelParams =
75+
let
76+
# PCI device passthroughs for vfio
77+
filterDevices = builtins.filter (d: d.vendorId != null && d.productId != null);
78+
mapPciIdsToString = map (d: "${d.vendorId}:${d.productId}");
79+
vfioPciIds = mapPciIdsToString (
80+
filterDevices (
81+
config.ghaf.hardware.definition.network.pciDevices
82+
++ config.ghaf.hardware.definition.gpu.pciDevices
83+
++ config.ghaf.hardware.definition.audio.pciDevices
84+
)
85+
);
86+
in
87+
config.ghaf.hardware.definition.host.kernelConfig.kernelParams
88+
++ [ "vfio-pci.ids=${builtins.concatStringsSep "," vfioPciIds}" ];
4989
};
50-
inherit (config.ghaf.hardware.definition.host.kernelConfig.stage2) kernelModules;
51-
kernelParams =
52-
let
53-
# PCI device passthroughs for vfio
54-
filterDevices = builtins.filter (d: d.vendorId != null && d.productId != null);
55-
mapPciIdsToString = map (d: "${d.vendorId}:${d.productId}");
56-
vfioPciIds = mapPciIdsToString (
57-
filterDevices (
58-
config.ghaf.hardware.definition.network.pciDevices
59-
++ config.ghaf.hardware.definition.gpu.pciDevices
60-
++ config.ghaf.hardware.definition.audio.pciDevices
61-
)
62-
);
63-
in
64-
config.ghaf.hardware.definition.host.kernelConfig.kernelParams
65-
++ [ "vfio-pci.ids=${builtins.concatStringsSep "," vfioPciIds}" ];
66-
};
90+
}
6791

6892
# Guest kernel configurations
69-
ghaf.kernel = optionalAttrs fullVirtualization {
70-
guivm = {
71-
boot = {
72-
initrd = {
73-
inherit (config.ghaf.hardware.definition.gpu.kernelConfig.stage1) kernelModules;
93+
{
94+
ghaf.kernel = optionalAttrs fullVirtualization {
95+
guivm = {
96+
boot = {
97+
initrd = {
98+
inherit (config.ghaf.hardware.definition.gpu.kernelConfig.stage1) kernelModules;
99+
};
100+
inherit (config.ghaf.hardware.definition.gpu.kernelConfig.stage2) kernelModules;
101+
inherit (config.ghaf.hardware.definition.gpu.kernelConfig) kernelParams;
74102
};
75-
inherit (config.ghaf.hardware.definition.gpu.kernelConfig.stage2) kernelModules;
76-
inherit (config.ghaf.hardware.definition.gpu.kernelConfig) kernelParams;
77103
};
78-
};
79-
audiovm = {
80-
boot = {
81-
initrd = {
82-
inherit (config.ghaf.hardware.definition.audio.kernelConfig.stage1) kernelModules;
104+
audiovm = {
105+
boot = {
106+
initrd = {
107+
inherit (config.ghaf.hardware.definition.audio.kernelConfig.stage1) kernelModules;
108+
};
109+
inherit (config.ghaf.hardware.definition.audio.kernelConfig.stage2) kernelModules;
110+
inherit (config.ghaf.hardware.definition.audio.kernelConfig) kernelParams;
83111
};
84-
inherit (config.ghaf.hardware.definition.audio.kernelConfig.stage2) kernelModules;
85-
inherit (config.ghaf.hardware.definition.audio.kernelConfig) kernelParams;
86112
};
87-
};
88-
netvm = {
89-
boot = {
90-
initrd = {
91-
inherit (config.ghaf.hardware.definition.network.kernelConfig.stage1) kernelModules;
113+
netvm = {
114+
boot = {
115+
initrd = {
116+
inherit (config.ghaf.hardware.definition.network.kernelConfig.stage1) kernelModules;
117+
};
118+
inherit (config.ghaf.hardware.definition.network.kernelConfig.stage2) kernelModules;
119+
inherit (config.ghaf.hardware.definition.network.kernelConfig) kernelParams;
92120
};
93-
inherit (config.ghaf.hardware.definition.network.kernelConfig.stage2) kernelModules;
94-
inherit (config.ghaf.hardware.definition.network.kernelConfig) kernelParams;
95121
};
96122
};
97-
};
98-
};
123+
}
124+
];
99125
}

modules/hardware/flake-module.nix

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@
77
./x86_64-generic
88
./common
99
./device-passthrough
10+
./common/kernel.nix
1011
];
1112
hardware-x86_64-generic.imports = [
1213
./definition.nix
1314
./x86_64-generic
1415
./device-passthrough
1516
./common/usb/vhotplug.nix
17+
./common/kernel.nix
1618
];
1719
hardware-x86_64-host-kernel.imports = [
1820
./x86_64-generic/kernel/host

modules/hardware/x86_64-generic/x86_64-linux.nix

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ in
1414
};
1515

1616
config = lib.mkIf cfg.enable {
17+
# Enable memory wiping for x86_64 host platforms
18+
ghaf.host.kernel.memory-wipe.enable = lib.mkDefault true;
1719

1820
# Add this for x86_64 hosts to be able to more generically support hardware.
1921
# For example Intel NUC 11's graphics card needs this in order to be able to

targets/vm/flake-module.nix

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ let
1818
};
1919
modules = [
2020
(builtins.getAttr format nixos-generators.nixosModules)
21+
self.nixosModules.common
2122
self.nixosModules.microvm
2223
self.nixosModules.profiles
2324
self.nixosModules.reference-appvms
@@ -108,7 +109,9 @@ let
108109
guivm.enable = withGraphics;
109110
};
110111

111-
host.networking.enable = true;
112+
host = {
113+
networking.enable = true;
114+
};
112115

113116
# Enable all the default UI applications
114117
profiles = {

0 commit comments

Comments
 (0)