Redirect qtaguid native call to netd fwmark client

In order to replace qtaguid module with new eBPF network monitoring
module. We firstly move the current qtaguid userspace implementation
into netd and hide the detail from other processes. The current API will
talk to netd fwmark client to pass down the qtaguid related request from
high level framework and netd will use the proper method to complete the
request.

Test: Current TrafficStats CTS tests should not fail.
Bug: 30950746
Change-Id: Ie90c28f3594ab2877746b2372a1b6944768bfb18
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index cfe8d29..b30336d 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -110,7 +110,7 @@
                 "klog.cpp",
                 "partition_utils.c",
                 "properties.cpp",
-                "qtaguid.c",
+                "qtaguid.cpp",
                 "trace-dev.c",
                 "uevent.c",
             ],
diff --git a/libcutils/include/cutils/qtaguid.h b/libcutils/include/cutils/qtaguid.h
new file mode 100644
index 0000000..3f5e41f
--- /dev/null
+++ b/libcutils/include/cutils/qtaguid.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CUTILS_QTAGUID_H
+#define __CUTILS_QTAGUID_H
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Set tags (and owning UIDs) for network sockets.
+ */
+extern int qtaguid_tagSocket(int sockfd, int tag, uid_t uid);
+
+/*
+ * Untag a network socket before closing.
+ */
+extern int qtaguid_untagSocket(int sockfd);
+
+/*
+ * For the given uid, switch counter sets.
+ * The kernel only keeps a limited number of sets.
+ * 2 for now.
+ */
+extern int qtaguid_setCounterSet(int counterSetNum, uid_t uid);
+
+/*
+ * Delete all tag info that relates to the given tag an uid.
+ * If the tag is 0, then ALL info about the uid is freed.
+ * The delete data also affects active tagged sockets, which are
+ * then untagged.
+ * The calling process can only operate on its own tags.
+ * Unless it is part of the happy AID_NET_BW_ACCT group.
+ * In which case it can clobber everything.
+ */
+extern int qtaguid_deleteTagData(int tag, uid_t uid);
+
+/*
+ * Enable/disable qtaguid functionnality at a lower level.
+ * When pacified, the kernel will accept commands but do nothing.
+ */
+extern int qtaguid_setPacifier(int on);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_QTAG_UID_H */
diff --git a/libcutils/qtaguid.cpp b/libcutils/qtaguid.cpp
new file mode 100644
index 0000000..86a5dc4
--- /dev/null
+++ b/libcutils/qtaguid.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #define LOG_NDEBUG 0
+
+#define LOG_TAG "qtaguid"
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <cutils/qtaguid.h>
+#include <log/log.h>
+
+class netdHandler {
+  public:
+    int (*netdTagSocket)(int, uint32_t, uid_t);
+    int (*netdUntagSocket)(int);
+    int (*netdSetCounterSet)(uint32_t, uid_t);
+    int (*netdDeleteTagData)(uint32_t, uid_t);
+};
+
+int dummyTagSocket(int, uint32_t, uid_t) {
+    return -EREMOTEIO;
+}
+
+int dummyUntagSocket(int) {
+    return -EREMOTEIO;
+}
+
+int dummySetCounterSet(uint32_t, uid_t) {
+    return -EREMOTEIO;
+}
+
+int dummyDeleteTagData(uint32_t, uid_t) {
+    return -EREMOTEIO;
+}
+
+netdHandler initHandler(void) {
+    netdHandler handler = {dummyTagSocket, dummyUntagSocket, dummySetCounterSet, dummyDeleteTagData};
+
+    void* netdClientHandle = dlopen("libnetd_client.so", RTLD_NOW);
+    if (!netdClientHandle) {
+        ALOGE("Failed to open libnetd_client.so: %s", dlerror());
+        return handler;
+    }
+
+    handler.netdTagSocket = (int (*)(int, uint32_t, uid_t))dlsym(netdClientHandle, "tagSocket");
+    if (!handler.netdTagSocket) {
+        ALOGE("load netdTagSocket handler failed: %s", dlerror());
+    }
+
+    handler.netdUntagSocket = (int (*)(int))dlsym(netdClientHandle, "untagSocket");
+    if (!handler.netdUntagSocket) {
+        ALOGE("load netdUntagSocket handler failed: %s", dlerror());
+    }
+
+    handler.netdSetCounterSet = (int (*)(uint32_t, uid_t))dlsym(netdClientHandle, "setCounterSet");
+    if (!handler.netdSetCounterSet) {
+        ALOGE("load netdSetCounterSet handler failed: %s", dlerror());
+    }
+
+    handler.netdDeleteTagData = (int (*)(uint32_t, uid_t))dlsym(netdClientHandle, "deleteTagData");
+    if (!handler.netdDeleteTagData) {
+        ALOGE("load netdDeleteTagData handler failed: %s", dlerror());
+    }
+    return handler;
+}
+
+// The language guarantees that this object will be initialized in a thread-safe way.
+static netdHandler& getHandler() {
+    static netdHandler instance = initHandler();
+    return instance;
+}
+
+int qtaguid_tagSocket(int sockfd, int tag, uid_t uid) {
+    // Check the socket fd passed to us is still valid before we load the netd
+    // client. Pass a already closed socket fd to netd client may let netd open
+    // the unix socket with the same fd number and pass it to server for
+    // tagging.
+    // TODO: move the check into netdTagSocket.
+    int res = fcntl(sockfd, F_GETFD);
+    if (res < 0) return res;
+
+    ALOGV("Tagging socket %d with tag %u for uid %d", sockfd, tag, uid);
+    return getHandler().netdTagSocket(sockfd, tag, uid);
+}
+
+int qtaguid_untagSocket(int sockfd) {
+    // Similiar to tag socket. We need a check before untag to make sure untag a closed socket fail
+    // as expected.
+    // TODO: move the check into netdTagSocket.
+    int res = fcntl(sockfd, F_GETFD);
+    if (res < 0) return res;
+
+    ALOGV("Untagging socket %d", sockfd);
+    return getHandler().netdUntagSocket(sockfd);
+}
+
+int qtaguid_setCounterSet(int counterSetNum, uid_t uid) {
+    ALOGV("Setting counters to set %d for uid %d", counterSetNum, uid);
+    return getHandler().netdSetCounterSet(counterSetNum, uid);
+}
+
+int qtaguid_deleteTagData(int tag, uid_t uid) {
+    ALOGV("Deleting tag data with tag %u for uid %d", tag, uid);
+    return getHandler().netdDeleteTagData(tag, uid);
+}
diff --git a/libqtaguid/include/qtaguid/qtaguid.h b/libqtaguid/include/qtaguid/qtaguid.h
index 803fe0d..72285e5 100644
--- a/libqtaguid/include/qtaguid/qtaguid.h
+++ b/libqtaguid/include/qtaguid/qtaguid.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef __CUTILS_QTAGUID_H
-#define __CUTILS_QTAGUID_H
+#ifndef __LEGACY_QTAGUID_H
+#define __LEGACY_QTAGUID_H
 
 #include <stdint.h>
 #include <sys/types.h>
@@ -30,19 +30,19 @@
  * by calling qtaguid_untagSocket() before closing it, otherwise the qtaguid
  * module will keep a reference to it even after close.
  */
-extern int qtaguid_tagSocket(int sockfd, int tag, uid_t uid);
+extern int legacy_tagSocket(int sockfd, int tag, uid_t uid);
 
 /*
  * Untag a network socket before closing.
  */
-extern int qtaguid_untagSocket(int sockfd);
+extern int legacy_untagSocket(int sockfd);
 
 /*
  * For the given uid, switch counter sets.
  * The kernel only keeps a limited number of sets.
  * 2 for now.
  */
-extern int qtaguid_setCounterSet(int counterSetNum, uid_t uid);
+extern int legacy_setCounterSet(int counterSetNum, uid_t uid);
 
 /*
  * Delete all tag info that relates to the given tag an uid.
@@ -53,16 +53,10 @@
  * Unless it is part of the happy AID_NET_BW_ACCT group.
  * In which case it can clobber everything.
  */
-extern int qtaguid_deleteTagData(int tag, uid_t uid);
-
-/*
- * Enable/disable qtaguid functionnality at a lower level.
- * When pacified, the kernel will accept commands but do nothing.
- */
-extern int qtaguid_setPacifier(int on);
+extern int legacy_deleteTagData(int tag, uid_t uid);
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* __CUTILS_QTAG_UID_H */
+#endif /* __LEGACY_QTAGUID_H */
diff --git a/libqtaguid/qtaguid.c b/libqtaguid/qtaguid.c
index af9fbfa..cd38bad 100644
--- a/libqtaguid/qtaguid.c
+++ b/libqtaguid/qtaguid.c
@@ -26,13 +26,11 @@
 #include <string.h>
 #include <unistd.h>
 
-#include <cutils/qtaguid.h>
 #include <log/log.h>
+#include <qtaguid/qtaguid.h>
 
 static const char* CTRL_PROCPATH = "/proc/net/xt_qtaguid/ctrl";
 static const int CTRL_MAX_INPUT_LEN = 128;
-static const char* GLOBAL_PACIFIER_PARAM = "/sys/module/xt_qtaguid/parameters/passive";
-static const char* TAG_PACIFIER_PARAM = "/sys/module/xt_qtaguid/parameters/tag_tracking_passive";
 
 /*
  * One per proccess.
@@ -46,7 +44,7 @@
 pthread_once_t resTrackInitDone = PTHREAD_ONCE_INIT;
 
 /* Only call once per process. */
-void qtaguid_resTrack(void) {
+void legacy_resTrack(void) {
     resTrackFd = TEMP_FAILURE_RETRY(open("/dev/xt_qtaguid", O_RDONLY | O_CLOEXEC));
 }
 
@@ -79,28 +77,12 @@
     return -savedErrno;
 }
 
-static int write_param(const char* param_path, const char* value) {
-    int param_fd;
-    int res;
-
-    param_fd = TEMP_FAILURE_RETRY(open(param_path, O_WRONLY | O_CLOEXEC));
-    if (param_fd < 0) {
-        return -errno;
-    }
-    res = TEMP_FAILURE_RETRY(write(param_fd, value, strlen(value)));
-    if (res < 0) {
-        return -errno;
-    }
-    close(param_fd);
-    return 0;
-}
-
-int qtaguid_tagSocket(int sockfd, int tag, uid_t uid) {
+int legacy_tagSocket(int sockfd, int tag, uid_t uid) {
     char lineBuf[CTRL_MAX_INPUT_LEN];
     int res;
     uint64_t kTag = ((uint64_t)tag << 32);
 
-    pthread_once(&resTrackInitDone, qtaguid_resTrack);
+    pthread_once(&resTrackInitDone, legacy_resTrack);
 
     snprintf(lineBuf, sizeof(lineBuf), "t %d %" PRIu64 " %d", sockfd, kTag, uid);
 
@@ -115,7 +97,7 @@
     return res;
 }
 
-int qtaguid_untagSocket(int sockfd) {
+int legacy_untagSocket(int sockfd) {
     char lineBuf[CTRL_MAX_INPUT_LEN];
     int res;
 
@@ -130,7 +112,7 @@
     return res;
 }
 
-int qtaguid_setCounterSet(int counterSetNum, uid_t uid) {
+int legacy_setCounterSet(int counterSetNum, uid_t uid) {
     char lineBuf[CTRL_MAX_INPUT_LEN];
     int res;
 
@@ -141,14 +123,14 @@
     return res;
 }
 
-int qtaguid_deleteTagData(int tag, uid_t uid) {
+int legacy_deleteTagData(int tag, uid_t uid) {
     char lineBuf[CTRL_MAX_INPUT_LEN];
     int cnt = 0, res = 0;
     uint64_t kTag = (uint64_t)tag << 32;
 
     ALOGV("Deleting tag data with tag %" PRIx64 "{%d,0} for uid %d", kTag, tag, uid);
 
-    pthread_once(&resTrackInitDone, qtaguid_resTrack);
+    pthread_once(&resTrackInitDone, legacy_resTrack);
 
     snprintf(lineBuf, sizeof(lineBuf), "d %" PRIu64 " %d", kTag, uid);
     res = write_ctrl(lineBuf);
@@ -159,16 +141,3 @@
 
     return res;
 }
-
-int qtaguid_setPacifier(int on) {
-    const char* value;
-
-    value = on ? "Y" : "N";
-    if (write_param(GLOBAL_PACIFIER_PARAM, value) < 0) {
-        return -errno;
-    }
-    if (write_param(TAG_PACIFIER_PARAM, value) < 0) {
-        return -errno;
-    }
-    return 0;
-}