Merge "Tag with TAG_SYSTEM_DNS for dns packets."
am: c6c4f15de8

Change-Id: Iaae0bbe0bca3963bdf5259247c1c29ee83054335
diff --git a/Android.bp b/Android.bp
index e098bc3..6d566d6 100644
--- a/Android.bp
+++ b/Android.bp
@@ -207,10 +207,14 @@
         "libcrypto",
         "libcutils",
         "libssl",
+        "libbinder_ndk",
     ],
     static_libs: [
         "dnsresolver_aidl_interface-V2-cpp",
+        "dnsresolver_aidl_interface-V2-ndk_platform",
+        "netd_event_listener_interface-V1-ndk_platform",
         "libgmock",
+        "liblog",
         "libnetd_resolv",
         "libnetd_test_dnsresponder",
         "libnetd_test_resolv_utils",
diff --git a/DnsResolver.cpp b/DnsResolver.cpp
index 092ff3f..70ecc7e 100644
--- a/DnsResolver.cpp
+++ b/DnsResolver.cpp
@@ -30,7 +30,15 @@
     LOG(INFO) << __func__ << ": Initializing resolver";
     resolv_set_log_severity(android::base::WARNING);
 
-    android::net::gResNetdCallbacks = *callbacks;
+    using android::net::gApiLevel;
+    gApiLevel = android::base::GetUintProperty<uint64_t>("ro.build.version.sdk", 0);
+    using android::net::gResNetdCallbacks;
+    gResNetdCallbacks.check_calling_permission = callbacks->check_calling_permission;
+    gResNetdCallbacks.get_network_context = callbacks->get_network_context;
+    gResNetdCallbacks.log = callbacks->log;
+    if (gApiLevel >= 30) {
+        gResNetdCallbacks.tagSocket = callbacks->tagSocket;
+    }
     android::net::gDnsResolv = android::net::DnsResolver::getInstance();
     return android::net::gDnsResolv->start();
 }
@@ -41,8 +49,14 @@
 namespace {
 
 bool verifyCallbacks() {
-    return gResNetdCallbacks.check_calling_permission && gResNetdCallbacks.get_network_context &&
-           gResNetdCallbacks.log;
+    if (!(gResNetdCallbacks.check_calling_permission && gResNetdCallbacks.get_network_context &&
+          gResNetdCallbacks.log)) {
+        return false;
+    }
+    if (gApiLevel >= 30) {
+        return gResNetdCallbacks.tagSocket != nullptr;
+    }
+    return true;
 }
 
 }  // namespace
@@ -50,6 +64,7 @@
 DnsResolver* gDnsResolv = nullptr;
 ResolverNetdCallbacks gResNetdCallbacks;
 netdutils::Log gDnsResolverLog("dnsResolver");
+uint64_t gApiLevel = 0;
 
 DnsResolver* DnsResolver::getInstance() {
     // Instantiated on first use.
diff --git a/DnsResolver.h b/DnsResolver.h
index 6d8d2ce..2efa341 100644
--- a/DnsResolver.h
+++ b/DnsResolver.h
@@ -44,6 +44,7 @@
 extern DnsResolver* gDnsResolv;
 extern ResolverNetdCallbacks gResNetdCallbacks;
 extern netdutils::Log gDnsResolverLog;
+extern uint64_t gApiLevel;
 
 }  // namespace net
 }  // namespace android
diff --git a/DnsTlsSocket.cpp b/DnsTlsSocket.cpp
index 838886a..14aadd4 100644
--- a/DnsTlsSocket.cpp
+++ b/DnsTlsSocket.cpp
@@ -39,6 +39,7 @@
 #include <netdutils/ThreadUtil.h>
 
 #include "private/android_filesystem_config.h"  // AID_DNS
+#include "resolv_private.h"
 
 // NOTE: Inject CA certificate for internal testing -- do NOT enable in production builds
 #ifndef RESOLV_INJECT_CA_CERTIFICATE
@@ -96,9 +97,7 @@
         return Status(errno);
     }
 
-    if (fchown(mSslFd.get(), AID_DNS, -1) == -1) {
-        LOG(WARNING) << "Failed to chown socket: %s" << strerror(errno);
-    }
+    resolv_tag_socket(mSslFd.get(), AID_DNS);
 
     const socklen_t len = sizeof(mMark);
     if (setsockopt(mSslFd.get(), SOL_SOCKET, SO_MARK, &mMark, len) == -1) {
diff --git a/include/netd_resolv/resolv.h b/include/netd_resolv/resolv.h
index 400d56d..17cf2aa 100644
--- a/include/netd_resolv/resolv.h
+++ b/include/netd_resolv/resolv.h
@@ -81,6 +81,7 @@
 typedef void (*get_network_context_callback)(unsigned netid, uid_t uid,
                                              android_net_context* netcontext);
 typedef void (*log_callback)(const char* msg);
+typedef int (*tagSocketCallback)(int sockFd, uint32_t tag, uid_t uid);
 
 /*
  * Some functions needed by the resolver (e.g. checkCallingPermission()) live in
@@ -92,8 +93,11 @@
     check_calling_permission_callback check_calling_permission;
     get_network_context_callback get_network_context;
     log_callback log;
+    tagSocketCallback tagSocket;
 };
 
+#define TAG_SYSTEM_DNS 0xFFFFFF82
+
 LIBNETD_RESOLV_PUBLIC bool resolv_has_nameservers(unsigned netid);
 
 // Set callbacks and bring DnsResolver up.
diff --git a/res_send.cpp b/res_send.cpp
index f86e5f6..35c9c5f 100644
--- a/res_send.cpp
+++ b/res_send.cpp
@@ -772,9 +772,7 @@
                     return -1;
             }
         }
-        if (fchown(statp->_vcsock, statp->uid, -1) == -1) {
-            PLOG(WARNING) << __func__ << ": Failed to chown socket";
-        }
+        resolv_tag_socket(statp->_vcsock, statp->uid);
         if (statp->_mark != MARK_UNSET) {
             if (setsockopt(statp->_vcsock, SOL_SOCKET, SO_MARK, &statp->_mark,
                            sizeof(statp->_mark)) < 0) {
@@ -1017,9 +1015,7 @@
             }
         }
 
-        if (fchown(statp->_u._ext.nssocks[ns], statp->uid, -1) == -1) {
-            PLOG(WARNING) << __func__ << ": Failed to chown socket";
-        }
+        resolv_tag_socket(statp->_u._ext.nssocks[ns], statp->uid);
         if (statp->_mark != MARK_UNSET) {
             if (setsockopt(statp->_u._ext.nssocks[ns], SOL_SOCKET, SO_MARK, &(statp->_mark),
                            sizeof(statp->_mark)) < 0) {
diff --git a/resolv_private.h b/resolv_private.h
index 0e0cbad..96fc23a 100644
--- a/resolv_private.h
+++ b/resolv_private.h
@@ -61,6 +61,7 @@
 #include <string>
 #include <vector>
 
+#include "DnsResolver.h"
 #include "netd_resolv/params.h"
 #include "netd_resolv/resolv.h"
 #include "netd_resolv/stats.h"
@@ -225,4 +226,16 @@
 
 android::net::IpVersion ipFamilyToIPVersion(int ipFamily);
 
+inline void resolv_tag_socket(int sock, uid_t uid) {
+    if (android::net::gResNetdCallbacks.tagSocket != nullptr) {
+        if (int err = android::net::gResNetdCallbacks.tagSocket(sock, TAG_SYSTEM_DNS, uid)) {
+            LOG(WARNING) << "Failed to tag socket: " << strerror(-err);
+        }
+    }
+
+    if (fchown(sock, uid, -1) == -1) {
+        LOG(WARNING) << "Failed to chown socket: " << strerror(errno);
+    }
+}
+
 #endif  // NETD_RESOLV_PRIVATE_H