kmemleak Reports: Separate Unreachable Allocations from Legitimately Retained Driver State
A kmemleak entry identifies an allocation that the scanner could not reach through the references it recognizes; it is a leak suspect, not an instruction to free the printed address. Investigate the allocation’s owner and complete cleanup boundary, then repeat a controlled operation to see which suspects persist or accumulate. Total free memory alone cannot answer that question.
This guide is pinned to upstream Linux v6.12 and kernel allocations visible to kmemleak. It is not a userspace heap profiler or a general detector for every physical page. The procedure is for a recoverable development target with diagnostic access already approved. No kmemleak-enabled kernel or device operation was run for this article.
Confirm the observer before collecting suspects
The v6.12 kmemleak reference describes tracing allocation/free operations and scanning memory for values that point into tracked allocations. Unreferenced objects are reported through debugfs. The detector reports them; it does not garbage-collect the suspected allocations.
Check CONFIG_DEBUG_KMEMLEAK, the final boot parameters, and whether default-off configuration requires explicit activation. Preserve startup errors, including tracking-resource exhaustion. Verify the debugfs interface exists and can be read on the selected diagnostic image. Do not assume a missing report means a successful scan if initialization failed.
Record the scan policy and instrumentation overhead separately from the original failure. Use bounded capture files on a suitable destination. Debugfs access and diagnostic logs can expose addresses and application data embedded in allocations, so keep raw artifacts within the project’s approved analysis environment.
Define the lifecycle checkpoint
Choose one operation whose ownership is understandable: create a channel, start a transfer, stop it, then destroy the channel. Identify the final point after callbacks, deferred releases and driver-owned references are expected to disappear. A snapshot taken halfway through teardown is a different state from a quiescent checkpoint.
For every suspect class, prepare a ledger containing allocation backtrace, object size, logical owner, expected last user and release function. Distinguish one-time retained driver state from per-operation resources. A bounded cache is legitimate only if its retention policy, capacity and eventual teardown are intentional; the word “cache” is not a substitute for an owner.
For a hypothetical capture device, a permanent control object may remain until device removal, while a per-session descriptor should disappear after session close. Compare equivalent session-close checkpoints first. Only use device-removal checkpoints when the test explicitly includes device removal and the release path has completed.

Use scan, archive, clear, operation and scan deliberately
- Bring the diagnostic image to the chosen initial checkpoint. Trigger a documented manual scan, allow the scanner and pending work to finish, then save the full baseline report.
- Archive that report before using
clear. While kmemleak remains active, this marks currently reported unreferenced objects grey to establish a new reporting baseline; it does not free the suspected driver objects. - Run the single bounded operation and its complete cleanup sequence. Record operation identifiers, failures and deferred-work completion.
- Trigger another manual scan and save the resulting report at the same checkpoint.
- Repeat the operation and scans without clearing after every suspect. Look for persistence and additional allocations from the same source path.
The documented control words are written to /sys/kernel/debug/kmemleak; reading that interface retrieves the report. This is a proposed sequence, not an executed shell transcript. Do not include the irreversible off control in routine cleanup. Its behavior is different from pausing automatic scans, and clearing after the detector has been disabled has different internal-cleanup semantics.
Do not require an immediate scan to report every new allocation. The detector has age and scanning constraints, and the driver may release objects asynchronously. Choose a post-operation observation window from the actual cleanup protocol and detector configuration. Save those conditions rather than inventing one universal sleep duration.
Read the allocation backtrace as provenance
The backtrace says where the object was allocated. It does not directly identify the branch that lost the final reference. Trace ownership forward from construction through registration, publication, error handling and release. For a report appearing only after one failed initialization step, compare that failure branch with the successful object’s teardown.
Group suspects by allocation path and object role before comparing counts. One lost root object can leave several child allocations unreachable, so a long report may represent one missing ownership transition. Investigate the earliest relevant allocation and its children without assuming every row is an independent defect.
Keep raw addresses as per-run identifiers rather than cross-boot keys. Reuse can give the same address a new object generation. A useful cross-run signature combines allocation stack, size, operation phase and logical type; retain individual records whenever those attributes differ.
Separate unreachable state from scanner limitations
A real allocation can be missed if unrelated memory happens to contain a value that looks like a pointer into it. Conversely, an object can appear unreferenced because its real reference is not visible in a representation or interval the scanner recognizes. The source discusses transient reports and false positives and negatives; neither an empty report nor one suspicious row settles lifetime correctness.
Check where the last intended reference lives. Encoded pointers, device-owned state and custom allocation integration deserve source-specific review. Do not add a detector annotation merely because a suspect is inconvenient. Establish a legitimate owner and release contract first, then explain exactly why the tracking model fails to represent it.
Annotations such as marking an object not-a-leak or ignoring it have different scanning effects. The v6.12 API documentation distinguishes them. Suppressing a parent can also affect visibility of references to other objects; therefore annotation review must include the object’s outgoing pointers, not only whether its own report disappears.
Turn observations into decisions
- New objects from one allocation site appear after every completed cycle: audit the matching failure or teardown path and minimize the operation sequence.
- A first-cycle allocation remains but later cycles do not add more: verify the documented retained-state owner and budget; do not label it a leak solely because it survives.
- A suspect disappears after the real deferred-release checkpoint: fix the experiment’s phase labeling, then confirm the release is bounded.
- Application memory grows while kmemleak remains quiet: inspect coverage, reachable-but-unwanted retention and nontracked memory classes.
These are investigation branches, not automatic verdicts. In the hypothetical capture driver, a descriptor lost only when the second setup stage fails calls for a targeted error-path test. A control object deliberately retained until final detach calls for a lifecycle budget and a detach test.
Close the ownership loop
Accept a repair when the affected allocation has an explicit release owner, its normal and failure paths balance resources, and repeated equivalent checkpoints no longer accumulate unexplained suspects. Preserve the before/after reports and operation counts. Run a production-like workload separately to assess resource and timing effects outside the instrumented image.
The deliverable is an allocation/backtrace lifecycle ledger with scan evidence and stated blind spots. A manually cleared report is a fresh baseline, not proof that memory was reclaimed or that the driver is leak-free.