From 9314126fb6a45c0847a716dd3a5a5678b90a80b2 Mon Sep 17 00:00:00 2001 From: "M. Mert Yildiran" Date: Tue, 31 May 2022 15:20:38 +0300 Subject: [PATCH] Make `golang_dial_writes` key `__u64` and include the PID --- tap/tlstapper/bpf/golang_uprobes.c | 11 +++++++---- tap/tlstapper/bpf/include/maps.h | 4 ++-- tap/tlstapper/tlstapper_bpfeb.o | Bin 124984 -> 125440 bytes tap/tlstapper/tlstapper_bpfel.o | Bin 124984 -> 125440 bytes 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/tap/tlstapper/bpf/golang_uprobes.c b/tap/tlstapper/bpf/golang_uprobes.c index d95040e55..be3b4adee 100644 --- a/tap/tlstapper/bpf/golang_uprobes.c +++ b/tap/tlstapper/bpf/golang_uprobes.c @@ -26,6 +26,8 @@ const struct golang_read_write *unused __attribute__((unused)); SEC("uprobe/golang_crypto_tls_write") static __always_inline int golang_crypto_tls_write_uprobe(struct pt_regs *ctx) { void* stack_addr = (void*)ctx->rsp; + __u64 pid_tgid = bpf_get_current_pid_tgid(); + __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); @@ -34,7 +36,8 @@ static __always_inline int golang_crypto_tls_write_uprobe(struct pt_regs *ctx) { return 0; } - struct socket *s = bpf_map_lookup_elem(&golang_dial_writes, &key_dial); + __u64 key_dial_full = (pid << 32) + key_dial; + struct socket *s = bpf_map_lookup_elem(&golang_dial_writes, &key_dial_full); if (s == NULL) { bpf_printk("[golang_crypto_tls_write_uprobe] error getting socket"); return 0; @@ -46,8 +49,7 @@ static __always_inline int golang_crypto_tls_write_uprobe(struct pt_regs *ctx) { return 0; } - __u64 pid_tgid = bpf_get_current_pid_tgid(); - b->pid = pid_tgid >> 32; + b->pid = pid; b->fd = s->fd; // 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 @@ -105,7 +107,8 @@ static __always_inline int golang_net_socket_uprobe(struct pt_regs *ctx) { struct socket b = { .pid = s->pid, .fd = ctx->rax, .key_dial = s->key_dial }; - __u32 status = bpf_map_update_elem(&golang_dial_writes, &s->key_dial, &b, BPF_ANY); + __u64 key_dial_full = (pid << 32) + s->key_dial; + __u32 status = bpf_map_update_elem(&golang_dial_writes, &key_dial_full, &b, BPF_ANY); if (status != 0) { bpf_printk("[golang_net_socket_uprobe] error updating socket file descriptor: %d", status); } diff --git a/tap/tlstapper/bpf/include/maps.h b/tap/tlstapper/bpf/include/maps.h index edc785eb8..3b5815014 100644 --- a/tap/tlstapper/bpf/include/maps.h +++ b/tap/tlstapper/bpf/include/maps.h @@ -56,7 +56,7 @@ struct fd_info { struct socket { __u32 pid; __u32 fd; - __u32 key_dial; + __u64 key_dial; }; #define BPF_MAP(_name, _type, _key_type, _value_type, _max_entries) \ @@ -90,7 +90,7 @@ BPF_PERF_OUTPUT(chunks_buffer); BPF_PERF_OUTPUT(log_buffer); BPF_LRU_HASH(golang_socket_dials, __u64, struct socket); -BPF_LRU_HASH(golang_dial_writes, __u32, struct socket); +BPF_LRU_HASH(golang_dial_writes, __u64, struct socket); BPF_RINGBUF(golang_read_writes); #endif /* __MAPS__ */ diff --git a/tap/tlstapper/tlstapper_bpfeb.o b/tap/tlstapper/tlstapper_bpfeb.o index 05526beae6ebb70ede85b072ffeb4f7ef1083fb5..71f39d94ca491477b80390472a3cc0f001e6527c 100644 GIT binary patch delta 7553 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 voCg^rKFj)5R#HlgXW4-G=RsV$>C!APf> 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 delta 7411 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