Skip to content

Commit a32a89c

Browse files
committed
components: standardise CLI parsing and diagnostic output
New include/kasld/cli.h: one option parser (kasld_cli — -v/--verbose, -t/--time SECS, -h) and a levelled stderr logger (kasld_info/debug/err/ found). stdout is now the machine channel (wire lines only); every bracketed [.]/[-]/[+] diagnostic moves to the logger. mincore gains -t (tunable give-up budget); kernelsnitch's per-iteration firehose is demoted to kasld_debug so it no longer floods -v. tests/check-component-output ratchets the stream rule (no new raw stdout printf); the older non-bracketed data-echo lines are baselined as a tracked follow-on. Standard documented in CONTRIBUTING.
1 parent 28e4742 commit a32a89c

81 files changed

Lines changed: 654 additions & 323 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CONTRIBUTING.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,40 @@ failed to randomise) emits scalar facts via `kasld_emit_scalar()` instead of an
158158
address; which facts, and how the engine consumes each, are documented in
159159
[docs/architecture.md → KASLR runtime states](docs/architecture.md#kaslr-runtime-states).
160160

161+
### Diagnostics and options
162+
163+
Two channels, kept separate (`include/kasld/cli.h`):
164+
165+
- **stdout is the machine channel***only* the `P`/`V`/`S` wire lines the
166+
emitter helpers print. Never write a human message to stdout (so
167+
`component 2>/dev/null` is clean, parseable output).
168+
- **stderr is the human channel** — every diagnostic, through the levelled
169+
logger, never a bare `printf`/`fprintf`:
170+
171+
| Macro | Prefix | Use |
172+
|---|---|---|
173+
| `kasld_info(fmt, …)` | `[.]` | normal progress |
174+
| `kasld_debug(fmt, …)` | `[.]` | firehose detail — printed only under verbose |
175+
| `kasld_err(fmt, …)` | `[-]` | failure / data unavailable |
176+
| `kasld_found(fmt, …)` | `[+]` | a leak was produced |
177+
178+
The `info`/`debug` split matters: verbose means different things per component
179+
(a couple of lines for `proc_iomem`, a per-collision firehose for
180+
`kernelsnitch`). Demote firehose lines to `kasld_debug` so a normal run — and
181+
`kasld -v` — stay readable; they surface only under the component's own
182+
verbose. `tests/check-component-output` ratchets this: a *new* component
183+
printing a diagnostic to stdout fails the build.
184+
185+
**Options** are optional and **manual** (testing/debugging — the orchestrator
186+
passes none and sets no env). If a component takes any, parse them with
187+
`kasld_cli(argc, argv)` rather than hand-rolling `argv` — it gives every
188+
component the same `-v` / `--verbose`, `-t SECS` / `--time` (the component's own
189+
probe budget, in seconds — *not* kasld's kill timeout), and `-h` / `--help`. A
190+
component then reads `kasld_verbose` (or `kasld_is_verbose()`) and `kasld_time_s`
191+
as it cares; one with no options stays `int main(void)`. `kasld_is_verbose()`
192+
also honours `$KASLD_VERBOSE`, so a `main(void)` component is debuggable without
193+
an `argc/argv` conversion.
194+
161195
### Exit code convention
162196

163197
Components signal their outcome to the orchestrator via exit code:

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,7 @@ test : $(TEST_BIN) $(TEST_RENDER_BIN) $(TEST_EST_BIN) $(TEST_EV_BIN) $(TEST_ENG_
306306
@$(TEST_DIR)/run-all
307307
@$(TEST_DIR)/check-self-edges
308308
@$(TEST_DIR)/check-truncation
309+
@$(TEST_DIR)/check-component-output
309310

310311
.PHONY: test-integration
311312
test-integration : $(TEST_INT_BIN)

src/components/bcm_msg_head_struct.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
// <bcoles@gmail.com>
3333

3434
#include "include/kasld/api.h"
35+
#include "include/kasld/cli.h"
3536
#include <fcntl.h>
3637
#include <linux/can.h>
3738
#include <linux/can/bcm.h>
@@ -106,7 +107,7 @@ static unsigned long get_kernel_addr_from_bcm_msg_head_struct(void) {
106107
char *endptr;
107108
unsigned long addr = 0;
108109

109-
printf("[.] trying bcm_msg_head struct stack pointer leak ...\n");
110+
kasld_info("trying bcm_msg_head struct stack pointer leak ...");
110111

111112
sock = socket(AF_CAN, SOCK_DGRAM, CAN_BCM);
112113

@@ -173,7 +174,7 @@ static unsigned long get_kernel_addr_from_bcm_msg_head_struct(void) {
173174
(void)addrs;
174175
(void)endptr;
175176
(void)addr;
176-
printf("[-] BCM bcm_msg_head leak shape targets a 64-bit kernel; skipping\n");
177+
kasld_err("BCM bcm_msg_head leak shape targets a 64-bit kernel; skipping");
177178
#endif
178179

179180
return 0;
@@ -184,7 +185,7 @@ static unsigned long get_kernel_addr_from_bcm_msg_head_struct(void) {
184185
int main(void) {
185186
unsigned long addr = get_kernel_addr_from_bcm_msg_head_struct();
186187
if (!addr) {
187-
printf("[-] no kernel address leaked via BCM socket\n");
188+
kasld_err("no kernel address leaked via BCM socket");
188189
return 0;
189190
}
190191

src/components/boot_config.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
// <bcoles@gmail.com>
1919

2020
#include "include/kasld/api.h"
21+
#include "include/kasld/cli.h"
2122
#include "include/kconfig.h"
2223
#include <errno.h>
2324
#include <stdio.h>
@@ -66,7 +67,7 @@ static int open_boot_config(FILE **fpp) {
6667
return 0;
6768
}
6869

69-
fprintf(stderr, "[-] could not find kernel config\n");
70+
kasld_err("could not find kernel config");
7071
return -1;
7172
}
7273

@@ -89,7 +90,7 @@ int main(void) {
8990
/* Detect PAGE_OFFSET (32-bit vmsplit) */
9091
unsigned long virt_page_offset = get_kconfig_page_offset(fp);
9192
if (virt_page_offset) {
92-
printf("[.] CONFIG_PAGE_OFFSET: %#lx\n", virt_page_offset);
93+
kasld_info("CONFIG_PAGE_OFFSET: %#lx", virt_page_offset);
9394
kasld_result_base(KASLD_TYPE_VIRT, REGION_PAGE_OFFSET, virt_page_offset,
9495
NULL, CONF_PARSED);
9596
}
@@ -101,7 +102,7 @@ int main(void) {
101102
* raises the floor to the precise position at CONF_PARSED. */
102103
unsigned long phys_start = get_kconfig_physical_start(fp);
103104
if (phys_start) {
104-
printf("[.] CONFIG_PHYSICAL_START: %#lx\n", phys_start);
105+
kasld_info("CONFIG_PHYSICAL_START: %#lx", phys_start);
105106
kasld_emit_scalar(SF_PHYSICAL_START, phys_start, CONF_PARSED);
106107
}
107108

@@ -112,7 +113,7 @@ int main(void) {
112113
* Q_KASLR_ALIGN / Q_PHYS_KASLR_ALIGN regardless of source. */
113114
unsigned long phys_align = get_kconfig_physical_align(fp);
114115
if (phys_align) {
115-
printf("[.] CONFIG_PHYSICAL_ALIGN: %#lx\n", phys_align);
116+
kasld_info("CONFIG_PHYSICAL_ALIGN: %#lx", phys_align);
116117
kasld_emit_scalar(SF_PHYS_KERNEL_ALIGN, phys_align, CONF_PARSED);
117118
}
118119

@@ -133,7 +134,7 @@ int main(void) {
133134
* with CONFIG_RANDOMIZE_MEMORY=y. Consumed by directmap_kaslr_disabled_pin.
134135
*/
135136
if (is_kconfig_set(fp, "CONFIG_KASAN")) {
136-
printf("[.] CONFIG_KASAN=y\n");
137+
kasld_info("CONFIG_KASAN=y");
137138
kasld_emit_scalar(SF_KASAN_ENABLED, 1, CONF_PARSED);
138139
}
139140

src/components/boot_params_e820.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959

6060
#define _POSIX_C_SOURCE 200809L
6161
#include "include/kasld/api.h"
62+
#include "include/kasld/cli.h"
6263
#include <errno.h>
6364
#include <fcntl.h>
6465
#include <stdint.h>
@@ -127,8 +128,8 @@ static inline uint64_t read_le64(const uint8_t *p) {
127128
int main(void) {
128129
static uint8_t buf[BOOT_PARAMS_SIZE];
129130

130-
printf("[.] reading E820 memory map and initrd address from " BOOT_PARAMS_PATH
131-
" ...\n");
131+
kasld_info("reading E820 memory map and initrd address from " BOOT_PARAMS_PATH
132+
" ...");
132133

133134
int fd = kasld_open(BOOT_PARAMS_PATH, O_RDONLY);
134135
if (fd < 0) {
@@ -143,9 +144,8 @@ int main(void) {
143144
close(fd);
144145

145146
if (n != (ssize_t)sizeof(buf)) {
146-
fprintf(stderr,
147-
"[-] short read from " BOOT_PARAMS_PATH " (%zd of %u bytes)\n", n,
148-
BOOT_PARAMS_SIZE);
147+
kasld_err("short read from " BOOT_PARAMS_PATH " (%zd of %u bytes)", n,
148+
BOOT_PARAMS_SIZE);
149149
return KASLD_EXIT_UNAVAILABLE;
150150
}
151151

@@ -159,7 +159,7 @@ int main(void) {
159159
e820_entries = E820_MAX_ENTRIES;
160160

161161
if (e820_entries == 0) {
162-
printf("[-] E820 table is empty\n");
162+
kasld_err("E820 table is empty");
163163
} else {
164164
unsigned long lo = ~0ul;
165165
unsigned long hi = 0;
@@ -193,7 +193,7 @@ int main(void) {
193193
}
194194

195195
if (ram_count == 0) {
196-
printf("[-] no E820 RAM entries found\n");
196+
kasld_err("no E820 RAM entries found");
197197
} else {
198198
if (lo != ~0ul) {
199199
printf("leaked E820 DRAM low: 0x%016lx\n", lo);
@@ -243,7 +243,7 @@ int main(void) {
243243
uint64_t initrd_size = ((uint64_t)hi_sz << 32) | lo_sz;
244244

245245
if (!initrd_start || !initrd_size) {
246-
printf("[-] no initrd found in boot_params\n");
246+
kasld_err("no initrd found in boot_params");
247247
return 0;
248248
}
249249

src/components/cmdline_hugepages.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include "include/cmdline.h"
2424
#include "include/kasld/api.h"
25+
#include "include/kasld/cli.h"
2526
#include <stdio.h>
2627

2728
KASLD_EXPLAIN(
@@ -38,10 +39,10 @@ KASLD_META("method:detection\n"
3839
int main(void) {
3940
#if defined(__x86_64__) || defined(__i386__)
4041
if (!cmdline_has_prefix("hugepages=")) {
41-
fprintf(stderr, "[-] no `hugepages=` on /proc/cmdline\n");
42+
kasld_err("no `hugepages=` on /proc/cmdline");
4243
return 1;
4344
}
44-
printf("[.] cmdline carries `hugepages=` (EFI stub will zero phys seed)\n");
45+
kasld_info("cmdline carries `hugepages=` (EFI stub will zero phys seed)");
4546
kasld_emit_scalar(SF_CMDLINE_HUGEPAGES, 1, CONF_PARSED);
4647
#endif
4748
return 0;

src/components/cmdline_mem.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
#include "include/cmdline.h"
2929
#include "include/kasld/api.h"
30+
#include "include/kasld/cli.h"
3031
#include <stdio.h>
3132

3233
KASLD_EXPLAIN(
@@ -45,10 +46,10 @@ int main(void) {
4546
#if defined(__x86_64__) || defined(__i386__)
4647
unsigned long mem = 0;
4748
if (!cmdline_get_memparse("mem=", &mem) || mem == 0) {
48-
fprintf(stderr, "[-] no `mem=` token on /proc/cmdline\n");
49+
kasld_err("no `mem=` token on /proc/cmdline");
4950
return 1;
5051
}
51-
printf("[.] cmdline mem= cap: %#lx (%lu bytes)\n", mem, mem);
52+
kasld_info("cmdline mem= cap: %#lx (%lu bytes)", mem, mem);
5253
kasld_emit_scalar(SF_PHYS_CMDLINE_MEM, mem, CONF_PARSED);
5354
#endif
5455
/* Other arches: emit nothing (mem= does not constrain KASLR placement). */

src/components/cmdline_memmap.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636

3737
#include "include/cmdline.h"
3838
#include "include/kasld/api.h"
39+
#include "include/kasld/cli.h"
3940
#include <stdio.h>
4041

4142
KASLD_EXPLAIN(
@@ -82,7 +83,7 @@ int main(void) {
8283
#if defined(__x86_64__) || defined(__i386__)
8384
FILE *f = kasld_fopen("/proc/cmdline", "r");
8485
if (!f) {
85-
fprintf(stderr, "[-] /proc/cmdline unavailable\n");
86+
kasld_err("/proc/cmdline unavailable");
8687
return 1;
8788
}
8889
char buf[2048];
@@ -108,7 +109,7 @@ int main(void) {
108109
if (is_avoid) {
109110
char name[16];
110111
snprintf(name, sizeof(name), "memmap%c", sep);
111-
printf("[.] cmdline %s -> [%#lx, %#lx]\n", name, lo, hi);
112+
kasld_info("cmdline %s -> [%#lx, %#lx]", name, lo, hi);
112113
kasld_result_range(KASLD_TYPE_PHYS, REGION_CMDLINE_MEMMAP, lo, hi,
113114
name, CONF_PARSED);
114115
emitted_avoid++;
@@ -124,7 +125,7 @@ int main(void) {
124125
if (with_offset > 0)
125126
kasld_emit_scalar(SF_CMDLINE_MEMMAP_COUNT, with_offset, CONF_PARSED);
126127
if (emitted_avoid == 0 && with_offset == 0)
127-
fprintf(stderr, "[-] no avoidance `memmap=` reservations on cmdline\n");
128+
kasld_err("no avoidance `memmap=` reservations on cmdline");
128129
#endif
129130
/* Other arches: emit nothing. */
130131
return 0;

src/components/dmesg_acpi_dynamic_ssdt.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
#define _GNU_SOURCE
6565
#include "include/dmesg.h"
6666
#include "include/kasld/api.h"
67+
#include "include/kasld/cli.h"
6768
#include <stdint.h>
6869
#include <stdio.h>
6970
#include <stdlib.h>
@@ -144,12 +145,12 @@ static int on_match(const char *line, void *ctx) {
144145
int main(void) {
145146
struct ssdt_ctx s = {0, {0}};
146147

147-
printf("[.] searching dmesg for ACPI dynamic OEM table loads ...\n");
148+
kasld_info("searching dmesg for ACPI dynamic OEM table loads ...");
148149
int ds = dmesg_search("ACPI: SSDT 0x", on_match, &s);
149150

150151
if (!s.addr) {
151-
printf("[-] no ACPI dynamic OEM table load with a direct-map virtual "
152-
"address found in dmesg\n");
152+
kasld_err("no ACPI dynamic OEM table load with a direct-map virtual "
153+
"address found in dmesg");
153154
if (ds < 0)
154155
return KASLD_EXIT_NOPERM;
155156
return 0;

src/components/dmesg_android_ion_snapshot.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#define _GNU_SOURCE
3939
#include "include/dmesg.h"
4040
#include "include/kasld/api.h"
41+
#include "include/kasld/cli.h"
4142
#include <stdint.h>
4243
#include <stdio.h>
4344
#include <stdlib.h>
@@ -79,13 +80,13 @@ static int on_match(const char *line, void *ctx) {
7980
int main(void) {
8081
unsigned long addr = 0;
8182

82-
printf("[.] searching dmesg for 'ion_snapshot: ' ...\n");
83+
kasld_info("searching dmesg for 'ion_snapshot: ' ...");
8384
int ds = dmesg_search("ion_snapshot: ", on_match, &addr);
8485

8586
if (!addr) {
8687
if (ds < 0)
8788
return KASLD_EXIT_NOPERM;
88-
printf("[-] ion_snapshot not found in dmesg\n");
89+
kasld_err("ion_snapshot not found in dmesg");
8990
return 0;
9091
}
9192

0 commit comments

Comments
 (0)