2

我正在寻找追踪ip_forward_finish。目的是跟踪通过基于 linux 的网关路由器的所有 TCP 连接的延迟。因此想到了跟踪ip_forward_finish核函数。并在路由器上捕获SYN,SYN-ACK和消息的时间戳。ACK

问题是iphdr在跟踪函数内部访问使验证者抱怨以下错误:

bpf: Failed to load program: Permission denied
0: (79) r6 = *(u64 *)(r1 +96)
1: (b7) r1 = 0
2: (6b) *(u16 *)(r10 -24) = r1
3: (bf) r3 = r6
4: (07) r3 += 192
5: (bf) r1 = r10
6: (07) r1 += -24
7: (b7) r2 = 2
8: (85) call bpf_probe_read#4
9: (69) r1 = *(u16 *)(r10 -24)
10: (55) if r1 != 0x8 goto pc+7
 R0=inv(id=0) R1=inv8 R6=inv(id=0) R10=fp0
11: (69) r1 = *(u16 *)(r6 +196)
R6 invalid mem access 'inv'

HINT: The invalid mem access 'inv' error can happen if you try to dereference
    memory without first using bpf_probe_read() to copy it to the BPF stack.
    Sometimes the bpf_probe_read is automatic by the bcc rewriter, other times
    you'll need to be explicit.

我最初拥有的代码片段如下,当访问时发生崩溃ip_Hdr->protocol。而且我还检查了ip_Hdr它不为空。

int trace_forward_finish(struct pt_regs *ctx,struct net *net,
                         struct sock *sk, struct sk_buff *skb)
{
    if (skb->protocol != htons(ETH_P_IP))
        return 0;

    struct iphdr* ip_Hdr = (struct iphdr *) skb_network_header(skb);

    if (ip_Hdr->protocol != IPPROTO_TCP)
        return 0;

    /// More code
}

根据消息中的提示,我确实尝试更改为bpf_probe_read但结果仍然相同

int trace_forward_finish(struct pt_regs *ctx,struct net *net,
                         struct sock *sk, struct sk_buff *skb)
{
    if (skb->protocol != htons(ETH_P_IP))
        return 0;

    struct iphdr ip_Hdr;
    bpf_probe_read(&ip_Hdr, sizeof(ip_Hdr), (void*)ip_hdr(skb)); 

    if (ip_Hdr.protocol != IPPROTO_TCP)
        return 0;

    return 0;
}

任何帮助,将不胜感激。

4

1 回答 1

1

bcc 将尝试将您对内核指针的取消引用转换为对bpf_probe_read. debug=4您可以通过传递给BPF()调用来看到这种情况。

在您的情况下,我怀疑您需要skb_network_header在代码中包含函数,以便 bcc 能够重写它。

如果这还不够,那么您可能需要手动调用以从' 的指针bpf_probe_read中检索结构。struct iphdrskb_network_header

于 2020-05-07T05:54:56.773 回答