kubeshark/tap/tlstapper/bpf/fd_to_address_tracepoints.c
2022-03-28 14:19:06 +03:00

212 lines
4.6 KiB
C

/*
Note: This file is licenced differently from the rest of the project
SPDX-License-Identifier: GPL-2.0
Copyright (C) UP9 Inc.
*/
#include "include/headers.h"
#include "include/util.h"
#include "include/maps.h"
#include "include/log.h"
#include "include/logger_messages.h"
#include "include/pids.h"
#define IPV4_ADDR_LEN (16)
struct accept_info {
__u64* sockaddr;
__u32* addrlen;
};
BPF_HASH(accept_syscall_context, __u64, struct accept_info);
struct sys_enter_accept4_ctx {
__u64 __unused_syscall_header;
__u32 __unused_syscall_nr;
__u64 fd;
__u64* sockaddr;
__u32* addrlen;
};
SEC("tracepoint/syscalls/sys_enter_accept4")
void sys_enter_accept4(struct sys_enter_accept4_ctx *ctx) {
__u64 id = bpf_get_current_pid_tgid();
if (!should_tap(id >> 32)) {
return;
}
struct accept_info info = {};
info.sockaddr = ctx->sockaddr;
info.addrlen = ctx->addrlen;
long err = bpf_map_update_elem(&accept_syscall_context, &id, &info, BPF_ANY);
if (err != 0) {
log_error(ctx, LOG_ERROR_PUTTING_ACCEPT_INFO, id, err, 0l);
}
}
struct sys_exit_accept4_ctx {
__u64 __unused_syscall_header;
__u32 __unused_syscall_nr;
__u64 ret;
};
SEC("tracepoint/syscalls/sys_exit_accept4")
void sys_exit_accept4(struct sys_exit_accept4_ctx *ctx) {
__u64 id = bpf_get_current_pid_tgid();
if (!should_tap(id >> 32)) {
return;
}
if (ctx->ret < 0) {
bpf_map_delete_elem(&accept_syscall_context, &id);
return;
}
struct accept_info *infoPtr = bpf_map_lookup_elem(&accept_syscall_context, &id);
if (infoPtr == NULL) {
log_error(ctx, LOG_ERROR_GETTING_ACCEPT_INFO, id, 0l, 0l);
return;
}
struct accept_info info;
long err = bpf_probe_read(&info, sizeof(struct accept_info), infoPtr);
bpf_map_delete_elem(&accept_syscall_context, &id);
if (err != 0) {
log_error(ctx, LOG_ERROR_READING_ACCEPT_INFO, id, err, 0l);
return;
}
__u32 addrlen;
bpf_probe_read(&addrlen, sizeof(__u32), info.addrlen);
if (addrlen != IPV4_ADDR_LEN) {
// Currently only ipv4 is supported linux-src/include/linux/inet.h
return;
}
struct fd_info fdinfo = {
.flags = 0
};
bpf_probe_read(fdinfo.ipv4_addr, sizeof(fdinfo.ipv4_addr), info.sockaddr);
__u32 pid = id >> 32;
__u32 fd = (__u32) ctx->ret;
__u64 key = (__u64) pid << 32 | fd;
err = bpf_map_update_elem(&file_descriptor_to_ipv4, &key, &fdinfo, BPF_ANY);
if (err != 0) {
log_error(ctx, LOG_ERROR_PUTTING_FD_MAPPING, id, err, ORIGIN_SYS_EXIT_ACCEPT4_CODE);
}
}
struct connect_info {
__u64 fd;
__u64* sockaddr;
__u32 addrlen;
};
BPF_HASH(connect_syscall_info, __u64, struct connect_info);
struct sys_enter_connect_ctx {
__u64 __unused_syscall_header;
__u32 __unused_syscall_nr;
__u64 fd;
__u64* sockaddr;
__u32 addrlen;
};
SEC("tracepoint/syscalls/sys_enter_connect")
void sys_enter_connect(struct sys_enter_connect_ctx *ctx) {
__u64 id = bpf_get_current_pid_tgid();
if (!should_tap(id >> 32)) {
return;
}
struct connect_info info = {};
info.sockaddr = ctx->sockaddr;
info.addrlen = ctx->addrlen;
info.fd = ctx->fd;
long err = bpf_map_update_elem(&connect_syscall_info, &id, &info, BPF_ANY);
if (err != 0) {
log_error(ctx, LOG_ERROR_PUTTING_CONNECT_INFO, id, err, 0l);
}
}
struct sys_exit_connect_ctx {
__u64 __unused_syscall_header;
__u32 __unused_syscall_nr;
__u64 ret;
};
SEC("tracepoint/syscalls/sys_exit_connect")
void sys_exit_connect(struct sys_exit_connect_ctx *ctx) {
__u64 id = bpf_get_current_pid_tgid();
if (!should_tap(id >> 32)) {
return;
}
// Commented because of async connect which set errno to EINPROGRESS
//
// if (ctx->ret != 0) {
// bpf_map_delete_elem(&accept_syscall_context, &id);
// return;
// }
struct connect_info *infoPtr = bpf_map_lookup_elem(&connect_syscall_info, &id);
if (infoPtr == NULL) {
log_error(ctx, LOG_ERROR_GETTING_CONNECT_INFO, id, 0l, 0l);
return;
}
struct connect_info info;
long err = bpf_probe_read(&info, sizeof(struct connect_info), infoPtr);
bpf_map_delete_elem(&connect_syscall_info, &id);
if (err != 0) {
log_error(ctx, LOG_ERROR_READING_CONNECT_INFO, id, err, 0l);
return;
}
if (info.addrlen != IPV4_ADDR_LEN) {
// Currently only ipv4 is supported linux-src/include/linux/inet.h
return;
}
struct fd_info fdinfo = {
.flags = FLAGS_IS_CLIENT_BIT
};
bpf_probe_read(fdinfo.ipv4_addr, sizeof(fdinfo.ipv4_addr), info.sockaddr);
__u32 pid = id >> 32;
__u32 fd = (__u32) info.fd;
__u64 key = (__u64) pid << 32 | fd;
err = bpf_map_update_elem(&file_descriptor_to_ipv4, &key, &fdinfo, BPF_ANY);
if (err != 0) {
log_error(ctx, LOG_ERROR_PUTTING_FD_MAPPING, id, err, ORIGIN_SYS_EXIT_CONNECT_CODE);
}
}