Skip to content

Commit 8ab9499

Browse files
committed
feat(ebpf): make socket_dup don't rely on sys_enter/exit
Assumes handling of compat syscalls is handled by get_task_pt_reg()
1 parent ce3f1bb commit 8ab9499

File tree

4 files changed

+199
-167
lines changed

4 files changed

+199
-167
lines changed

pkg/ebpf/c/tracee.bpf.c

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -487,21 +487,19 @@ statfunc int send_socket_dup(program_data_t *p, u64 oldfd, u64 newfd)
487487
if (f == NULL)
488488
return -1;
489489

490-
// this is a socket - submit the SOCKET_DUP event
491-
492-
save_to_submit_buf(&(p->event->args_buf), &oldfd, sizeof(u32), 0);
493-
save_to_submit_buf(&(p->event->args_buf), &newfd, sizeof(u32), 1);
494-
495490
// get the address
496491
struct socket *socket_from_file = (struct socket *) BPF_CORE_READ(f, private_data);
497492
if (socket_from_file == NULL)
498493
return -1;
499494

500495
struct sock *sk = get_socket_sock(socket_from_file);
501496
u16 family = get_sock_family(sk);
502-
if ((family != AF_INET) && (family != AF_INET6) && (family != AF_UNIX))
497+
if ((family != AF_INET) && (family != AF_INET6))
503498
return 0;
504499

500+
save_to_submit_buf(&(p->event->args_buf), &oldfd, sizeof(u32), 0);
501+
save_to_submit_buf(&(p->event->args_buf), &newfd, sizeof(u32), 1);
502+
505503
if (family == AF_INET) {
506504
net_conn_v4_t net_details = {};
507505
struct sockaddr_in remote;
@@ -520,51 +518,56 @@ statfunc int send_socket_dup(program_data_t *p, u64 oldfd, u64 newfd)
520518

521519
save_to_submit_buf(
522520
&(p->event->args_buf), &remote, bpf_core_type_size(struct sockaddr_in6), 2);
523-
} else if (family == AF_UNIX) {
524-
struct unix_sock *unix_sk = (struct unix_sock *) sk;
525-
struct sockaddr_un sockaddr = get_unix_sock_addr(unix_sk);
526-
527-
save_to_submit_buf(
528-
&(p->event->args_buf), &sockaddr, bpf_core_type_size(struct sockaddr_un), 2);
529521
}
530522

531523
return events_perf_submit(p, 0);
532524
}
533525

534-
SEC("raw_tracepoint/sys_dup")
535-
int sys_dup_exit_tail(void *ctx)
526+
statfunc int do_socket_dup(struct pt_regs *ctx, struct pt_regs *task_ctx, int ret_val)
536527
{
537528
program_data_t p = {};
538-
if (!init_tailcall_program_data(&p, ctx))
539-
return 0;
540-
541-
syscall_data_t *sys = &p.task_info->syscall_data;
542-
543-
if (sys->ret < 0) {
544-
// dup failed
545-
return 0;
546-
}
547-
548-
if (!reset_event(p.event, SOCKET_DUP))
529+
if (!init_program_data(&p, ctx, SOCKET_DUP))
549530
return 0;
550531

551532
if (!evaluate_scope_filters(&p))
552533
return 0;
553534

554-
if (sys->id == SYSCALL_DUP) {
555-
// args.args[0]: oldfd
556-
// retval: newfd
557-
send_socket_dup(&p, sys->args.args[0], sys->ret);
558-
} else if (sys->id == SYSCALL_DUP2 || sys->id == SYSCALL_DUP3) {
559-
// args.args[0]: oldfd
560-
// args.args[1]: newfd
561-
// retval: retval
562-
send_socket_dup(&p, sys->args.args[0], sys->args.args[1]);
535+
int syscall_id = p.event->context.syscall;
536+
int old_fd = PT_REGS_PARM1_CORE(task_ctx);
537+
538+
if (syscall_id == SYSCALL_DUP) {
539+
int new_fd = ret_val;
540+
if (new_fd < 0)
541+
return 1;
542+
send_socket_dup(&p, old_fd, new_fd);
543+
} else if (likely(syscall_id == SYSCALL_DUP2 || syscall_id == SYSCALL_DUP3)) {
544+
send_socket_dup(&p, old_fd, PT_REGS_PARM2_CORE(task_ctx));
563545
}
564546

565547
return 0;
566548
}
567549

550+
SEC("kretprobe/trace_dup_ret")
551+
int BPF_KPROBE(trace_dup_ret)
552+
{
553+
struct pt_regs *task_context = get_task_pt_regs(
554+
(struct task_struct *) bpf_get_current_task()); // since this is a kretprobe, fetch the
555+
// syscall args via the pt_regs of the task
556+
return do_socket_dup(
557+
ctx,
558+
task_context,
559+
PT_REGS_RC(ctx)); // use the return value received via the kretprobe context
560+
}
561+
562+
SEC("kprobe/trace_dup_2_3")
563+
int BPF_KPROBE(trace_dup_2_3, unsigned int oldfd, unsigned int newfd)
564+
{
565+
struct pt_regs *task_context = get_task_pt_regs(
566+
(struct task_struct *)
567+
bpf_get_current_task()); // use this helper to avoid the unwrapping of struct pt_regs
568+
return do_socket_dup(ctx, task_context, 0);
569+
}
570+
568571
// trace/events/sched.h: TP_PROTO(struct task_struct *parent, struct task_struct *child)
569572
SEC("raw_tracepoint/sched_process_fork")
570573
int tracepoint__sched__sched_process_fork(struct bpf_raw_tracepoint_args *ctx)

0 commit comments

Comments
 (0)