I have this ebpf program that I am trying to do. Basically, I am trapping recvfrom
function call and trying to share my recvfrom
buffer to my userspace application. This is the code:
SEC("kprobe/__x64_sys_recvfrom")
int bpf_prog1(struct pt_regs *ctx,int fd, const char *buf, size_t count)
{
struct S {
int pid;
char cookie[90];
} data={1,""};
//data.pid =count;// bpf_get_current_pid_tgid();
//if(buf==NULL)
// memcpy(data.cookie,buf,20);
// data.cookie[0]=buf[0];
bpf_get_current_comm(&data.cookie, sizeof(data.cookie));
int i=0;
bpf_perf_event_output(ctx, &my_map, 1, &data, sizeof(data));
return 0;
}
So, it seems like I have signature of bpf_prog function
and in it, I have buffer from recvfrom
function but when I try to access it, I simply can't because my program is loading complains.
root@this:/home/ubuntu/Desktop/ebpf/Linux-exFilter-main/pkg/probe/bpf# ./trace
libbpf: load bpf program failed: Permission denied
libbpf: -- BEGIN DUMP LOG ---
libbpf:
R1 type=ctx expected=fp
; int bpf_prog1(struct pt_regs *ctx,int fd, const char *buf, size_t count)
0: (bf) r6 = r1
1: (b7) r1 = 0
; } data={1,""};
2: (7b) *(u64 *)(r10 -8) = r1
last_idx 2 first_idx 0
regs=2 stack=0 before 1: (b7) r1 = 0
3: (7b) *(u64 *)(r10 -16) = r1
4: (7b) *(u64 *)(r10 -24) = r1
5: (7b) *(u64 *)(r10 -32) = r1
6: (7b) *(u64 *)(r10 -40) = r1
7: (7b) *(u64 *)(r10 -48) = r1
8: (7b) *(u64 *)(r10 -56) = r1
9: (7b) *(u64 *)(r10 -64) = r1
10: (7b) *(u64 *)(r10 -72) = r1
11: (b7) r1 = 1
12: (63) *(u32 *)(r10 -96) = r1
; memcpy(data.cookie,buf,20);
13: (71) r4 = *(u8 *)(r3 1)
R3 !read_ok
processed 14 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0
libbpf: -- END LOG --
libbpf: failed to load program 'bpf_prog1'
libbpf: failed to load object './kprobe_send.o'
ERROR: loading BPF object file failed
And there is a function like bpf_get_current_comm(&data.cookie, sizeof(data.cookie));
and bpf_perf_event_output(ctx, &my_map, 1, &data, sizeof(data));
and use of these functions giving me garbage data. So I like to know how to read the function parameters in ebpf programs. Is there any conventional way of doing it
I know ebpf is having maps and maps are to share info between ebpf program and userspace application. Sharing parameters is a basic thing but I dont know why I haven't seen it on the internet
CodePudding user response:
You can read the parameters of recvfrom
by using the PT_REGS_PARM macros, in this case PT_REGS_PARM2(ctx)
. This is an example from the tracex4 sample:
SEC("kprobe/kmem_cache_free")
int bpf_prog1(struct pt_regs *ctx)
{
long ptr = PT_REGS_PARM2(ctx);
bpf_map_delete_elem(&my_map, &ptr);
return 0;
}
In the case of recvfrom
, the second param should be a pointer to the buffer:
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
To communicate from kernel to userspace you indeed need a map. You will notice that your call to bpf_perf_event_output
also takes a pointer to a map: &my_map
.
The bpf_perf_event_output
helper function requires a map of type BPF_MAP_TYPE_PERF_EVENT_ARRAY
to function. But unlike most map types this map type works like a uni-directional stream of data from the eBPF program to the userspace.
I believe your code is loosly based on the trace_output_kern sample in the kernel. You will notice they define a map here as well:
struct {
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
__uint(key_size, sizeof(int));
__uint(value_size, sizeof(u32));
__uint(max_entries, 2);
} my_map SEC(".maps");