GPL/HostIsolation/KprobeConnectHook/KprobeConnectHook.bpf.c (47 lines of code) (raw):
// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
/*
* Copyright (C) 2021 Elasticsearch BV
*
* This software is dual-licensed under the BSD 2-Clause and GPL v2 licenses.
* You may choose either one of them if you use this software.
*/
// Host Isolation - this eBPF program hooks into tcp_v4_connect kprobe and adds
// entries to the IP allowlist if an allowed process tries to initiate a
// connection.
// flag needed to pick the right PT_REGS macros in bpf_tracing.h
#define __KERNEL__
#include "Kerneldefs.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
// taken from libbpf uapi include dir
#include <linux/bpf.h>
// not to be defined in production builds
//#define DEBUG_TRACE_PRINTK
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(key_size, sizeof(u32));
__uint(value_size, sizeof(u32));
__uint(max_entries, 512);
} allowed_IPs SEC(".maps");
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(key_size, sizeof(u32));
__uint(value_size, sizeof(u32));
__uint(max_entries, 128);
} allowed_pids SEC(".maps");
static __always_inline void add_IP_to_allowlist(__u32 daddr)
{
// add new entry
u32 val = 1;
long rv = bpf_map_update_elem(&allowed_IPs, &daddr, &val, BPF_ANY);
#ifdef DEBUG_TRACE_PRINTK
if (rv) {
bpf_printk("Error updating hashmap\n");
}
#endif
}
static __always_inline int enter_tcp_connect(struct sockaddr *uaddr)
{
__u64 pid_tgid = bpf_get_current_pid_tgid();
__u32 tgid = pid_tgid >> 32;
__u32 *elem = NULL;
__u32 daddr = 0;
struct sockaddr_in *sin = (struct sockaddr_in *)uaddr;
bpf_probe_read(&daddr, sizeof(daddr), &sin->sin_addr.s_addr);
// check if tgid (userspace PID) is allowed
elem = bpf_map_lookup_elem(&allowed_pids, &tgid);
if (elem) {
// tgid (userspace PID) is allowed, add destination IP to IP allowlist
add_IP_to_allowlist(daddr);
}
return 0;
}
// IMPORTANT:
// BPF_KPROBE uses PT_REGS_PARM2 macro underneath to get the arg
// define ARCH env var so that it gets the argument from the right register
SEC("kprobe/tcp_v4_connect")
int BPF_KPROBE(tcp_v4_connect, void *sk, struct sockaddr *uaddr)
{
return enter_tcp_connect(uaddr);
}
char LICENSE[] SEC("license") = "Dual BSD/GPL";