What Is the Difference Between kmalloc() and kvmalloc()? – Best Linux Device Drivers Training in Hyderabad

Linux Kernel Memory Allocation Tutorial
kmalloc, kzalloc & kfree Explained — Free Linux Kernel Development Course
100% Free
Beginner Friendly
Updated for Modern Kernels

Every Linux kernel module, driver, or subsystem eventually needs to allocate memory dynamically, and doing this correctly is one of the core skills you build in any serious Linux kernel development course. In this lesson of our free Linux kernel development course, we take a deep, practical look at Linux kernel memory allocation using the slab/slub allocator interfaces — specifically kmalloc(), kzalloc(), and kfree() — along with the modern APIs and best practices used in current kernel releases.

This tutorial is part of EmbeddedPathashala’s free Linux device drivers course and free embedded systems course content, aimed at helping engineers move from user-space programming into confident, safe kernel-space development.

Topics covered in this lesson:

kmalloc()
kzalloc()
kfree()
kfree_sensitive()
SLUB allocator
GFP flags
kvmalloc()
Integer overflow safety
Cacheline alignment

What You Will Learn

By the end of this Linux kernel memory allocation lesson, you will be able to:

  • Explain how kmalloc() and kzalloc() work internally and how they differ from user-space malloc().
  • Choose the correct GFP flag for your allocation context.
  • Avoid integer overflow bugs when calculating allocation sizes.
  • Safely free kernel memory using kfree() and kfree_sensitive().
  • Recognize and avoid common kernel memory bugs such as double-free and use-after-free.
  • Apply cacheline-aware data structure design for better driver performance.

Prerequisites

This lesson assumes you have already covered the earlier modules of this free Linux kernel development course:

  • Comfortable reading and writing C code, including pointers and structs.
  • Basic understanding of how to write and load a Linux Kernel Module (LKM).
  • Familiarity with kernel logs via dmesg and printk().

Why Linux Kernel Memory Allocation Is Different

Kernel code cannot rely on the C library’s malloc() and free() because there is no glibc, no heap in the user-space sense, and no memory protection safety net. Instead, the kernel provides its own family of allocators, the most commonly used being the slab-based interfaces. On current mainline kernels the underlying implementation is SLUB (the older SLAB allocator was removed from the tree in kernel 6.5, and SLOB was removed even earlier), so understanding the modern allocator behaviour matters if you are learning kernel memory allocation today rather than from an outdated reference.

Two functions dominate everyday kernel memory allocation: kmalloc() and kzalloc(). Both are declared in <linux/slab.h> and both return a kernel logical address — a virtual address that maps to physically contiguous RAM.

Kernel Memory Allocation Lifecycle
kzalloc(size, GFP_KERNEL)
→
Zeroed, cacheline-aligned buffer
→
Driver uses buffer
→
kfree(ptr)

kmalloc() vs kzalloc(): What’s the Real Difference?

Both APIs take the same two arguments: the number of bytes to allocate, and a set of GFP (Get Free Page) flags describing the allocation context. The only functional difference is that kzalloc() zeroes out the returned memory before handing it back, while kmalloc() leaves the contents undefined (whatever garbage happened to be in that slab previously).

void *kmalloc(size_t size, gfp_t flags);
void *kzalloc(size_t size, gfp_t flags);
void  kfree(const void *ptr);

In modern kernel development, kzalloc() is the recommended default. The small cost of zeroing memory is almost never significant compared to the class of bugs it prevents — uninitialized-memory reads, accidental information disclosure to user space, and subtle logic errors. Reserve plain kmalloc() for genuinely hot, latency-sensitive paths where you will overwrite every byte immediately anyway (for example, certain networking and block I/O fast paths).

API Zeroes Memory? Typical Use Case
kmalloc() No Performance-critical paths where the buffer is fully overwritten right after allocation
kzalloc() Yes General-purpose driver and subsystem allocations (recommended default)
kcalloc() Yes Allocating an array, with built-in overflow checking on count × size
kvmalloc() No Larger allocations that may not fit as a single contiguous slab chunk
kvzalloc() Yes Same as kvmalloc(), zeroed

Understanding GFP Flags for Kernel Memory Allocation

The second parameter to every slab allocation call tells the memory management subsystem how it is allowed to behave while satisfying the request — can it sleep, can it trigger reclaim, is it running in an interrupt handler? Getting this wrong is one of the most common beginner mistakes in Linux kernel memory allocation.

  • GFP_KERNEL – the standard flag for normal process-context code. The call may sleep while the kernel frees up memory.
  • GFP_ATOMIC – used inside interrupt handlers, spinlock-protected sections, or anywhere sleeping is forbidden. The allocator will not block, but the request may fail more readily under memory pressure.
  • GFP_NOWAIT – similar intent to GFP_ATOMIC in that it will not sleep, but it does not dip into emergency memory reserves the way GFP_ATOMIC can.
  • GFP_DMA / GFP_DMA32 – request memory usable by devices with limited DMA addressing ranges.

Tip: if you are unsure which flag to use, ask yourself one question — “can this code path legally sleep?” If yes, use GFP_KERNEL. If you are inside an interrupt context, a tasklet, or holding a spinlock, use GFP_ATOMIC.

Avoiding Integer Overflow in Allocation Size Calculations

A well-known class of kernel security bugs comes from computing an allocation size dynamically — for example, multiplying a count by an element size — without checking for overflow. If that multiplication wraps around, the kernel ends up allocating a buffer far smaller than the code assumes, opening the door to a heap overflow.

Modern kernel code avoids open-coded arithmetic in allocation arguments and instead relies on overflow-checked helpers:

/* Preferred: overflow-checked array allocation */
ptr = kcalloc(count, sizeof(*ptr), GFP_KERNEL);

/* Preferred: struct_size() helper for flexible-array-member structs */
ptr = kzalloc(struct_size(ptr, items, num_items), GFP_KERNEL);

Both kcalloc() and the struct_size() macro will safely fail the allocation (returning NULL) rather than silently wrapping around, which is exactly the behaviour you want when writing secure kernel code today.

Freeing Memory Correctly with kfree()

The counterpart to allocation is kfree(). It takes a single pointer argument — the exact value returned by kmalloc(), kzalloc(), or one of their variants — and returns that slab chunk to the allocator’s free list.

void kfree(const void *ptr);

A few practical rules that will save you painful debugging sessions:

  • kfree(NULL) is explicitly safe and a documented no-op, so you never need to wrap a free call in a NULL check.
  • kfree() does not reset the pointer variable to NULL for you. If your code frees a pointer inside a loop and does not reassign it, you risk a dangerous double-free on the next iteration.
  • Passing a pointer to kfree() that was not returned by a slab allocator (for example, a pointer into the middle of an allocation, or a stack address) corrupts kernel memory and can crash or compromise the system.
Double-Free Bug Pattern to Avoid
Iteration 1: allocate → use → free
Iteration 2: pointer still non-NULL → allocation skipped → free() called again → corruption

Wiping Sensitive Memory: kfree_sensitive()

Freeing a slab chunk only returns it to the allocator’s free list — it does not clear the data inside it. If that buffer held sensitive material such as cryptographic keys, credentials, or user data, the old bytes can remain readable to whoever gets that slab chunk next, creating an information-leak vulnerability.

Older kernel documentation and tutorials reference kzfree() for this purpose, but that name has been renamed in current kernels to kfree_sensitive(). It clears the memory using a compiler-safe wipe before releasing it, and it is the correct API to reach for whenever sensitive kernel buffers are freed:

void kfree_sensitive(const void *ptr);

Use kfree_sensitive() any time the buffer being released could plausibly contain secrets. For everyday, non-sensitive allocations, plain kfree() remains perfectly fine.

Cacheline-Aware Data Structure Design

Memory returned by the slab allocator is guaranteed to be cacheline-aligned, which is a real performance advantage — but only if you design your data structures to take advantage of it. CPUs move data between RAM and cache in fixed-size blocks (commonly 64 bytes on modern x86 and ARM cores; check yours with getconf -a | grep LINESIZE).

A simple, high-value practice: group the fields your driver accesses most frequently (“hot” fields) together at the top of the struct, and push rarely-used or “cold” fields to the end. This way, touching one hot field pulls the rest of the hot fields into cache in the same fetch, reducing costly cache misses on performance-sensitive code paths such as interrupt handlers or per-packet networking code.

Hot vs Cold Struct Layout
Hot fields
(top of struct,
same cacheline)
Cold fields
(bottom of struct,
separate cacheline)

Real-World Use Cases

  • Character and block device drivers allocate per-device private structures with kzalloc() during probe().
  • Network drivers use GFP_ATOMIC allocations inside interrupt-driven receive paths where sleeping is not permitted.
  • Filesystem code relies on slab caches heavily for inode and buffer management, often via dedicated kmem_cache objects built on the same underlying allocator.

Common Mistakes and Troubleshooting Tips

Mistake Consequence Fix
Using GFP_KERNEL in interrupt context System hang or kernel warning (“scheduling while atomic”) Use GFP_ATOMIC in atomic/interrupt context
Freeing a pointer twice Memory corruption, crashes, potential security exploit Set the pointer to NULL immediately after kfree()
Open-coded size arithmetic (count * size) Integer overflow, undersized buffer, heap overflow Use kcalloc() or struct_size()
Using kmalloc() for sensitive buffers and forgetting to wipe on free Information leak to future allocations Use kfree_sensitive()

If you suspect a memory bug in your module, enable KASAN (Kernel Address Sanitizer) in a debug kernel build. It reliably catches use-after-free, out-of-bounds, and double-free bugs in slab allocations that are otherwise very difficult to reproduce.

Best Practices Checklist

  • Default to kzalloc() unless you have a proven performance reason to use plain kmalloc().
  • Always match the GFP flag to the calling context.
  • Never hand-roll size arithmetic for allocations; use kcalloc() or struct_size().
  • Set pointers to NULL right after freeing them.
  • Use kfree_sensitive() for any buffer that may contain secrets.
  • Design structs with hot fields grouped together for cache efficiency.

Performance and Security Considerations

The SLUB allocator that backs kmalloc()/kzalloc() on current kernels is designed to be largely lock-free on the fast path, using per-CPU freelists so that most allocations and frees never need a global lock. For most drivers this means allocation cost is not the bottleneck — correctness and safe cleanup matter far more. From a security standpoint, treat every kernel allocation as something that could eventually be exposed to user space through a bug; zeroing on allocation and wiping on free for sensitive data are cheap insurance against serious vulnerabilities.

Summary / Key Takeaways

  • kmalloc() and kzalloc() are the primary APIs for Linux kernel memory allocation, returning physically contiguous, cacheline-aligned memory.
  • Prefer kzalloc() by default; it prevents an entire class of uninitialized-memory bugs.
  • Choose GFP flags based on whether your code can sleep.
  • Use overflow-safe helpers like kcalloc() and struct_size() instead of hand-computed sizes.
  • kfree_sensitive() replaces the older kzfree() for wiping sensitive buffers on free.
  • Cacheline-aware struct layout is a free performance win once you understand it.

Conclusion

Mastering Linux kernel memory allocation is a foundational skill for anyone serious about writing drivers, working on the kernel core, or pursuing embedded Linux engineering as a career. The APIs themselves are simple, but the discipline around GFP flag selection, overflow-safe sizing, and correct freeing is what separates production-quality kernel code from code that crashes systems in the field. Keep practicing these patterns in your own kernel modules as you continue through this free Linux kernel development course.

Frequently Asked Questions

Q1. What is the difference between kmalloc() and malloc()?
kmalloc() allocates kernel-space memory that is physically contiguous and cacheline-aligned, and it requires a GFP flag describing the allocation context. malloc() is a user-space glibc call with no direct relationship to kmalloc(); they operate in entirely separate memory spaces.

Q2. Should I always use kzalloc() instead of kmalloc()?
In most driver and subsystem code, yes. kzalloc() is safer because it prevents uninitialized-memory bugs. Use plain kmalloc() only in performance-critical paths where you will overwrite the entire buffer immediately.

Q3. What happened to kzfree()?
kzfree() was renamed to kfree_sensitive() in current kernels. Its purpose is unchanged: it wipes memory before returning it to the allocator, which is important for sensitive data.

Q4. Is it safe to call kfree(NULL)?
Yes, kfree(NULL) is explicitly documented as a safe no-op, so you never need to guard a kfree() call with a NULL check.

Q5. What GFP flag should I use inside an interrupt handler?
Use GFP_ATOMIC. Interrupt handlers cannot sleep, and GFP_KERNEL allocations may block, which is not permitted in that context.

Q6. Why does the kernel avoid open-coded multiplication for allocation sizes?
Because count * size arithmetic can silently overflow, resulting in a much smaller buffer than intended and creating a heap overflow vulnerability. kcalloc() and struct_size() check for this safely.

Q7. Does the Linux kernel still use the SLAB allocator?
No. The original SLAB allocator was removed from the mainline kernel in version 6.5. SLUB is now the sole slab-based allocator, alongside the simpler SLOB, which was removed earlier.

Q8. What should I use for large allocations that might not fit as one contiguous slab chunk?
Use kvmalloc() (or kvzalloc() for zeroed memory), which transparently falls back to vmalloc()-backed memory when a contiguous kmalloc() allocation of that size is not available.

Continue Your Free Linux Kernel Development Course

Keep learning kernel memory management, device drivers, and embedded Linux — completely free on EmbeddedPathashala.

Leave a Reply

Your email address will not be published. Required fields are marked *