You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

BPF程序tracepoint上下文flags字段访问及打印方法问询

问题:BPF程序无法正确识别openat调用的O_RDONLY标志,如何调试flags字段?

我想要实现一个BPF程序,仅当openat系统调用携带O_RDONLY标志时,才向trace_pipe写入内容。我参照/sys/kernel/debug/tracing/events/syscalls/sys_enter_open/format的格式构建了结构体,但第二个if语句始终为假,推测没有正确访问flags字段。

我的疑问是:

  • 我是否正确访问了flags字段?
  • 有没有办法打印flags变量的内容?

我的代码如下:

struct syscalls_enter_openat_args { __u64 pad; int __syscall_nr; const char * filename; int flags; unsigned short modep; };
SEC("tracepoint/syscalls/sys_enter_openat") int bpf_sys(struct syscalls_enter_openat_args *ctx) {
    char fmt[] = "llo\n";
    int flags = ctx->flags;
    if (flags){
        if (flags == O_RDONLY)
            bpf_trace_printk(fmt, sizeof(fmt));
    }
    return 0;
}
char _license[] SEC("license") = "GPL";

问题分析与解决方案

首先,你的代码存在两个核心问题,导致无法正确识别O_RDONLY标志:

1. 结构体定义错误,导致flags字段访问偏移错误

你参照的是sys_enter_open的tracepoint格式,但sys_enter_openat的参数结构和open不一样!openat系统调用的原型是:

int openat(int dfd, const char *pathname, int flags, mode_t mode);

对应的tracepoint结构体syscalls_enter_openat_args会比sys_enter_open多一个dfd(文件描述符)字段。你当前的结构体跳过了这个字段,导致ctx->flags访问的是内存中错误的位置,拿到的根本不是真实的flags值。

你可以通过以下命令查看sys_enter_openat的正确格式:

cat /sys/kernel/debug/tracing/events/syscalls/sys_enter_openat/format

正确的结构体应该是这样的:

struct syscalls_enter_openat_args {
    __u64 pad;
    int __syscall_nr;
    int dfd;  // 你漏掉的关键字段
    const char *filename;
    int flags;
    unsigned short mode;
};

2. if (flags)的判断直接过滤掉了O_RDONLY的情况

O_RDONLY的宏定义是0,当调用openat使用纯只读模式时,flags的值就是0,你的第一个if (flags)条件会直接为假,跳过后续所有逻辑,自然永远不会触发第二个if的判断。


如何打印flags的内容调试

要打印flags的数值,只需要修改bpf_trace_printk的格式字符串,添加整型占位符%d,并将flags作为参数传入:

char fmt[] = "openat flags value: %d\n";
bpf_trace_printk(fmt, sizeof(fmt), ctx->flags);

之后你可以通过以下命令查看输出:

cat /sys/kernel/debug/tracing/trace_pipe

修正后的完整代码

// 注意:要确保结构体与sys_enter_openat的格式完全匹配
struct syscalls_enter_openat_args {
    __u64 pad;
    int __syscall_nr;
    int dfd;
    const char *filename;
    int flags;
    unsigned short mode;
};

SEC("tracepoint/syscalls/sys_enter_openat")
int bpf_sys(struct syscalls_enter_openat_args *ctx) {
    char fmt[] = "Detected O_RDONLY openat! Flags: %d\n";
    int flags = ctx->flags;

    // 直接判断严格的O_RDONLY模式
    if (flags == O_RDONLY) {
        bpf_trace_printk(fmt, sizeof(fmt), flags);
    }

    // 如果需要匹配所有包含只读权限的调用(比如O_RDONLY | O_CLOEXEC),可以用掩码判断:
    // if ((flags & O_ACCMODE) == O_RDONLY) {
    //     bpf_trace_printk(fmt, sizeof(fmt), flags);
    // }

    return 0;
}

char _license[] SEC("license") = "GPL";

内容的提问来源于stack exchange,提问作者Maicake

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:25:06