Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 2 additions & 23 deletions GPL/Events/EbpfEventProto.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@
#define EBPF_EVENTPROBE_EBPFEVENTPROTO_H

#define TASK_COMM_LEN 16
// The theoretical max size of DNS packets over UDP is 512.
// Like so many things in DNS this number probaby isn't 100% accurate.
// DNS extensions in RFC2671 and RFC6891 mean the actual size can be larger.
#define MAX_DNS_PACKET 4096

#ifndef __KERNEL__
#include <stdint.h>
Expand Down Expand Up @@ -44,7 +40,6 @@ enum ebpf_event_type {
EBPF_EVENT_PROCESS_SHMGET = (1 << 17),
EBPF_EVENT_PROCESS_PTRACE = (1 << 18),
EBPF_EVENT_PROCESS_LOAD_MODULE = (1 << 19),
EBPF_EVENT_NETWORK_DNS_PKT = (1 << 20),
};

struct ebpf_event_header {
Expand Down Expand Up @@ -72,7 +67,6 @@ enum ebpf_varlen_field_type {
EBPF_VL_FIELD_SYMLINK_TARGET_PATH,
EBPF_VL_FIELD_MOD_VERSION,
EBPF_VL_FIELD_MOD_SRCVERSION,
EBPF_VL_FIELD_DNS_BODY,
};

// Convenience macro to iterate all the variable length fields in an event
Expand Down Expand Up @@ -374,11 +368,6 @@ enum ebpf_net_udp_info {
EBPF_NETWORK_EVENT_IP_SEND_UDP = 2,
};

enum ebpf_net_packet_direction {
EBPF_NETWORK_DIR_EGRESS = 1,
EBPF_NETWORK_DIR_INGRESS = 2,
};

struct ebpf_net_info_tcp_close {
uint64_t bytes_sent;
uint64_t bytes_received;
Expand Down Expand Up @@ -410,20 +399,10 @@ struct ebpf_net_event {
char comm[TASK_COMM_LEN];
} __attribute__((packed));

struct ebpf_dns_event {
struct ebpf_event_header hdr;
uint32_t tgid;
uint32_t cap_len;
uint32_t orig_len;
enum ebpf_net_packet_direction direction;
struct ebpf_varlen_fields_start vl_fields;
} __attribute__((packed));

// Basic event statistics
struct ebpf_event_stats {
uint64_t lost; // lost events due to a full ringbuffer
uint64_t sent; // events sent through the ringbuffer
uint64_t dns_zero_body; // indicates that the dns body of a sk_buff was unavailable
uint64_t lost; // lost events due to a full ringbuffer
uint64_t sent; // events sent through the ringbuffer
};

#endif // EBPF_EVENTPROBE_EBPFEVENTPROTO_H
226 changes: 0 additions & 226 deletions GPL/Events/Network/Probe.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,229 +197,3 @@ int BPF_KPROBE(kprobe__tcp_close, struct sock *sk, long timeout)
{
return tcp_close__enter(sk);
}

#ifdef notyet
/*
* XXX naive, only handles ROUTING and DEST, untested, ipv6 needs more work to
* be enabled.
*/
int skb_peel_nexthdr(struct __sk_buff *skb, u8 wanted)
{
struct ipv6hdr ip6;
int off;
u16 next;

off = 0;
if (bpf_skb_load_bytes(skb, off, &ip6, sizeof(ip6)))
return (-1);
off += sizeof(ip6);
next = ip6.nexthdr;

for (;;) {
if (next == wanted)
return (off);
switch (next) {
case NEXTHDR_ROUTING: /* FALLTHROUGH */
case NEXTHDR_DEST:
if (bpf_skb_load_bytes(skb, off, &next, sizeof(next)))
return (-1);
off += ((next >> 8) + 1) * 8;
next = next & 0xff;
continue;
default:
return (-1);
}
}

return (-1); /* NOTREACHED */
}
#endif

int skb_in_or_egress(struct __sk_buff *skb, int ingress)
{
struct udphdr udp;
struct bpf_sock *sk;
u32 *tgid, cap_len, zero = 0;
u64 *sk_addr;
struct ebpf_dns_event *event;
struct ebpf_varlen_field *field;

if (skb->family != AF_INET && skb->family != AF_INET6)
goto ignore;
if ((sk = skb->sk) == NULL)
goto ignore;
if ((sk = bpf_sk_fullsock(sk)) == NULL)
goto ignore;
if (sk->protocol != IPPROTO_UDP)
goto ignore;

if (sk->family == AF_INET) {
struct iphdr ip;

if (bpf_skb_load_bytes(skb, 0, &ip, sizeof(ip)))
goto ignore;
if (ip.protocol != IPPROTO_UDP)
goto ignore;
if (bpf_skb_load_bytes(skb, ip.ihl << 2, &udp, sizeof(udp)))
goto ignore;
} else {
goto ignore;
}
#ifdef notyet /* ipv6 needs further work */
else if (sk->family == AF_INET6)
{
int t_off;

t_off = skb_peel_nexthdr(skb, NEXTHDR_UDP);
if (t_off == -1)
goto ignore;

if (bpf_skb_load_bytes(skb, t_off, &udp, sizeof(udp)))
goto ignore;
}
#endif

if (bpf_ntohs(udp.dest) != 53 && bpf_ntohs(udp.source) != 53)
goto ignore;

/*
* Needed for kernels prior to f79efcb0075a20633cbf9b47759f2c0d538f78d8
* bpf: Permits pointers on stack for helper calls
*/
sk_addr = bpf_map_lookup_elem(&scratch64, &zero);
if (sk_addr == NULL)
goto ignore;
*sk_addr = (u64)sk;
tgid = bpf_map_lookup_elem(&sk_to_tgid, sk_addr);
if (tgid == NULL)
goto ignore;

cap_len = skb->len;
/*
* verifier will complain, even with a skb->len
* check at the beginning.
*/
if (cap_len > MAX_DNS_PACKET)
cap_len = MAX_DNS_PACKET;

/*
* Yes this code is weird, but it convinces old verifiers (5.10), don't
* blame me, be sure to test 5.10 if you change it. The minimal packet
* should be iphlen + udphlen + 12(dns header size). Old verifiers
* (5.10) are very sensitive here and a non constant right expression
* (since iphlen is not constant due to options) fails. Do what we can
* and filter the remaining bad packets in userland, same applies to
* ipv6. Also be careful with `if cap_len > 0`, as clang will compile it
* to a JNZ, which doesn't adjust umin, causing the
* bpf_skb_load_bytes() down below to think cap_len can be zero.
*/
if (cap_len >= (sizeof(struct iphdr) + sizeof(udp) + 12)) {
event = get_event_buffer();
if (event == NULL)
goto ignore;

event->hdr.type = EBPF_EVENT_NETWORK_DNS_PKT;
event->hdr.ts = bpf_ktime_get_ns();
event->hdr.ts_boot = bpf_ktime_get_boot_ns_helper();
event->tgid = *tgid;
event->cap_len = cap_len;
event->orig_len = skb->len;
event->direction = ingress ? EBPF_NETWORK_DIR_INGRESS : EBPF_NETWORK_DIR_EGRESS;

ebpf_vl_fields__init(&event->vl_fields);
field = ebpf_vl_field__add(&event->vl_fields, EBPF_VL_FIELD_DNS_BODY);
if (bpf_skb_load_bytes(skb, 0, field->data, cap_len))
goto ignore;
ebpf_vl_field__set_size(&event->vl_fields, field, cap_len);

ebpf_ringbuf_write(&ringbuf, event, EVENT_SIZE(event), 0);
}

ignore:
return (1);
}

SEC("cgroup_skb/egress")
int skb_egress(struct __sk_buff *skb)
{
return skb_in_or_egress(skb, 0);
}

SEC("cgroup_skb/ingress")
int skb_ingress(struct __sk_buff *skb)
{
return skb_in_or_egress(skb, 1);
}

int sk_maybe_save_tgid(struct bpf_sock *sk)
{
u32 tgid, zero = 0;
u64 *sk_addr;

if (sk->protocol != IPPROTO_UDP)
return (1);

tgid = bpf_get_current_pid_tgid() >> 32;

/*
* Needed for kernels prior to f79efcb0075a20633cbf9b47759f2c0d538f78d8
* bpf: Permits pointers on stack for helper calls
*/
sk_addr = bpf_map_lookup_elem(&scratch64, &zero);
if (sk_addr == NULL)
return (1);
*sk_addr = (u64)sk;
bpf_map_update_elem(&sk_to_tgid, sk_addr, &tgid, BPF_ANY);

return (1);
}

/*
* We save tgid again in send/recv/connect as the file descriptor might have
* been passed to another process.
*/
SEC("cgroup/sendmsg4")
int sendmsg4(struct bpf_sock_addr *sa)
{
return sk_maybe_save_tgid(sa->sk);
}

SEC("cgroup/recvmsg4")
int recvmsg4(struct bpf_sock_addr *sa)
{
return sk_maybe_save_tgid(sa->sk);
}

SEC("cgroup/connect4")
int connect4(struct bpf_sock_addr *sa)
{
return sk_maybe_save_tgid(sa->sk);
}

SEC("cgroup/sock_create")
int sock_create(struct bpf_sock *sk)
{
return sk_maybe_save_tgid(sk);
}

SEC("cgroup/sock_release")
int sock_release(struct bpf_sock *sk)
{
u32 zero = 0;
u64 *sk_addr;

if (sk->protocol != IPPROTO_UDP)
return (1);

/*
* Needed for kernels prior to f79efcb0075a20633cbf9b47759f2c0d538f78d8
* bpf: Permits pointers on stack for helper calls
*/
sk_addr = bpf_map_lookup_elem(&scratch64, &zero);
if (sk_addr == NULL)
return (1);
*sk_addr = (u64)sk;
bpf_map_delete_elem(&sk_to_tgid, sk_addr);

return (1);
}
8 changes: 0 additions & 8 deletions GPL/Events/State.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,6 @@ static long ebpf_events_scratch_space__set(enum ebpf_events_state_op op,
return bpf_map_update_elem(&elastic_ebpf_events_scratch_space, &key, ss, BPF_ANY);
}

/* Scratch 64bits as an array, as bpf_get_current_pid_tgid is not always available */
struct {
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
__type(key, u32);
__type(value, u64);
__uint(max_entries, 1);
} scratch64 SEC(".maps");

/* Trusted Apps - list of trusted pids */
struct {
__uint(type, BPF_MAP_TYPE_HASH);
Expand Down
44 changes: 0 additions & 44 deletions non-GPL/Events/EventsTrace/EventsTrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ enum cmdline_opts {
NETWORK_CONNECTION_ATTEMPTED,
NETWORK_CONNECTION_ACCEPTED,
NETWORK_CONNECTION_CLOSED,
NETWORK_DNS_PKT,
CMDLINE_MAX
};

Expand All @@ -90,7 +89,6 @@ static uint64_t cmdline_to_lib[CMDLINE_MAX] = {
x(NETWORK_CONNECTION_ATTEMPTED)
x(NETWORK_CONNECTION_ACCEPTED)
x(NETWORK_CONNECTION_CLOSED)
x(NETWORK_DNS_PKT)
#undef x
// clang-format on
};
Expand All @@ -116,7 +114,6 @@ static const struct argp_option opts[] = {
{"process-load-module", PROCESS_LOAD_MODULE, NULL, false, "Print kernel module load events", 0},
{"net-conn-accept", NETWORK_CONNECTION_ACCEPTED, NULL, false,
"Print network connection accepted events", 0},
{"net-conn-dns-pkt", NETWORK_DNS_PKT, NULL, false, "Print DNS events", 0},
{"net-conn-attempt", NETWORK_CONNECTION_ATTEMPTED, NULL, false,
"Print network connection attempted events", 0},
{"net-conn-closed", NETWORK_CONNECTION_CLOSED, NULL, false,
Expand Down Expand Up @@ -176,7 +173,6 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
case NETWORK_CONNECTION_ACCEPTED:
case NETWORK_CONNECTION_ATTEMPTED:
case NETWORK_CONNECTION_CLOSED:
case NETWORK_DNS_PKT:
g_events_env |= cmdline_to_lib[key];
break;
case ARGP_KEY_ARG:
Expand Down Expand Up @@ -1084,43 +1080,6 @@ static void out_network_connection_accepted_event(struct ebpf_net_event *evt)
out_network_event("NETWORK_CONNECTION_ACCEPTED", evt);
}

static void out_network_dns_event(struct ebpf_dns_event *event)
{
out_object_start();
out_event_type("DNS_PKT");
out_comma();

out_int("tgid", event->tgid);
out_comma();

out_int("cap_len", event->cap_len);
out_comma();

out_int("orig_len", event->orig_len);
out_comma();

out_string("direction", event->direction == EBPF_NETWORK_DIR_INGRESS ? "in" : "out");
out_comma();

printf("\"data\":");
out_array_start();
struct ebpf_varlen_field *field;
FOR_EACH_VARLEN_FIELD(event->vl_fields, field)
{
for (size_t i = 0; i < field->size; i++) {
uint8_t part = field->data[i];
printf("%d", part);
if (i < field->size - 1) {
printf(", ");
}
}
}
out_array_end();

out_object_end();
out_newline();
}

static void out_network_connection_attempted_event(struct ebpf_net_event *evt)
{
out_network_event("NETWORK_CONNECTION_ATTEMPTED", evt);
Expand Down Expand Up @@ -1200,9 +1159,6 @@ static int event_ctx_callback(struct ebpf_event_header *evt_hdr)
case EBPF_EVENT_NETWORK_CONNECTION_CLOSED:
out_network_connection_closed_event((struct ebpf_net_event *)evt_hdr);
break;
case EBPF_EVENT_NETWORK_DNS_PKT:
out_network_dns_event((struct ebpf_dns_event *)evt_hdr);
break;
}

return 0;
Expand Down
Loading