You already know what an extended Berkley Pocket Filter (eBPF) is, together with its precursor, the Berkley Pocket Filter (BPF). If you are new to these terms, we recommend you read our first article on eBPF for System Calls Tracing.
In this article, we will analyze the many powerful abilities of eBPF. Read on as we discuss Uretprobes and Uprobes: What they are and how they can help developers build seamless user-space applications. Furthermore, we will discuss in detail how Kretprobes and Kpropes help you dynamically trace your kernels, offering you invaluable data to analyze.
What Are Uprobes?
User probes or Uprobes is a nifty tool in the Linux kernel. They let developers monitor and tweak user-space applications without directly messing with the code. With Uprobes, you can drop breakpoints at certain spots in an app. This makes it a breeze to collect data, track function calls, debug, and analyze performance. Uprobes are a developer’s secret weapon for fine-tuning user-space apps, and they’re convenient.
What Are Uretprobes?
Uretprobes, abbreviation “User Return Probes,” is another tool in the Linux kernel. Their primary function is to provide developers with the means to meticulously trace and oversee the return paths of functions within user-space applications. Distinct from uprobes, designed to instrument and intercept function entry points, Uretprobes are tailored to zero in on the critical exit points and return paths. This specialized feature empowers developers to establish probes that activate when specific functions conclude their execution and return to their originating callers. Uretprobes are invaluable for in-depth analysis and monitoring within user-space application development.
Check below for an example of a user probe used in an eBPF program to trace the printf function available in the standard GNU C Library.
If you have read our first article, you would already know how to load an eBPF file and effectively read logs in the file /sys/kernel/tracing/trace_pipe using a loader.
What Are Kprobes?
Kernel Probes or Kprobes enable Kernel functions to be dynamically traced and debugged. Their utility extends to diverse tasks, including performance analysis, pinpointing and diagnosing bugs, and comprehensive system monitoring. Kprobes offer a non-invasive means to acquire real-time insights the kernel provides, all without necessitating alterations to the kernel’s core code. Furthermore, they empower users to trace certain function calls, capture parameters, return values, and amass statistical data regarding function execution, making them an indispensable tool for kernel-level observation and analysis.
What Are Kretprobes?
Kretprobes, or Kernel return probes, are somewhat similar to the functionalities of Uretprobes. Similarly, Kretprobes also dynamically helps trace and debug kernel function return points. Much like their counterpart Kprobes, Kretprobes operate by inserting a probe handler function, which triggers just as a designated kernel function is on the verge of returning. This functionality empowers system administrators and developers to collect critical data, customize returning values, or execute supplementary actions precisely at the juncture of function return.
Below is an eBPF program that harnesses kernel probes to meticulously trace the kernel function known as “prepare_kernel_cred.” This function serves the crucial purpose of generating a fresh struct cred object, symbolizing the credentials or privileges linked to a kernel task. Notably, it frequently plays a pivotal role in privilege escalation exploits aimed at obtaining root access. Tracing this function allows us to pinpoint all processes that invoke it, bestowing invaluable insights into detecting and assessing potential malicious behaviors.
The notation SEC(“kprobe/prepare_kernel_cred”) signifies the connection between an eBPF program and the Kprobe event linked to the “prepare_kernel_cred” kernel function. This event is a dynamic tracing and debugging mechanism by intercepting the function’s entry point.
Meanwhile, the struct pt_regs is a critical data structure that offers entry to the program’s register state during execution, furnishing eBPF programs with a comprehensive snapshot of the register state at execution. While the eBPF program is invoked, essential data on the CPU registers are collected and stored in this structure. This access to register data enables precise and powerful monitoring, tracing, and debugging capabilities within the eBPF framework, making it an indispensable component for in-depth analysis and observability.
Check below for its definition:
We will employ the following program to simplify the process of loading the eBPF program mentioned earlier.
The loader and the eBPF file can be compiled using a MakeFile function.
eBPF is a game-changing technology for present-day cloud-native infrastructure. eBPF’s attributes of performance, safety, and observability grant you the unprecedented ability to trace system calls with unparalleled efficiency. You can quickly implement and monitor user-space applications using powerful tools such as Uretprobes and Uprobes. While also dynamically tracing and debugging kernel functions with the help of Kprobes and Kretprobes.
You are armed with a formidable toolkit when you are using eBPF. The abilities of eBPF usher in a new era of monitoring and analyzing in real-time that promises to reshape the landscape of system observability. Make it an essential cloud-native tool for all security enthusiasts.
Our engineers Ashutosh More and Rakshit Awasthi originally published this article on Falco’s blog.