Merge "Add detailed kernel version when checking bpf support"
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 <linux/bpf.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+/* 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 @@
 
 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 @@
      * 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 <bpf_helpers.h>
 #include <linux/bpf.h>
 #include <linux/if.h>
 #include <linux/if_ether.h>
@@ -30,8 +31,6 @@
 #include <stdint.h>
 #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 @@
     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 @@
 #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 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 __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 @@
         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 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 @@
         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 @@
 
     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;
     }