bpf/accesslog/syscalls/transfer.c (458 lines of code) (raw):

// Licensed to Apache Software Foundation (ASF) under one or more contributor // license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright // ownership. Apache Software Foundation (ASF) licenses this file to you under // the Apache License, Version 2.0 (the "License"); you may // not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. #include "api.h" #include "socket_opts.h" #include "../process/process.h" #include "../common/data_args.h" #include "../common/sock.h" #include "../l24/l24.h" #include "transfer.h" struct trace_event_raw_skb_copy_datagram_iovec { struct trace_entry ent; const void *skbaddr; int len; char __data[0]; } __attribute__((preserve_access_index)); #define BPF_PROBE_READ_VAR(value, ptr) bpf_probe_read(&value, sizeof(value), ptr) SEC("tracepoint/syscalls/sys_enter_write") int tracepoint_enter_write(struct syscall_trace_enter *ctx) { uint64_t id = bpf_get_current_pid_tgid(); if (tgid_should_trace(id >> 32) == false) { return 0; } struct sock_data_args_t data_args = {}; data_args.fd = (__u32)ctx->args[0]; data_args.buf = (char *)ctx->args[1]; data_args.start_nacs = bpf_ktime_get_ns(); data_args.data_id = generate_socket_data_id(id, data_args.fd, SOCKET_OPTS_TYPE_WRITE, false); bpf_map_update_elem(&socket_data_args, &id, &data_args, 0); return 0; } SEC("tracepoint/syscalls/sys_exit_write") int tracepoint_exit_write(struct syscall_trace_exit *ctx) { __u64 id = bpf_get_current_pid_tgid(); struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id); if (data_args && data_args->is_sock_event) { ssize_t bytes_count = ctx->ret; process_write_data(ctx, id, data_args, bytes_count, SOCK_DATA_DIRECTION_EGRESS, false, SOCKET_OPTS_TYPE_WRITE, false); } bpf_map_delete_elem(&socket_data_args, &id); return 0; } SEC("tracepoint/syscalls/sendto") int tracepoint_enter_sendto(struct syscall_trace_enter *ctx) { uint64_t id = bpf_get_current_pid_tgid(); if (tgid_should_trace(id >> 32) == false) { return 0; } if ((struct sockaddr *)ctx->args[4] != NULL) { struct connect_args_t connect_args = {}; connect_args.addr = (struct sockaddr *)ctx->args[4]; connect_args.fd = (__u32)ctx->args[0]; bpf_map_update_elem(&conecting_args, &id, &connect_args, 0); } struct sock_data_args_t data_args = {}; data_args.fd = (__u32)ctx->args[0]; data_args.buf = (char *)ctx->args[1]; data_args.start_nacs = bpf_ktime_get_ns(); data_args.data_id = generate_socket_data_id(id, data_args.fd, SOCKET_OPTS_TYPE_SENDTO, false); bpf_map_update_elem(&socket_data_args, &id, &data_args, 0); return 0; } SEC("tracepoint/syscalls/sys_exit_sendto") int tracepoint_exit_sendto(struct syscall_trace_exit *ctx) { __u64 id = bpf_get_current_pid_tgid(); ssize_t bytes_count = ctx->ret; // connection struct connect_args_t *connect_args = bpf_map_lookup_elem(&conecting_args, &id); if (connect_args && bytes_count > 0) { submit_connection_when_not_exists(ctx, id, connect_args, SOCKET_OPTS_TYPE_SENDTO, CONNECTION_ROLE_TYPE_CLIENT); } bpf_map_delete_elem(&conecting_args, &id); struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id); if (data_args) { process_write_data(ctx, id, data_args, bytes_count, SOCK_DATA_DIRECTION_EGRESS, false, SOCKET_OPTS_TYPE_SENDTO, false); } bpf_map_delete_elem(&socket_data_args, &id); return 0; } SEC("tracepoint/syscalls/sys_enter_writev") int tracepoint_enter_writev(struct syscall_trace_enter *ctx) { uint64_t id = bpf_get_current_pid_tgid(); if (tgid_should_trace(id >> 32) == false) { return 0; } struct sock_data_args_t data_args = {}; data_args.fd = (__u32)ctx->args[0]; data_args.iovec = (struct iovec *)ctx->args[1]; data_args.iovlen = (size_t)ctx->args[2]; data_args.start_nacs = bpf_ktime_get_ns(); data_args.data_id = generate_socket_data_id(id, data_args.fd, SOCKET_OPTS_TYPE_WRITE, false); bpf_map_update_elem(&socket_data_args, &id, &data_args, 0); return 0; } SEC("tracepoint/syscalls/sys_exit_writev") int tracepoint_exit_writev(struct syscall_trace_exit *ctx) { __u64 id = bpf_get_current_pid_tgid(); struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id); if (data_args && data_args->is_sock_event) { ssize_t bytes_count = ctx->ret; process_write_data(ctx, id, data_args, bytes_count, SOCK_DATA_DIRECTION_EGRESS, true, SOCKET_OPTS_TYPE_WRITEV, false); } bpf_map_delete_elem(&socket_data_args, &id); return 0; } SEC("tracepoint/syscalls/sys_enter_sendmsg") int tracepoint_enter_sendmsg(struct syscall_trace_enter *ctx) { uint64_t id = bpf_get_current_pid_tgid(); if (tgid_should_trace(id >> 32) == false) { return 0; } struct user_msghdr* msghdr = (struct user_msghdr*)ctx->args[1]; if (msghdr == NULL) { return 0; } struct sockaddr* addr = _(msghdr->msg_name); if (addr != NULL) { struct connect_args_t connect_args = {}; connect_args.addr = addr; connect_args.fd = (__u32)ctx->args[0]; connect_args.start_nacs = bpf_ktime_get_ns(); bpf_map_update_elem(&conecting_args, &id, &connect_args, 0); } struct sock_data_args_t data_args = {}; data_args.fd = (__u32)ctx->args[0]; data_args.iovec = _(msghdr->msg_iov); data_args.iovlen = _(msghdr->msg_iovlen); data_args.start_nacs = bpf_ktime_get_ns(); data_args.data_id = generate_socket_data_id(id, data_args.fd, SOCKET_OPTS_TYPE_SENDMSG, false); bpf_map_update_elem(&socket_data_args, &id, &data_args, 0); return 0; } SEC("tracepoint/syscalls/sys_exit_sendmsg") int tracepoint_exit_sendmsg(struct syscall_trace_exit *ctx) { __u64 id = bpf_get_current_pid_tgid(); ssize_t bytes_count = ctx->ret; // connection struct connect_args_t *connect_args = bpf_map_lookup_elem(&conecting_args, &id); if (connect_args && bytes_count > 0) { submit_connection_when_not_exists(ctx, id, connect_args, SOCKET_OPTS_TYPE_SENDMSG, CONNECTION_ROLE_TYPE_CLIENT); } bpf_map_delete_elem(&conecting_args, &id); struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id); if (data_args) { process_write_data(ctx, id, data_args, bytes_count, SOCK_DATA_DIRECTION_EGRESS, true, SOCKET_OPTS_TYPE_SENDMSG, false); } bpf_map_delete_elem(&socket_data_args, &id); return 0; } SEC("tracepoint/syscalls/sys_enter_sendmmsg") int tracepoint_enter_sendmmsg(struct syscall_trace_enter *ctx) { uint64_t id = bpf_get_current_pid_tgid(); if (tgid_should_trace(id >> 32) == false) { return 0; } struct mmsghdr* mmsghdr = (struct mmsghdr*)ctx->args[1]; __u32 vlen = (__u32)ctx->args[2]; if (mmsghdr == NULL || vlen <= 0) { return 0; } struct sockaddr* addr = _(mmsghdr->msg_hdr.msg_name); if (addr != NULL) { struct connect_args_t connect_args = {}; connect_args.addr = addr; connect_args.fd = (__u32)ctx->args[0]; connect_args.start_nacs = bpf_ktime_get_ns(); bpf_map_update_elem(&conecting_args, &id, &connect_args, 0); } struct sock_data_args_t data_args = {}; data_args.fd = (__u32)ctx->args[0]; struct iovec *msg_iov = _(mmsghdr->msg_hdr.msg_iov); data_args.iovec = msg_iov; size_t msg_iovlen = _(mmsghdr->msg_hdr.msg_iovlen); data_args.iovlen = msg_iovlen; data_args.msg_len = (unsigned int*)(&mmsghdr->msg_hdr.msg_iovlen); data_args.start_nacs = bpf_ktime_get_ns(); data_args.data_id = generate_socket_data_id(id, data_args.fd, SOCKET_OPTS_TYPE_SENDMSG, false); bpf_map_update_elem(&socket_data_args, &id, &data_args, 0); return 0; } SEC("tracepoint/syscalls/sys_exit_sendmmsg") int tracepoint_exit_sendmmsg(struct syscall_trace_exit *ctx) { __u64 id = bpf_get_current_pid_tgid(); ssize_t bytes_count = ctx->ret; // connection struct connect_args_t *connect_args = bpf_map_lookup_elem(&conecting_args, &id); if (connect_args && bytes_count > 0) { submit_connection_when_not_exists(ctx, id, connect_args, SOCKET_OPTS_TYPE_SENDMMSG, CONNECTION_ROLE_TYPE_CLIENT); } bpf_map_delete_elem(&conecting_args, &id); struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id); if (data_args) { __u32 bytes_count; BPF_PROBE_READ_VAR(bytes_count, data_args->msg_len); process_write_data(ctx, id, data_args, bytes_count, SOCK_DATA_DIRECTION_EGRESS, true, SOCKET_OPTS_TYPE_SENDMMSG, false); } bpf_map_delete_elem(&socket_data_args, &id); return 0; } SEC("tracepoint/syscalls/sys_enter_read") int tracepoint_enter_read(struct syscall_trace_enter *ctx) { uint64_t id = bpf_get_current_pid_tgid(); if (tgid_should_trace(id >> 32) == false) { return 0; } struct sock_data_args_t data_args = {}; data_args.fd = (__u32)ctx->args[0]; data_args.buf = (char *)ctx->args[1]; data_args.start_nacs = bpf_ktime_get_ns(); data_args.data_id = generate_socket_data_id(id, data_args.fd, SOCKET_OPTS_TYPE_READ, false); bpf_map_update_elem(&socket_data_args, &id, &data_args, 0); return 0; } SEC("tracepoint/syscalls/sys_exit_read") int tracepoint_exit_read(struct syscall_trace_exit *ctx) { __u64 id = bpf_get_current_pid_tgid(); struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id); if (data_args && data_args->is_sock_event) { ssize_t bytes_count = ctx->ret; process_write_data(ctx, id, data_args, bytes_count, SOCK_DATA_DIRECTION_INGRESS, false, SOCKET_OPTS_TYPE_READ, false); } bpf_map_delete_elem(&socket_data_args, &id); return 0; } SEC("tracepoint/syscalls/sys_enter_readv") int tracepoint_enter_readv(struct syscall_trace_enter *ctx) { uint64_t id = bpf_get_current_pid_tgid(); if (tgid_should_trace(id >> 32) == false) { return 0; } struct sock_data_args_t data_args = {}; data_args.fd = (__u32)ctx->args[0]; data_args.iovec = (struct iovec *)ctx->args[1]; data_args.iovlen = (size_t)ctx->args[2]; data_args.start_nacs = bpf_ktime_get_ns(); data_args.data_id = generate_socket_data_id(id, data_args.fd, SOCKET_OPTS_TYPE_READV, false); bpf_map_update_elem(&socket_data_args, &id, &data_args, 0); return 0; } SEC("tracepoint/syscalls/sys_exit_readv") int tracepoint_exit_readv(struct syscall_trace_exit *ctx) { __u64 id = bpf_get_current_pid_tgid(); struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id); if (data_args && data_args->is_sock_event) { ssize_t bytes_count = ctx->ret; process_write_data(ctx, id, data_args, bytes_count, SOCK_DATA_DIRECTION_INGRESS, true, SOCKET_OPTS_TYPE_READV, false); } bpf_map_delete_elem(&socket_data_args, &id); return 0; } SEC("kprobe/recv") int sys_recv(struct pt_regs* ctx) { uint64_t id = bpf_get_current_pid_tgid(); if (tgid_should_trace(id >> 32) == false) { return 0; } char* buf = (void *)SYSCALL_PARM_2(ctx); struct sock_data_args_t data_args = {}; data_args.fd = SYSCALL_PARM_1(ctx); data_args.buf = buf; data_args.start_nacs = bpf_ktime_get_ns(); data_args.data_id = generate_socket_data_id(id, data_args.fd, SOCKET_OPTS_TYPE_RECV, false); bpf_map_update_elem(&socket_data_args, &id, &data_args, 0); return 0; } SEC("kretprobe/recv") int sys_recv_ret(struct pt_regs* ctx) { __u64 id = bpf_get_current_pid_tgid(); struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id); if (data_args) { ssize_t bytes_count = PT_REGS_RC(ctx); process_write_data(ctx, id, data_args, bytes_count, SOCK_DATA_DIRECTION_INGRESS, false, SOCKET_OPTS_TYPE_RECV, false); } bpf_map_delete_elem(&socket_data_args, &id); return 0; } SEC("tracepoint/syscalls/sys_enter_recvfrom") int tracepoint_enter_recvfrom(struct syscall_trace_enter *ctx) { uint64_t id = bpf_get_current_pid_tgid(); if (tgid_should_trace(id >> 32) == false) { return 0; } if ((struct sockaddr *)ctx->args[4] != NULL) { struct connect_args_t connect_args = {}; connect_args.addr = (struct sockaddr *)ctx->args[4]; connect_args.fd = (__u32)ctx->args[0]; bpf_map_update_elem(&conecting_args, &id, &connect_args, 0); } struct sock_data_args_t data_args = {}; data_args.fd = (__u32)ctx->args[0]; data_args.buf = (char *)ctx->args[1]; data_args.start_nacs = bpf_ktime_get_ns(); data_args.data_id = generate_socket_data_id(id, data_args.fd, SOCKET_OPTS_TYPE_RECVFROM, false); bpf_map_update_elem(&socket_data_args, &id, &data_args, 0); return 0; } SEC("tracepoint/syscalls/sys_exit_recvfrom") int tracepoint_exit_recvfrom(struct syscall_trace_exit *ctx) { __u64 id = bpf_get_current_pid_tgid(); ssize_t bytes_count = ctx->ret; // connection struct connect_args_t *connect_args = bpf_map_lookup_elem(&conecting_args, &id); if (connect_args && bytes_count > 0) { submit_connection_when_not_exists(ctx, id, connect_args, SOCKET_OPTS_TYPE_RECVFROM, CONNECTION_ROLE_TYPE_SERVER); } bpf_map_delete_elem(&conecting_args, &id); struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id); if (data_args) { process_write_data(ctx, id, data_args, bytes_count, SOCK_DATA_DIRECTION_INGRESS, false, SOCKET_OPTS_TYPE_RECVFROM, false); } bpf_map_delete_elem(&socket_data_args, &id); return 0; } SEC("tracepoint/syscalls/sys_enter_recvmsg") int tracepoint_enter_recvmsg(struct syscall_trace_enter *ctx) { uint64_t id = bpf_get_current_pid_tgid(); if (tgid_should_trace(id >> 32) == false) { return 0; } struct user_msghdr* msghdr = (struct user_msghdr*)ctx->args[1]; if (msghdr == NULL) { return 0; } struct sockaddr* addr = _(msghdr->msg_name); if (addr != NULL) { struct connect_args_t connect_args = {}; connect_args.addr = addr; connect_args.fd = (__u32)ctx->args[0]; connect_args.start_nacs = bpf_ktime_get_ns(); bpf_map_update_elem(&conecting_args, &id, &connect_args, 0); } struct sock_data_args_t data_args = {}; data_args.fd = (__u32)ctx->args[0]; data_args.iovec = _(msghdr->msg_iov); data_args.iovlen = _(msghdr->msg_iovlen); data_args.start_nacs = bpf_ktime_get_ns(); data_args.data_id = generate_socket_data_id(id, data_args.fd, SOCKET_OPTS_TYPE_RECVMSG, false); bpf_map_update_elem(&socket_data_args, &id, &data_args, 0); return 0; } SEC("tracepoint/syscalls/sys_exit_recvmsg") int tracepoint_exit_recvmsg(struct syscall_trace_exit *ctx) { __u64 id = bpf_get_current_pid_tgid(); ssize_t bytes_count = ctx->ret; // connection struct connect_args_t *connect_args = bpf_map_lookup_elem(&conecting_args, &id); if (connect_args && bytes_count > 0) { submit_connection_when_not_exists(ctx, id, connect_args, SOCKET_OPTS_TYPE_RECVMSG, CONNECTION_ROLE_TYPE_SERVER); } bpf_map_delete_elem(&conecting_args, &id); struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id); if (data_args) { process_write_data(ctx, id, data_args, bytes_count, SOCK_DATA_DIRECTION_INGRESS, true, SOCKET_OPTS_TYPE_RECVMSG, false); } bpf_map_delete_elem(&socket_data_args, &id); return 0; } SEC("tracepoint/syscalls/sys_enter_recvmmsg") int tracepoint_enter_recvmmsg(struct syscall_trace_enter *ctx) { uint64_t id = bpf_get_current_pid_tgid(); if (tgid_should_trace(id >> 32) == false) { return 0; } struct mmsghdr* mmsghdr = (struct mmsghdr*)ctx->args[1]; __u32 vlen = (__u32)ctx->args[2]; if (mmsghdr == NULL || vlen <= 0) { return 0; } struct sockaddr* addr = _(mmsghdr->msg_hdr.msg_name); if (addr != NULL) { struct connect_args_t connect_args = {}; connect_args.addr = addr; connect_args.fd = (__u32)ctx->args[0]; connect_args.start_nacs = bpf_ktime_get_ns(); bpf_map_update_elem(&conecting_args, &id, &connect_args, 0); } struct sock_data_args_t data_args = {}; data_args.fd = (__u32)ctx->args[0]; struct iovec *msg_iov = _(mmsghdr->msg_hdr.msg_iov); data_args.iovec = msg_iov; size_t msg_iovlen = _(mmsghdr->msg_hdr.msg_iovlen); data_args.iovlen = msg_iovlen; data_args.msg_len = (unsigned int*)(&mmsghdr->msg_hdr.msg_iovlen); data_args.start_nacs = bpf_ktime_get_ns(); data_args.data_id = generate_socket_data_id(id, data_args.fd, SOCKET_OPTS_TYPE_RECVMMSG, false); bpf_map_update_elem(&socket_data_args, &id, &data_args, 0); return 0; } SEC("tracepoint/syscalls/sys_exit_recvmmsg") int tracepoint_exit_recvmmsg(struct syscall_trace_exit *ctx) { __u64 id = bpf_get_current_pid_tgid(); ssize_t bytes_count = ctx->ret; // connection struct connect_args_t *connect_args = bpf_map_lookup_elem(&conecting_args, &id); if (connect_args && bytes_count > 0) { submit_connection_when_not_exists(ctx, id, connect_args, SOCKET_OPTS_TYPE_RECVMMSG, CONNECTION_ROLE_TYPE_SERVER); } bpf_map_delete_elem(&conecting_args, &id); struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id); if (data_args) { __u32 bytes_count; BPF_PROBE_READ_VAR(bytes_count, data_args->msg_len); process_write_data(ctx, id, data_args, bytes_count, SOCK_DATA_DIRECTION_INGRESS, true, SOCKET_OPTS_TYPE_RECVMMSG, false); } bpf_map_delete_elem(&socket_data_args, &id); return 0; } SEC("tracepoint/skb/skb_copy_datagram_iovec") int tracepoint_skb_copy_datagram_iovec(struct trace_event_raw_skb_copy_datagram_iovec* ctx) { __u64 id = bpf_get_current_pid_tgid(); struct sk_buff *buff = (struct sk_buff *)ctx->skbaddr; struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id); if (data_args == NULL) { bpf_map_delete_elem(&sk_buff_receive_detail_map, &buff); return 0; } struct sock *sock = _(buff->sk); if (sock != NULL) { data_args->sk_role = get_sock_role(data_args->sk_role, sock); } data_args->package_count++; data_args->total_package_size += _(buff->len); struct skb_receive_detail *detail = bpf_map_lookup_elem(&sk_buff_receive_detail_map, &buff); if (detail == NULL) { return 0; } bpf_map_delete_elem(&sk_buff_receive_detail_map, &buff); // l4 data_args->enter_l4_time = detail->enter_tcp_rcv_time; data_args->exit_l4_time = detail->exit_tcp_rcv_time; // l3 if (detail->exit_ip_rcv_time > 0 && detail->enter_ip_rcv_time > 0) { data_args->l3_duration += detail->exit_ip_rcv_time - detail->enter_ip_rcv_time; } if (detail->ip_rcv_finish_time > 0 && detail->enter_ip_rcv_time > 0) { data_args->l3_rcv_duration += detail->ip_rcv_finish_time - detail->enter_ip_rcv_time; } if (detail->ip_local_finish_time > 0 && detail->ip_local_time > 0) { data_args->l3_local_duration += detail->ip_local_finish_time - detail->ip_local_time; } data_args->total_net_filter_count += detail->total_nf_count; data_args->total_net_filter_time += detail->total_nf_time; // l2 data_args->ifindex = detail->ifindex; if (detail->netif_receive_time > 0 && detail->ip_local_time > 0) { data_args->total_package_to_queue_time += detail->ip_local_time - detail->netif_receive_time; } if (detail->ip_local_time > 0) { data_args->total_package_receive_from_queue_time += bpf_ktime_get_ns() - detail->ip_local_time; } return 0; } SEC("kprobe/security_socket_sendmsg") int security_socket_sendmsg(struct pt_regs* ctx) { __u64 id = bpf_get_current_pid_tgid(); struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id); if (data_args != NULL) { data_args->is_sock_event = true; } return 0; } SEC("kprobe/security_socket_recvmsg") int security_socket_recvmsg(struct pt_regs* ctx) { __u64 id = bpf_get_current_pid_tgid(); struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id); if (data_args != NULL) { data_args->is_sock_event = true; } return 0; }