【问题标题】:Incomplete definition and forward declaration of type 'struct mnt_namespace' using BPF tools?使用 BPF 工具对“struct mnt_namespace”类型的不完整定义和前向声明?
【发布时间】:2020-05-17 08:07:37
【问题描述】:

我想要什么:

execsnoop bcc 工具添加一个网络命名空间选项,以仅跟踪具有指定网络命名空间的日志,就像我们在许多其他 bcc 工具中具有过滤 PID 选项一样。例如:execsnoop -N "ns_id"

我尝试了什么:

int syscall__execve(struct pt_regs *ctx,
    const char __user *filename,
    const char __user *const __user *__argv,
    const char __user *const __user *__envp)
{
    // create data here and pass to submit_arg to save stack space (#555)
    struct data_t data = {};
    struct task_struct *task;


    data.pid = bpf_get_current_pid_tgid() >> 32;
    task = (struct task_struct *)bpf_get_current_task();
    // Some kernels, like Ubuntu 4.13.0-generic, return 0
    // as the real_parent->tgid.
    // We use the get_ppid function as a fallback in those cases. (#1883)

    data.ppid = task->real_parent->tgid;
    data.netns = task->nsproxy->mnt_ns->ns.inum; // I tried to mount namespace here

    bpf_get_current_comm(&data.comm, sizeof(data.comm));
    data.type = EVENT_ARG;

    __submit_arg(ctx, (void *)filename, &data);

    // skip first arg, as we submitted filename
    #pragma unroll
    for (int i = 1; i < MAXARG; i++) {
        if (submit_arg(ctx, (void *)&__argv[i], &data) == 0)
             goto out;
    }

    // handle truncated argument list
    char ellipsis[] = "...";
    __submit_arg(ctx, (void *)ellipsis, &data);
out:
    return 0;
}

收到错误:

/virtual/main.c:98:39: error: incomplete definition of type 'struct mnt_namespace'
    data.netns = task->nsproxy->mnt_ns->ns.inum;
                 ~~~~~~~~~~~~~~~~~~~~~^
include/linux/nsproxy.h:8:8: note: forward declaration of 'struct mnt_namespace'
struct mnt_namespace;
       ^
1 error generated.
Traceback (most recent call last):
  File "./execsnoop", line 230, in <module>
    b = BPF(text=bpf_text)
  File "/usr/lib/python2.7/dist-packages/bcc/__init__.py", line 325, in __init__
    raise Exception("Failed to compile BPF text")
Exception: Failed to compile BPF text

我也尝试包含 mnt_namespace.h 头文件,但未解决。

【问题讨论】:

    标签: c linux ubuntu linux-kernel bcc-bpf


    【解决方案1】:

    密件抄送工具mountsnoop.py 似乎可以实现您想要实现的目标。他们重新定义了一些结构,并带有以下注释:

    /*
     * XXX: struct mnt_namespace is defined in fs/mount.h, which is private to the
     * VFS and not installed in any kernel-devel packages. So, let's duplicate the
     * important part of the definition. There are actually more members in the
     * real struct, but we don't need them, and they're more likely to change.
     */
    struct mnt_namespace {
        atomic_t count;
        struct ns_common ns;
    };
    

    确实fs/mount.h 中的结构没有被导出。所以我怀疑你只需要在你的代码中做同样的事情:部分重新定义struct mnt_namespace

    【讨论】:

    • 谢谢 - 我关注了 mountsnoop.py 并解决了这个错误,但我没有得到预期的结果。我总是得到这个 task-&gt;nsproxy-&gt;mnt_ns-&gt;ns.inum; 的值 0,而不是我想要命名空间 id
    • 嗯,可能是因为内核中的结构定义使用了__randomized_layout 属性。我不确定密件抄送是如何解决这个问题的,似乎他们正在使用bpf_probe_read()for task_struct,不确定它是否可以在这里提供帮助。
    • 嗯忘记我之前的评论,如果我理解正确的话,如果需要,bcc 应该已经call bpf_probe_read() automatically,所以你不应该关心它。话虽如此,您确定 mnt_ns 是您说要查找的网络命名空间吗? ns_proxy-&gt;net 听起来像是更好的候选人?
    • 我试过nsproxy-&gt;net_ns,但是我遇到了另一个与将frompointer转换为unsigned int有关的问题,我在这里打开了一个问题:stackoverflow.com/questions/61862376/…。你能调查一下并指导我可能出什么问题吗?谢谢
    猜你喜欢
    • 2013-07-09
    • 1970-01-01
    • 1970-01-01
    • 2014-02-02
    • 2011-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-28
    相关资源
    最近更新 更多