(Focus Keyphrase: Kprobes internals Linux kernel)
🔁 Quick Recap
So far in this series:
- Part 1: What Kprobes are
- Part 2: How to use Kprobes in real debugging
- Part 3: How Kretprobes help capture return values
At this point, you can already use Kprobes effectively.
However, one important question still remains:
💭 What actually happens inside the kernel when a probe is hit?
The Real Curiosity
When you write:
kp.symbol_name = "do_sys_open";
register_kprobe(&kp);
It looks simple.
But internally, something powerful happens:
👉 The kernel modifies execution flow without changing source code
So the real question is:
💭 How does the kernel intercept a function call at runtime?
⚙️ Step 1: Resolving the Symbol
When you register a Kprobe, the kernel first resolves the symbol name.
- It looks up the function address (e.g.,
do_sys_open) - This is done using kernel symbol tables
👉 At this stage, the kernel knows where to place the probe.
⚙️ Step 2: Inserting a Breakpoint
Now comes the most critical part.
The kernel:
👉 Replaces the first instruction of the target function
👉 With a breakpoint instruction
Depending on architecture:
- x86 →
int3 - ARM → breakpoint instruction (
BRK/ undefined instruction)
🔍 What This Means
Instead of executing the original instruction:
👉 CPU hits the breakpoint
👉 Control jumps into the kernel’s probe handler
This is how the kernel “hooks” the function.
⚙️ Step 3: Trap Handling
When the breakpoint is hit:
- CPU triggers an exception
- Kernel enters trap handler
- Kprobe framework takes control
At this point:
👉 Your pre_handler gets executed
⚙️ Step 4: Single Stepping the Original Instruction
Now the kernel must continue normal execution.
However, the original instruction was overwritten.
So what does it do?
👉 It executes the original instruction in a safe buffer
👉 Uses single-step execution
This ensures correctness.
⚙️ Step 5: Resuming Execution
Once the original instruction is executed:
👉 Control returns to the next instruction
👉 Program continues normally
From the application’s perspective:
✔ Nothing changed
✔ No code modification visible
Putting It All Together
Here’s the complete flow:
- Function is about to execute
- Breakpoint is hit
- Kernel trap handler runs
- Kprobe handler executes
- Original instruction runs safely
- Execution resumes
👉 All of this happens transparently at runtime
What About Kretprobes?
Kretprobes work slightly differently.
Instead of modifying entry:
👉 They hook the return address
- The return address is replaced
- A trampoline is inserted
- When the function returns → handler executes
⚠️ Important Considerations
Because Kprobes work at instruction level:
- They are architecture-dependent
- Not all instructions are safe to probe
- Recursive probing must be avoided
Therefore, careful usage is important.
Key Insight
Earlier, we used Kprobes as a tool.
Now you understand:
👉 It is not magic
👉 It is controlled manipulation of execution flow
This realization is important.
Because once you understand internals:
👉 You know where to probe
👉 You know what to expect
👉 You debug with confidence
🔜 What’s Next?
Now that you understand:
✔ Entry (Kprobes)
✔ Exit (Kretprobes)
✔ Internals (this blog)
The next step is:
💭 What are the alternatives?
💭 When should you use ftrace or eBPF instead?
👉 In the next blog, we will compare Kprobes vs ftrace vs eBPF
Build Real Kernel-Level Understanding
Using tools is one thing.
Understanding how they work is what makes you confident.
If you want to build strong foundations in:
✔ Embedded Linux
✔ Kernel internals
✔ Debugging techniques
Explore:
👉 https://embitude.in/embedded-linux-bundle/
🎥 Learn more:
👉 https://www.youtube.com/@PradeepTewani
🤝 Join the community:
👉 https://embitudeinfotech.graphy.com/s/community