Merge "bpf netd: block local network calls if permission is not allowed." into main
diff --git a/bpf/progs/netd.c b/bpf/progs/netd.c
index 4ff68da..aab9c26 100644
--- a/bpf/progs/netd.c
+++ b/bpf/progs/netd.c
@@ -104,6 +104,12 @@
                    BPFLOADER_MAINLINE_25Q2_VERSION, BPFLOADER_MAX_VER, LOAD_ON_ENG, LOAD_ON_USER,
                    LOAD_ON_USERDEBUG, 0)
 
+// not preallocated
+DEFINE_BPF_MAP_EXT(local_net_blocked_uid_map, HASH, uint32_t, bool, -1000,
+                   AID_ROOT, AID_NET_BW_ACCT, 0060, "fs_bpf_net_shared", "", PRIVATE,
+                   BPFLOADER_MAINLINE_25Q2_VERSION, BPFLOADER_MAX_VER, LOAD_ON_ENG, LOAD_ON_USER,
+                   LOAD_ON_USERDEBUG, 0)
+
 // iptables xt_bpf programs need to be usable by both netd and netutils_wrappers
 // selinux contexts, because even non-xt_bpf iptables mutations are implemented as
 // a full table dump, followed by an update in userspace, and then a reload into the kernel,
@@ -250,10 +256,15 @@
     return v ? *v : true;
 }
 
-static __always_inline inline
-bool should_block_local_network_packets(struct __sk_buff *skb,
-                                        const struct egress_bool egress,
-                                        const struct kver_uint kver) {
+static __always_inline inline bool should_block_local_network_packets(struct __sk_buff *skb,
+                                   const uint32_t uid, const struct egress_bool egress,
+                                   const struct kver_uint kver) {
+    if (is_system_uid(uid)) return false;
+
+    bool* block_local_net = bpf_local_net_blocked_uid_map_lookup_elem(&uid);
+    if (!block_local_net) return false; // uid not found in map
+    if (!*block_local_net) return false; // lookup returned 'bool false'
+
     struct in6_addr remote_ip6;
     uint8_t ip_proto;
     uint8_t L4_off;
@@ -548,7 +559,7 @@
     }
 
     if (SDK_LEVEL_IS_AT_LEAST(lvl, 25Q2) && (match != DROP)) {
-        if (should_block_local_network_packets(skb, egress, kver)) match = DROP;
+        if (should_block_local_network_packets(skb, uid, egress, kver)) match = DROP;
     }
 
     // If an outbound packet is going to be dropped, we do not count that traffic.
diff --git a/bpf/progs/netd.h b/bpf/progs/netd.h
index 6561311..8400679 100644
--- a/bpf/progs/netd.h
+++ b/bpf/progs/netd.h
@@ -186,6 +186,7 @@
 #define PACKET_TRACE_ENABLED_MAP_PATH BPF_NETD_PATH "map_netd_packet_trace_enabled_map"
 #define DATA_SAVER_ENABLED_MAP_PATH BPF_NETD_PATH "map_netd_data_saver_enabled_map"
 #define LOCAL_NET_ACCESS_MAP_PATH BPF_NETD_PATH "map_netd_local_net_access_map"
+#define LOCAL_NET_BLOCKED_UID_MAP_PATH BPF_NETD_PATH "map_netd_local_net_blocked_uid_map"
 
 #endif // __cplusplus
 
diff --git a/bpf/tests/mts/bpf_existence_test.cpp b/bpf/tests/mts/bpf_existence_test.cpp
index d605379..2cfa546 100644
--- a/bpf/tests/mts/bpf_existence_test.cpp
+++ b/bpf/tests/mts/bpf_existence_test.cpp
@@ -169,6 +169,7 @@
 // Provided by *current* mainline module for 25Q2+ devices
 static const set<string> MAINLINE_FOR_25Q2_PLUS = {
     NETD "map_netd_local_net_access_map",
+    NETD "map_netd_local_net_blocked_uid_map",
 };
 
 static void addAll(set<string>& a, const set<string>& b) {