Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add UDP probes in anticipation of DNS monitoring #206

Merged
merged 49 commits into from
Sep 23, 2024
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
d243908
add upd send/recv msg probes
fearful-symmetry Aug 30, 2024
52bbe58
format
fearful-symmetry Aug 30, 2024
21af8bb
first pass at DNS packet fetching
fearful-symmetry Sep 6, 2024
fbf1608
use skb functions
fearful-symmetry Sep 6, 2024
608b1a5
Revert "use skb functions"
fearful-symmetry Sep 9, 2024
b8c6559
try to make recvmsg portable
fearful-symmetry Sep 9, 2024
58bb331
only use kprobes for udp methods, pray this works
fearful-symmetry Sep 9, 2024
5527d13
verifier logic has changed?
fearful-symmetry Sep 9, 2024
d76c6df
Merge remote-tracking branch 'origin/main' into udp-connect-probes
fearful-symmetry Sep 10, 2024
06d8327
testing skb methods
fearful-symmetry Sep 10, 2024
5aa36cd
clean up skb code
fearful-symmetry Sep 10, 2024
049b2c1
format
fearful-symmetry Sep 10, 2024
d8c7e25
still testing
fearful-symmetry Sep 10, 2024
40fa09a
typo
fearful-symmetry Sep 10, 2024
5477112
still cleaning up test code
fearful-symmetry Sep 10, 2024
d2770ff
cleanup
fearful-symmetry Sep 10, 2024
17a5e4d
rename enums
fearful-symmetry Sep 11, 2024
c3a53b3
format
fearful-symmetry Sep 11, 2024
5ce5121
cleanup, use proper skbuff offsets
fearful-symmetry Sep 11, 2024
067fe9e
use varlen for packet body
fearful-symmetry Sep 11, 2024
30bc829
use json for output
fearful-symmetry Sep 11, 2024
ed64454
further cleanup
fearful-symmetry Sep 11, 2024
6baa2a1
cleanup
fearful-symmetry Sep 12, 2024
2a263af
skip peeked calls in kprobe
fearful-symmetry Sep 12, 2024
251154e
change DNS max packet size
fearful-symmetry Sep 12, 2024
e59b322
add counter for headlen==0 events
fearful-symmetry Sep 16, 2024
520c8d4
cleanup, error handling
fearful-symmetry Sep 17, 2024
7ea1643
add new counter for sk_buff failures
fearful-symmetry Sep 17, 2024
72b356c
format..
fearful-symmetry Sep 17, 2024
43f126a
update name
fearful-symmetry Sep 17, 2024
55f89af
update docs, var name
fearful-symmetry Sep 17, 2024
49e1ea1
tiny rewording
haesbaert Sep 17, 2024
274ac5a
add tests, clean up json
fearful-symmetry Sep 18, 2024
7542b84
Merge remote-tracking branch 'origin/udp-connect-probes' into udp-con…
fearful-symmetry Sep 18, 2024
28231f2
use host command
fearful-symmetry Sep 18, 2024
c25ae02
use path..
fearful-symmetry Sep 18, 2024
00bd9d9
use arg array
fearful-symmetry Sep 18, 2024
5b494d1
use bash for test
fearful-symmetry Sep 18, 2024
88f021e
use bash for test
fearful-symmetry Sep 18, 2024
318f491
use sh
fearful-symmetry Sep 18, 2024
1f55596
test with a special binary...
fearful-symmetry Sep 18, 2024
d149867
format
fearful-symmetry Sep 18, 2024
b74eec9
clean up
fearful-symmetry Sep 18, 2024
fbe2a42
format...
fearful-symmetry Sep 18, 2024
08648ca
set correct read len for outgoing packets
fearful-symmetry Sep 18, 2024
5c027da
revert changes to utils
fearful-symmetry Sep 18, 2024
d38841f
use better udp send
fearful-symmetry Sep 19, 2024
802fa43
format
fearful-symmetry Sep 19, 2024
e827ae9
clean up
fearful-symmetry Sep 19, 2024
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
44 changes: 44 additions & 0 deletions GPL/Events/EbpfEventProto.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#define EBPF_EVENTPROBE_EBPFEVENTPROTO_H

#define TASK_COMM_LEN 16
#define MAX_DNS_PACKET 512
#define MAX_NR_SEGS 8
fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved

#ifndef __KERNEL__
#include <stdint.h>
Expand Down Expand Up @@ -40,6 +42,9 @@ 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_UDP_SEND = (1 << 20),
EBPF_EVENT_NETWORK_UDP_RECV = (1 << 21),
EBPF_EVENT_NETWORK_DNS_PKT = (1 << 22),
fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved
nicholasberlin marked this conversation as resolved.
Show resolved Hide resolved
};

struct ebpf_event_header {
Expand Down Expand Up @@ -341,6 +346,7 @@ struct ebpf_process_load_module_event {

enum ebpf_net_info_transport {
EBPF_NETWORK_EVENT_TRANSPORT_TCP = 1,
EBPF_NETWORK_EVENT_TRANSPORT_UDP = 2,
};

enum ebpf_net_info_af {
Expand Down Expand Up @@ -379,6 +385,44 @@ struct ebpf_net_event {
char comm[TASK_COMM_LEN];
} __attribute__((packed));

struct dns_pkt_header {
uint16_t transaction_id;
uint16_t flags;
uint16_t num_questions;
uint16_t num_answers;
uint16_t num_auth_rrs;
uint16_t num_additional_rrs;
} __attribute__((packed));
fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved

struct dns_body {
fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved
size_t len;
uint8_t pkt[MAX_DNS_PACKET];
} __attribute((packed));

// from vmlinux.h, modified to make the ip addrs u8 arrays
struct skb_iphdr {
uint8_t ihl : 4;
uint8_t version : 4;
uint8_t tos;
uint16_t tot_len;
uint16_t id;
uint16_t frag_off;
uint8_t ttl;
uint8_t protocol;
uint16_t check;
uint8_t saddr[4];
uint8_t daddr[4];
};
fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved

struct ebpf_dns_event {
struct ebpf_event_header hdr;
struct ebpf_pid_info pids;
struct ebpf_net_info net;
char comm[TASK_COMM_LEN];
enum ebpf_event_type udp_evt;
struct dns_body pkts[MAX_NR_SEGS];
fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved
} __attribute__((packed));

// Basic event statistics
struct ebpf_event_stats {
uint64_t lost; // lost events due to a full ringbuffer
Expand Down
22 changes: 22 additions & 0 deletions GPL/Events/Helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ const volatile int consumer_pid = 0;
// From include/uapi/asm-generic/termbits.h
#define ECHO 0x00008

/* tty_write */
DECL_FIELD_OFFSET(iov_iter, __iov);

static bool IS_ERR_OR_NULL(const void *ptr)
{
return (!ptr) || (unsigned long)ptr >= (unsigned long)-MAX_ERRNO;
Expand Down Expand Up @@ -357,4 +360,23 @@ static int is_equal_prefix(const char *str1, const char *str2, int len)
return !strncmp(str1, str2, len);
}

static int get_iovec_nr_segs_or_max(struct iov_iter *from)
{
u64 nr_segs = BPF_CORE_READ(from, nr_segs);
nr_segs = nr_segs > MAX_NR_SEGS ? MAX_NR_SEGS : nr_segs;
return nr_segs;
}
fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved

struct udp_ctx {
struct sk_buff *skb;
} __attribute__((packed));

// scratchspace map for fetching the arguments from a kretprobe
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, u64);
__type(value, struct udp_ctx);
__uint(max_entries, 1024);
} pkt_ctx SEC(".maps");

fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved
#endif // EBPF_EVENTPROBE_HELPERS_H
11 changes: 11 additions & 0 deletions GPL/Events/Network/Network.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@
#define AF_INET 2
#define AF_INET6 10

#define MSG_PEEK 2
fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved
fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved

// See RFC1035
#define DNS_QR_BIT 1 << 15
fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved

// I have made this number up to make the verifier happy
#define DNS_MAX_LABELS 255
fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved

static int ebpf_sock_info__fill(struct ebpf_net_info *net, struct sock *sk)
{
int err = 0;
Expand Down Expand Up @@ -67,6 +75,9 @@ static int ebpf_sock_info__fill(struct ebpf_net_info *net, struct sock *sk)
case IPPROTO_TCP:
net->transport = EBPF_NETWORK_EVENT_TRANSPORT_TCP;
break;
case IPPROTO_UDP:
net->transport = EBPF_NETWORK_EVENT_TRANSPORT_UDP;
fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved
break;
default:
err = -1;
goto out;
Expand Down
165 changes: 161 additions & 4 deletions GPL/Events/Network/Probe.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

DECL_FUNC_RET(inet_csk_accept);

static int inet_csk_accept__exit(struct sock *sk)
static int sock_object_handle(struct sock *sk, enum ebpf_event_type evt_type)
{
fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved
if (!sk)
goto out;
Expand All @@ -36,24 +36,181 @@ static int inet_csk_accept__exit(struct sock *sk)
goto out;
}

event->hdr.type = EBPF_EVENT_NETWORK_CONNECTION_ACCEPTED;
event->hdr.type = evt_type;
bpf_ringbuf_submit(event, 0);

out:
return 0;
}

/*
=============================== DNS probes ===============================
*/
fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved

static int handle_consume(struct sk_buff *skb, int len, enum ebpf_event_type evt_type)
{

if (ebpf_events_is_trusted_pid())
return 0;
fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved

struct ebpf_dns_event *event = bpf_ringbuf_reserve(&ringbuf, sizeof(*event), 0);
if (!event)
return 0;
fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved
fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved

// read from skbuf
unsigned char *data = BPF_CORE_READ(skb, head);
// get lengths
fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved
u16 net_header_offset = BPF_CORE_READ(skb, network_header);
u16 transport_header_offset = BPF_CORE_READ(skb, transport_header);

u8 iphdr_first_byte = 0;
bpf_core_read(&iphdr_first_byte, 1, data + net_header_offset);
iphdr_first_byte = iphdr_first_byte >> 4;

u8 proto = 0;
if (iphdr_first_byte == 4) {
struct iphdr ip_hdr;
bpf_core_read(&ip_hdr, sizeof(struct iphdr), data + net_header_offset);
fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved

proto = ip_hdr.protocol;
bpf_probe_read(event->net.saddr, 4, (void *)&ip_hdr.saddr);
bpf_probe_read(event->net.daddr, 4, (void *)&ip_hdr.daddr);

fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved
} else if (iphdr_first_byte == 6) {
struct ipv6hdr ip6_hdr;
bpf_core_read(&ip6_hdr, sizeof(struct ipv6hdr), data + net_header_offset);
proto = ip6_hdr.nexthdr;

bpf_probe_read(event->net.saddr6, 16, ip6_hdr.saddr.in6_u.u6_addr8);
bpf_probe_read(event->net.daddr6, 16, ip6_hdr.daddr.in6_u.u6_addr8);
fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved
}

if (proto != IPPROTO_UDP) {
goto out;
}

struct udphdr udp_hdr;
bpf_core_read(&udp_hdr, sizeof(struct udphdr), data + transport_header_offset);
event->net.dport = bpf_ntohs(udp_hdr.dest);
event->net.sport = bpf_ntohs(udp_hdr.source);

struct task_struct *task = (struct task_struct *)bpf_get_current_task();
ebpf_pid_info__fill(&event->pids, task);
bpf_get_current_comm(event->comm, TASK_COMM_LEN);
event->hdr.ts = bpf_ktime_get_ns();

// filter out non-dns packets
if (event->net.sport != 53 && event->net.dport != 53) {
bpf_printk("not a dns packet...");
fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved
goto out;
}

// constrain the read size to make the verifier happy
long readsize = BPF_CORE_READ(skb, len);
if (readsize > MAX_DNS_PACKET) {
fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved
readsize = MAX_DNS_PACKET;
}

// udp_send_skb includes the IP and UDP header, so offset
long offset = transport_header_offset + sizeof(struct udphdr);
fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved

long ret = bpf_probe_read_kernel(event->pkts[0].pkt, readsize, data + offset);
fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved
if (ret != 0) {
bpf_printk("error reading in data buffer: %d", ret);
goto out;
}

fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved
event->hdr.type = EBPF_EVENT_NETWORK_DNS_PKT;
event->udp_evt = evt_type;
bpf_ringbuf_submit(event, 0);

fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved
return 0;

fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved
out:
bpf_ringbuf_discard(event, 0);
return 0;
}

SEC("fentry/ip_send_skb")
int BPF_PROG(fentry__ip_send_skb, struct net *net, struct sk_buff *skb)
{
return handle_consume(skb, skb->len, EBPF_EVENT_NETWORK_UDP_SEND);
}

SEC("fexit/skb_consume_udp")
int BPF_PROG(fexit__skb_consume_udp, struct sock *sk, struct sk_buff *skb, int len)
fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved
{
// skip peek operations
bpf_printk("consume len: %d", len);
if (len < 0) {
return 0;
}
return handle_consume(skb, len, EBPF_EVENT_NETWORK_UDP_RECV);
}

SEC("kprobe/ip_send_skb")
int BPF_KPROBE(kprobe__ip_send_udp, struct net *net, struct sk_buff *skb)
{
long len = BPF_CORE_READ(skb, len);
return handle_consume(skb, len, EBPF_EVENT_NETWORK_UDP_SEND);
fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved
}

SEC("kprobe/skb_consume_udp")
int BPF_KPROBE(kprobe__skb_consume_udp, struct net *net, struct sk_buff *skb)
nicholasberlin marked this conversation as resolved.
Show resolved Hide resolved
{
// return handle_consume(skb, len, EBPF_EVENT_NETWORK_UDP_SENDMSG);
struct udp_ctx kctx;

// I suspect that using the PID_TID isn't the most reliable way to map the sockets/iters
// not sure what else we could use that's accessable from the kretprobe, though.
u64 pid_tid = bpf_get_current_pid_tgid();

long iter_err = bpf_probe_read(&kctx.skb, sizeof(kctx.skb), &skb);
if (iter_err != 0) {
bpf_printk("error reading skb in skb_consume_skb: %d", iter_err);
return 0;
}

long update_err = bpf_map_update_elem(&pkt_ctx, &pid_tid, &kctx, BPF_ANY);
if (update_err != 0) {
bpf_printk("error updating context map in udp_recvmsg: %d", update_err);
return 0;
}

return 0;
fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved
}

SEC("kretprobe/skb_consume_udp")
int BPF_KRETPROBE(kretprobe__skb_consume_udp, int ret)
{
u64 pid_tid = bpf_get_current_pid_tgid();
fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved
void *vctx = bpf_map_lookup_elem(&pkt_ctx, &pid_tid);

struct udp_ctx kctx;
long read_err = bpf_probe_read(&kctx, sizeof(kctx), vctx);
if (read_err != 0) {
bpf_printk("error reading back context in skb_consume_skb: %d", read_err);
return 0;
}

return handle_consume(kctx.skb, ret, EBPF_EVENT_NETWORK_UDP_RECV);
}

/*
=============================== TCP probes ===============================
*/

SEC("fexit/inet_csk_accept")
int BPF_PROG(fexit__inet_csk_accept)
{
struct sock *ret = FUNC_RET_READ(___type(ret), inet_csk_accept);
return inet_csk_accept__exit(ret);
return sock_object_handle(ret, EBPF_EVENT_NETWORK_CONNECTION_ACCEPTED);
}

SEC("kretprobe/inet_csk_accept")
int BPF_KRETPROBE(kretprobe__inet_csk_accept, struct sock *ret)
{
return inet_csk_accept__exit(ret);
return sock_object_handle(ret, EBPF_EVENT_NETWORK_CONNECTION_ACCEPTED);
}

static int tcp_connect(struct sock *sk, int ret)
Expand Down
8 changes: 1 addition & 7 deletions GPL/Events/Process/Probe.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@
#include "State.h"
#include "Varlen.h"

/* tty_write */
DECL_FIELD_OFFSET(iov_iter, __iov);

// Limits on large things we send up as variable length parameters.
//
// These should be kept _well_ under half the size of the event_buffer_map or
Expand Down Expand Up @@ -526,8 +523,6 @@ int BPF_KPROBE(kprobe__commit_creds, struct cred *new)
return commit_creds__enter(new);
}

#define MAX_NR_SEGS 8

static int output_tty_event(struct ebpf_tty_dev *slave, const void *base, size_t base_len)
{
struct ebpf_process_tty_write_event *event;
Expand Down Expand Up @@ -611,8 +606,7 @@ static int tty_write__enter(struct kiocb *iocb, struct iov_iter *from)
else
goto out;

u64 nr_segs = BPF_CORE_READ(from, nr_segs);
nr_segs = nr_segs > MAX_NR_SEGS ? MAX_NR_SEGS : nr_segs;
u64 nr_segs = get_iovec_nr_segs_or_max(from);

fearful-symmetry marked this conversation as resolved.
Show resolved Hide resolved
if (nr_segs == 0) {
u64 count = BPF_CORE_READ(from, count);
Expand Down
Loading
Loading