mirror of
https://github.com/eunomia-bpf/bpf-developer-tutorial.git
synced 2026-02-09 13:15:14 +08:00
Add new post for 28 29 34 (#92)
* add 28 blog * update test * add 34 * Update test-libbpf.yml * add link * update 28 * add read only * Update english version * update 29 * update 29 * fix ci for 34
This commit is contained in:
@@ -1,52 +1,106 @@
|
||||
# 在用户态应用退出后运行 eBPF 程序:eBPF 程序的生命周期
|
||||
# 在应用程序退出后运行 eBPF 程序:eBPF 程序的生命周期
|
||||
|
||||
通过使用 detach 的方式运行 eBPF 程序,用户空间加载器可以退出,而不会停止 eBPF 程序。
|
||||
eBPF(Extended Berkeley Packet Filter)是 Linux 内核中的一项重大技术创新,允许用户在内核空间中执行自定义程序,而无需修改内核源代码或加载任何内核模块。这为开发人员提供了极大的灵活性,可以观察、修改和控制 Linux 系统。
|
||||
|
||||
本文将介绍 eBPF 程序的生命周期,以及如何在用户空间应用程序退出后继续运行 eBPF 程序的方法,还将介绍如何使用 "pin" 在不同进程之间共享 eBPF 对象。本文是 eBPF 开发者教程的一部分,更多详细信息可以在 <https://github.com/eunomia-bpf/bpf-developer-tutorial> 和 <https://eunomia.dev/tutorials> 中找到。
|
||||
|
||||
通过使用 "detach" 方法来运行 eBPF 程序,用户空间加载程序可以在不停止 eBPF 程序的情况下退出。另外,使用 "pin" 的方法可以在进程之间共享 eBPF 对象,使其保持活动状态。
|
||||
|
||||
## eBPF 程序的生命周期
|
||||
|
||||
首先,我们需要了解一些关键的概念,如 BPF 对象(包括程序,地图和调试信息),文件描述符 (FD),引用计数(refcnt)等。在 eBPF 系统中,用户空间通过文件描述符访问 BPF 对象,而每个对象都有一个引用计数。当一个对象被创建时,其引用计数初始为1。如果该对象不再被使用(即没有其他程序或文件描述符引用它),它的引用计数将降至0,并在 RCU 宽限期后被内存清理。
|
||||
BPF对象(包括程序、映射和调试信息)通过文件描述符(FD)进行访问,并具有引用计数器。每个对象都有一个引用计数器,用于追踪对象被引用的次数。例如,当创建一个映射时,内核会分配一个struct bpf_map对象,并将其引用计数器初始化为1。然后,将映射的文件描述符返回给用户空间进程。如果进程退出或崩溃,文件描述符将被关闭,并且映射的引用计数将减少。当引用计数为零时,内存将被释放。
|
||||
|
||||
接下来,我们需要了解 eBPF 程序的生命周期。首先,当你创建一个 BPF 程序,并将它连接到某个“钩子”(例如网络接口,系统调用等),它的引用计数会增加。然后,即使原始创建和加载该程序的用户空间进程退出,只要 BPF 程序的引用计数大于 0,它就会保持活动状态。然而,这个过程中有一个重要的点是:不是所有的钩子都是相等的。有些钩子是全局的,比如 XDP、tc's clsact 和 cgroup-based 钩子。这些全局钩子会一直保持 BPF 程序的活动状态,直到这些对象自身消失。而有些钩子是局部的,只在拥有它们的进程存活期间运行。
|
||||
BPF程序使用 maps 有两个阶段。首先,创建 maps 并将其文件描述符存储为BPF_LD_IMM64指令的一部分。当内核验证程序时,它会增加程序使用的 maps 的引用计数,并将程序的引用计数初始化为1。此时,用户空间可以关闭与maps 相关的文件描述符,但 maps 不会被销毁,因为程序仍然在使用它们。当程序文件描述符关闭且引用计数为零时,销毁逻辑将减少 maps 的引用计数。这允许多个不同类型的程序同时使用同一个 maps。
|
||||
|
||||
对于 BPF 对象(程序或映射)的生命周期管理,另一个关键的操作是“分离”(detach)。这个操作会阻止已附加程序的任何未来执行。然后,对于需要替换 BPF 程序的情况,你可以使用替换(replace)操作。这是一个复杂的过程,因为你需要确保在替换过程中,不会丢失正在处理的事件,而且新旧程序可能在不同的 CPU 上同时运行。
|
||||
当程序附加到一个挂钩时,程序的引用计数增加。用户空间进程创建 maps 和程序,然后加载程序并将其附加到挂钩上后,就可以退出了。此时,由用户空间创建的 maps 和程序将保持活动状态,因为引用计数>0。这就是BPF对象的生命周期。只要BPF对象的引用计数>0,内核将保持其活动状态。
|
||||
|
||||
最后,除了通过文件描述符和引用计数来管理 BPF 对象的生命周期,还有一个叫做 BPFFS 的方法,也就是“BPF 文件系统”。用户空间进程可以在 BPFFS 中“固定”(pin)一个 BPF 程序或映射,这将增加对象的引用计数,使得即使 BPF 程序未附加到任何地方或 BPF 映射未被任何程序使用,该 BPF 对象也将保持活动状态。
|
||||
然而,不同的附加点的行为不同。一些附加点(如XDP、tc的clsact和基于cgroup的hooks)是全局的,即使没有进程使用它们,程序也会继续处理数据包。另一些附加点(如kprobe、uprobe、tracepoint、perf_event、raw_tracepoint、socket过滤器和so_reuseport挂钩)只在持有事件的进程的生命周期内生效。当这些进程崩溃时,内核将分离BPF程序并减少其引用计数。
|
||||
|
||||
所以,当我们谈论在后台运行 eBPF 程序时,我们需要清楚这个过程的含义。在某些情况下,即使用户空间进程已经退出,我们可能还希望 BPF 程序保持运行。这就需要我们正确地管理 BPF 对象的生命周期
|
||||
总结:XDP、tc、lwt和cgroup挂钩是全局的,而kprobe、uprobe、tracepoint、perf_event、raw_tracepoint、socket过滤器和so_reuseport挂钩是本地于进程的。基于文件描述符的API具有自动清理的优点,因此如果用户空间进程出现问题,内核将自动清理所有对象。在网络方面,基于文件描述符的API可以防止程序无限制地运行。
|
||||
|
||||
## 运行
|
||||
另一种保持 BPF 程序和映射活动的方法是 BPFFS,即BPF文件系统。通过将程序或 maps 固定(pin)到BPFFS中的某个位置,可以增加其引用计数,并使其保持活动状态,即使没有附加到任何位置或任何程序使用固定的BPF程序和 maps 。
|
||||
|
||||
这里还是采用了上一个的字符串替换的应用,来体现对应可能的安全风险。通过使用 `--detach` 运行程序,用户空间加载器可以退出,而不会停止 eBPF 程序。
|
||||
了解BPF程序和 maps 的生命周期对于用户安全、可靠地使用BPF是非常重要的。文件描述符、引用计数器和 BPFFS 等机制有助于管理BPF对象的生命周期,确保它们的正确创建、附加、分离和替换。
|
||||
|
||||
编译:
|
||||
### Kubernetes 中的 eBPF:通过远程过程调用(RPC)部署 eBPF 程序
|
||||
|
||||
```bash
|
||||
make
|
||||
在 Kubernetes 环境中,部署 eBPF 程序通常需要更高级别的系统权限。通常,这些应用程序需要至少 CAP_BPF 权限,根据程序类型的不同,可能还需要其他权限。在多租户的 Kubernetes 环境中,为每个容器或应用程序授予广泛的权限可能带来安全风险。
|
||||
|
||||
为了解决权限问题,一种方法是通过固定(pinning)eBPF 映射来减轻权限要求。固定允许 eBPF 对象在创建它们的进程的生命周期之外保持活动状态,以便其他进程可以访问它们。在 Kubernetes 中,不同的容器可能需要与相同的 eBPF 对象进行交互,因此固定对象很有用。
|
||||
|
||||
例如,可以使用特权的初始化器容器来创建并固定一个 eBPF 映射。随后的容器(可能以较低权限运行)可以与固定的 eBPF 对象进行交互。这种方法将权限要求限制在初始化阶段,增强了整体安全性。
|
||||
|
||||
在这种背景下,bpfman 项目发挥了关键作用。bpfman,即 BPF Daemon,旨在以更受控且更安全的方式管理 eBPF 程序和映射的生命周期。它充当用户空间与内核空间之间的中间层,提供加载和管理 eBPF 程序的机制,而无需为每个单独的容器或应用程序授予广泛的权限。
|
||||
|
||||
在 Kubernetes 中,bpfman 可以作为特权服务部署,负责在集群的不同节点上加载和管理 eBPF 程序。它可以处理 eBPF 生命周期管理的复杂性,如加载、卸载、更新 eBPF 程序,并对其状态进行管理。这种集中化的方法简化了在 Kubernetes 集群中部署和管理 eBPF 程序的过程,同时符合安全最佳实践。
|
||||
|
||||
## 使用 Detach 在应用程序退出后通过任何程序替换 eBPF
|
||||
|
||||
在 libbpf 中,可以使用 `bpf_object__pin_maps` 函数将映射固定到 BPF 对象中。对于程序和链接,也有类似的 API。
|
||||
|
||||
以下是一个示例,演示如何使用类似于前一节中的 textreplace 程序的字符串替换示例来展示 detach 方法。可以使用类似的代码将程序、映射和链接固定到 BPF 对象中:
|
||||
|
||||
```c
|
||||
int pin_program(struct bpf_program *prog, const char* path)
|
||||
{
|
||||
int err;
|
||||
err = bpf_program__pin(prog, path);
|
||||
if (err) {
|
||||
fprintf(stdout, "could not pin prog %s: %d\n", path, err);
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int pin_map(struct bpf_map *map, const char* path)
|
||||
{
|
||||
int err;
|
||||
err = bpf_map__pin(map, path);
|
||||
if (err) {
|
||||
fprintf(stdout, "could not pin map %s: %d\n", path, err);
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int pin_link(struct bpf_link *link, const char* path)
|
||||
{
|
||||
int err;
|
||||
err = bpf_link__pin(link, path);
|
||||
if (err) {
|
||||
fprintf(stdout, "could not pin link %s: %d\n", path, err);
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
```
|
||||
|
||||
在运行前,请首先确保 bpf 文件系统已经被挂载:
|
||||
## 运行示例
|
||||
|
||||
在这个示例中,我们将继续使用前一节中的字符串替换示例来演示在应用程序退出后运行 eBPF 程序的方法,并展示潜在的安全风险。通过使用 `--detach` 参数运行该程序,可以使用户空间加载程序在不停止 eBPF 程序的情况下退出。完整的示例代码可以在 <https://github.com/eunomia-bpf/bpf-developer-tutorial/tree/main/src/28-detach> 中找到。
|
||||
|
||||
在运行之前,请确保已经挂载了 BPF 文件系统:
|
||||
|
||||
```bash
|
||||
sudo mount bpffs -t bpf /sys/fs/bpf
|
||||
mkdir /sys/fs/bpf/textreplace
|
||||
```
|
||||
|
||||
然后,你可以分离运行 text-replace2:
|
||||
然后,可以使用以下命令运行带有 detach 参数的 text-replace2 程序:
|
||||
|
||||
```bash
|
||||
./textreplace2 -f /proc/modules -i 'joydev' -r 'cryptd' -d
|
||||
```
|
||||
|
||||
这将在 `/sys/fs/bpf/textreplace` 下创建一些 eBPF 链接文件。
|
||||
一旦加载器成功运行,你可以通过运行以下命令检查日志:
|
||||
这将在 `/sys/fs/bpf/textreplace` 目录下创建一些 eBPF 链接文件。加载程序成功运行后,可以使用以下命令检查日志:
|
||||
|
||||
```bash
|
||||
sudo cat /sys/kernel/debug/tracing/trace_pipe
|
||||
# 确认链接文件存在
|
||||
# 确认链接文件是否存在
|
||||
sudo ls -l /sys/fs/bpf/textreplace
|
||||
```
|
||||
|
||||
然后,要停止,只需删除链接文件即可:
|
||||
最后,要停止程序,只需删除链接文件:
|
||||
|
||||
```bash
|
||||
sudo rm -r /sys/fs/bpf/textreplace
|
||||
@@ -54,5 +108,8 @@ sudo rm -r /sys/fs/bpf/textreplace
|
||||
|
||||
## 参考资料
|
||||
|
||||
- <https://github.com/pathtofile/bad-bpf>
|
||||
- <https://facebookmicrosites.github.io/bpf/blog/2018/08/31/object-lifetime.html>
|
||||
您可以访问我们的教程代码仓库 <https://github.com/eunomia-bpf/bpf-developer-tutorial> 或网站 <https://eunomia.dev/zh/tutorials/> 以获取更多示例和完整的教程。
|
||||
|
||||
- [bad-bpf](https://github.com/pathtofile/bad-bpf)
|
||||
- [Object Lifetime in the Linux kernel](https://facebookmicrosites.github.io/bpf/blog/2018/08/31/object-lifetime.html)
|
||||
- [BPFMan: A Novel Way to Manage eBPF—Beyond Capsule Mode](https://bpfman.io/main/blog/2023/09/07/bpfman-a-novel-way-to-manage-ebpf)
|
||||
|
||||
@@ -1,23 +1,91 @@
|
||||
# Running eBPF Programs After User-Space Application Exits: The Lifecycle of eBPF Programs
|
||||
# Running eBPF After Application Exits: The Lifecycle of eBPF Programs
|
||||
|
||||
By using the detach method to run eBPF programs, the user space loader can exit without stopping the eBPF program.
|
||||
eBPF (Extended Berkeley Packet Filter) is a revolutionary technology in the Linux kernel that allows users to execute custom programs in kernel space without modifying the kernel source code or loading any kernel modules. This provides developers with great flexibility to observe, modify, and control the Linux system.
|
||||
|
||||
This article introduces the Lifecycle of eBPF Programs, how to run eBPF programs after user-space application exits, and how to use pin to share eBPF objects between processes. This article is part of the eBPF Developer Tutorial, more details can be found in <https://github.com/eunomia-bpf/bpf-developer-tutorial> and <https://eunomia.dev/tutorials>
|
||||
|
||||
By using the detach method to run eBPF programs, the user space loader can exit without stopping the eBPF program. Another common use case for pinning is sharing eBPF objects between processes. For example, one could create a Map from Go, pin it, and inspect it using `bpftool map dump pinned /sys/fs/bpf/my_map`.
|
||||
|
||||
## The Lifecycle of eBPF Programs
|
||||
|
||||
First, we need to understand some key concepts, such as BPF objects (including programs, maps, and debug information), file descriptors (FDs), reference counting (refcnt), etc. In the eBPF system, user space accesses BPF objects through file descriptors, and each object has a reference count. When an object is created, its reference count is initialized to 1. If the object is no longer in use (i.e., no other programs or file descriptors reference it), its reference count will decrease to 0 and be cleaned up in memory after the RCU grace period.
|
||||
File descriptors and reference counters are used to manage BPF objects (progs, maps, and debug info). When a map is created, the kernel initializes its reference counter to 1 and returns a file descriptor to the user space process. If the process exits or crashes, the file descriptor is closed and the reference counter of the map is decremented. After the RCU grace period, the map is freed from memory.
|
||||
|
||||
Next, we need to understand the lifecycle of eBPF programs. First, when you create a BPF program and attach it to a "hook" (e.g., a network interface, a system call, etc.), its reference count increases. Then, even if the user space process that originally created and loaded the program exits, as long as the reference count of the BPF program is greater than 0, it will remain active. However, there is an important point in this process: not all hooks are equal. Some hooks are global, such as XDP, tc's clsact, and cgroup-based hooks. These global hooks keep the BPF program active until the objects themselves disappear. Some hooks are local and only run during the lifetime of the process that owns them.
|
||||
BPF programs that use BPF maps are loaded in two phases. The maps are created and their file descriptors are stored in the program's 'imm' field. The kernel increments the reference counters of the maps used by the program and initializes the program's reference counter to 1. Even if the user space process closes the file descriptors associated with the maps, the maps will not disappear because the program is still "using" them. When the file descriptor of the program is closed and its reference counter reaches zero, the destruction logic decrements the reference counters of all maps used by the program. This allows the same map to be used by multiple programs at once.
|
||||
|
||||
For managing the lifecycle of BPF objects (programs or maps), another key operation is "detach." This operation prevents any future execution of the attached program. Then, in cases where you need to replace a BPF program, you can use the replace operation. This is a complex process because you need to ensure that during the replacement process, no events being processed are lost, and the old and new program may run simultaneously on different CPUs.
|
||||
When a program is attached to a hook, its reference counter is incremented. The user space process that created the maps and program can then exit, and the maps and program will remain alive as long as their reference counters are greater than zero. This is the lifecycle of a BPF object.
|
||||
|
||||
Finally, in addition to managing the lifecycle of BPF objects through file descriptors and reference counting, there is another method called BPFFS, which is the "BPF Filesystem." User space processes can "pin" a BPF program or map in BPFFS, which increases the reference count of the object, keeping the BPF object active even if the BPF program is not attached anywhere or the BPF map is not used by any program.
|
||||
Not all attachment points are the same. XDP, tc's clsact, and cgroup-based hooks are global, meaning that programs will stay attached to them as long as the corresponding objects are alive. On the other hand, programs attached to kprobe, uprobe, tracepoint, perf_event, raw_tracepoint, socket filters, and so_reuseport hooks are local to the process. If the process crashes or closes the file descriptors associated with these hooks, the kernel will detach the BPF program and decrement its reference counter.
|
||||
|
||||
So when we talk about running eBPF programs in the background, we need to understand the meaning of this process. In some cases, even if the user space process has exited, we may still want the BPF program to keep running. This requires us to manage the lifecycle of BPF objects correctly.
|
||||
The file descriptor based interface provides auto-cleanup, meaning that if anything goes wrong with the user space process, the kernel will automatically clean up all BPF objects. This interface is useful for networking as well. The use of BPFFS (BPF File System) allows a process to pin a BPF program or map, which increments their reference counters and keeps them alive even if they are not attached or used by any program. This is useful when an admin wants to examine a map even when the associated program is not running.
|
||||
|
||||
Detach and replace are important aspects of the lifetime of a BPF program. The detach hook prevents the execution of a previously attached program from any future events, while the replace feature allows a program to be replaced in cgroup-based hooks. There is a window where the old and new programs can be executing on different CPUs, but the kernel guarantees that one of them will be processing events. Some BPF developers use a scheme where the new program is loaded with the same maps as the old program to ensure safe replacement.
|
||||
|
||||
Overall, understanding the lifetime of BPF programs and maps is crucial for users to use BPF safely and without surprises. The use of file descriptors, reference counters, and BPFFS helps manage the lifecycle of BPF objects, ensuring their proper creation, attachment, detachment, and replacement.
|
||||
|
||||
### eBPF in Kubernetes: Deploy eBPF Programs via Remote Procedure Call
|
||||
|
||||
In a Kubernetes environment, deploying eBPF programs often necessitates a higher level of system privileges. Typically, these applications require at least CAP_BPF permissions, and depending on the program type, they may need even more. This requirement poses a challenge in a multi-tenant Kubernetes environment where granting extensive privileges can be a security risk.
|
||||
|
||||
#### Using Pin to Mitigate Privilege Requirements
|
||||
|
||||
One way to address the privilege issue is through the use of pinning eBPF maps. Pinning allows eBPF objects to persist beyond the life of the process that created them, making them accessible to other processes. This method can be particularly useful in Kubernetes, where different containers might need to interact with the same eBPF objects.
|
||||
|
||||
For example, an eBPF map can be created and pinned by a privileged initializer container. Subsequent containers, which may run with fewer privileges, can then interact with the pinned eBPF objects. This approach limits the need for elevated privileges to the initialization phase, thereby enhancing overall security.
|
||||
|
||||
#### The Role of bpfman in eBPF Lifecycle Management
|
||||
|
||||
The bpfman project can play a crucial role in this context. bpfman, or BPF Daemon, is designed to manage the lifecycle of eBPF programs and maps in a more controlled and secure manner. It acts as a mediator between user space and kernel space, providing a mechanism to load and manage eBPF programs without granting extensive privileges to each individual container or application.
|
||||
|
||||
In Kubernetes, bpfman could be deployed as a privileged service, responsible for loading and managing eBPF programs across different nodes in the cluster. It can handle the intricacies of eBPF lifecycle management, such as loading, unloading, updating eBPF programs, and managing their state. This centralized approach simplifies the deployment and management of eBPF programs in a Kubernetes cluster, while adhering to security best practices.
|
||||
|
||||
## Use Detach to Replace by Any Program with eBPF After it Exits
|
||||
|
||||
In libbpf, the `bpf_object__pin_maps` function can be used to pin the maps in the BPF object, the programs and links has similar API.
|
||||
|
||||
Here we use similar programs as textreplace in the previous section to demonstrate the detach method, the pin eBPF code is like:
|
||||
|
||||
```c
|
||||
|
||||
int pin_program(struct bpf_program *prog, const char* path)
|
||||
{
|
||||
int err;
|
||||
err = bpf_program__pin(prog, path);
|
||||
if (err) {
|
||||
fprintf(stdout, "could not pin prog %s: %d\n", path, err);
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int pin_map(struct bpf_map *map, const char* path)
|
||||
{
|
||||
int err;
|
||||
err = bpf_map__pin(map, path);
|
||||
if (err) {
|
||||
fprintf(stdout, "could not pin map %s: %d\n", path, err);
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int pin_link(struct bpf_link *link, const char* path)
|
||||
{
|
||||
int err;
|
||||
err = bpf_link__pin(link, path);
|
||||
if (err) {
|
||||
fprintf(stdout, "could not pin link %s: %d\n", path, err);
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
```
|
||||
|
||||
## Running
|
||||
|
||||
Here, we still use the example of string replacement used in the previous application to demonstrate potential security risks. By using `--detach` to run the program, the user space loader can exit without stopping the eBPF program.
|
||||
|
||||
The code of This example can be found in <https://github.com/eunomia-bpf/bpf-developer-tutorial/tree/main/src/28-detach>
|
||||
|
||||
Compilation:
|
||||
|
||||
```bash
|
||||
@@ -53,5 +121,8 @@ sudo rm -r /sys/fs/bpf/textreplace
|
||||
|
||||
## References
|
||||
|
||||
You can visit our tutorial code repository [at https://github.com/eunomia-bpf/bpf-developer-tutorial](https://github.com/eunomia-bpf/bpf-developer-tutorial) or our website [at https://eunomia.dev/zh/tutorials/](https://eunomia.dev/zh/tutorials/) for more examples and a complete tutorial.
|
||||
|
||||
- <https://github.com/pathtofile/bad-bpf>
|
||||
- <https://facebookmicrosites.github.io/bpf/blog/2018/08/31/object-lifetime.html>
|
||||
- <https://facebookmicrosites.github.io/bpf/blog/2018/08/31/object-lifetime.html>
|
||||
- <https://bpfman.io/main/blog/2023/09/07/bpfman-a-novel-way-to-manage-ebpf>
|
||||
|
||||
@@ -245,6 +245,8 @@ int BPF_PROG(find_possible_addrs, struct pt_regs *regs, long ret)
|
||||
return 0;
|
||||
}
|
||||
|
||||
char name_cmp[TEXT_LEN_MAX+1];
|
||||
|
||||
SEC("fexit/__x64_sys_read")
|
||||
int BPF_PROG(check_possible_addresses, struct pt_regs *regs, long ret)
|
||||
{
|
||||
@@ -260,7 +262,6 @@ int BPF_PROG(check_possible_addresses, struct pt_regs *regs, long ret)
|
||||
unsigned int newline_counter = 0;
|
||||
unsigned int match_counter = 0;
|
||||
|
||||
char name[TEXT_LEN_MAX+1];
|
||||
unsigned int j = 0;
|
||||
char old = 0;
|
||||
|
||||
@@ -289,14 +290,15 @@ int BPF_PROG(check_possible_addresses, struct pt_regs *regs, long ret)
|
||||
if (name_addr == 0) {
|
||||
break;
|
||||
}
|
||||
bpf_probe_read_user(&name, TEXT_LEN_MAX, (char*)name_addr);
|
||||
bpf_probe_read_user(&name_cmp, TEXT_LEN_MAX, (char*)name_addr);
|
||||
for (j = 0; j < TEXT_LEN_MAX; j++) {
|
||||
if (name[j] != pFind->text[j]) {
|
||||
if (name_cmp[j] != pFind->text[j]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// for newer kernels, maybe use bpf_strncmp
|
||||
// if (bpf_strncmp(pFind->text, TEXT_LEN_MAX, name) == 0) {
|
||||
// const char *p = name_cmp;
|
||||
// if (bpf_strncmp(pFind->text, TEXT_LEN_MAX, p) == 0) {
|
||||
if (j >= name_len) {
|
||||
// ***********
|
||||
// We've found out text!
|
||||
|
||||
Reference in New Issue
Block a user