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

调用bpf_probe_write_user返回错误-14的技术求助

sys_enter_execve中bpf_probe_write_user返回-14失败排查

我正在进行一个eBPF实验,目标是在sys_enter_execve的tracepoint中修改第一个参数(被执行程序的文件路径),但调用bpf_probe_write_user时返回-14,修改失败。

环境信息

  • 内核版本:Linux cjh 5.15.0-152-generic #162-Ubuntu SMP Wed Jul 23 09:48:42 UTC 2025 x86_64
  • libbpf:由内核源码编译而来

相关代码

eBPF代码(exechijack.bpf.c)

// SPDX-License-Identifier: BSD-3-Clause
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>
#include "exechijack.h"

char LICENSE[] SEC("license") = "Dual BSD/GPL";

// Ringbuffer Map to pass messages from kernel to user
struct {
    __uint(type, BPF_MAP_TYPE_RINGBUF);
    __uint(max_entries, 256 * 1024);
} rb SEC(".maps");

struct TASK_COMM {
   char comm[8];
};

// Optional Target Parent PID
const volatile int target_ppid = 340126;

SEC("tp/syscalls/sys_enter_execve")
int handle_execve_enter(struct trace_event_raw_sys_enter *ctx)
{
    size_t pid_tgid = bpf_get_current_pid_tgid();
    // Check if we're a process of interest
    if (target_ppid != 0) {
        struct task_struct *task = (struct task_struct *)bpf_get_current_task();
        int ppid = BPF_CORE_READ(task, real_parent, tgid);
        if (ppid != target_ppid) {
            return 0;
        }
    }

    char prog_name[TASK_COMM_LEN];
    // Read in program from first arg of execve
    char prog_name_orig[TASK_COMM_LEN];
    __builtin_memset(prog_name, '\x00', TASK_COMM_LEN);
    bpf_probe_read_user(&prog_name, TASK_COMM_LEN, (void*)ctx->args[0]);

    // Program can't be less than out two-char name
    if (prog_name[1] == '\x00') {
        bpf_printk("[EXECVE_HIJACK] program name too small\n");
        return 0;
    }

    prog_name[0] = '/';
    prog_name[1] = 'a';
    for (int i = 2; i < TASK_COMM_LEN ; i++) {
        prog_name[i] = '\x00';
    }

    long ret = bpf_probe_write_user((void*)ctx->args[0], prog_name, 3);
    bpf_printk("[EXECVE_HIJACK] ret: %d, %s\n", ret, (void*)ctx->args[0]);

    return 0;
}

用户态加载代码(exechijack.c)

#include <stdio.h>
// #include <bpf/bpf.h>
#include "exechijack.skel.h"


int main() {

    //int zero = 0;

    struct exechijack_bpf *_obj = exechijack_bpf__open_and_load();
    exechijack_bpf__attach(_obj);
    printf("attach ...\n");

    while (1);

    return 0;
}

被劫持的用户程序(victim2.c)

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/wait.h>

// const char *proga = "./proga";

int main()
{
        int pid = getpid();
        printf("current pid: %d\n", pid);
        while (1) {
                pid = fork();
                if (pid == 0) {
                        char *args[] = {"a", NULL};
                        printf("./proga");

                        execv("./proga", args);
                        usleep(1000 * 3000);
                }
                else {
                        // waitpid
                        wait(NULL);
                }
                usleep(1000 * 3000);
        }
        return 0;
}

构建脚本

clang -g -O2 -target bpf -D__TARGET_ARCH_x86 -I/usr/local/include/ -c exechijack.bpf.c -o exechijack.bpf.o
bpftool gen skeleton exechijack.bpf.o > exechijack.skel.h
gcc -g -Wall -I/usr/local/include/ exechijack.c -lelf -lz -lbpf -o exechijack
gcc -O0 victim2.c -o victim2

trace_pipe输出

<...>-339834  [002] ....1 87540.993130: bpf_trace_printk: [EXECVE_HIJACK] ret: -14, ./proga

           <...>-340159  [002] ....1 88515.102412: bpf_trace_printk: [EXECVE_HIJACK] ret: -14, ./proga

           <...>-340160  [002] ....1 88518.103038: bpf_trace_printk: [EXECVE_HIJACK] ret: -14, ./proga

           <...>-340161  [000] ....1 88521.103815: bpf_trace_printk: [EXECVE_HIJACK] ret: -14, ./proga

         victim2-340162  [003] ....1 88524.104488: bpf_trace_printk: [EXECVE_HIJACK] ret: -14, ./proga

         victim2-340163  [003] ....1 88527.105239: bpf_trace_printk: [EXECVE_HIJACK] ret: -14, ./proga

         victim2-340164  [003] ....1 88530.105970: bpf_trace_printk: [EXECVE_HIJACK] ret: -14, ./proga

         victim2-340165  [003] ....1 88533.106663: bpf_trace_printk: [EXECVE_HIJACK] ret: -14, ./proga

         victim2-340166  [003] ....1 88536.107434: bpf_trace_printk: [EXECVE_HIJACK] ret: -14, ./proga

         victim2-340167  [003] ....1 88539.108153: bpf_trace_printk: [EXECVE_HIJACK] ret: -14, ./proga

排查情况

已确认失败并非权限问题(如缺少CAP_SYS_ADMIN),且在其他测试BPF程序中bpf_probe_write_user可以正常工作,无法定位当前场景下的失败原因,寻求帮助。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 11:14:53