-
Notifications
You must be signed in to change notification settings - Fork 52
Expand file tree
/
Copy pathcollect
More file actions
executable file
·499 lines (460 loc) · 21.2 KB
/
Copy pathcollect
File metadata and controls
executable file
·499 lines (460 loc) · 21.2 KB
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
#!/bin/sh
# This file is part of KASLD - https://github.com/bcoles/kasld
#
# collect — capture a portable, self-identifying bundle of this system's
# KASLD-relevant state.
#
# Bundle layout:
# <bundle>/
# meta.txt # arch (raw + canonical), kernel, distro, kasld id, date
# verbose.txt # full `kasld -v 2>&1` (the reference conclusions)
# dmesg.txt # dmesg output, if permitted (parsed by dmesg_* sources)
# sysroot/ # faithful path-preserving copy of the files read
# proc/meminfo, proc/cpuinfo, sys/firmware/memmap/..., boot/config-*, ...
#
# The sysroot mirror is replayed by pointing the analysis at it
# (KASLD_SYSROOT=<bundle>/sysroot), so paths under sysroot/ must match the
# real layout.
# ---
# <bcoles@gmail.com>
# `set -u` catches unset-variable bugs. We deliberately do NOT use `set -e`:
# a diagnostic collector must gather everything it can on a locked-down or
# unusual system and *note* what it couldn't — never abort midway and leave a
# silent partial bundle. Fatal setup failures are checked explicitly.
set -u
# A bundle holds /proc/cmdline, dmesg, and with --kallsyms the kernel's real
# symbol addresses. It sits in the working directory until it is reviewed and
# shared, so create it readable only by the user who ran the capture rather than
# at whatever the ambient umask allows.
umask 077
PROG=$(basename "$0")
COLLECT_VERSION=2
die() { echo "$PROG: $*" >&2; exit 2; }
need_val() { [ "$1" -ge 2 ] || die "$2 requires a value"; }
usage() {
cat <<EOF
Usage: $PROG [OPTIONS]
Capture a KASLD diagnostic/fixture bundle for this system.
Options:
-o, --out DIR Bundle output directory (default: ./kasld-bundle-<arch>-<rel>-<ts>)
-k, --kasld PATH kasld binary to run for verbose.txt (default: auto-detect)
-t, --tar Also produce <bundle>.tar.gz
-a, --anonymize Best-effort scrub of identifying data (hostname, CPU brand
string, UUIDs/MACs and sensitive cmdline values), keeping
the numeric facts inference reads. NOT a guarantee — always
review the bundle before sharing (see PRIVACY below).
--kallsyms Include /proc/kallsyms (large; the actual leak target —
omitted by default)
-h, --help This help
PRIVACY: this bundle captures system state that can contain identifying or
sensitive data — /proc/cmdline (may carry boot secrets), dmesg (hostnames,
MAC addresses, serials), /proc/iomem, /proc/modules, and (with --kallsyms)
kernel symbol addresses. REVIEW the bundle before attaching it to a public
bug report. --anonymize reduces this but is best-effort. A PRIVACY file
listing exactly what was collected is written into every bundle.
The bundle is corpus-agnostic. To file it into the kasld test corpus, move it
to tests/fixtures/<canonical-arch>/<distro>-<rel>-<kver>/ (the suggested id is
printed at the end and recorded in meta.txt). Note: verbose.txt (kasld's own
output) is volatile across kasld versions and is git-ignored — only the raw
inputs (sysroot/, meta.txt, sizes.txt, dmesg.txt) belong in the committed
corpus.
EOF
}
# ---------------------------------------------------------------------------
# Args
# ---------------------------------------------------------------------------
OUT=""
KASLD=""
DO_TAR=0
ANON=0
WANT_KALLSYMS=0
while [ $# -gt 0 ]; do
case "$1" in
-o|--out) need_val "$#" "$1"; OUT=$2; shift 2 ;;
-k|--kasld) need_val "$#" "$1"; KASLD=$2; shift 2 ;;
-t|--tar) DO_TAR=1; shift ;;
-a|--anonymize) ANON=1; shift ;;
--kallsyms) WANT_KALLSYMS=1; shift ;;
-h|--help) usage; exit 0 ;;
*) echo "$PROG: unknown option: $1" >&2; usage >&2; exit 2 ;;
esac
done
# ---------------------------------------------------------------------------
# Arch normalization: map `uname -m` onto kasld's arch identifiers (mirrors
# the dispatch in src/include/kasld/api.h).
# ---------------------------------------------------------------------------
canonical_arch() {
m=$1
case "$m" in
x86_64|amd64) echo x86_64 ;;
i386|i486|i586|i686) echo x86_32 ;;
aarch64|aarch64_be|arm64) echo arm64 ;;
arm*) echo arm32 ;;
mips64|mips64el) echo mips64 ;;
mips|mipsel) echo mips32 ;;
ppc64|ppc64le|powerpc64) echo ppc64 ;;
ppc|powerpc|powerpc32) echo ppc32 ;;
riscv64) echo riscv64 ;;
riscv32) echo riscv32 ;;
loongarch64|loong64) echo loongarch64 ;;
s390x|s390) echo s390 ;;
sparc64|sparc) echo sparc ;;
*) echo "unknown" ;;
esac
}
RAW_ARCH=$(uname -m 2>/dev/null || echo unknown)
KARCH=$(canonical_arch "$RAW_ARCH")
REL=$(uname -r 2>/dev/null || echo unknown)
# Distro id from os-release, best-effort. Parsed (not sourced) so we never
# execute the file's contents.
DISTRO="unknown"
if [ -r /etc/os-release ]; then
_id=$(sed -n 's/^ID=//p' /etc/os-release 2>/dev/null | tr -d '"' | head -1)
_ver=$(sed -n 's/^VERSION_ID=//p' /etc/os-release 2>/dev/null | tr -d '"' | head -1)
DISTRO="${_id:-unknown}-${_ver:-}"
elif command -v getprop >/dev/null 2>&1; then
# Android ships no /etc/os-release, and /system/build.prop is root-only, so
# an unprivileged capture would otherwise be filed as "unknown". The property
# service answers regardless of who asks.
_rel=$(getprop ro.build.version.release 2>/dev/null)
_sdk=$(getprop ro.build.version.sdk 2>/dev/null)
[ -n "${_rel:-}${_sdk:-}" ] && DISTRO="android-${_rel:-$_sdk}"
fi
# Sanitize a token for use in a filename.
sanitize() { printf '%s' "$1" | tr -c 'A-Za-z0-9._-' '_'; }
TS=$(date -u +%Y%m%d%H%M%S 2>/dev/null || echo 0)
FIXTURE_ID="$(sanitize "$DISTRO")-$(sanitize "$REL")"
if [ -z "$OUT" ]; then
OUT="./kasld-bundle-$(sanitize "$KARCH")-$(sanitize "$REL")-$TS"
fi
# Fatal setup check (no `set -e`, so check explicitly). Warn if reusing a
# non-empty directory — stale files from a prior run could mix in.
if [ -d "$OUT" ] && [ -n "$(ls -A "$OUT" 2>/dev/null)" ]; then
echo "$PROG: warning: $OUT exists and is not empty; merging into it" >&2
fi
mkdir -p "$OUT/sysroot" || die "cannot create bundle dir: $OUT"
# ---------------------------------------------------------------------------
# Locate kasld for verbose.txt (best-effort; bundle is still useful without).
# ---------------------------------------------------------------------------
if [ -z "$KASLD" ]; then
if [ -n "${KASLD_BIN:-}" ] && [ -x "${KASLD_BIN:-}" ]; then
KASLD=$KASLD_BIN
else
script_dir=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd)
for c in "$script_dir/../build/$RAW_ARCH"*/kasld "$script_dir/../build"/*/kasld \
"$script_dir/../kasld"; do
[ -x "$c" ] && { KASLD=$c; break; }
done
[ -z "$KASLD" ] && KASLD=$(command -v kasld 2>/dev/null || true)
fi
fi
# ---------------------------------------------------------------------------
# Capture helpers
# ---------------------------------------------------------------------------
NOTES="$OUT/sysroot/.collect-notes"
: > "$NOTES"
# grab PATH — copy a single file into the sysroot mirror, preserving its path.
grab() {
src=$1
[ -e "$src" ] || { echo "absent: $src" >> "$NOTES"; return 0; }
dst="$OUT/sysroot$src"
mkdir -p "$(dirname "$dst")"
if cat "$src" > "$dst" 2>/dev/null; then
:
else
echo "unreadable: $src" >> "$NOTES"
rm -f "$dst"
fi
}
# Capture named attributes of every member of a sysfs class. grab_tree cannot:
# /sys/class/<class>/<name> is a symlink into /sys/devices and its walk does not
# follow links. Materialising the attributes as plain files is what the replay
# layer opens, and it keeps the capture to what the analysis reads rather than a
# whole device subtree.
grab_class_attr() {
cls=$1
shift
[ -d "/sys/class/$cls" ] || { echo "absent: /sys/class/$cls" >> "$NOTES"; return 0; }
# Record the class directory even when empty: "registered but no members" is
# a different state from "class absent", and both are worth replaying.
mkdir -p "$OUT/sysroot/sys/class/$cls"
for e in "/sys/class/$cls"/*; do
[ -e "$e" ] || continue
n=$(basename "$e")
for a in "$@"; do
[ -r "$e/$a" ] || continue
mkdir -p "$OUT/sysroot/sys/class/$cls/$n"
if cat "$e/$a" > "$OUT/sysroot/sys/class/$cls/$n/$a" 2>/dev/null; then
:
else
echo "unreadable: /sys/class/$cls/$n/$a" >> "$NOTES"
rm -f "$OUT/sysroot/sys/class/$cls/$n/$a"
fi
done
done
}
# grab_tree DIR — copy a (small) directory subtree into the mirror.
grab_tree() {
d=$1
[ -d "$d" ] || { echo "absent: $d" >> "$NOTES"; return 0; }
# Walk regular files only; bounded by the small kernel-exposed trees.
find "$d" -type f 2>/dev/null | while IFS= read -r f; do
dst="$OUT/sysroot$f"
mkdir -p "$(dirname "$dst")" 2>/dev/null || continue
cat "$f" > "$dst" 2>/dev/null || { echo "unreadable: $f" >> "$NOTES"; rm -f "$dst"; }
done
}
# Boot images are multi-MiB and usually root-only (0600). The analysis needs
# only their *size*: kernel_image_facts reads it (execute on the directory, not
# read on the file) and ceiling_from_image_size consumes it. So we record the
# size in sizes.txt and do
# NOT store the file itself — committing a tens-of-MiB sparse placeholder per
# fixture would materialise as that many zero bytes on checkout. The replay
# harness reconstructs a sparse file of the recorded size on the fly, into a
# scratch (gitignored) sysroot.
#
# boot_image PATH MODE:
# hdr : also capture a small (<=HDR_BYTES) real header prefix when readable
# — kernel image only, whose leading bytes are the EFI/PE boot stub
# (not kernel addresses). The harness lays this prefix down and
# truncate-extends it, so the exact-size header estimate (arm64/
# riscv64 Image header) replays faithfully. Costs a few KiB, and
# nothing on the common root-only case.
# size : size only. System.map/vmlinux bytes are kernel symbol addresses we
# keep out of the corpus, and only their length is ever read.
SIZES="$OUT/sizes.txt"
: > "$SIZES"
HDR_BYTES=4096
boot_image() {
p=$1
mode=$2
[ -e "$p" ] || { echo "absent: $p" >> "$NOTES"; return 0; }
sz=$(stat -c %s "$p" 2>/dev/null || stat -f %z "$p" 2>/dev/null || echo "")
[ -n "$sz" ] || { echo "unsized: $p" >> "$NOTES"; return 0; }
printf '%s %s\n' "$sz" "$p" >> "$SIZES"
if [ "$mode" = hdr ]; then
dst="$OUT/sysroot$p"
mkdir -p "$(dirname "$dst")"
if dd if="$p" of="$dst" bs="$HDR_BYTES" count=1 2>/dev/null && [ -s "$dst" ]; then
echo "header: $p (${HDR_BYTES}B prefix; full size $sz in sizes.txt)" >> "$NOTES"
else
rm -f "$dst"
echo "size-only (header unreadable): $p" >> "$NOTES"
fi
fi
}
# ---------------------------------------------------------------------------
# /proc, /sys facts the analysis reads (see the audited source list).
# ---------------------------------------------------------------------------
for f in \
/proc/meminfo /proc/cpuinfo /proc/zoneinfo /proc/cmdline \
/proc/iomem /proc/modules /proc/version \
/proc/sys/kernel/kptr_restrict /proc/sys/kernel/dmesg_restrict \
/proc/sys/kernel/perf_event_paranoid /proc/sys/kernel/randomize_va_space \
/proc/sys/kernel/unprivileged_bpf_disabled \
/sys/kernel/security/lockdown \
/sys/kernel/boot_params/data /sys/kernel/boot_params/setup_data \
/sys/kernel/notes
do
grab "$f"
done
grab_tree /sys/firmware/memmap
# ---------------------------------------------------------------------------
# Vantage: what the analysis reads to establish where it stands rather than
# what the kernel looks like. A capture without these replays as an unconfined
# root shell on a host with no mandatory access control, which is the one
# vantage most systems do not have -- and on a system whose sources are gated
# by policy rather than by their absence, the vantage IS the finding.
# ---------------------------------------------------------------------------
for f in \
/proc/self/status /proc/self/attr/current /etc/group \
/sys/kernel/security/lsm /sys/module/apparmor/parameters/enabled \
/sys/fs/selinux/enforce /sys/fs/selinux/policyvers /sys/fs/selinux/mls \
/proc/self/cgroup /proc/1/cgroup /.dockerenv /run/.containerenv
do
grab "$f"
done
# iSCSI transports: `handle` is the address of the registering driver's static
# struct iscsi_transport (CVE-2021-27363), one per transport the host has
# loaded. Read by sysfs_iscsi_transport_handle, which enumerates the class.
grab_class_attr iscsi_transport handle
# Device tree is exposed at both paths depending on arch/kernel; capture both.
grab_tree /proc/device-tree/chosen
grab_tree /proc/device-tree/rtas
grab_tree /sys/firmware/devicetree/base/chosen
grab_tree /sys/firmware/devicetree/base/rtas
# Full flattened device tree: one ~tens-of-KB blob (vs the hundreds of tiny
# files under /proc/device-tree). Feeds the DT components that need the whole
# tree (sysfs_devicetree_mmio / _memory / _reserved_memory); the replay harness
# unflattens it into sysroot/sys/firmware/devicetree/base/ at setup time.
# NOTE: before committing a shared fixture, scrub board-identifying properties
# (serial-number, local-mac-address) with extra/anonymize-fdt. The kaslr-seed /
# rng-seed are deliberately kept (random, non-identifying, and read by KASLD).
grab /sys/firmware/fdt
if [ -s "$OUT/sysroot/sys/firmware/fdt" ]; then
w="WARNING: captured /sys/firmware/fdt may contain board-identifying data \
(serial number, MAC address). Run extra/anonymize-fdt on it before sharing or \
committing this capture."
echo "$w" >&2
echo "$w" >> "$NOTES"
fi
# efi_present probes this path itself (kasld_access), so the directory must
# exist in the sysroot; a bare directory cannot be captured by grab.
if [ -e /sys/firmware/efi ]; then
echo "present: /sys/firmware/efi" >> "$NOTES"
mkdir -p "$OUT/sysroot/sys/firmware/efi"
fi
# /boot: copy the config (small), mirror the big images as sparse placeholders.
grab "/boot/config-$REL"
grab /proc/config.gz
boot_image "/boot/vmlinuz-$REL" hdr
boot_image "/boot/Image-$REL" hdr
boot_image "/boot/vmlinux-$REL" size
boot_image "/boot/System.map-$REL" size
if [ "$WANT_KALLSYMS" -eq 1 ]; then
grab /proc/kallsyms
else
echo "skipped: /proc/kallsyms (use --kallsyms to include)" >> "$NOTES"
fi
# dmesg stream (parsed by the dmesg_* sources), if permitted. klogctl(2) is a
# syscall and can't be redirected, so for offline replay seed the captured log
# at /var/log/dmesg inside the sysroot — the fallback path the dmesg readers
# use when klogctl is denied. A top-level copy is kept for humans.
# (Caveat: the live reference run reads dmesg via klogctl; its formatting may
# differ slightly from dmesg(1), so dmesg-derived bounds replay best-effort.)
DMESG_DST="$OUT/sysroot/var/log/dmesg"
mkdir -p "$(dirname "$DMESG_DST")"
if dmesg > "$DMESG_DST" 2>/dev/null && [ -s "$DMESG_DST" ]; then
cp "$DMESG_DST" "$OUT/dmesg.txt" 2>/dev/null || true
else
rm -f "$DMESG_DST"
echo "unavailable: dmesg" >> "$NOTES"
fi
# ---------------------------------------------------------------------------
# kasld reference output (the conclusions to diff a replay against).
# ---------------------------------------------------------------------------
KASLD_ID="not-run"
if [ -n "$KASLD" ] && [ -x "$KASLD" ]; then
KASLD_ID=$("$KASLD" --version 2>/dev/null | head -1 || echo "unknown")
"$KASLD" -v > "$OUT/verbose.txt" 2>&1 || \
echo "(kasld exited non-zero; output captured)" >> "$OUT/verbose.txt"
else
echo "kasld binary not found — verbose.txt omitted." \
"Pass --kasld PATH (e.g. a cross-compiled binary copied into the guest)." \
> "$OUT/verbose.txt"
fi
# ---------------------------------------------------------------------------
# Anonymize (optional): best-effort scrub of identifying data, keeping the
# facts inference reads. NOT a guarantee — the bundle should still be reviewed.
# ---------------------------------------------------------------------------
# Redact secret-bearing tokens from a text stream in place: UUIDs, MAC
# addresses, and the values of sensitive kernel-cmdline keys (root=, resume=,
# ip=, BOOT_IMAGE=, *_token=, etc.). Bare flags like `nokaslr` are kept, so the
# KASLR-relevant signal inference cares about survives.
scrub_secrets() {
f=$1
[ -f "$f" ] || return 0
H=$(hostname 2>/dev/null || true)
sed -E \
-e 's/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/[uuid]/g' \
-e 's/([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}/[mac]/g' \
-e 's/(root|resume|resume_offset|ip|nfsroot|BOOT_IMAGE|cryptdevice)=[^[:space:]]*/\1=[redacted]/g' \
-e 's/([A-Za-z_]*(token|key|secret|pass|cred)[A-Za-z_]*)=[^[:space:]]*/\1=[redacted]/Ig' \
"$f" > "$f.tmp" 2>/dev/null && mv "$f.tmp" "$f"
if [ -n "${H:-}" ]; then
sed "s/$H/HOST/g" "$f" > "$f.tmp" 2>/dev/null && mv "$f.tmp" "$f"
fi
}
if [ "$ANON" -eq 1 ]; then
ci="$OUT/sysroot/proc/cpuinfo"
if [ -f "$ci" ]; then
grep -v -e '^model name' -e '^Model' -e '^Hardware' -e '^Serial' "$ci" \
> "$ci.tmp" 2>/dev/null && mv "$ci.tmp" "$ci"
fi
# /etc/group's fourth field lists the account names in each group, which
# names the system's users. Inference reads only the name and the gid, so the
# member list is dropped rather than scrubbed. A trailing colon is kept: the
# field is empty, not missing.
gf="$OUT/sysroot/etc/group"
if [ -f "$gf" ]; then
sed -E 's/^([^:]*:[^:]*:[^:]*:).*$/\1/' "$gf" > "$gf.tmp" 2>/dev/null \
&& mv "$gf.tmp" "$gf"
fi
# Identity, not secrets: the collecting process's own uid/gid/groups are the
# vantage being recorded. Only the name it ran under is scrubbed.
scrub_secrets "$OUT/sysroot/proc/self/status"
# Container ids embed the runtime's own UUIDs, which scrub_secrets rewrites.
scrub_secrets "$OUT/sysroot/proc/self/cgroup"
scrub_secrets "$OUT/sysroot/proc/1/cgroup"
scrub_secrets "$OUT/sysroot/proc/cmdline"
scrub_secrets "$OUT/sysroot/proc/version"
scrub_secrets "$OUT/verbose.txt"
scrub_secrets "$OUT/dmesg.txt"
scrub_secrets "$OUT/sysroot/var/log/dmesg"
# The kernel command line is also exposed as the device-tree /chosen/bootargs
# (both paths), a separate copy of the same string — scrub it too, or a MAC /
# root=UUID in bootargs survives the cmdline scrub.
scrub_secrets "$OUT/sysroot/proc/device-tree/chosen/bootargs"
scrub_secrets "$OUT/sysroot/sys/firmware/devicetree/base/chosen/bootargs"
echo "anonymized: host identity, CPU brand, UUIDs/MACs, sensitive cmdline values redacted" >> "$NOTES"
fi
# ---------------------------------------------------------------------------
# Metadata
# ---------------------------------------------------------------------------
{
echo "collect_version: $COLLECT_VERSION"
echo "collected_utc: $(date -u 2>/dev/null || echo unknown)"
echo "uname_m_raw: $RAW_ARCH"
echo "arch_canonical: $KARCH"
echo "kernel_release: $REL"
echo "distro: $DISTRO"
echo "kasld: $KASLD_ID"
echo "suggested_fixture: tests/fixtures/$KARCH/$FIXTURE_ID/"
echo "anonymized: $ANON"
echo "kallsyms: $WANT_KALLSYMS"
} > "$OUT/meta.txt"
# ---------------------------------------------------------------------------
# PRIVACY note — in every bundle, so a recipient knows what's inside.
# ---------------------------------------------------------------------------
{
echo "KASLD diagnostic bundle — what this contains"
echo "==========================================="
echo
echo "REVIEW THIS BUNDLE BEFORE SHARING IT PUBLICLY."
echo
echo "Captured from this system (anonymized=$ANON):"
echo " sysroot/ raw /proc, /sys, /boot facts the analysis reads."
echo " Includes proc/cmdline (may carry boot secrets),"
echo " proc/cpuinfo, proc/iomem, proc/modules."
echo " Also the vantage: the collecting process's identity"
echo " (proc/self/status, proc/self/attr/current), the"
echo " active LSM, and etc/group. With --anonymize the"
echo " group member lists are dropped, since they name the"
echo " system's users and inference reads only name + gid."
echo " dmesg.txt kernel log, if permitted (hostnames, MACs, serials)."
echo " verbose.txt kasld output, including leaked kernel addresses."
if [ "$WANT_KALLSYMS" -eq 1 ]; then
echo " sysroot/proc/kallsyms kernel symbol addresses (--kallsyms)."
fi
echo
echo "--anonymize is best-effort (host identity, CPU brand, UUIDs/MACs,"
echo "sensitive cmdline values) and is NOT a guarantee. Inspect before"
echo "attaching to a public issue."
echo
echo "For the test corpus, only the raw inputs are committed; verbose.txt"
echo "is volatile across kasld versions and is git-ignored."
} > "$OUT/PRIVACY"
# ---------------------------------------------------------------------------
# Optional tarball
# ---------------------------------------------------------------------------
if [ "$DO_TAR" -eq 1 ]; then
base=$(basename "$OUT")
( cd "$(dirname "$OUT")" && tar czf "$base.tar.gz" "$base" ) 2>/dev/null \
&& echo "tarball: $OUT.tar.gz"
fi
echo "bundle: $OUT"
echo "arch: $RAW_ARCH -> $KARCH kernel: $REL distro: $DISTRO"
if [ "$KARCH" = "unknown" ]; then
echo "warning: '$RAW_ARCH' did not map to a known kasld arch — check canonical_arch()." >&2
fi
echo "file into corpus as: tests/fixtures/$KARCH/$FIXTURE_ID/"