mm/kfence/report.c
Source file repositories/reference/linux-study-clean/mm/kfence/report.c
File Facts
- System
- Linux kernel
- Corpus path
mm/kfence/report.c- Extension
.c- Size
- 11527 bytes
- Lines
- 376
- Domain
- Core OS
- Bucket
- Memory Management
- Inferred role
- Core OS: implementation source
- Status
- source implementation candidate
Why This File Exists
Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.
- Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/stdarg.hlinux/bug.hlinux/init.hlinux/kernel.hlinux/lockdep.hlinux/math.hlinux/panic.hlinux/printk.hlinux/sched/debug.hlinux/seq_file.hlinux/sprintf.hlinux/stacktrace.hlinux/string.hlinux/string_choices.hlinux/sched/clock.htrace/events/error_report.hasm/kfence.hkfence.h
Detected Declarations
function early_kfence_faultfunction seq_con_printffunction get_stack_skipnrfunction kfence_print_stackfunction kfence_print_objectfunction print_diff_canaryfunction kfence_report_errorfunction kfence_handle_faultfunction kfence_to_kp_stackfunction __kfence_obj_info
Annotated Snippet
switch (*type) {
case KFENCE_ERROR_UAF:
case KFENCE_ERROR_OOB:
case KFENCE_ERROR_INVALID:
/*
* kfence_handle_page_fault() may be called with pt_regs
* set to NULL; in that case we'll simply show the full
* stack trace.
*/
return 0;
case KFENCE_ERROR_CORRUPTION:
case KFENCE_ERROR_INVALID_FREE:
break;
}
}
for (skipnr = 0; skipnr < num_entries; skipnr++) {
int len = scnprintf(buf, sizeof(buf), "%ps", (void *)stack_entries[skipnr]);
if (str_has_prefix(buf, ARCH_FUNC_PREFIX "kfence_") ||
str_has_prefix(buf, ARCH_FUNC_PREFIX "__kfence_") ||
str_has_prefix(buf, ARCH_FUNC_PREFIX "__kmem_cache_free") ||
!strncmp(buf, ARCH_FUNC_PREFIX "__slab_free", len)) {
/*
* In case of tail calls from any of the below to any of
* the above, optimized by the compiler such that the
* stack trace would omit the initial entry point below.
*/
fallback = skipnr + 1;
}
/*
* The below list should only include the initial entry points
* into the slab allocators. Includes the *_bulk() variants by
* checking prefixes.
*/
if (str_has_prefix(buf, ARCH_FUNC_PREFIX "kfree") ||
str_has_prefix(buf, ARCH_FUNC_PREFIX "kmem_cache_free") ||
str_has_prefix(buf, ARCH_FUNC_PREFIX "__kmalloc") ||
str_has_prefix(buf, ARCH_FUNC_PREFIX "kmem_cache_alloc"))
goto found;
}
if (fallback < num_entries)
return fallback;
found:
skipnr++;
return skipnr < num_entries ? skipnr : 0;
}
static void kfence_print_stack(struct seq_file *seq, const struct kfence_metadata *meta,
bool show_alloc)
__must_hold(&meta->lock)
{
const struct kfence_track *track = show_alloc ? &meta->alloc_track : &meta->free_track;
u64 ts_sec = track->ts_nsec;
unsigned long rem_nsec = do_div(ts_sec, NSEC_PER_SEC);
u64 interval_nsec = local_clock() - track->ts_nsec;
unsigned long rem_interval_nsec = do_div(interval_nsec, NSEC_PER_SEC);
/* Timestamp matches printk timestamp format. */
seq_con_printf(seq, "%s by task %d on cpu %d at %lu.%06lus (%lu.%06lus ago):\n",
show_alloc ? "allocated" : meta->state == KFENCE_OBJECT_RCU_FREEING ?
"rcu freeing" : "freed", track->pid,
track->cpu, (unsigned long)ts_sec, rem_nsec / 1000,
(unsigned long)interval_nsec, rem_interval_nsec / 1000);
if (track->num_stack_entries) {
/* Skip allocation/free internals stack. */
int i = get_stack_skipnr(track->stack_entries, track->num_stack_entries, NULL);
/* stack_trace_seq_print() does not exist; open code our own. */
for (; i < track->num_stack_entries; i++)
seq_con_printf(seq, " %pS\n", (void *)track->stack_entries[i]);
} else {
seq_con_printf(seq, " no %s stack\n", show_alloc ? "allocation" : "deallocation");
}
}
void kfence_print_object(struct seq_file *seq, const struct kfence_metadata *meta)
{
const int size = abs(meta->size);
const unsigned long start = meta->addr;
const struct kmem_cache *const cache = meta->cache;
lockdep_assert_held(&meta->lock);
if (meta->state == KFENCE_OBJECT_UNUSED) {
seq_con_printf(seq, "kfence-#%td unused\n", meta - kfence_metadata);
return;
}
Annotation
- Immediate include surface: `linux/stdarg.h`, `linux/bug.h`, `linux/init.h`, `linux/kernel.h`, `linux/lockdep.h`, `linux/math.h`, `linux/panic.h`, `linux/printk.h`.
- Detected declarations: `function early_kfence_fault`, `function seq_con_printf`, `function get_stack_skipnr`, `function kfence_print_stack`, `function kfence_print_object`, `function print_diff_canary`, `function kfence_report_error`, `function kfence_handle_fault`, `function kfence_to_kp_stack`, `function __kfence_obj_info`.
- Atlas domain: Core OS / Memory Management.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.