bpf netd: block local network calls if permission is not allowed.
Adding map local_net_blocked_uid_map, which will store uid for
the applications that have opted in but do not have the required
permission. The entry would be absent or the value would be false if the
application is allowed to access local network.
Test: Manually populating the values and checking EPERM error.
Bug: 390168818
Change-Id: Idf6caff204295a3f0aa7f552ea4af50bfd2df78c
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.