Merge 91bd9db65b819e58dbf14eef67b8729b419ebc8d on remote branch
Change-Id: I5206f3fceb5227127c8af87a765f5e2becd4fdd1
diff --git a/bpf_progs/clatd.c b/bpf_progs/clatd.c
index 102ecd9..e758692 100644
--- a/bpf_progs/clatd.c
+++ b/bpf_progs/clatd.c
@@ -26,6 +26,10 @@
#include <stdbool.h>
#include <stdint.h>
+// bionic kernel uapi linux/udp.h header is munged...
+#define __kernel_udphdr udphdr
+#include <linux/udp.h>
+
#include "bpf_helpers.h"
#include "bpf_net_helpers.h"
#include "netdbpf/bpf_shared.h"
@@ -226,9 +230,18 @@
switch (ip4->protocol) {
case IPPROTO_TCP: // For TCP & UDP the checksum neutrality of the chosen IPv6
- case IPPROTO_UDP: // address means there is no need to update their checksums.
- case IPPROTO_GRE: // We do not need to bother looking at GRE/ESP headers,
- case IPPROTO_ESP: // since there is never a checksum to update.
+ case IPPROTO_GRE: // address means there is no need to update their checksums.
+ case IPPROTO_ESP: // We do not need to bother looking at GRE/ESP headers,
+ break; // since there is never a checksum to update.
+
+ case IPPROTO_UDP: // See above comment, but must also have UDP header...
+ if (data + sizeof(*ip4) + sizeof(struct udphdr) > data_end) return TC_ACT_OK;
+ const struct udphdr* uh = (const struct udphdr*)(ip4 + 1);
+ // If IPv4/UDP checksum is 0 then fallback to clatd so it can calculate the
+ // checksum. Otherwise the network or more likely the NAT64 gateway might
+ // drop the packet because in most cases IPv6/UDP packets with a zero checksum
+ // are invalid. See RFC 6935. TODO: calculate checksum via bpf_csum_diff()
+ if (!uh->check) return TC_ACT_OK;
break;
default: // do not know how to handle anything else
diff --git a/bpf_progs/netd.c b/bpf_progs/netd.c
index 70e0ae7..f347028 100644
--- a/bpf_progs/netd.c
+++ b/bpf_progs/netd.c
@@ -30,6 +30,7 @@
#include "netdbpf/bpf_shared.h"
// This is defined for cgroup bpf filter only.
+#define BPF_DROP_UNLESS_DNS 2
#define BPF_PASS 1
#define BPF_DROP 0
@@ -206,7 +207,7 @@
if (direction == BPF_INGRESS && (uidRules & IIF_MATCH)) {
// Drops packets not coming from lo nor the whitelisted interface
if (allowed_iif && skb->ifindex != 1 && skb->ifindex != allowed_iif) {
- return BPF_DROP;
+ return BPF_DROP_UNLESS_DNS;
}
}
return BPF_PASS;
@@ -247,6 +248,17 @@
tag = 0;
}
+// Workaround for secureVPN with VpnIsolation enabled, refer to b/159994981 for details.
+// Keep TAG_SYSTEM_DNS in sync with DnsResolver/include/netd_resolv/resolv.h
+// and TrafficStatsConstants.java
+#define TAG_SYSTEM_DNS 0xFFFFFF82
+ if (tag == TAG_SYSTEM_DNS && uid == AID_DNS) {
+ uid = sock_uid;
+ if (match == BPF_DROP_UNLESS_DNS) match = BPF_PASS;
+ } else {
+ if (match == BPF_DROP_UNLESS_DNS) match = BPF_DROP;
+ }
+
StatsKey key = {.uid = uid, .tag = tag, .counterSet = 0, .ifaceIndex = skb->ifindex};
uint8_t* counterSet = bpf_uid_counterset_map_lookup_elem(&uid);
diff --git a/server/main.cpp b/server/main.cpp
index 0a86b0a..4949ff6 100644
--- a/server/main.cpp
+++ b/server/main.cpp
@@ -83,6 +83,8 @@
}
int tagSocketCallback(int sockFd, uint32_t tag, uid_t uid, pid_t) {
+ // Workaround for secureVPN with VpnIsolation enabled, refer to b/159994981 for details.
+ if (tag == TAG_SYSTEM_DNS) uid = AID_DNS;
return gCtls->trafficCtrl.tagSocket(sockFd, tag, uid, geteuid());
}