What Are Kernel Space Stacks in Linux? – Free Linux Device Driver Training

Linux Kernel Space Stacks Explained | Free Linux Kernel Programming Course – EmbeddedPathashala

Linux Kernel Space Stacks Explained
Free Linux Kernel Programming Course | EmbeddedPathashala
Level
Intermediate
Topic
Kernel Internals
Kernel
Linux 6.x

Understanding Linux Kernel Space Stacks — A Complete Guide for Kernel and Driver Developers

When you write a Linux kernel module or a device driver, every function call you make consumes space on the kernel-mode stack. Unlike user-space programs that can grow their stack dynamically, the kernel-mode stack is fixed in size and very small. Misunderstanding this can crash your system or cause silent data corruption.

This tutorial is part of the free Linux kernel programming course at EmbeddedPathashala. By the end of this article, you will have a solid mental model of how kernel space manages stacks for every thread on the system.

What You Will Learn

  • What the kernel space portion of the Virtual Address Space (VAS) looks like
  • How many stacks exist on a running Linux system and why
  • The difference between kernel-mode stacks and user-mode stacks
  • How struct task_struct ties to every thread on the system
  • Why kernel-mode stacks are small and what risks that creates
  • The per-CPU interrupt stack and why it exists on x86 and ARM64
  • How to use CONFIG_FRAME_WARN to catch stack overflow risks at compile time
  • Stack overflow prevention best practices for kernel and driver developers

Prerequisites

  • Basic understanding of Linux processes and threads
  • Familiarity with Virtual Address Space (VAS) concepts — user space vs kernel space
  • Some experience writing or reading Linux kernel module code is helpful but not required
Key Concepts in This Article
kernel-mode stack task_struct kernel space VAS stack frame CONFIG_FRAME_WARN per-CPU interrupt stack kernel thread stack overflow prevention

How the Linux Kernel Organises Its Virtual Address Space

Every process running on a Linux system has its own Virtual Address Space (VAS). This VAS is divided into two regions: user space (where your application code runs) and kernel space (where the kernel itself resides). Kernel space is shared across all processes — the same kernel code and kernel data structures are mapped into the top portion of every process’s address space.

Within kernel space, the kernel must track and manage every thread that is currently alive on the system — both user-mode threads (threads belonging to user-space applications) and kernel threads (threads created entirely within the kernel itself, such as kworker, ksoftirqd, or kthreadd). Each of these threads requires dedicated resources inside kernel space, and the two most important ones are:

  • A task structure — struct task_struct — which stores all metadata about the thread
  • A kernel-mode stack — a small, fixed-size region of kernel memory used whenever that thread executes kernel code
Figure 1 — Kernel Space: task_struct and kernel-mode stacks for user threads and kernel threads
User Process P1
(main thread)
User Process P2
(main + thrd2 + thrd3)
Kernel Thread kthrd1 Kernel Thread kthrd2
task_struct
(metadata for main)
Kernel-mode
Stack

(8KB on 64-bit)
task_struct (main)
task_struct (thrd2)
task_struct (thrd3)
K-stack (main)
K-stack (thrd2)
K-stack (thrd3)
task_struct
(kernel thread)
Kernel-mode
Stack

(only stack it has)
task_struct
(kernel thread)
Kernel-mode
Stack

(only stack it has)
User threads — each has BOTH a user-mode stack AND a kernel-mode stack Kernel threads — ONLY have a kernel-mode stack (no user-space mapping)

How Many Stacks Does a Running Linux System Have?

This is a question that surprises most people when they first encounter it. Let’s reason through it carefully because this is fundamental to understanding how the Linux kernel manages every thread on a live system.

Consider a snapshot of a running system where:

  • There are 1,053 user-mode threads (threads belonging to user-space processes)
  • There are 181 kernel threads (threads that live entirely in kernel space)

This gives a total of 1,234 threads on the system. How many stacks does this require?

Figure 2 — Stack Count Breakdown on a Live Linux System
Thread Type Count User-mode Stack Kernel-mode Stack Total Stacks
User-mode threads 1,053 1,053 ✓ 1,053 ✓ 2,106
Kernel threads 181 None (no user mapping) 181 ✓ 181
Grand Total Stacks on System → 2,287

The key insight here is that every user-mode thread carries two stacks: one in user space (for executing user-space code) and one in kernel space (for executing kernel code on behalf of that thread — for example, during a system call). Kernel threads, on the other hand, live entirely in kernel space and have no user-space mapping at all, so they only get a single kernel-mode stack.

The task_struct — The Kernel’s Control Block for Every Thread

For every thread alive on the system — whether it is a user thread or a kernel thread — the Linux kernel maintains a data structure called struct task_struct. This is essentially the kernel’s “control block” for a thread. It stores everything the kernel needs to know about that thread: its state, its priority, its open file descriptors, its memory mappings, its signal handlers, and much more.

From our example system snapshot:

  • There are 1,234 task structures in kernel memory — one per thread
  • 1,053 of these represent user threads
  • 181 of these represent kernel threads
Note for Kernel Module Developers: The task_struct of the currently executing task is accessible inside kernel code via the current macro. For example, current->pid gives you the PID of the currently running thread. This is one of the most frequently used macros in kernel and driver development.

What is a Kernel-Mode Stack and How Does it Work?

Every time a user-mode thread enters kernel space — through a system call, a hardware interrupt, a page fault, or any other exception — the CPU switches from using the thread’s user-mode stack to its dedicated kernel-mode stack. This is a fundamental mechanism of the x86 and ARM64 privilege level switch.

Key Properties of the Kernel-Mode Stack in Linux 6.x

Property 32-bit Linux 64-bit Linux (x86_64, ARM64)
Size 2 pages (typically 8 KB) 4 pages (typically 16 KB)
Allocation time At thread creation — during kernel_clone() (previously _do_fork() in older kernels)
Growth direction Downward — toward lower virtual addresses (same as user-mode stacks)
Size at runtime Fixed — cannot grow dynamically
Stack Pointer register ESP (32-bit) RSP on x86_64 / SP on ARM64
Linux 6.x Update: In modern Linux (5.x onward), thread creation is handled by kernel_clone() rather than _do_fork(). The function _do_fork() was removed and its functionality merged into kernel_clone() in Linux 5.10. The kernel-mode stack is still allocated at thread creation time — this behaviour has not changed.

How a Stack Frame is Built on the Kernel Stack

Each time a function is called inside the kernel, the CPU sets up a stack frame on the kernel-mode stack. A stack frame contains:

  • The return address (so the CPU knows where to jump back after the function returns)
  • Saved registers (caller-saved or callee-saved, depending on the ABI)
  • Local variables declared inside that function
  • Any arguments passed on the stack (architecture-dependent)
Figure 3 — Kernel-Mode Stack Growing Downward During a System Call
High
SP+
Top of kernel-mode stack
Stack frame of sys_read() entry point
Stack frame of vfs_read()
Stack frame of ext4_file_read_iter()
SP →
← Current stack pointer (growing downward ↓)
[ free space — decreases with every function call ]
Low
⚠ Stack bottom — overflow here = system crash
Total size: 16 KB on 64-bit (4 × 4 KB pages) — fixed, cannot grow

Why is the Kernel-Mode Stack So Small? The Risks for Driver Developers

The kernel-mode stack is intentionally kept small. This is a deliberate design decision with important reasons:

  • There can be thousands of kernel-mode stacks alive at any moment (one per thread). If each were large, the total memory footprint would be enormous.
  • Kernel code is expected to be lean and efficient — deep recursion or large local arrays on the kernel stack are design mistakes, not features.
  • A small stack encourages kernel developers to allocate large buffers on the heap (using kmalloc() or vmalloc()) instead of the stack.
⚠ Critical Warning for Kernel and Driver Developers:
The kernel-mode stack is only 16 KB on 64-bit systems. Never declare large local arrays or buffers on the stack in kernel code. Use dynamic allocation (kmalloc()) for anything beyond a few hundred bytes. Also, avoid deep recursion in kernel code — each recursive call adds another stack frame and can exhaust the stack silently, leading to a kernel panic or memory corruption.

Catching Stack Overflow Risk at Compile Time: CONFIG_FRAME_WARN

The Linux kernel build system includes a configurable option called CONFIG_FRAME_WARN that instructs GCC to emit a warning whenever a single function’s stack frame exceeds a specified size. This is an important safety net for kernel and driver developers.

# In your kernel .config or via menuconfig:
# Kernel hacking → Compile-time checks and compiler options → Warn for stack frames larger than (bytes)

CONFIG_FRAME_WARN=1024   # Warn if any stack frame exceeds 1024 bytes

When enabled, GCC will produce a build-time warning like:

drivers/mydriver/mydriver.c:128:1: warning: the frame size of 1280 bytes is larger than 1024 bytes [-Wframe-larger-than=]
Tip: When developing kernel modules, always build with CONFIG_FRAME_WARN enabled and treat any such warning as a bug that must be fixed. Refactor large stack frames to use kmalloc()-allocated memory instead.

What to Do When You Need Large Buffers in Kernel Code

/* ❌ Wrong — large buffer on kernel stack (dangerous!) */
static int my_driver_read(struct file *f, char __user *buf, size_t count, loff_t *pos)
{
    char tmp[4096];   /* 4 KB on a 16 KB stack — very risky */
    /* ... */
}

/* ✅ Correct — dynamically allocated on the kernel heap */
static int my_driver_read(struct file *f, char __user *buf, size_t count, loff_t *pos)
{
    char *tmp;

    tmp = kmalloc(4096, GFP_KERNEL);
    if (!tmp)
        return -ENOMEM;

    /* ... use tmp ... */

    kfree(tmp);
    return 0;
}

The Per-CPU Interrupt Stack — A Third Type of Stack in the Linux Kernel

Beyond user-mode stacks and kernel-mode stacks, modern Linux on architectures like x86_64 and ARM64 also maintains a per-CPU interrupt stack. This is a separate, dedicated stack used specifically when a hardware interrupt is being handled.

Why Does the Interrupt Stack Exist?

When a hardware interrupt fires — say, from a network card or a disk controller — the CPU’s interrupt mechanism takes control away from whatever thread was running and begins executing the interrupt service routine (ISR). If this ISR were to use the interrupted thread’s kernel-mode stack, it would put additional pressure on an already small 16 KB stack. In deeply nested interrupt scenarios, this could easily overflow.

The solution: each CPU has its own dedicated interrupt stack that is separate from any thread’s kernel-mode stack. When an interrupt fires, the CPU switches to this per-CPU interrupt stack for the duration of the interrupt handling.

Figure 4 — Per-CPU Interrupt Stack (x86_64 / ARM64)
CPU 0
Per-CPU Interrupt Stack
(separate, dedicated)
Thread A kernel-mode stack
CPU 1
Per-CPU Interrupt Stack
(separate, dedicated)
Thread B kernel-mode stack
Each CPU core has its own interrupt stack — prevents stack overflow on the interrupted thread’s stack

Complete Summary: Stacks and Task Structures on a Linux System

For Every Thread on the System
Resource User Thread Kernel Thread
struct task_struct ✓ One per thread (in kernel memory) ✓ One per thread (in kernel memory)
User-mode stack ✓ Dynamic, in user space ✗ None — no user-space mapping
Kernel-mode stack ✓ Fixed, 16 KB on 64-bit ✓ Fixed, 16 KB on 64-bit
Per-CPU interrupt stack Shared per CPU (not per thread) — used during hardware interrupt handling

Best Practices for Linux Kernel and Driver Stack Management

  • Never allocate large local arrays on the kernel stack. Use kmalloc() or vmalloc() for buffers larger than a few hundred bytes.
  • Avoid deep recursion in kernel code. Convert recursive algorithms to iterative ones if they will be called in kernel context.
  • Enable CONFIG_FRAME_WARN in your kernel build configuration during development and fix all warnings before shipping a driver.
  • Use CONFIG_KASAN (Kernel Address Sanitizer) during development to detect stack overflows and other memory errors early.
  • Keep interrupt handlers short. If heavy processing is needed, defer it using workqueues or tasklets — which get their own kernel stacks — rather than doing it directly in the interrupt handler.
  • Check /proc/<pid>/stack during debugging to see the current kernel-mode stack of any thread (requires root and appropriate kernel configuration).

Common Mistakes Made by Kernel and Driver Developers

Mistake 1: Large Stack Allocations in Interrupt Context

Interrupt handlers and softirq handlers run on the per-CPU interrupt stack. Allocating large structures here is especially dangerous because the interrupt stack is typically the same size or smaller than the kernel-mode stack.

Mistake 2: Passing Large Structs by Value in Kernel Functions

When you pass a large structure by value to a kernel function, a copy is placed on the kernel stack. Pass pointers instead and use dynamic allocation for the structure itself.

Mistake 3: Assuming the Kernel Stack Behaves Like a User Stack

User-mode stacks can grow dynamically (the kernel will allocate more pages via demand paging when a guard page is hit). The kernel-mode stack cannot grow — hitting its limit causes a kernel panic or silent corruption. There is no guard page mechanism for the kernel-mode stack in the same way.

Key Takeaways

  • Every thread (user or kernel) has exactly one struct task_struct in kernel memory.
  • Every user-mode thread has two stacks: a user-mode stack and a kernel-mode stack.
  • Kernel threads have only one stack: a kernel-mode stack.
  • Kernel-mode stacks are fixed in size: 8 KB on 32-bit systems, 16 KB on 64-bit systems.
  • They are allocated at thread creation time via kernel_clone() in Linux 6.x.
  • Modern Linux on x86_64 and ARM64 uses a per-CPU interrupt stack to isolate interrupt handling from thread stacks.
  • Use CONFIG_FRAME_WARN to catch stack frame size issues at compile time.
  • Always use kmalloc() for large buffers — never the kernel stack.

Conclusion

Understanding how Linux manages kernel space stacks is foundational knowledge for anyone pursuing Linux kernel programming or Linux device driver development. The kernel-mode stack underpins every system call, every interrupt handler, and every line of code in your kernel module. Its small, fixed size is both a constraint and a discipline that pushes kernel developers toward clean, efficient code.

In the next article in this free Linux kernel development course, we will look at how to actually view and inspect both the kernel-mode and user-mode stacks of any running thread using the /proc filesystem and modern eBPF-based tools.

Frequently Asked Questions (FAQ)

Q1: What is the size of the kernel-mode stack in Linux 6.x on a 64-bit system?

On a 64-bit system (x86_64 or ARM64) running Linux 6.x, the kernel-mode stack is 4 pages × 4 KB = 16 KB per thread. On 32-bit systems it is 2 pages × 4 KB = 8 KB.

Q2: Does a kernel thread have a user-mode stack?

No. Kernel threads have no user-space mapping and therefore no user-mode stack. They execute entirely in kernel space and only have a kernel-mode stack.

Q3: What happens if the kernel-mode stack overflows?

A kernel stack overflow typically leads to a kernel panic, a system hang, or silent memory corruption — all of which are catastrophic. Unlike user-mode stack overflows (which generate a segfault the OS can catch), kernel stack overflows have no safe recovery mechanism.

Q4: When is the kernel-mode stack allocated for a thread?

The kernel-mode stack is allocated when the thread is created, inside kernel_clone() (Linux 5.10 and later). In older kernels this was done inside _do_fork(). Once allocated, the stack size does not change.

Q5: What is CONFIG_FRAME_WARN and why should I use it?

CONFIG_FRAME_WARN is a kernel build option that instructs GCC to emit a compile-time warning if any function’s stack frame exceeds a specified size (e.g., 1024 bytes). This helps kernel and driver developers catch potential stack overflow risks before they cause runtime problems.

Q6: What is the per-CPU interrupt stack?

On architectures like x86_64 and ARM64, each CPU core has a dedicated interrupt stack that is used only when handling hardware interrupts. This prevents the interrupt handler from consuming space on the interrupted thread’s already small kernel-mode stack.

Q7: How is kmalloc() different from stack allocation in the kernel?

kmalloc() allocates memory from the kernel’s heap (slab allocator), which is much larger than the 16 KB kernel stack. Use kmalloc(GFP_KERNEL) for buffers that would otherwise be too large for the stack. Always check for allocation failure and free with kfree().

Q8: Can I see the kernel stack of a running process?

Yes. The Linux kernel exposes the kernel-mode call stack of any thread via /proc/<pid>/stack. This requires root access. On modern kernels, this is restricted to root by default to prevent information leakage. We cover this in the next tutorial in this series.

Q9: Does struct task_struct store the kernel-mode stack?

The task_struct contains (or points to) the kernel-mode stack through its stack field, which points to the base of the thread’s kernel stack. The stack itself is a separate allocation — task_struct is the metadata, the stack is the execution resource.

Q10: How many kernel-mode stacks can exist on a production Linux server?

On a production server with thousands of threads (which is common), you can have thousands of kernel-mode stacks. Each consumes 16 KB of kernel memory. A server with 5,000 threads would have up to 80 MB of memory consumed by kernel stacks alone — which is why keeping them small is important.

References and Further Reading

Continue the Free Linux Kernel Programming Course

EmbeddedPathashala offers 100% free, in-depth courses on Linux kernel internals, Linux device drivers, and embedded systems programming.

Next: Viewing Kernel Stacks via /proc → ← Back to Course Index

Leave a Reply

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