Embitude Infotech1

Inside Kprobes – How the Linux Kernel Hooks Functions at Runtime (Part 4)

(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:

  1. CPU triggers an exception
  2. Kernel enters trap handler
  3. 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:

  1. Function is about to execute
  2. Breakpoint is hit
  3. Kernel trap handler runs
  4. Kprobe handler executes
  5. Original instruction runs safely
  6. 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


Leave a Comment

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

Scroll to Top