Skip to content

Commit 6997ea4

Browse files
committed
render: give the readout one grammar and state entropy once
The compact readout, the evidence list and the verbose Memory KASLR block each described the same kinds of thing their own way: three range notations, three vocabularies for a grade, and a label column that the longest quantity name filled exactly, so "Physical image base not derandomized" read as a sentence rather than two columns. Quantity names now head their own block with a bracketed verdict, every value row states its grade, windows print first and last candidate over ".." with the count and pitch beside them, and addresses are right-aligned without zero padding so a 16 MiB physical address is not dressed as a 64-bit pointer. Window edges snap to the candidate grid: an edge off the grid is a bound, not a value the quantity can take. Residual entropy is stated once per quantity, against the entropy the KASLR window started with where that is a randomization window rather than an addressable range -- true for the virtual base, not for the physical or direct-map tops. The leak list becomes "Evidence": it carries side-channel measurements alongside disclosures, and only the latter are leaks. The extent-position tag precedes the value it qualifies, provenance moves to its own line introduced by "from" so component names cannot be read as kernel symbols, and the heading counts findings and contributing components separately. The Memory KASLR block gets the same notation, and its direct-map row is now named and formatted exactly as the readout names it -- previously one quantity appeared as "Direct map base" in one view and "virt_page_offset_base" in the other with nothing relating them. Its residual entropy comes from the summary rather than a renderer-local ceil-log2 that duplicated the orchestrator's. Every readout line now fits 80 columns.
1 parent b7316b4 commit 6997ea4

8 files changed

Lines changed: 604 additions & 350 deletions

File tree

README.md

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -78,18 +78,31 @@ Target: x86_64 / 6.15.6
7878
Running 94 of 97 components (3 experimental skipped; use -x to enable)...
7979
[####################] 100% 94/94 13.9s
8080
81-
Virtual image base 0xffffffff8fe00000 slide +0xee00000
82-
Physical image base 0x0000000034600000 slide +0x33600000
83-
Direct map base >= 0xffff800000000000
84-
Phys/Virt coupling physical and virtual text randomize independently
85-
86-
Leaks (6):
87-
virt kernel text 0xffffffff8ff04104 [interior] (perf_event_open, proc_kallsyms)
88-
virt kernel image 0xffffffff8fe00000 [base] (perf_event_open, prefetch, proc_kallsyms)
89-
virt directmap 0xffff9eeb80000000 [base] (prefetch_directmap)
90-
phys kernel image 0x0000000034600000 [base] (proc_iomem_kernel)
91-
phys kernel data 0x0000000036000000 [base] (proc_iomem_kernel)
92-
phys kernel BSS 0x0000000036b34000 [base] (proc_iomem_kernel)
81+
Layout
82+
Virtual image base (pinned)
83+
guaranteed 0xffffffff8fe00000 slide +0xee00000
84+
85+
Physical image base (pinned)
86+
guaranteed 0x34600000 slide +0x33600000
87+
88+
Direct map base (narrowed to ~9 bits)
89+
guaranteed >= 0xffff800000000000
90+
91+
Note: physical and virtual text randomize independently
92+
93+
Evidence (6 findings, 5 components)
94+
virt kernel text [interior] 0xffffffff8ff04104
95+
from perf_event_open, proc_kallsyms
96+
virt kernel image [base] 0xffffffff8fe00000
97+
from perf_event_open, prefetch, proc_kallsyms
98+
virt directmap [base] 0xffff9eeb80000000
99+
from prefetch_directmap
100+
phys kernel image [base] 0x34600000
101+
from proc_iomem_kernel
102+
phys kernel data [base] 0x36000000
103+
from proc_iomem_kernel
104+
phys kernel BSS [base] 0x36b34000
105+
from proc_iomem_kernel
93106
94107
[-v: detailed results, memory map, system info] [-H: hardening assessment]
95108
```

docs/architecture.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,9 @@ raise the floor (DRAM bounds) and the 2 MiB `IMAGE_ALIGN` slot grid is applied.
9898
With only this one leak the result is still a window — several slots wide:
9999

100100
```
101-
Virtual image base narrowed ~3 of 9 bits
102-
0xffffffff81000000 - 0xffffffff81f41000 guaranteed (8 x 2.0 MiB)
101+
Layout
102+
Virtual image base (narrowed to ~3 of 9 bits)
103+
guaranteed 0xffffffff81000000 .. 0xffffffff81e00000 8 x 2 MiB
103104
```
104105

105106
A second observation — a `_stext` base witness, a DRAM floor, or the
@@ -112,7 +113,9 @@ narrowed window above, or, once the constraints collapse to one slot, the pinned
112113
base and its slide:
113114

114115
```
115-
Virtual image base 0xffffffff81e00000 slide +0xe00000
116+
Layout
117+
Virtual image base (pinned)
118+
guaranteed 0xffffffff81e00000 slide +0xe00000
116119
```
117120

118121
That is the whole path: a log line becomes an observation, a rule turns it into a

docs/usage.md

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -133,21 +133,34 @@ config, no memory-layout diagram.
133133
KASLD 0.3.1-dev -- Kernel ASLR derandomization
134134
Target: x86_64 / 6.15.6
135135
136-
Running 94 components (3 experimental skipped; use -x to enable)...
136+
Running 94 of 97 components (3 experimental skipped; use -x to enable)...
137137
[####################] 100% 94/94 13.9s
138138
139-
Virtual image base 0xffffffff8fe00000 slide +0xee00000
140-
Physical image base 0x0000000034600000 slide +0x33600000
141-
Direct map base >= 0xffff800000000000
142-
Phys/Virt coupling physical and virtual text randomize independently
139+
Layout
140+
Virtual image base (pinned)
141+
guaranteed 0xffffffff8fe00000 slide +0xee00000
143142
144-
Leaks (6):
145-
virt kernel text 0xffffffff8ff04104 [interior] (perf_event_open, proc_kallsyms)
146-
virt kernel image 0xffffffff8fe00000 [base] (perf_event_open, prefetch, proc_kallsyms)
147-
virt directmap 0xffff9eeb80000000 [base] (prefetch_directmap)
148-
phys kernel image 0x0000000034600000 [base] (proc_iomem_kernel)
149-
phys kernel data 0x0000000036000000 [base] (proc_iomem_kernel)
150-
phys kernel BSS 0x0000000036b34000 [base] (proc_iomem_kernel)
143+
Physical image base (pinned)
144+
guaranteed 0x34600000 slide +0x33600000
145+
146+
Direct map base (narrowed to ~9 bits)
147+
guaranteed >= 0xffff800000000000
148+
149+
Note: physical and virtual text randomize independently
150+
151+
Evidence (6 findings, 5 components)
152+
virt kernel text [interior] 0xffffffff8ff04104
153+
from perf_event_open, proc_kallsyms
154+
virt kernel image [base] 0xffffffff8fe00000
155+
from perf_event_open, prefetch, proc_kallsyms
156+
virt directmap [base] 0xffff9eeb80000000
157+
from prefetch_directmap
158+
phys kernel image [base] 0x34600000
159+
from proc_iomem_kernel
160+
phys kernel data [base] 0x36000000
161+
from proc_iomem_kernel
162+
phys kernel BSS [base] 0x36b34000
163+
from proc_iomem_kernel
151164
152165
[-v: detailed results, memory map, system info] [-H: hardening assessment]
153166
```
@@ -300,9 +313,9 @@ KASLR analysis:
300313
Physical KASLR entropy: 0 bits (pinned)
301314
302315
Memory KASLR (directmap / vmalloc / vmemmap):
303-
virt_page_offset_base >= 0xffff800000000000
304-
virt_vmalloc_base 0xffff810040000000 - 0xffffdcffc0000000 (94206 candidates, 17 bits)
305-
virt_vmemmap_base 0xffffa10080000000 - 0xfffffd0000000000 (94206 candidates, 17 bits)
316+
Direct map base guaranteed >= 0xffff800000000000
317+
vmalloc base guaranteed 0xffff810040000000 .. 0xffffdcffc0000000 94206 slots, ~17 bits
318+
vmemmap base guaranteed 0xffffa10080000000 .. 0xfffffd0000000000 94206 slots, ~17 bits
306319
307320
----------------------------------------
308321
Virtual memory layout (decoupled):

src/include/kasld/internal.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,10 @@ struct kaslr_info {
450450
* are excluded, matching the headline vslots/pslots). Renderers derive bits
451451
* via ilog2. 0 when the region is unresolved / not a both-sided window. */
452452
unsigned long virt_page_offset_slots, virt_page_offset_likely_slots;
453+
/* Residual entropy over each window, derived from the hole-aware slot counts
454+
* at the engine boundary. Carried here rather than recomputed in a renderer:
455+
* the same quantity must not be derived two ways. */
456+
int virt_page_offset_bits, virt_vmalloc_bits, virt_vmemmap_bits;
453457
unsigned long virt_vmalloc_slots, virt_vmalloc_likely_slots;
454458
unsigned long virt_vmemmap_slots, virt_vmemmap_likely_slots;
455459
};

src/orchestrator.c

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2782,6 +2782,13 @@ void compute_kaslr_info(struct summary *s) {
27822782
: 0;
27832783
}
27842784
#endif
2785+
s->kaslr.virt_page_offset_bits = s->kaslr.virt_page_offset_slots > 0
2786+
? ilog2(s->kaslr.virt_page_offset_slots)
2787+
: 0;
2788+
s->kaslr.virt_vmalloc_bits =
2789+
s->kaslr.virt_vmalloc_slots > 0 ? ilog2(s->kaslr.virt_vmalloc_slots) : 0;
2790+
s->kaslr.virt_vmemmap_bits =
2791+
s->kaslr.virt_vmemmap_slots > 0 ? ilog2(s->kaslr.virt_vmemmap_slots) : 0;
27852792

27862793
#ifndef KASLD_TESTING
27872794
/* Speculative "likely" sub-windows for the memory-KASLR regions: the engine's
@@ -4135,11 +4142,27 @@ int main(int argc, char *argv[]) {
41354142
(sysroot && *sysroot) ? "skipped" : "skipped by --skip";
41364143
/* "N of M" rather than a bare N: the skipped counts that follow are
41374144
* excluded from N, so a bare count reads either way. */
4138-
if (num_active_components == 0)
4139-
/* Nothing to run (e.g. -s '*'): the result below is the engine's
4140-
* leak-free structural inference, not a scan. */
4141-
printf("Structural baseline - no components run\n");
4142-
else if (nf > 0 && ne > 0)
4145+
if (num_active_components == 0) {
4146+
/* Every discovered component was filtered out, so the result below is
4147+
* the engine's leak-free structural inference rather than a scan. Name
4148+
* which filter emptied the set: the three causes (--skip, experimental
4149+
* gating, KASLD_SYSROOT dropping live probes) need different responses.
4150+
* A component directory that is missing or empty cannot reach here --
4151+
* discover_components() fails the run before any output. */
4152+
if (nf > 0 && ne > 0)
4153+
printf("Structural baseline: no components ran (%d %s, %d experimental;"
4154+
" use -x to enable)\n",
4155+
nf, skipped_by, ne);
4156+
else if (nf > 0)
4157+
printf("Structural baseline: no components ran (all %d %s)\n", nf,
4158+
skipped_by);
4159+
else if (ne > 0)
4160+
printf("Structural baseline: no components ran (all %d experimental;"
4161+
" use -x to enable)\n",
4162+
ne);
4163+
else
4164+
printf("Structural baseline: no components ran\n");
4165+
} else if (nf > 0 && ne > 0)
41434166
printf("Running %d of %d components (%d %s, %d experimental "
41444167
"skipped; use -x to enable)...\n",
41454168
num_active_components, num_components, nf, skipped_by, ne);

src/render/markdown.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,10 @@ void render_markdown(const struct summary *s) {
379379
enum kasld_addr_type type_order[] = {KASLD_TYPE_PHYS, KASLD_TYPE_VIRT,
380380
KASLD_TYPE_UNKNOWN};
381381

382-
printf("## Leak Results\n\n");
382+
/* "Evidence", matching the text readout: the block carries side-channel
383+
* measurements alongside actual disclosures, and only the latter are leaks.
384+
*/
385+
printf("## Evidence\n\n");
383386

384387
if (verbose) {
385388
/* Verbose: individual result rows */

0 commit comments

Comments
 (0)