Skip to content

Commit 61991e7

Browse files
committed
docs: update docs
1 parent 438ba9d commit 61991e7

4 files changed

Lines changed: 75 additions & 22 deletions

File tree

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ version of this technique as `dmesg_free_reserved_area.c`, which additionally
288288
classifies the address by range and derives the physical address on coupled
289289
architectures. To see this exact result flow through a rule, the engine, and the
290290
rendered output, follow
291-
[the end-to-end walkthrough](../docs/architecture.md#a-leak-from-end-to-end).
291+
[the end-to-end walkthrough](docs/architecture.md#a-leak-from-end-to-end).
292292
293293
Components that leak a physical address with a known extent (e.g. a
294294
`/proc/iomem` region) should use `kasld_result_range` to convey both

README.md

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,20 @@
88
<img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License: MIT"/>
99
</p>
1010

11-
KASLD derandomizes the Linux kernel's virtual and physical memory layout
12-
as an unprivileged local user. It recovers the kernel text base where a
13-
leak or side channel allows, and otherwise reduces it to the smallest set
14-
of placements the available evidence supports. On a fully-patched modern
11+
KASLD answers a practical question: **how effective is KASLR on this
12+
system, against an unprivileged local attacker?** It derandomizes the
13+
Linux kernel's virtual and physical memory layout from an unprivileged
14+
local process — recovering the kernel text base outright where a leak or
15+
side channel allows, and otherwise narrowing it to the smallest set of
16+
placements the available evidence supports. The inference engine fuses
17+
evidence from dozens of independent techniques with the architecture's
18+
known invariants, narrowing the kernel's placement to a residual window —
19+
reported as the surviving slot count and bits of entropy: a measure of
20+
how much protection KASLR actually retains. On a fully-patched modern
1521
kernel — where x86-64 side channels are mitigated and no direct
1622
kernel-text leak survives — full recovery is often impossible, but the
17-
constraint set is rarely empty. The inference engine combines parsed
18-
bootloader artifacts, `dmesg` landmarks, `/proc` and `/sys` facts, and
19-
architectural invariants to narrow the kernel's possible placement to a
20-
residual window, reported as the surviving slot count and bits of
21-
entropy. On architectures without KASLR, the engine locates the
22-
bootloader-chosen load address.
23+
constraint set is rarely empty. On architectures without KASLR, the
24+
engine locates the bootloader-chosen load address.
2325

2426
Supports:
2527

@@ -61,7 +63,7 @@ can temporarily relax these settings (requires root).
6163
The default text mode prints an answer-first overview:
6264

6365
```
64-
KASLD 0.3.0 -- Kernel ASLR derandomization
66+
KASLD 0.3.1-dev -- Kernel ASLR derandomization
6567
Target: x86_64 / 6.15.6
6668
6769
Running 83 components (10 experimental skipped; use -x to enable)...
@@ -71,9 +73,7 @@ Running 83 components (10 experimental skipped; use -x to enable)...
7173
Physical image base not derandomized ~9 bits
7274
0x0000000001000000 - 0x000000003c20ca00 (473 x 2.0 MiB)
7375
Direct map base >= 0xffff800000000000
74-
75-
Coupling virt and phys text are independent on this arch.
76-
A phys leak does NOT reveal the virt text base.
76+
Phys/Virt Coupling physical and virtual text randomize independently
7777
7878
Leaks (1):
7979
virt kernel text 0xffffffff83800000 (prefetch)
@@ -92,6 +92,12 @@ details, explain mode, and hardening assessment.
9292

9393
## Documentation
9494

95+
New to KASLD? Read in order: [docs/kaslr.md](docs/kaslr.md) (what KASLR is and
96+
what it randomizes) → [docs/architecture.md → A leak from end to
97+
end](docs/architecture.md#a-leak-from-end-to-end) (how KASLD turns one leak into
98+
an answer) → [CONTRIBUTING.md](CONTRIBUTING.md) (add a leak component or
99+
inference rule). The table below is the per-audience reference.
100+
95101
| Audience | Document |
96102
|---|---|
97103
| End user / operator | [docs/usage.md](docs/usage.md) — CLI, output modes, explain mode, hardening assessment |

docs/architecture.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ mechanics of adding a component or rule, see
2222
- [Phases](#phases)
2323
- [The inference engine](#the-inference-engine)
2424
- [Three layers](#three-layers)
25+
- [A constraint feeding the next pass](#a-constraint-feeding-the-next-pass)
2526
- [Soundness, monotonicity, and termination](#soundness-monotonicity-and-termination)
2627
- [Estimate narrowing and the store-vs-read seam](#estimate-narrowing-and-the-store-vs-read-seam)
2728
- [Design invariants: seams in the data flow](#design-invariants-seams-in-the-data-flow)
@@ -201,6 +202,38 @@ estimates then drive the reported summary, slot counts, and entropy. Every rule
201202
is listed once in `../src/engine_rules.c`, the single registry shared by the
202203
orchestrator and the test suite.
203204

205+
### A constraint feeding the next pass
206+
207+
The fixpoint earns its keep when one quantity's estimate is *input* to another
208+
rule. A worked example on x86_64, where the `vmalloc` base floor depends on the
209+
direct-map base (`Q_PAGE_OFFSET`):
210+
211+
**Pass 1**`randomize_memory_page_offset` reads a direct-map leak and a RAM
212+
base record and resolves `Q_PAGE_OFFSET`:
213+
214+
```
215+
Q_PAGE_OFFSET full VAS window -> 0xffff8a0000000000
216+
Q_VMALLOC_BASE unchanged — its rule has no tight PAGE_OFFSET to read yet
217+
```
218+
219+
**Pass 2**`x86_64_vmalloc_base_bound` now reads the tightened `Q_PAGE_OFFSET`
220+
plus `max_pfn` (the direct-map span, from physical memory size) and raises the
221+
`vmalloc` floor to `PAGE_OFFSET + directmap_span + PUD_SIZE`:
222+
223+
```
224+
Q_VMALLOC_BASE >= 0xffff8a0000000000 + 0x10000000000 + 0x40000000
225+
= 0xffff8b0040000000 (C_LOWER_BOUND, conf=inferred)
226+
```
227+
228+
**Pass 3** — every rule re-runs; nothing narrows further, so the engine stops.
229+
230+
The `vmalloc` floor could not have been computed in pass 1: its rule reads
231+
`est[Q_PAGE_OFFSET]`, which was still the full window until pass 1 tightened it.
232+
That is why the resolver iterates — and why rule order is irrelevant. Had the
233+
`vmalloc` rule run first, it would have read the wide `PAGE_OFFSET`, emitted a
234+
weak bound, and re-emitted the tight one on the next pass once `PAGE_OFFSET`
235+
resolved. Because estimates only narrow, re-emission can never undo progress.
236+
204237
### Soundness, monotonicity, and termination
205238

206239
Three properties make that fixpoint well-defined and the result trustworthy:

docs/usage.md

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ derived from, and a hint about the verbose mode. No banner, no system
8888
config, no memory-layout diagram.
8989

9090
```
91-
KASLD 0.3.0 -- Kernel ASLR derandomization
91+
KASLD 0.3.1-dev -- Kernel ASLR derandomization
9292
Target: x86_64 / 6.15.6
9393
9494
Running 83 components (10 experimental skipped; use -x to enable)...
@@ -98,16 +98,19 @@ Running 83 components (10 experimental skipped; use -x to enable)...
9898
Physical image base not derandomized ~9 bits
9999
0x0000000001000000 - 0x000000003c20ca00 (473 x 2.0 MiB)
100100
Direct map base >= 0xffff800000000000
101-
102-
Coupling virt and phys text are independent on this arch.
103-
A phys leak does NOT reveal the virt text base.
101+
Phys/Virt Coupling physical and virtual text randomize independently
104102
105103
Leaks (1):
106104
virt kernel text 0xffffffff83800000 (prefetch)
107105
108106
[-v: detailed results, memory map, system info] [-H: hardening assessment]
109107
```
110108

109+
Terms in this readout (slide, directmap, coupling, slot/entropy) are defined in
110+
the [kaslr.md glossary](kaslr.md#glossary); the engine vocabulary behind them
111+
(quantity, estimate, honest top) is in the
112+
[architecture.md glossary](architecture.md#glossary).
113+
111114
### Verbose (`-v`)
112115

113116
`-v` (`--verbose`) restores the full banner, system-config block,
@@ -126,7 +129,7 @@ and a compact bracket-format virtual + physical memory layout:
126129
███▐██▄ ███ ███ ███ ███ ███ ███
127130
███ ▀███▄ ███ ███ ▄█ ███ ███▌ ▄ ███ ▄███
128131
███ ▀█▀ ███ █▀ ▄████████▀ █████▄▄██ ████████▀
129-
▀ ▀ v0.3.0
132+
▀ ▀ v0.3.1-dev
130133
131134
Kernel release: 6.15.6
132135
Kernel version: #1 SMP PREEMPT_DYNAMIC Wed Jun 17 13:04:17 EDT 2026
@@ -666,8 +669,10 @@ their machine-readable metadata. The assessment has seven sections:
666669
no PRNG, insufficient memory). The kernel still relocates but lands
667670
at a firmware-/boot-stub-deterministic position rather than the
668671
link-time default — meaningfully different from a deliberate
669-
opt-out, which the main results banner already reports. Omitted
670-
when KASLR is healthy or opted out.
672+
opt-out, which the main results banner already reports. The full set
673+
of runtime states is catalogued in
674+
[kaslr.md — KASLR runtime states](kaslr.md#kaslr-runtime-states).
675+
Omitted when KASLR is healthy or opted out.
671676

672677
2. **Active defenses** — runtime security settings detected on the system
673678
(`dmesg_restrict`, `kptr_restrict`, `perf_event_paranoid`, `%pK` pointer
@@ -694,6 +699,15 @@ their machine-readable metadata. The assessment has seven sections:
694699
represent leak vectors that cannot be blocked by runtime hardening
695700
alone.
696701

702+
When the kernel-text function order can be determined, the assessment also
703+
prints a **Function layout** block above these sections: `text ordering`
704+
(canonical, or reordered static / per-boot) and `symbol resolution` (whether a
705+
generic `System.map` resolves symbols, or only this build's does). Reordered
706+
text is the [FG-KASLR / reordered-text class](kaslr.md#function-granular-kaslr-fg-kaslr)
707+
(LTO, AutoFDO, Propeller, or FG-KASLR): functions no longer sit at a constant
708+
offset from `_text`, so a leaked address pins only its own symbol and a generic
709+
`System.map` no longer locates the rest.
710+
697711
The hardening assessment is also available in JSON output (`-j -H`),
698712
where it appears in a top-level `"hardening"` object with fields
699713
`exposure`, `kaslr_posture` (always present; `state` is one of

0 commit comments

Comments
 (0)