diff --git a/tap/tlstapper/bpf/golang_uprobes.c b/tap/tlstapper/bpf/golang_uprobes.c index 59a821faa..7bc6f0cba 100644 --- a/tap/tlstapper/bpf/golang_uprobes.c +++ b/tap/tlstapper/bpf/golang_uprobes.c @@ -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); diff --git a/tap/tlstapper/bpf/include/maps.h b/tap/tlstapper/bpf/include/maps.h index 1367e7080..7968d4817 100644 --- a/tap/tlstapper/bpf/include/maps.h +++ b/tap/tlstapper/bpf/include/maps.h @@ -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__ */ diff --git a/tap/tlstapper/tls_poller.go b/tap/tlstapper/tls_poller.go index 05473f875..5149df5c1 100644 --- a/tap/tlstapper/tls_poller.go +++ b/tap/tlstapper/tls_poller.go @@ -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 } diff --git a/tap/tlstapper/tlstapper_bpfeb.go b/tap/tlstapper/tlstapper_bpfeb.go index ff61a8d51..9622b3284 100644 --- a/tap/tlstapper/tlstapper_bpfeb.go +++ b/tap/tlstapper/tlstapper_bpfeb.go @@ -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, diff --git a/tap/tlstapper/tlstapper_bpfeb.o b/tap/tlstapper/tlstapper_bpfeb.o index 1a5eaef31..119665920 100644 Binary files a/tap/tlstapper/tlstapper_bpfeb.o and b/tap/tlstapper/tlstapper_bpfeb.o differ diff --git a/tap/tlstapper/tlstapper_bpfel.go b/tap/tlstapper/tlstapper_bpfel.go index f98174e49..0c8313b51 100644 --- a/tap/tlstapper/tlstapper_bpfel.go +++ b/tap/tlstapper/tlstapper_bpfel.go @@ -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, diff --git a/tap/tlstapper/tlstapper_bpfel.o b/tap/tlstapper/tlstapper_bpfel.o index 2c2aff6d2..45e501e12 100644 Binary files a/tap/tlstapper/tlstapper_bpfel.o and b/tap/tlstapper/tlstapper_bpfel.o differ