Case 175: kABI CRC Changed¶
| Field | Value |
|---|---|
| Verdict | ๐ด BREAKING |
| Category | Breaking |
| Platforms | Linux |
| Flags | ABI break |
Detected ChangeKinds |
kabi_crc_changed |
| Source files | examples/case175_kabi_crc_changed/ |
Category: Linux Kernel Module ABI (kABI) | Verdict: ๐ด BREAKING
Verdict and consumer impact¶
ext4_iget keeps its symbol name, module, export type, and namespace โ
every field a naive symbol-presence diff would look at is identical
between v1 and v2. Only its CRC changed. The CRC is not a version number a
maintainer sets; it is a hash genksyms computes at build time from the
symbol's type signature โ its return type, parameter types, and
(transitively) every type they reference. A CRC change means a type behind
ext4_iget changed, even though the function itself may look untouched.
With CONFIG_MODVERSIONS enabled (the default on distro kernels), every
out-of-tree module embeds the CRC of each symbol it imports at build time;
insmod/modprobe reject a module whose embedded CRC disagrees with the
running kernel's, with disagrees about version of symbol ext4_iget โ a
hard load failure for a symbol that unambiguously still exists.
Old/new diff¶
| v1.symvers | v2.symvers |
|---|---|
0x8f3a2c11 ext4_iget fs/ext4/ext4 EXPORT_SYMBOL_GPL EXT4 |
0xd41d8cd9 ext4_iget fs/ext4/ext4 EXPORT_SYMBOL_GPL EXT4 |
(both files also carry an unrelated, unchanged ext4_mark_iloc_dirty line โ
abicheck correctly leaves it out of the finding.)
abicheck command¶
Expected abicheck finding¶
Verdict: BREAKING (exit 4)
- kabi_crc_changed: Kernel symbol CRC changed: ext4_iget (0x8f3a2c11 -> 0xd41d8cd9)
-- modversions will reject the module
> A kernel-exported symbol's genksyms CRC changed. Even though the symbol
still exists, CONFIG_MODVERSIONS embeds the old CRC in out-of-tree
modules and the loader rejects the module ('disagrees about version of
symbol') -- the type signature behind the symbol changed.
Minimum evidence¶
min_evidence: L0 โ the two Module.symvers manifests are read directly
(one <CRC>\t<Symbol>\t<Module>\t<Export Type>\t<Namespace> line per
exported symbol); no kernel build and no compiler are needed.
Why abicheck catches it¶
abicheck parses each Module.symvers line into its five columns and diffs
by symbol name across the two manifests. A CRC delta with every other
column identical is exactly kabi_crc_changed โ the tool never needs to
know which type changed, only that the hash summarizing "everything
ext4_iget's signature transitively touches" no longer matches.
Real-world deployment scenario¶
This is what a CI job diffing two kernel build trees' Module.symvers
across a kernel update sees โ e.g. a distro's kABI-stability gate (RHEL-style
kABI whitelists) checked before publishing a kernel update, or an
out-of-tree driver vendor verifying their module still loads against an
upcoming kernel release before shipping it. A plain nm/symbol-presence
diff of the running kernel would report no change at all; only reading the
CRC column catches the break before a customer's insmod fails in the
field.
Safe redesign¶
Treat any change to a struct or typedef reachable from an
EXPORT_SYMBOL* function's signature as a kABI break, even when the
function itself is untouched โ the CRC is transitive. If a field genuinely
must change, add a new exported accessor rather than changing the layout
an existing one depends on, and gate merges on Module.symvers diffing (not
just symbol-presence checks) for any kernel ABI series with a stability
guarantee.
Cross-tool comparison¶
abidiff/abi-compliance-checker diff DWARF-carrying compiled binaries
(.so/kernel modules with debug info); neither reads Module.symvers
directly, so there is no equivalent invocation of either tool for this
fixture pair.
References¶
- Linux kernel: Symbol Versioning (kbuild docs)
- Related case:
case176_kabi_symbol_namespace_changed
Source files¶
v1.symversv2.symvers
See also: Examples overview ยท All BREAKING cases ยท Category: Breaking.