Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use of "__kprobes" and how it works?

Tags:

c

linux-kernel

While referring to memory module of Linux kernel some functions are not clear to me. One of the functions is shown below:

static inline int __kprobes notify_page_fault(struct pt_regs *regs)
{
int ret = 0;

/* kprobe_running() needs smp_processor_id() */
if (kprobes_built_in() && !user_mode_vm(regs)) {
    preempt_disable();
    if (kprobe_running() && kprobe_fault_handler(regs, 14))
        ret = 1;
    preempt_enable();
}

return ret;
} 

I am confused with the "__kprobes" between return type and function name. When I looked at the initialization of "__kprobes" in compiler.h, I found below:

/*Ignore/forbid kprobes attach on very low level functions marked by 
this attribute:*/
#ifdef CONFIG_KPROBES
# define __kprobes  __attribute__((__section__(".kprobes.text")))
#else
# define __kprobes
#endif

Well, I know that at compile time __kprobe is going to be replaced with its defined part.

Questions:

1.) What is the significance of __attribute__((__section__(".kprobes.text")))?
and
2.) What does it do at compile time and at run time when it is used before "function_name"?

I read about kprobe and found that it has to do something about breakpoints and back trace. What I understand about kprobe is it will help debugger in creating back traces and breakpoints. Could someone please explain me in simple words how does it really works and please correct me if I am wrong.

like image 939
user3508953 Avatar asked Oct 28 '25 17:10

user3508953


1 Answers

TL;DR

  1. __attribute__((__section__(".kprobes.text"))) will place that function in separate section which is not findable by kprobes thus preventing infinite breakpoints.
  2. You must use it before "function_name" to place whole "function_name" symbol in separate section.

Real answer

kprobes (kernel probes) is Linux kernel mechanism for dynamic tracing. It allows you to insert breakpoint at almost any kernel function, invoke your handler and then continue executing. It works by runtime patching kernel image with so-called kernel probe/kprobe - see struct kprobe. This probe will allow you to pass control to your handler, and that handler is usually do some tracing.

So, what's going under the hood:

  • You create your struct kprobe by defining address at which to break and handler to pass reference.
  • You register your probe with register_kprobe
  • Kernel kprobe subsystem finds address from your probe
  • Then kprobe:
    • inserts breakpoint CPU instruction (int 3 for x86) at given address
    • adds some wrapper code to save context(registers, etc.)
    • adds even more code to help you get access to function arguments or return values.
  • Now when kernel execution hits that probed address:
    • it will fall into CPU trap
    • it will save context
    • it will pass control to your handler via notifier_call_chain
    • ...
    • after all it will restore context

That's how it works. As you can see it's a really neat and dirty hack, but some kernel function is so terribly low-level that it's just pointless to probe them. notify_page_fault is one of those functions - as a part of notifier_call_chain it's used in passing control to your handler.

So if you probe at notify_page_fault you'll get infinite loop of breakpoints, which is not what you want. What you really want is to protect that kind of functions and kprobes do this by placing it in separate section .kprobes.text. This will prevent to probe at that functions because kprobe will not lookup for address in that section. And that's a job for __attribute__((__section__(".kprobes.text"))).

like image 121
Alexander Dzyoba Avatar answered Oct 31 '25 07:10

Alexander Dzyoba