Sweep of all Rust in the kernel tree, grouped into logical verification units, with the metrics that drive Charon/Aeneas planning. Full per-unit data in inventory.csv.
Environment: kernel ~/linux v7.2-rc2 (read-only) · Charon ~/charon commit 909ff09a, v0.1.220.
- 122 units total; 117 in-scope (5 vendored third-party crates excluded from verification).
- In-scope code totals 92,308 lines across three tiers: kernel crate (55.3k), drivers (27.5k), samples + support + misc (9.5k).
- The in-scope code has 2,020
unsafeblocks, 84% of them in the kernel crate (1,703), which is the FFI surface. - 13 units parse untrusted input, the verification-target candidates.
- 12 units touch a
union(own Rust union or a C__bindgen_anonfield), the known Aeneas blocker (AeneasVerif/aeneas#1199). - 4 units are both (parse untrusted input and touch a union):
nova_core,android_binder,kernel::drm,kernel::iov. Each carries a known downstream blocker.
| Category | Units | LOC | unsafe blocks |
|---|---|---|---|
kernel-crate (rust/kernel/*) |
80 | 55,317 | 1,703 |
driver (drivers/**) |
10 | 27,541 | 183 |
support (rust/macros, pin-init, ffi, …) |
5 | 6,487 | 128 |
sample (samples/rust/*) |
15 | 2,044 | 4 |
| misc-host (build tooling) | 2 | 654 | 0 |
| misc-test (in-tree tests) | 2 | 126 | 2 |
| support-gen (generated shims) | 2 | 115 | 0 |
| sample-host (userspace) | 1 | 24 | 0 |
| in-scope total | 117 | 92,308 | 2,020 |
| vendored (out of scope) | 5 | 90,111 | 344 |
Vendored (zerocopy, zerocopy-derive, syn, quote, proc-macro2) are third-party crates
pulled in for the build (proc-macro toolchain / byte-cast helpers), not kernel verification targets.
Sorted by LOC. The union column flags the known Aeneas blocker; together these two columns
are the planning signal. (Full reasons in the CSV.)
| Unit | LOC | unsafe | union | Why untrusted |
|---|---|---|---|---|
nova_core |
13,451 | 29 | yes | parses VBIOS image + GSP firmware/command-queue blobs from the device |
android_binder |
9,489 | 147 | yes | parses binder transaction buffers & flat objects from userspace IPC |
kernel::drm |
2,770 | 144 | yes | DRM ioctl dispatch decodes userspace ioctl argument structs |
drm_tyr |
2,167 | 1 | no | panthor GPU dev_query ioctl args come from userspace |
kernel::debugfs |
1,752 | 31 | no | read/write file callbacks exchange bytes with userspace |
kernel::str |
1,066 | 18 | no | (marginal) CStr/BStr constructors validate arbitrary byte slices |
kernel::configfs |
1,044 | 40 | no | store callbacks parse userspace-written attribute bytes |
kernel::uaccess |
664 | 14 | no | UserSliceReader/Writer over untrusted user memory |
kernel::miscdevice |
439 | 30 | no | dispatches userspace ioctl/read/write to driver callbacks |
kernel::iov |
314 | 15 | yes | iov_iter ingesting user-supplied I/O vectors |
sample_rust_misc_device |
291 | 0 | no | ioctl + copy_from_user handling (demo) |
drm_nova |
226 | 0 | no | GPU ioctl args from userspace (skeleton driver) |
sample_rust_debugfs_scoped |
144 | 0 | no | reads userspace bytes via uaccess write callback |
The smallest untrusted-input, union-free, low-unsafe units are the natural Phase 2 starting
points: kernel::uaccess, kernel::miscdevice, and the debugfs samples. The larger targets
(nova_core, android_binder, kernel::drm, kernel::iov) all carry the union blocker, so
even a CLEAN Charon pass leaves an open Aeneas item on them.
own = Rust union declared in the unit; anon = references to C __bindgen_anon_* union fields.
| Unit | own | anon | untrusted | Note |
|---|---|---|---|---|
android_binder |
1 | 10 | yes | BinderObject union + binder_transaction_data uapi unions |
nova_core |
4 | 8 | yes | GSP firmware bindgen unions (GspFwWprMeta, RPC message) |
kernel::drm |
0 | 3 | yes | drm.h ioctl unions via gpuvm sm_ops |
kernel::mm |
0 | 6 | no | VMA/page bindgen union fields |
kernel::iov |
0 | 4 | yes | iov_iter bindgen union |
kernel::iommu |
0 | 2 | no | page-table bindgen union |
kernel::gpu |
0 | 2 | no | GPU buddy-allocator bindgen union |
kernel::maple_tree |
0 | 1 | no | maple-node bindgen union |
kernel::module_param |
0 | 1 | no | kernel_param bindgen union |
kernel::bitmap |
1 | 0 | no | BitmapRepr inline/pointer Rust union |
rust_macros |
0 | 1 | no | module! macro emits a kernel_param union field |
vendor_zerocopy |
5 | 0 | n/a | vendored (out of scope) |
The Rust UAPI surface is narrow. Only 8 C headers are bindgen'd (binder.h, drm.h,
panthor_drm.h, nova_drm.h, mdio.h, mii.h, ethtool.h, ioctl.h), of which binder.h,
drm.h, panthor_drm.h, and ethtool.h contain unions. Union exposure concentrates in binder,
the DRM/GPU stack, and the mm/iommu bindgen fields.
- LOC = raw line count of the unit's
.rsfiles.unsafeblocks =unsafe { … }occurrences (separately,unsafe_itemscountsunsafe fn/impl/trait, in the CSV). own_union_declscounts realunion Name { … }declarations (doc-comment examples excluded).bindgen_anon_refscounts__bindgen_anonfield accesses, i.e. use of a C union member.kernel_deps= most-frequentkernel::<x>references per unit (includes prelude macros).- Generated bindings (
uapi_generated.rs,bindings_generated.rs) are build outputs and are not in the read-only tree; union exposure via UAPI was assessed from the C headers directly. - Two kernel submodules (
kernel::drm,kernel::iommu) are declared viamod.rswith no top-level.rsfile and are included as units.
Reproduce: SP=<scratch> python3 tools/metrics.py > $SP/metrics.csv && python3 tools/classify.py.