kubeshark/tap/tlstapper/bpf/tcp_kprobes.c
Nimrod Gilboa Markevich 692c500b0f
Improve Go TLS address availability (#1207)
Fetch source and destination addresses with bpf from tcp kprobes, similar to how it is done for openssl lib.
Chunk contains both source address and destination address.
FD is no longer used to obtain addresses.
2022-07-19 14:31:27 +03:00

119 lines
3.7 KiB
C

#include "include/headers.h"
#include "include/maps.h"
#include "include/log.h"
#include "include/logger_messages.h"
#include "include/pids.h"
#include "include/common.h"
static __always_inline int tcp_kprobes_get_address_pair_from_ctx(struct pt_regs *ctx, __u64 id, struct address_info *address_info_ptr) {
long err;
struct sock *sk = (struct sock *) PT_REGS_PARM1(ctx);
short unsigned int family;
err = bpf_probe_read(&family, sizeof(family), (void *)&sk->__sk_common.skc_family);
if (err != 0) {
log_error(ctx, LOG_ERROR_READING_SOCKET_FAMILY, id, err, 0l);
return -1;
}
if (family != AF_INET) {
return -1;
}
// daddr, saddr and dport are in network byte order (big endian)
// sport is in host byte order
__be32 saddr;
__be32 daddr;
__be16 dport;
__u16 sport;
err = bpf_probe_read(&saddr, sizeof(saddr), (void *)&sk->__sk_common.skc_rcv_saddr);
if (err != 0) {
log_error(ctx, LOG_ERROR_READING_SOCKET_SADDR, id, err, 0l);
return -1;
}
err = bpf_probe_read(&daddr, sizeof(daddr), (void *)&sk->__sk_common.skc_daddr);
if (err != 0) {
log_error(ctx, LOG_ERROR_READING_SOCKET_DADDR, id, err, 0l);
return -1;
}
err = bpf_probe_read(&dport, sizeof(dport), (void *)&sk->__sk_common.skc_dport);
if (err != 0) {
log_error(ctx, LOG_ERROR_READING_SOCKET_DPORT, id, err, 0l);
return -1;
}
err = bpf_probe_read(&sport, sizeof(sport), (void *)&sk->__sk_common.skc_num);
if (err != 0) {
log_error(ctx, LOG_ERROR_READING_SOCKET_SPORT, id, err, 0l);
return -1;
}
address_info_ptr->daddr = daddr;
address_info_ptr->saddr = saddr;
address_info_ptr->dport = dport;
address_info_ptr->sport = bpf_htons(sport);
return 0;
}
static __always_inline void tcp_kprobes_forward_go(struct pt_regs *ctx, __u64 id, __u32 fd, struct address_info address_info, struct bpf_map_def *map_fd_go_user_kernel) {
__u32 pid = id >> 32;
__u64 key = (__u64) pid << 32 | fd;
long err = bpf_map_update_elem(map_fd_go_user_kernel, &key, &address_info, BPF_ANY);
if (err != 0) {
log_error(ctx, LOG_ERROR_PUTTING_GO_USER_KERNEL_CONTEXT, id, fd, err);
return;
}
}
static void __always_inline tcp_kprobes_forward_openssl(struct ssl_info *info_ptr, struct address_info address_info) {
info_ptr->address_info.daddr = address_info.daddr;
info_ptr->address_info.saddr = address_info.saddr;
info_ptr->address_info.dport = address_info.dport;
info_ptr->address_info.sport = address_info.sport;
}
static __always_inline void tcp_kprobe(struct pt_regs *ctx, struct bpf_map_def *map_fd_openssl, struct bpf_map_def *map_fd_go_kernel, struct bpf_map_def *map_fd_go_user_kernel) {
long err;
__u64 id = bpf_get_current_pid_tgid();
if (!should_tap(id >> 32)) {
return;
}
struct address_info address_info;
if (0 != tcp_kprobes_get_address_pair_from_ctx(ctx, id, &address_info)) {
return;
}
struct ssl_info *info_ptr = bpf_map_lookup_elem(map_fd_openssl, &id);
__u32 *fd_ptr;
if (info_ptr == NULL) {
fd_ptr = bpf_map_lookup_elem(map_fd_go_kernel, &id);
// Connection is used by a Go program
if (fd_ptr == NULL) {
// Connection was not created by a Go program or by openssl lib
return;
}
tcp_kprobes_forward_go(ctx, id, *fd_ptr, address_info, map_fd_go_user_kernel);
} else {
// Connection is used by openssl lib
tcp_kprobes_forward_openssl(info_ptr, address_info);
}
}
SEC("kprobe/tcp_sendmsg")
void BPF_KPROBE(tcp_sendmsg) {
__u64 id = bpf_get_current_pid_tgid();
tcp_kprobe(ctx, &openssl_write_context, &go_kernel_write_context, &go_user_kernel_write_context);
}
SEC("kprobe/tcp_recvmsg")
void BPF_KPROBE(tcp_recvmsg) {
__u64 id = bpf_get_current_pid_tgid();
tcp_kprobe(ctx, &openssl_read_context, &go_kernel_read_context, &go_user_kernel_read_context);
}