Add a resolver option to enforce AID_DNS on query

The default behavior is that plaintext DNS queries are sent by the
application's UID using fchown(). DoT are sent with an UID of AID_DNS
This option control the plaintext uid of DNS query.

Bug: 154910763
Test: atest
Change-Id: Iada5d850d8bb9d7b0ad46f5c28a1fff22c7d11a6
diff --git a/tests/resolv_integration_test.cpp b/tests/resolv_integration_test.cpp
index fddb96e..2777885 100644
--- a/tests/resolv_integration_test.cpp
+++ b/tests/resolv_integration_test.cpp
@@ -4051,6 +4051,71 @@
     ExpectDnsEvent(INetdEventListener::EVENT_RES_NSEND, EAI_SYSTEM, "howdy.example.com", {});
 }
 
+TEST_F(ResolverTest, EnforceDnsUid) {
+    SKIP_IF_BPF_NOT_SUPPORTED;
+
+    constexpr char listen_addr1[] = "127.0.0.4";
+    constexpr char listen_addr2[] = "::1";
+    constexpr char host_name[] = "howdy.example.com.";
+    const std::vector<DnsRecord> records = {
+            {host_name, ns_type::ns_t_a, "1.2.3.4"},
+            {host_name, ns_type::ns_t_aaaa, "::1.2.3.4"},
+    };
+    INetd* netdService = mDnsClient.netdService();
+
+    test::DNSResponder dns1(listen_addr1);
+    test::DNSResponder dns2(listen_addr2);
+    StartDns(dns1, records);
+    StartDns(dns2, records);
+
+    // switch uid of DNS queries from applications to AID_DNS
+    ResolverParamsParcel parcel = DnsResponderClient::GetDefaultResolverParamsParcel();
+    parcel.servers = {listen_addr1, listen_addr2};
+    ASSERT_TRUE(mDnsClient.resolvService()->setResolverConfiguration(parcel).isOk());
+
+    uint8_t buf[MAXPACKET] = {};
+    int rcode;
+    {
+        ScopeBlockedUIDRule scopeBlockUidRule(netdService, TEST_UID);
+        // Dns Queries should be blocked
+        int fd1 = resNetworkQuery(TEST_NETID, host_name, ns_c_in, ns_t_a, 0);
+        int fd2 = resNetworkQuery(TEST_NETID, host_name, ns_c_in, ns_t_aaaa, 0);
+        EXPECT_TRUE(fd1 != -1);
+        EXPECT_TRUE(fd2 != -1);
+
+        int res = getAsyncResponse(fd2, &rcode, buf, MAXPACKET);
+        EXPECT_EQ(-ECONNREFUSED, res);
+
+        memset(buf, 0, MAXPACKET);
+        res = getAsyncResponse(fd1, &rcode, buf, MAXPACKET);
+        EXPECT_EQ(-ECONNREFUSED, res);
+    }
+
+    parcel.resolverOptions.enforceDnsUid = true;
+    ASSERT_TRUE(mDnsClient.resolvService()->setResolverConfiguration(parcel).isOk());
+    {
+        ScopeBlockedUIDRule scopeBlockUidRule(netdService, TEST_UID);
+        // Dns Queries should NOT be blocked
+        int fd1 = resNetworkQuery(TEST_NETID, host_name, ns_c_in, ns_t_a, 0);
+        int fd2 = resNetworkQuery(TEST_NETID, host_name, ns_c_in, ns_t_aaaa, 0);
+        EXPECT_TRUE(fd1 != -1);
+        EXPECT_TRUE(fd2 != -1);
+
+        int res = getAsyncResponse(fd2, &rcode, buf, MAXPACKET);
+        EXPECT_EQ("::1.2.3.4", toString(buf, res, AF_INET6));
+
+        memset(buf, 0, MAXPACKET);
+        res = getAsyncResponse(fd1, &rcode, buf, MAXPACKET);
+        EXPECT_EQ("1.2.3.4", toString(buf, res, AF_INET));
+
+        // @TODO: So far we know that uid of DNS queries are no more set to DNS requester. But we
+        // don't check if they are actually being set to AID_DNS, because system uids are always
+        // allowed in bpf_owner_match(). Audit by firewallSetUidRule(AID_DNS) + sending queries is
+        // infeasible. Fix it if the behavior of bpf_owner_match() is changed in the future, or if
+        // we have better idea to deal with this.
+    }
+}
+
 namespace {
 
 const std::string kDotConnectTimeoutMsFlag(