eBPF 스택 추적의 명령 포인터에 동일한 IP가 두 번 있고 관련이 없는 이상한 IP가 있는 eBPF 프로그램이 포함되어 있는 이유는 무엇입니까?

eBPF 스택 추적의 명령 포인터에 동일한 IP가 두 번 있고 관련이 없는 이상한 IP가 있는 eBPF 프로그램이 포함되어 있는 이유는 무엇입니까?

eBPF 프로그램에서 커널 스택 추적을 얻을 때 중복되고 이상한 항목이 나타납니다. 누군가 이것을 설명할 수 있습니까?

먼저 관련 eBPF 프로그램 조각부터 시작하겠습니다. 다음과 같이 스택 추적 그래프를 선언합니다.

struct {
    __uint(type, BPF_MAP_TYPE_STACK_TRACE);
    __type(key, u32);
    __type(value, stack);
    __uint(max_entries, 1 << 14);
} stacks SEC(".maps");

나중에 첨부할 eBPF 프로그램에서 cap_capable다음과 같이 스택 추적을 저장한 다음 스택 추적 ID를 사용자 공간으로 보냅니다.

kstackid = bpf_get_stackid(ctx, &stacks, 0);

Go의 사용자 공간 측면에서 Cilium을 사용하는 것이 매우 유용합니다.ebpf Go 모듈. 특정 스택 추적에 대한 명령 포인터를 읽으려면 다음을 수행합니다.

ips := make([]uint64, MaxStackDepth)
if err := objs.Stacks.Lookup(event.Kstackid, ips); err != nil {
    slog.Error("looking up kernel stack trace", "error", err)
    continue
}
l := len(ips)
for idx, ip := range ips {
    if ip == 0 {
        l = idx
        break
    }
}
ev := Event{
    bpfCapevent: event,
    KernelStack: ips[:l],
}

이제 데이터를 사용하여 명령 포인터를 구문 분석하면 /proc/kallsymsIP도 표시하는 다음과 같은 스택이 생성됩니다.

bpf_prog_47f71ae01d77a0b5_fentry_cap_capable ffffffffc00860ed
bpf_prog_47f71ae01d77a0b5_fentry_cap_capable ffffffffc00860ed
udp_tunnel_nic_init_module ffffffffc0e2004f
cap_capable ffffffff9ea9b1a5
  1. 왜 거기에 있습니까?Fentry의 IP 주소는 무엇입니까 cap_capable? 둘 다 동일한 반송 주소인데 여기서 무슨 일이 일어나고 있는 걸까요?
  2. cap_capable내 eBPF 프로그램 사이의 중간 기능은 무엇입니까 udp_tunnel_nic_init_module? 오해가 있는 것 같나요? 트램폴린과 관련이 있는걸까요...?

관련 정보