使用BPF从struct msghr中提取数据包数据。

huangapple go评论65阅读模式
英文:

Extract packet data using BPF from struct msghr

问题

以下是您的代码的翻译部分:

我正在尝试钩住sock_sendmsg并打印数据包数据。以下是我的代码。

#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>
#define IP_169_254_169_254 0xFEA9FEA
#define TASK_COMM_LEN 128

SEC("fentry/sock_sendmsg")
int BPF_PROG(sock_sendmsg, struct socket *sock, struct msghdr *msg)
{
        
        u32 pid = bpf_get_current_pid_tgid() >> 32;
        char comm[128];
        char pkt[128];
        int contains_payload;
        struct sock *sk = sock->sk;
        if (sk->__sk_common.skc_daddr == IP_169_254_169_254)
        {
                const struct iovec *iov = msg->msg_iter.iov;
                void *iovbase = iov->iov_base;
                bpf_probe_read_str(&pkt, sizeof(pkt), iovbase);
                if(pkt[0] == '
我正在尝试钩住sock_sendmsg并打印数据包数据。以下是我的代码。

#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>
#define IP_169_254_169_254 0xFEA9FEA
#define TASK_COMM_LEN 128

SEC("fentry/sock_sendmsg")
int BPF_PROG(sock_sendmsg, struct socket *sock, struct msghdr *msg)
{
        
        u32 pid = bpf_get_current_pid_tgid() >> 32;
        char comm[128];
        char pkt[128];
        int contains_payload;
        struct sock *sk = sock->sk;
        if (sk->__sk_common.skc_daddr == IP_169_254_169_254)
        {
                const struct iovec *iov = msg->msg_iter.iov;
                void *iovbase = iov->iov_base;
                bpf_probe_read_str(&pkt, sizeof(pkt), iovbase);
                if(pkt[0] == '\0'){
                        contains_payload = 0;
                }
                else
                {
                        contains_payload = 1;
                }
                bpf_get_current_comm(&comm, sizeof(comm));      
                bpf_printk("%d , %s, %d, %s", pid, comm, contains_payload, pkt);
        }
        return 0;
}

char _license[] SEC("license") = "GPL";
'
){
contains_payload = 0; } else { contains_payload = 1; } bpf_get_current_comm(&comm, sizeof(comm)); bpf_printk("%d , %s, %d, %s", pid, comm, contains_payload, pkt); } return 0; } char _license[] SEC("license") = "GPL";

请注意,我已经将HTML编码的引号字符还原为正常的引号字符,以便代码在编译时不会出现问题。

至于代码中的问题,您提到在尝试使用 bpf_printk 打印 pkt 时出现问题。如果删除 bpf_printk 中的 pkt,则能够打印出进程、comm 和 pkt 中的数据。此错误消息表明 BPF 程序加载失败,可能是因为数据结构的定义问题或其他原因导致加载失败。您需要仔细检查代码并确保类型定义和数据结构匹配正确。

如果您有关于特定问题的更多详细信息,可以提供给我,我会尽力提供进一步的指导。

英文:

I am trying to hook to sock_sendmsg and print the packet data. Here is my code.

#include &quot;vmlinux.h&quot;
#include &lt;bpf/bpf_helpers.h&gt;
#include &lt;bpf/bpf_tracing.h&gt;
#include &lt;bpf/bpf_core_read.h&gt;
#define IP_169_254_169_254 0xFEA9FEA
#define TASK_COMM_LEN 128

SEC(&quot;fentry/sock_sendmsg&quot;)
int BPF_PROG(sock_sendmsg, struct socket *sock, struct msghdr *msg)
{
        
        u32 pid = bpf_get_current_pid_tgid() &gt;&gt; 32;
        char comm[128];
        char pkt[128];
        int contains_payload;
        struct sock *sk = sock-&gt;sk;
        if (sk-&gt;__sk_common.skc_daddr == IP_169_254_169_254)
        {
                const struct iovec * iov = msg-&gt;msg_iter.iov;
                void *iovbase = iov-&gt;iov_base;
                bpf_probe_read_str(&amp;pkt, sizeof(pkt), iovbase);
                if(pkt[0] == &#39;
#include &quot;vmlinux.h&quot;
#include &lt;bpf/bpf_helpers.h&gt;
#include &lt;bpf/bpf_tracing.h&gt;
#include &lt;bpf/bpf_core_read.h&gt;
#define IP_169_254_169_254 0xFEA9FEA
#define TASK_COMM_LEN 128
SEC(&quot;fentry/sock_sendmsg&quot;)
int BPF_PROG(sock_sendmsg, struct socket *sock, struct msghdr *msg)
{
u32 pid = bpf_get_current_pid_tgid() &gt;&gt; 32;
char comm[128];
char pkt[128];
int contains_payload;
struct sock *sk = sock-&gt;sk;
if (sk-&gt;__sk_common.skc_daddr == IP_169_254_169_254)
{
const struct iovec * iov = msg-&gt;msg_iter.iov;
void *iovbase = iov-&gt;iov_base;
bpf_probe_read_str(&amp;pkt, sizeof(pkt), iovbase);
if(pkt[0] == &#39;\0&#39;){
contains_payload = 0;
}
else
{
contains_payload = 1;
}
bpf_get_current_comm(&amp;comm, sizeof(comm));      
bpf_printk(&quot;%d , %s, %d, %s&quot;,pid,comm, contains_payload, pkt);
}
return 0;
}
char _license[] SEC(&quot;license&quot;) = &quot;GPL&quot;;
&#39;){ contains_payload = 0; } else { contains_payload = 1; } bpf_get_current_comm(&amp;comm, sizeof(comm)); bpf_printk(&quot;%d , %s, %d, %s&quot;,pid,comm, contains_payload, pkt); } return 0; } char _license[] SEC(&quot;license&quot;) = &quot;GPL&quot;;

The issue comes when i try to print pkt using bpf_printk. If I don't try to print it and remove it from bpf_printk. I see the printed process, comm and that there is data in the pkt.

I wanted to know what I am doing wrong here and any guidance would be appreciated.

This is the crash data:

libbpf: loading object &#39;fentry_bpf&#39; from buffer
libbpf: elf: section(3) fentry/sock_sendmsg, size 312, link 0, flags 6, type=1
libbpf: sec &#39;fentry/sock_sendmsg&#39;: found program &#39;sock_sendmsg&#39; at insn offset 0 (0 bytes), code size 39 insns (312 bytes)
libbpf: elf: section(4) .relfentry/sock_sendmsg, size 16, link 23, flags 0, type=9
libbpf: elf: section(5) license, size 4, link 0, flags 3, type=1
libbpf: license of fentry_bpf is GPL
libbpf: elf: section(6) .maps, size 32, link 0, flags 3, type=1
libbpf: elf: section(7) .rodata, size 16, link 0, flags 2, type=1
libbpf: elf: section(14) .BTF, size 11492, link 0, flags 0, type=1
libbpf: elf: section(16) .BTF.ext, size 412, link 0, flags 0, type=1
libbpf: elf: section(18) .eh_frame, size 48, link 0, flags 2, type=1
libbpf: elf: skipping unrecognized data section(18) .eh_frame
libbpf: elf: section(19) .rel.eh_frame, size 16, link 23, flags 0, type=9
libbpf: elf: skipping relo section(19) .rel.eh_frame for section(18) .eh_frame
libbpf: elf: section(23) .symtab, size 244848, link 1, flags 0, type=2
libbpf: looking for externs among 10202 symbols...
libbpf: collected 0 externs total
libbpf: map &#39;imds_http_data&#39;: at sec_idx 6, offset 0.
libbpf: map &#39;imds_http_data&#39;: found type = 6.
libbpf: map &#39;imds_http_data&#39;: found key [8], sz = 4.
libbpf: map &#39;imds_http_data&#39;: found value [12], sz = 31884.
libbpf: map &#39;imds_http_data&#39;: found max_entries = 1.
libbpf: map &#39;fentry_b.rodata&#39; (global data): at sec_idx 7, offset 0, flags 80.
libbpf: map 1 is &quot;fentry_b.rodata&quot;
libbpf: sec &#39;.relfentry/sock_sendmsg&#39;: collecting relocation for section(3) &#39;fentry/sock_sendmsg&#39;
libbpf: sec &#39;.relfentry/sock_sendmsg&#39;: relo #0: insn #32 against &#39;.rodata&#39;
libbpf: prog &#39;sock_sendmsg&#39;: found data map 1 (fentry_b.rodata, sec 7, off 0) for insn 32
libbpf: loading kernel BTF &#39;/sys/kernel/btf/vmlinux&#39;: 0
libbpf: map &#39;imds_http_data&#39;: created successfully, fd=4
libbpf: map &#39;fentry_b.rodata&#39;: created successfully, fd=5
libbpf: sec &#39;fentry/sock_sendmsg&#39;: found 4 CO-RE relocations
libbpf: CO-RE relocating [22] struct socket: found target candidate [3213] struct socket in [vmlinux]
libbpf: prog &#39;sock_sendmsg&#39;: relo #0: &lt;byte_off&gt; [22] struct socket.sk (0:4 @ offset 24)
libbpf: prog &#39;sock_sendmsg&#39;: relo #0: matching candidate #0 &lt;byte_off&gt; [3213] struct socket.sk (0:4 @ offset 24)
libbpf: prog &#39;sock_sendmsg&#39;: relo #0: patched insn #4 (LDX/ST/STX) off 24 -&gt; 24
libbpf: CO-RE relocating [58] struct sock: found target candidate [2658] struct sock in [vmlinux]
libbpf: prog &#39;sock_sendmsg&#39;: relo #1: &lt;byte_off&gt; [58] struct sock.__sk_common.skc_daddr (0:0:0:1:0 @ offset 0)
libbpf: prog &#39;sock_sendmsg&#39;: relo #1: matching candidate #0 &lt;byte_off&gt; [2658] struct sock.__sk_common.skc_daddr (0:0:0:1:0 @ offset 0)
libbpf: prog &#39;sock_sendmsg&#39;: relo #1: patched insn #5 (LDX/ST/STX) off 0 -&gt; 0
libbpf: CO-RE relocating [168] struct msghdr: found target candidate [2682] struct msghdr in [vmlinux]
libbpf: prog &#39;sock_sendmsg&#39;: relo #2: &lt;byte_off&gt; [168] struct msghdr.msg_iter.iov (0:2:3:0 @ offset 40)
libbpf: prog &#39;sock_sendmsg&#39;: relo #2: matching candidate #0 &lt;byte_off&gt; [2682] struct msghdr.msg_iter.iov (0:2:3:0 @ offset 40)
libbpf: prog &#39;sock_sendmsg&#39;: relo #2: patched insn #9 (LDX/ST/STX) off 40 -&gt; 40
libbpf: CO-RE relocating [185] struct iovec: found target candidate [1695] struct iovec in [vmlinux]
libbpf: prog &#39;sock_sendmsg&#39;: relo #3: &lt;byte_off&gt; [185] struct iovec.iov_base (0:0 @ offset 0)
libbpf: prog &#39;sock_sendmsg&#39;: relo #3: matching candidate #0 &lt;byte_off&gt; [1695] struct iovec.iov_base (0:0 @ offset 0)
libbpf: prog &#39;sock_sendmsg&#39;: relo #3: patched insn #10 (LDX/ST/STX) off 0 -&gt; 0
libbpf: prog &#39;sock_sendmsg&#39;: BPF program load failed: Invalid argument
libbpf: prog &#39;sock_sendmsg&#39;: -- BEGIN PROG LOAD LOG --
arg#0 type is not a struct
Unrecognized arg#0 type PTR
; int BPF_PROG(sock_sendmsg, struct socket *sock, struct msghdr *msg)
0: (79) r7 = *(u64 *)(r1 +8)
func &#39;sock_sendmsg&#39; arg1 has btf_id 2682 type STRUCT &#39;msghdr&#39;
1: (79) r8 = *(u64 *)(r1 +0)
func &#39;sock_sendmsg&#39; arg0 has btf_id 3213 type STRUCT &#39;socket&#39;
; u32 pid = bpf_get_current_pid_tgid() &gt;&gt; 32;
2: (85) call bpf_get_current_pid_tgid#14
3: (bf) r6 = r0
; struct sock *sk = sock-&gt;sk;
4: (79) r1 = *(u64 *)(r8 +24)
; if (sk-&gt;__sk_common.skc_daddr == IP_169_254_169_254)
5: (61) r1 = *(u32 *)(r1 +0)
6: (18) r2 = 0xfea9fea9
; if (sk-&gt;__sk_common.skc_daddr == IP_169_254_169_254)
8: (5d) if r1 != r2 goto pc+28
R0_w=inv(id=1) R1_w=inv4272553641 R2_w=inv4272553641 R6_w=inv(id=1) R7_w=ptr_msghdr(id=0,off=0,imm=0) R8_w=ptr_socket(id=0,off=0,imm=0) R10=fp0
; const struct iovec * iov = msg-&gt;msg_iter.iov;
9: (79) r1 = *(u64 *)(r7 +40)
; void *iovbase = iov-&gt;iov_base;
10: (79) r3 = *(u64 *)(r1 +0)
11: (bf) r7 = r10
; const struct iovec * iov = msg-&gt;msg_iter.iov;
12: (07) r7 += -256
; bpf_probe_read_str(&amp;pkt, sizeof(pkt), iovbase);
13: (bf) r1 = r7
14: (b7) r2 = 128
15: (85) call bpf_probe_read_str#45
last_idx 15 first_idx 0
regs=4 stack=0 before 14: (b7) r2 = 128
; if(pkt[0] == &#39;\0&#39;){
16: (71) r9 = *(u8 *)(r10 -256)
17: (bf) r8 = r10
; const struct iovec * iov = msg-&gt;msg_iter.iov;
18: (07) r8 += -128
; bpf_get_current_comm(&amp;comm, sizeof(comm));	
19: (bf) r1 = r8
20: (b7) r2 = 128
21: (85) call bpf_get_current_comm#16
last_idx 21 first_idx 16
regs=4 stack=0 before 20: (b7) r2 = 128
22: (b7) r1 = 1
; if(pkt[0] == &#39;\0&#39;){
23: (55) if r9 != 0x0 goto pc+1
R0_w=inv(id=0) R1_w=inv1 R6=inv(id=1) R7=fp-256 R8_w=fp-128 R9_w=inv0 R10=fp0 fp-8=mmmmmmmm fp-16=mmmmmmmm fp-24=mmmmmmmm fp-32=mmmmmmmm fp-40=mmmmmmmm fp-48=mmmmmmmm fp-56=mmmmmmmm fp-64=mmmmmmmm fp-72=mmmmmmmm fp-80=mmmmmmmm fp-88=mmmmmmmm fp-96=mmmmmmmm fp-104=mmmmmmmm fp-112=mmmmmmmm fp-120=mmmmmmmm fp-128=mmmmmmmm fp-136=mmmmmmmm fp-144=mmmmmmmm fp-152=mmmmmmmm fp-160=mmmmmmmm fp-168=mmmmmmmm fp-176=mmmmmmmm fp-184=mmmmmmmm fp-192=mmmmmmmm fp-200=mmmmmmmm fp-208=mmmmmmmm fp-216=mmmmmmmm fp-224=mmmmmmmm fp-232=mmmmmmmm fp-240=mmmmmmmm fp-248=mmmmmmmm fp-256=mmmmmmmm
24: (b7) r1 = 0
; bpf_printk(&quot;%d , %s, %d, %s&quot;,pid,comm, contains_payload, pkt);
25: (7b) *(u64 *)(r10 -264) = r7
26: (7b) *(u64 *)(r10 -272) = r1
last_idx 26 first_idx 25
regs=2 stack=0 before 25: (7b) *(u64 *)(r10 -264) = r7
R0_w=inv(id=0) R1_rw=invP0 R6=inv(id=1) R7_r=fp-256 R8_w=fp-128 R9_w=inv0 R10=fp0 fp-8=mmmmmmmm fp-16=mmmmmmmm fp-24=mmmmmmmm fp-32=mmmmmmmm fp-40=mmmmmmmm fp-48=mmmmmmmm fp-56=mmmmmmmm fp-64=mmmmmmmm fp-72=mmmmmmmm fp-80=mmmmmmmm fp-88=mmmmmmmm fp-96=mmmmmmmm fp-104=mmmmmmmm fp-112=mmmmmmmm fp-120=mmmmmmmm fp-128=mmmmmmmm fp-136=mmmmmmmm fp-144=mmmmmmmm fp-152=mmmmmmmm fp-160=mmmmmmmm fp-168=mmmmmmmm fp-176=mmmmmmmm fp-184=mmmmmmmm fp-192=mmmmmmmm fp-200=mmmmmmmm fp-208=mmmmmmmm fp-216=mmmmmmmm fp-224=mmmmmmmm fp-232=mmmmmmmm fp-240=mmmmmmmm fp-248=mmmmmmmm fp-256=mmmmmmmm
parent didn&#39;t have regs=2 stack=0 marks
last_idx 24 first_idx 16
regs=2 stack=0 before 24: (b7) r1 = 0
27: (7b) *(u64 *)(r10 -280) = r8
; u32 pid = bpf_get_current_pid_tgid() &gt;&gt; 32;
28: (77) r6 &gt;&gt;= 32
; bpf_printk(&quot;%d , %s, %d, %s&quot;,pid,comm, contains_payload, pkt);
29: (7b) *(u64 *)(r10 -288) = r6
30: (bf) r3 = r10
31: (07) r3 += -288
32: (18) r1 = 0xffff8886d4b76110
34: (b7) r2 = 16
35: (b7) r4 = 32
36: (85) call unknown#177
invalid func unknown#177
processed 35 insns (limit 1000000) max_states_per_insn 0 total_states 2 peak_states 2 mark_read 2
-- END PROG LOAD LOG --
libbpf: prog &#39;sock_sendmsg&#39;: failed to load: -22
libbpf: failed to load object &#39;fentry_bpf&#39;
libbpf: failed to load BPF skeleton &#39;fentry_bpf&#39;: -22
Failed to open BPF skeleton

答案1

得分: 1

bpf_printk 是由 libbpf 定义的宏,根据您想要打印的参数数量选择 bpf_trace_printkbpf_trace_vprintk

BPF 辅助函数调用总共限制为 5 个参数,前两个参数被fmtsizeof(fmt)占用,因此使用可变参数的 bpf_trace_printk 只能接受最多 3 个变量。

bpf_trace_vprintk 辅助函数在内核版本 v5.16 中引入,它接受参数数组而不是可变参数,可以打印更多的参数。

因为您在以下代码中记录了 4 个变量:

 bpf_printk("%d , %s, %d, %s", pid, comm, contains_payload, pkt);

所以选择了 bpf_trace_vprintk 辅助函数。但是您可能正在运行一个不支持此辅助函数的较旧的内核,导致如下错误:

36: (85) call unknown#177
invalid func unknown#177

因此,请将每个 bpf_printf 记录的变量数量减少到 <= 3,或者升级您的内核至 >= v5.16。

英文:

bpf_printk is a macro defined by libbpf which picks between the bpf_trace_printk and bpf_trace_vprintk depending on the amount of arguments you want to print.

BPF helper calls are limited to 5 arguments total, the first 2 are taken up by fmt and sizeof(fmt) so the bpf_trace_printk which uses varadic arguments can only take up to 3 variables.

The bpf_trace_vprintk helper function was introduced in kernel version v5.16 and takes an array of parameters instead of varatic arguments which allows you to print a larger amount of arguments.

Because you are logging 4 variables in

 bpf_printk(&quot;%d , %s, %d, %s&quot;,pid,comm, contains_payload, pkt);

The bpf_trace_vprintk helper is picked. But you are likely running an older kernel which doesn't support this helper resulting in

36: (85) call unknown#177
invalid func unknown#177

So reduce the amount of variables logged per bpf_printf to <= 3 or update your kernel to >=v5.16

huangapple
  • 本文由 发表于 2023年6月16日 00:31:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76483747.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定