Change golang_read_writes map type from BPF_RINGBUF to BPF_PERF_OUTPUT

This commit is contained in:
M. Mert Yildiran 2022-06-02 22:22:10 +03:00
parent e5a1de9c71
commit 32c566705a
No known key found for this signature in database
GPG Key ID: D42ADB236521BF7A
7 changed files with 52 additions and 36 deletions

View File

@ -11,15 +11,22 @@ Copyright (C) UP9 Inc.
#include "include/logger_messages.h"
struct {
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
__uint(max_entries, 1);
__type(key, int);
__type(value, struct golang_read_write);
} golang_heap SEC(".maps");
SEC("uprobe/golang_crypto_tls_write")
static __always_inline int golang_crypto_tls_write_uprobe(struct pt_regs *ctx) {
__u64 pid_tgid = bpf_get_current_pid_tgid();
if (!should_tap(pid_tgid >> 32)) {
__u64 pid = pid_tgid >> 32;
if (!should_tap(pid)) {
return 0;
}
void* stack_addr = (void*)ctx->rsp;
__u64 pid = pid_tgid >> 32;
__u32 key_dial;
// Address at ctx->rsp + 0x20 is common between golang_crypto_tls_write_uprobe and golang_net_http_dialconn_uprobe
__u32 status = bpf_probe_read(&key_dial, sizeof(key_dial), stack_addr + 0x20);
@ -36,10 +43,14 @@ static __always_inline int golang_crypto_tls_write_uprobe(struct pt_regs *ctx) {
}
struct golang_read_write *b = NULL;
b = bpf_ringbuf_reserve(&golang_read_writes, sizeof(struct golang_read_write), 0);
int zero = 0;
b = bpf_map_lookup_elem(&golang_heap, &zero);
if (!b) {
return 0;
}
log_error(ctx, LOG_ERROR_ALLOCATING_CHUNK, pid, 0l, 0l);
return 0;
}
b->pid = pid;
b->fd = s->fd;
@ -52,11 +63,10 @@ static __always_inline int golang_crypto_tls_write_uprobe(struct pt_regs *ctx) {
status = bpf_probe_read(&b->data, CHUNK_SIZE, (void*)ctx->rbx);
if (status < 0) {
log_error(ctx, LOG_ERROR_GOLANG_WRITE_READING_DATA, pid_tgid, status, 0l);
bpf_ringbuf_discard(b, BPF_RB_FORCE_WAKEUP);
return 0;
}
bpf_ringbuf_submit(b, 0);
bpf_perf_event_output(ctx, &golang_read_writes, BPF_F_CURRENT_CPU, b, sizeof(struct golang_read_write));
return 0;
}
@ -64,7 +74,8 @@ static __always_inline int golang_crypto_tls_write_uprobe(struct pt_regs *ctx) {
SEC("uprobe/golang_crypto_tls_read")
static __always_inline int golang_crypto_tls_read_uprobe(struct pt_regs *ctx) {
__u64 pid_tgid = bpf_get_current_pid_tgid();
if (!should_tap(pid_tgid >> 32)) {
__u64 pid = pid_tgid >> 32;
if (!should_tap(pid)) {
return 0;
}
@ -78,12 +89,16 @@ static __always_inline int golang_crypto_tls_read_uprobe(struct pt_regs *ctx) {
}
struct golang_read_write *b = NULL;
b = bpf_ringbuf_reserve(&golang_read_writes, sizeof(struct golang_read_write), 0);
if (!b) {
return 0;
}
int zero = 0;
b->pid = pid_tgid >> 32;
b = bpf_map_lookup_elem(&golang_heap, &zero);
if (!b) {
log_error(ctx, LOG_ERROR_ALLOCATING_CHUNK, pid, 0l, 0l);
return 0;
}
b->pid = pid;
// ctx->rsi is common between golang_crypto_tls_write_uprobe and golang_crypto_tls_read_uprobe
b->conn_addr = ctx->rsi; // go.itab.*net.TCPConn,net.Conn address
b->is_request = false;
@ -93,22 +108,21 @@ static __always_inline int golang_crypto_tls_read_uprobe(struct pt_regs *ctx) {
status = bpf_probe_read(&b->data, CHUNK_SIZE, (void*)(data_p));
if (status < 0) {
log_error(ctx, LOG_ERROR_GOLANG_READ_READING_DATA, pid_tgid, status, 0l);
bpf_ringbuf_discard(b, BPF_RB_FORCE_WAKEUP);
return 0;
}
bpf_ringbuf_submit(b, 0);
bpf_perf_event_output(ctx, &golang_read_writes, BPF_F_CURRENT_CPU, b, sizeof(struct golang_read_write));
return 0;
}
SEC("uprobe/golang_net_socket")
static __always_inline int golang_net_socket_uprobe(struct pt_regs *ctx) {
__u64 pid_tgid = bpf_get_current_pid_tgid();
if (!should_tap(pid_tgid >> 32)) {
__u64 pid = pid_tgid >> 32;
if (!should_tap(pid)) {
return 0;
}
__u64 pid = pid_tgid >> 32;
// ctx->r14 is common between golang_net_socket_uprobe and golang_net_http_dialconn_uprobe
__u64 key_socket = (pid << 32) + ctx->r14;
struct golang_socket *s = bpf_map_lookup_elem(&golang_dial_to_socket, &key_socket);

View File

@ -95,12 +95,6 @@ const struct sys_close *unused2 __attribute__((unused));
#define BPF_LRU_HASH(_name, _key_type, _value_type) \
BPF_MAP(_name, BPF_MAP_TYPE_LRU_HASH, _key_type, _value_type, MAX_ENTRIES_LRU_HASH)
#define BPF_RINGBUF(_name) \
struct { \
__uint(type, BPF_MAP_TYPE_RINGBUF); \
__uint(max_entries, MAX_ENTRIES_RINGBUFF); \
} _name SEC(".maps"); \
BPF_HASH(pids_map, __u32, __u32);
BPF_LRU_HASH(ssl_write_context, __u64, struct ssl_info);
BPF_LRU_HASH(ssl_read_context, __u64, struct ssl_info);
@ -110,7 +104,7 @@ BPF_PERF_OUTPUT(log_buffer);
BPF_LRU_HASH(golang_dial_to_socket, __u64, struct golang_socket);
BPF_LRU_HASH(golang_socket_to_write, __u64, struct golang_socket);
BPF_RINGBUF(golang_read_writes);
BPF_PERF_OUTPUT(golang_read_writes);
BPF_PERF_OUTPUT(sys_closes);
#endif /* __MAPS__ */

View File

@ -16,7 +16,6 @@ import (
"strings"
"github.com/cilium/ebpf/perf"
"github.com/cilium/ebpf/ringbuf"
"github.com/go-errors/errors"
"github.com/hashicorp/golang-lru/simplelru"
"github.com/up9inc/mizu/logger"
@ -36,7 +35,7 @@ type tlsPoller struct {
closedReaders chan string
reqResMatcher api.RequestResponseMatcher
chunksReader *perf.Reader
golangReader *ringbuf.Reader
golangReader *perf.Reader
golangReadWriteMap *orderedmap.OrderedMap
sysCloses *perf.Reader
extension *api.Extension
@ -76,7 +75,7 @@ func (p *tlsPoller) init(bpfObjects *tlsTapperObjects, bufferSize int) error {
return errors.Wrap(err, 0)
}
p.golangReader, err = ringbuf.NewReader(bpfObjects.GolangReadWrites)
p.golangReader, err = perf.NewReader(bpfObjects.GolangReadWrites, bufferSize)
if err != nil {
return errors.Wrap(err, 0)
@ -123,7 +122,7 @@ func (p *tlsPoller) pollGolang(emitter api.Emitter, options *api.TrafficFilterin
go p.pollSysClose(p.sysCloses)
}
func (p *tlsPoller) pollGolangReadWrite(rd *ringbuf.Reader, emitter api.Emitter, options *api.TrafficFilteringOptions,
func (p *tlsPoller) pollGolangReadWrite(rd *perf.Reader, emitter api.Emitter, options *api.TrafficFilteringOptions,
streamsMap api.TcpStreamMap) {
nativeEndian := p.getByteOrder()
// tlsTapperGolangReadWrite is generated by bpf2go.
@ -131,17 +130,20 @@ func (p *tlsPoller) pollGolangReadWrite(rd *ringbuf.Reader, emitter api.Emitter,
for {
record, err := rd.Read()
if err != nil {
if errors.Is(err, ringbuf.ErrClosed) {
log.Println("received signal, exiting..")
if errors.Is(err, perf.ErrClosed) {
return
}
log.Printf("reading from reader: %s", err)
logger.Log.Errorf("reading from Golang tls reader: %s", err)
continue
}
if record.LostSamples != 0 {
logger.Log.Infof("Golang perf event ring buffer full, dropped %d samples", record.LostSamples)
continue
}
// Parse the ringbuf event entry into a tlsTapperGolangReadWrite structure.
if err := binary.Read(bytes.NewBuffer(record.RawSample), nativeEndian, &b); err != nil {
log.Printf("parsing ringbuf event: %s", err)
logger.Log.Errorf("parsing Golang perf event: %s", err)
continue
}
@ -212,17 +214,17 @@ func (p *tlsPoller) pollSysClose(rd *perf.Reader) {
if errors.Is(err, perf.ErrClosed) {
return
}
log.Printf("reading from perf event reader: %s", err)
logger.Log.Errorf("reading from sys_close tls reader: %s", err)
continue
}
if record.LostSamples != 0 {
log.Printf("perf event ring buffer full, dropped %d samples", record.LostSamples)
logger.Log.Info("sys_close perf event ring buffer full, dropped %d samples", record.LostSamples)
continue
}
if err := binary.Read(bytes.NewBuffer(record.RawSample), nativeEndian, &b); err != nil {
log.Printf("parsing perf event: %s", err)
logger.Log.Errorf("parsing sys_close perf event: %s", err)
continue
}

View File

@ -109,6 +109,7 @@ type tlsTapperMapSpecs struct {
ConnectSyscallInfo *ebpf.MapSpec `ebpf:"connect_syscall_info"`
FileDescriptorToIpv4 *ebpf.MapSpec `ebpf:"file_descriptor_to_ipv4"`
GolangDialToSocket *ebpf.MapSpec `ebpf:"golang_dial_to_socket"`
GolangHeap *ebpf.MapSpec `ebpf:"golang_heap"`
GolangReadWrites *ebpf.MapSpec `ebpf:"golang_read_writes"`
GolangSocketToWrite *ebpf.MapSpec `ebpf:"golang_socket_to_write"`
Heap *ebpf.MapSpec `ebpf:"heap"`
@ -143,6 +144,7 @@ type tlsTapperMaps struct {
ConnectSyscallInfo *ebpf.Map `ebpf:"connect_syscall_info"`
FileDescriptorToIpv4 *ebpf.Map `ebpf:"file_descriptor_to_ipv4"`
GolangDialToSocket *ebpf.Map `ebpf:"golang_dial_to_socket"`
GolangHeap *ebpf.Map `ebpf:"golang_heap"`
GolangReadWrites *ebpf.Map `ebpf:"golang_read_writes"`
GolangSocketToWrite *ebpf.Map `ebpf:"golang_socket_to_write"`
Heap *ebpf.Map `ebpf:"heap"`
@ -160,6 +162,7 @@ func (m *tlsTapperMaps) Close() error {
m.ConnectSyscallInfo,
m.FileDescriptorToIpv4,
m.GolangDialToSocket,
m.GolangHeap,
m.GolangReadWrites,
m.GolangSocketToWrite,
m.Heap,

Binary file not shown.

View File

@ -109,6 +109,7 @@ type tlsTapperMapSpecs struct {
ConnectSyscallInfo *ebpf.MapSpec `ebpf:"connect_syscall_info"`
FileDescriptorToIpv4 *ebpf.MapSpec `ebpf:"file_descriptor_to_ipv4"`
GolangDialToSocket *ebpf.MapSpec `ebpf:"golang_dial_to_socket"`
GolangHeap *ebpf.MapSpec `ebpf:"golang_heap"`
GolangReadWrites *ebpf.MapSpec `ebpf:"golang_read_writes"`
GolangSocketToWrite *ebpf.MapSpec `ebpf:"golang_socket_to_write"`
Heap *ebpf.MapSpec `ebpf:"heap"`
@ -143,6 +144,7 @@ type tlsTapperMaps struct {
ConnectSyscallInfo *ebpf.Map `ebpf:"connect_syscall_info"`
FileDescriptorToIpv4 *ebpf.Map `ebpf:"file_descriptor_to_ipv4"`
GolangDialToSocket *ebpf.Map `ebpf:"golang_dial_to_socket"`
GolangHeap *ebpf.Map `ebpf:"golang_heap"`
GolangReadWrites *ebpf.Map `ebpf:"golang_read_writes"`
GolangSocketToWrite *ebpf.Map `ebpf:"golang_socket_to_write"`
Heap *ebpf.Map `ebpf:"heap"`
@ -160,6 +162,7 @@ func (m *tlsTapperMaps) Close() error {
m.ConnectSyscallInfo,
m.FileDescriptorToIpv4,
m.GolangDialToSocket,
m.GolangHeap,
m.GolangReadWrites,
m.GolangSocketToWrite,
m.Heap,

Binary file not shown.