diff --git a/progs/include/bpf_helpers.h b/progs/include/bpf_helpers.h new file mode 100644 index 0000000..9fca3cd --- /dev/null +++ b/progs/include/bpf_helpers.h @@ -0,0 +1,49 @@ +/* Common BPF helpers to be used by all BPF programs loaded by Android */ + +#include +#include +#include + +/* place things in different elf sections */ +#define SEC(NAME) __attribute__((section(NAME), used)) + +/* + * Helper functions called from eBPF programs written in C. These are + * implemented in the kernel sources. + */ +/* generic functions */ +static void* (*bpf_map_lookup_elem)(void* map, void* key) = (void*) BPF_FUNC_map_lookup_elem; +static int (*bpf_map_update_elem)(void* map, void* key, void* value, + unsigned long long flags) = (void*) BPF_FUNC_map_update_elem; +static int (*bpf_map_delete_elem)(void* map, void* key) = (void*) BPF_FUNC_map_delete_elem; +static int (*bpf_probe_read)(void* dst, int size, void* unsafe_ptr) = (void*) BPF_FUNC_probe_read; +static unsigned long long (*bpf_ktime_get_ns)(void) = (void*) BPF_FUNC_ktime_get_ns; +static int (*bpf_trace_printk)(const char* fmt, int fmt_size, ...) = (void*) BPF_FUNC_trace_printk; +static unsigned long long (*bpf_get_current_pid_tgid)(void) = (void*) BPF_FUNC_get_current_pid_tgid; +static unsigned long long (*bpf_get_current_uid_gid)(void) = (void*) BPF_FUNC_get_current_uid_gid; +static unsigned long long (*bpf_get_smp_processor_id)(void) = (void*) BPF_FUNC_get_smp_processor_id; +/* networking */ +static uint64_t (*bpf_get_socket_cookie)(struct __sk_buff* skb) = (void*)BPF_FUNC_get_socket_cookie; +static uint32_t (*bpf_get_socket_uid)(struct __sk_buff* skb) = (void*)BPF_FUNC_get_socket_uid; +static int (*bpf_skb_load_bytes)(struct __sk_buff* skb, int off, void* to, + int len) = (void*)BPF_FUNC_skb_load_bytes; + +/* + * Map structure to be used by Android eBPF C programs. The Android eBPF loader + * uses this structure from eBPF object to create maps at boot time. + * + * The eBPF C program should define structure in the maps section using + * SEC("maps") otherwise it will be ignored by the eBPF loader. + * + * For example: + * struct bpf_map_def SEC("maps") mymap { .type=... , .key_size=... } + */ +struct bpf_map_def { + unsigned int type; + unsigned int key_size; + unsigned int value_size; + unsigned int max_entries; + unsigned int map_flags; + unsigned int pad1; + unsigned int pad2; +}; diff --git a/progs/netd.c b/progs/netd.c index 73e7d28..1d47c73 100644 --- a/progs/netd.c +++ b/progs/netd.c @@ -43,17 +43,17 @@ int xt_bpf_ingress_prog(struct __sk_buff* skb) { SEC("skfilter/whitelist/xtbpf") int xt_bpf_whitelist_prog(struct __sk_buff* skb) { - uint32_t sock_uid = get_socket_uid(skb); + uint32_t sock_uid = bpf_get_socket_uid(skb); if (is_system_uid(sock_uid)) return BPF_MATCH; - uint8_t* whitelistMatch = find_map_entry(&uid_owner_map, &sock_uid); + uint8_t* whitelistMatch = bpf_map_lookup_elem(&uid_owner_map, &sock_uid); if (whitelistMatch) return *whitelistMatch & HAPPY_BOX_MATCH; return BPF_NOMATCH; } SEC("skfilter/blacklist/xtbpf") int xt_bpf_blacklist_prog(struct __sk_buff* skb) { - uint32_t sock_uid = get_socket_uid(skb); - uint8_t* blacklistMatch = find_map_entry(&uid_owner_map, &sock_uid); + uint32_t sock_uid = bpf_get_socket_uid(skb); + uint8_t* blacklistMatch = bpf_map_lookup_elem(&uid_owner_map, &sock_uid); if (blacklistMatch) return *blacklistMatch & PENALTY_BOX_MATCH; return BPF_NOMATCH; } @@ -75,7 +75,7 @@ int inet_socket_create(struct bpf_sock* sk) { * run time. See UserHandle#isSameApp for detail. */ uint32_t appId = (gid_uid & 0xffffffff) % PER_USER_RANGE; - uint8_t* internetPermission = find_map_entry(&uid_permission_map, &appId); + uint8_t* internetPermission = bpf_map_lookup_elem(&uid_permission_map, &appId); if (internetPermission) return *internetPermission & ALLOW_SOCK_CREATE; return NO_PERMISSION; } diff --git a/progs/netd.h b/progs/netd.h index 4b8ea8a..fcf3a72 100644 --- a/progs/netd.h +++ b/progs/netd.h @@ -19,6 +19,7 @@ * program. */ +#include #include #include #include @@ -30,8 +31,6 @@ #include #include "netdbpf/bpf_shared.h" -#define SEC(NAME) __attribute__((section(NAME), used)) - struct uid_tag { uint32_t uid; uint32_t tag; @@ -55,17 +54,6 @@ struct IfaceValue { char name[IFNAMSIZ]; }; -/* helper functions called from eBPF programs written in C */ -static void* (*find_map_entry)(void* map, void* key) = (void*)BPF_FUNC_map_lookup_elem; -static int (*write_to_map_entry)(void* map, void* key, void* value, - uint64_t flags) = (void*)BPF_FUNC_map_update_elem; -static int (*delete_map_entry)(void* map, void* key) = (void*)BPF_FUNC_map_delete_elem; -static uint64_t (*get_socket_cookie)(struct __sk_buff* skb) = (void*)BPF_FUNC_get_socket_cookie; -static uint32_t (*get_socket_uid)(struct __sk_buff* skb) = (void*)BPF_FUNC_get_socket_uid; -static int (*bpf_skb_load_bytes)(struct __sk_buff* skb, int off, void* to, - int len) = (void*)BPF_FUNC_skb_load_bytes; -static uint64_t (*bpf_get_current_uid_gid)(void) = (void*)BPF_FUNC_get_current_uid_gid; - // This is defined for cgroup bpf filter only. #define BPF_PASS 1 #define BPF_DROP 0 @@ -83,16 +71,6 @@ static uint64_t (*bpf_get_current_uid_gid)(void) = (void*)BPF_FUNC_get_current_u #define TCP_FLAG_OFF 13 #define RST_OFFSET 2 -/* loader usage */ -struct bpf_map_def { - unsigned int type; - unsigned int key_size; - unsigned int value_size; - unsigned int max_entries; - unsigned int map_flags; - unsigned int pad[2]; -}; - struct bpf_map_def SEC("maps") cookie_tag_map = { .type = BPF_MAP_TYPE_HASH, .key_size = sizeof(uint64_t), @@ -163,11 +141,11 @@ static __always_inline int is_system_uid(uint32_t uid) { static __always_inline inline void bpf_update_stats(struct __sk_buff* skb, struct bpf_map_def* map, int direction, void* key) { struct stats_value* value; - value = find_map_entry(map, key); + value = bpf_map_lookup_elem(map, key); if (!value) { struct stats_value newValue = {}; - write_to_map_entry(map, key, &newValue, BPF_NOEXIST); - value = find_map_entry(map, key); + bpf_map_update_elem(map, key, &newValue, BPF_NOEXIST); + value = bpf_map_lookup_elem(map, key); } if (value) { if (direction == BPF_EGRESS) { @@ -221,7 +199,7 @@ static inline bool skip_owner_match(struct __sk_buff* skb) { static __always_inline BpfConfig getConfig(uint32_t configKey) { uint32_t mapSettingKey = configKey; - BpfConfig* config = find_map_entry(&configuration_map, &mapSettingKey); + BpfConfig* config = bpf_map_lookup_elem(&configuration_map, &mapSettingKey); if (!config) { // Couldn't read configuration entry. Assume everything is disabled. return DEFAULT_CONFIG; @@ -239,7 +217,7 @@ static inline int bpf_owner_match(struct __sk_buff* skb, uint32_t uid) { return BPF_PASS; } - uint8_t* uidEntry = find_map_entry(&uid_owner_map, &uid); + uint8_t* uidEntry = bpf_map_lookup_elem(&uid_owner_map, &uid); uint8_t uidRules = uidEntry ? *uidEntry : 0; if ((enabledRules & DOZABLE_MATCH) && !(uidRules & DOZABLE_MATCH)) { return BPF_DROP; @@ -263,7 +241,7 @@ static __always_inline inline void update_stats_with_config(struct __sk_buff* sk } static __always_inline inline int bpf_traffic_account(struct __sk_buff* skb, int direction) { - uint32_t sock_uid = get_socket_uid(skb); + uint32_t sock_uid = bpf_get_socket_uid(skb); int match = bpf_owner_match(skb, sock_uid); if ((direction == BPF_EGRESS) && (match == BPF_DROP)) { // If an outbound packet is going to be dropped, we do not count that @@ -271,8 +249,8 @@ static __always_inline inline int bpf_traffic_account(struct __sk_buff* skb, int return match; } - uint64_t cookie = get_socket_cookie(skb); - struct uid_tag* utag = find_map_entry(&cookie_tag_map, &cookie); + uint64_t cookie = bpf_get_socket_cookie(skb); + struct uid_tag* utag = bpf_map_lookup_elem(&cookie_tag_map, &cookie); uint32_t uid, tag; if (utag) { uid = utag->uid; @@ -284,11 +262,11 @@ static __always_inline inline int bpf_traffic_account(struct __sk_buff* skb, int struct stats_key key = {.uid = uid, .tag = tag, .counterSet = 0, .ifaceIndex = skb->ifindex}; - uint8_t* counterSet = find_map_entry(&uid_counterset_map, &uid); + uint8_t* counterSet = bpf_map_lookup_elem(&uid_counterset_map, &uid); if (counterSet) key.counterSet = (uint32_t)*counterSet; uint32_t mapSettingKey = CURRENT_STATS_MAP_CONFIGURATION_KEY; - uint8_t* selectedMap = find_map_entry(&configuration_map, &mapSettingKey); + uint8_t* selectedMap = bpf_map_lookup_elem(&configuration_map, &mapSettingKey); if (!selectedMap) { return match; }