mirror of
https://github.com/kubeshark/kubeshark.git
synced 2026-08-25 00:47:27 +00:00
Add vmlinux.h and implement get_goid_from_thread_local_storage
This commit is contained in:
@@ -64,6 +64,46 @@ enum ABI {
|
||||
ABIInternal=1,
|
||||
};
|
||||
|
||||
static __always_inline int get_goid_from_thread_local_storage(__u64 *goroutine_id) {
|
||||
int zero = 0;
|
||||
int one = 1;
|
||||
__u32* g_addr_offset = bpf_map_lookup_elem(&goid_offset_map, &zero);
|
||||
__u32* goid_offset = bpf_map_lookup_elem(&goid_offset_map, &one);
|
||||
if (g_addr_offset == NULL || goid_offset == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Since eBPF programs have such strict stack requirements
|
||||
// me must implement our own heap using a ringbuffer.
|
||||
// Reserve some memory in our "heap" for the task_struct.
|
||||
struct task_struct *task;
|
||||
task = bpf_ringbuf_reserve(&heap, sizeof(struct task_struct), 0);
|
||||
if (!task) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get the current task.
|
||||
__u64 task_ptr = bpf_get_current_task();
|
||||
if (!task_ptr) {
|
||||
bpf_ringbuf_discard(task, 0);
|
||||
return 0;
|
||||
}
|
||||
// The bpf_get_current_task helper returns us the address of the task_struct in
|
||||
// kernel memory. Use the bpf_probe_read_kernel helper to read the struct out of
|
||||
// kernel memory.
|
||||
bpf_probe_read_kernel(task, sizeof(struct task_struct), (void*)(task_ptr));
|
||||
|
||||
// Get the Goroutine ID which is stored in thread local storage.
|
||||
size_t g_addr;
|
||||
bpf_probe_read_user(&g_addr, sizeof(void *), (void*)(task->thread.fsbase + g_addr_offset));
|
||||
bpf_probe_read_user(goroutine_id, sizeof(void *), (void*)(g_addr + goid_offset));
|
||||
|
||||
// Free back up the memory we reserved for the task_struct.
|
||||
bpf_ringbuf_discard(task, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static __always_inline __u32 go_crypto_tls_get_fd_from_tcp_conn(struct pt_regs *ctx) {
|
||||
struct go_interface conn;
|
||||
long err;
|
||||
@@ -119,8 +159,18 @@ static __always_inline void go_crypto_tls_uprobe(struct pt_regs *ctx, struct bpf
|
||||
info.buffer = (void*)GO_ABI_INTERNAL_PT_REGS_R4(ctx);
|
||||
info.fd = go_crypto_tls_get_fd_from_tcp_conn(ctx);
|
||||
|
||||
// GO_ABI_INTERNAL_PT_REGS_GP is Goroutine address
|
||||
__u64 pid_fp = pid << 32 | GO_ABI_INTERNAL_PT_REGS_GP(ctx);
|
||||
__u64 goroutine_id;
|
||||
if (abi == ABI0) {
|
||||
// In case of ABI0 and amd64, it's stored in the thread-local storage
|
||||
int status = get_goid_from_thread_local_storage(&goroutine_id);
|
||||
if (!status) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// GO_ABI_INTERNAL_PT_REGS_GP is Goroutine address
|
||||
goroutine_id = GO_ABI_INTERNAL_PT_REGS_GP(ctx);
|
||||
}
|
||||
__u64 pid_fp = pid << 32 | goroutine_id;
|
||||
err = bpf_map_update_elem(go_context, &pid_fp, &info, BPF_ANY);
|
||||
|
||||
if (err != 0) {
|
||||
@@ -137,8 +187,18 @@ static __always_inline void go_crypto_tls_ex_uprobe(struct pt_regs *ctx, struct
|
||||
return;
|
||||
}
|
||||
|
||||
// GO_ABI_INTERNAL_PT_REGS_GP is Goroutine address
|
||||
__u64 pid_fp = pid << 32 | GO_ABI_INTERNAL_PT_REGS_GP(ctx);
|
||||
__u64 goroutine_id;
|
||||
if (abi == ABI0) {
|
||||
// In case of ABI0 and amd64, it's stored in the thread-local storage
|
||||
int status = get_goid_from_thread_local_storage(&goroutine_id);
|
||||
if (!status) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// GO_ABI_INTERNAL_PT_REGS_GP is Goroutine address
|
||||
goroutine_id = GO_ABI_INTERNAL_PT_REGS_GP(ctx);
|
||||
}
|
||||
__u64 pid_fp = pid << 32 | goroutine_id;
|
||||
struct ssl_info *info_ptr = bpf_map_lookup_elem(go_context, &pid_fp);
|
||||
|
||||
if (info_ptr == NULL) {
|
||||
|
||||
@@ -78,15 +78,15 @@ https://github.com/golang/go/blob/go1.17.6/src/cmd/compile/internal/ssa/gen/AMD6
|
||||
|
||||
#else
|
||||
|
||||
#define GO_ABI_INTERNAL_PT_REGS_R1(x) ((x)->rax)
|
||||
#define GO_ABI_INTERNAL_PT_REGS_R2(x) ((x)->rcx)
|
||||
#define GO_ABI_INTERNAL_PT_REGS_R3(x) ((x)->rdx)
|
||||
#define GO_ABI_INTERNAL_PT_REGS_R4(x) ((x)->rbx)
|
||||
#define GO_ABI_INTERNAL_PT_REGS_R5(x) ((x)->rbp)
|
||||
#define GO_ABI_INTERNAL_PT_REGS_R6(x) ((x)->rsi)
|
||||
#define GO_ABI_INTERNAL_PT_REGS_R7(x) ((x)->rdi)
|
||||
#define GO_ABI_INTERNAL_PT_REGS_SP(x) ((x)->rsp)
|
||||
#define GO_ABI_INTERNAL_PT_REGS_FP(x) ((x)->rbp)
|
||||
#define GO_ABI_INTERNAL_PT_REGS_R1(x) ((x)->ax)
|
||||
#define GO_ABI_INTERNAL_PT_REGS_R2(x) ((x)->cx)
|
||||
#define GO_ABI_INTERNAL_PT_REGS_R3(x) ((x)->dx)
|
||||
#define GO_ABI_INTERNAL_PT_REGS_R4(x) ((x)->bx)
|
||||
#define GO_ABI_INTERNAL_PT_REGS_R5(x) ((x)->bp)
|
||||
#define GO_ABI_INTERNAL_PT_REGS_R6(x) ((x)->si)
|
||||
#define GO_ABI_INTERNAL_PT_REGS_R7(x) ((x)->di)
|
||||
#define GO_ABI_INTERNAL_PT_REGS_SP(x) ((x)->sp)
|
||||
#define GO_ABI_INTERNAL_PT_REGS_FP(x) ((x)->bp)
|
||||
#define GO_ABI_INTERNAL_PT_REGS_GP(x) ((x)->r14)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -7,9 +7,7 @@ Copyright (C) UP9 Inc.
|
||||
#ifndef __HEADERS__
|
||||
#define __HEADERS__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include "vmlinux.h"
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include "bpf/bpf_tracing.h"
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ BPF_LRU_HASH(openssl_write_context, __u64, struct ssl_info);
|
||||
BPF_LRU_HASH(openssl_read_context, __u64, struct ssl_info);
|
||||
|
||||
// Go specific
|
||||
BPF_HASH(goid_offset, __u32, __u32);
|
||||
BPF_HASH(goid_offset_map, __u32, __u32);
|
||||
BPF_LRU_HASH(go_write_context, __u64, struct ssl_info);
|
||||
BPF_LRU_HASH(go_read_context, __u64, struct ssl_info);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -87,9 +87,12 @@ func (s *goHooks) installHooks(bpfObjects *tlsTapperObjects, ex *link.Executable
|
||||
s.goReadExProbes = append(s.goReadExProbes, probe)
|
||||
}
|
||||
|
||||
// Pass goid offset to an eBPF map to retrieve it in eBPF context
|
||||
goidOffsetMap := bpfObjects.tlsTapperMaps.GoidOffset
|
||||
if err := goidOffsetMap.Put(0, offsets.GoidOffset); err != nil {
|
||||
// Pass goid and g struct offsets to an eBPF map to retrieve it in eBPF context
|
||||
goidOffsetMap := bpfObjects.tlsTapperMaps.GoidOffsetMap
|
||||
if err := goidOffsetMap.Put(0, offsets.GStructOffset); err != nil {
|
||||
return errors.Wrap(err, 0)
|
||||
}
|
||||
if err := goidOffsetMap.Put(1, offsets.GoidOffset); err != nil {
|
||||
return errors.Wrap(err, 0)
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ type goOffsets struct {
|
||||
GoVersion string
|
||||
Abi goAbi
|
||||
GoidOffset dwarf.Offset
|
||||
GStructOffset dwarf.Offset
|
||||
}
|
||||
|
||||
type goExtendedOffset struct {
|
||||
@@ -43,7 +44,7 @@ const (
|
||||
)
|
||||
|
||||
func findGoOffsets(filePath string) (goOffsets, error) {
|
||||
offsets, goidOffset, err := getOffsets(filePath)
|
||||
offsets, goidOffset, gStructOffset, err := getOffsets(filePath)
|
||||
if err != nil {
|
||||
return goOffsets{}, err
|
||||
}
|
||||
@@ -80,10 +81,11 @@ func findGoOffsets(filePath string) (goOffsets, error) {
|
||||
GoVersion: goVersion,
|
||||
Abi: abi,
|
||||
GoidOffset: goidOffset,
|
||||
GStructOffset: gStructOffset,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getGoidOffset(elfFile *elf.File) (offset dwarf.Offset, err error) {
|
||||
func getGoidOffset(elfFile *elf.File) (goidOffset dwarf.Offset, gStructOffset dwarf.Offset, err error) {
|
||||
var dwarfData *dwarf.Data
|
||||
dwarfData, err = elfFile.DWARF()
|
||||
if err != nil {
|
||||
@@ -110,6 +112,7 @@ func getGoidOffset(elfFile *elf.File) (offset dwarf.Offset, err error) {
|
||||
if field.Attr == dwarf.AttrName {
|
||||
val := field.Val.(string)
|
||||
if val == "runtime.g" {
|
||||
gStructOffset = entry.Offset
|
||||
seenRuntimeG = true
|
||||
}
|
||||
}
|
||||
@@ -123,7 +126,7 @@ func getGoidOffset(elfFile *elf.File) (offset dwarf.Offset, err error) {
|
||||
if field.Attr == dwarf.AttrName {
|
||||
val := field.Val.(string)
|
||||
if val == "goid" {
|
||||
offset = entry.Offset
|
||||
goidOffset = entry.Offset
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -135,7 +138,7 @@ func getGoidOffset(elfFile *elf.File) (offset dwarf.Offset, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func getOffsets(filePath string) (offsets map[string]*goExtendedOffset, goidOffset dwarf.Offset, err error) {
|
||||
func getOffsets(filePath string) (offsets map[string]*goExtendedOffset, goidOffset dwarf.Offset, gStructOffset dwarf.Offset, err error) {
|
||||
var engine gapstone.Engine
|
||||
switch runtime.GOARCH {
|
||||
case "amd64":
|
||||
@@ -258,7 +261,7 @@ func getOffsets(filePath string) (offsets map[string]*goExtendedOffset, goidOffs
|
||||
offsets[sym.Name] = extendedOffset
|
||||
}
|
||||
|
||||
goidOffset, err = getGoidOffset(elfFile)
|
||||
goidOffset, gStructOffset, err = getGoidOffset(elfFile)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ type tlsTapperMapSpecs struct {
|
||||
FileDescriptorToIpv4 *ebpf.MapSpec `ebpf:"file_descriptor_to_ipv4"`
|
||||
GoReadContext *ebpf.MapSpec `ebpf:"go_read_context"`
|
||||
GoWriteContext *ebpf.MapSpec `ebpf:"go_write_context"`
|
||||
GoidOffset *ebpf.MapSpec `ebpf:"goid_offset"`
|
||||
GoidOffsetMap *ebpf.MapSpec `ebpf:"goid_offset_map"`
|
||||
Heap *ebpf.MapSpec `ebpf:"heap"`
|
||||
LogBuffer *ebpf.MapSpec `ebpf:"log_buffer"`
|
||||
OpensslReadContext *ebpf.MapSpec `ebpf:"openssl_read_context"`
|
||||
@@ -133,7 +133,7 @@ type tlsTapperMaps struct {
|
||||
FileDescriptorToIpv4 *ebpf.Map `ebpf:"file_descriptor_to_ipv4"`
|
||||
GoReadContext *ebpf.Map `ebpf:"go_read_context"`
|
||||
GoWriteContext *ebpf.Map `ebpf:"go_write_context"`
|
||||
GoidOffset *ebpf.Map `ebpf:"goid_offset"`
|
||||
GoidOffsetMap *ebpf.Map `ebpf:"goid_offset_map"`
|
||||
Heap *ebpf.Map `ebpf:"heap"`
|
||||
LogBuffer *ebpf.Map `ebpf:"log_buffer"`
|
||||
OpensslReadContext *ebpf.Map `ebpf:"openssl_read_context"`
|
||||
@@ -149,7 +149,7 @@ func (m *tlsTapperMaps) Close() error {
|
||||
m.FileDescriptorToIpv4,
|
||||
m.GoReadContext,
|
||||
m.GoWriteContext,
|
||||
m.GoidOffset,
|
||||
m.GoidOffsetMap,
|
||||
m.Heap,
|
||||
m.LogBuffer,
|
||||
m.OpensslReadContext,
|
||||
|
||||
Reference in New Issue
Block a user