Prevent netd from using the libnetd_client wrappers

Netd looping connections to itself via the libnetd_client connect()
wrapper has always unintended, although it worked until now. Once we
move the resolver into netd, the frequency of connect() calls will
increase, which makes it less acceptable.

There are several ways to detect if the calling process is netd.
Checking both uid == 0 and the argv[0] == netd makes it hard for
non-system components to spoof as netd.

Test: flash a device and check that netd logs the "Skipping..." message
Test: atest netd_integration_test
Change-Id: I9506facb4aa3094b16a98a913a1e2394056ce91a
diff --git a/libc/bionic/NetdClient.cpp b/libc/bionic/NetdClient.cpp
index a1071d2..966cbcc 100644
--- a/libc/bionic/NetdClient.cpp
+++ b/libc/bionic/NetdClient.cpp
@@ -24,6 +24,8 @@
 
 #include <dlfcn.h>
 #include <pthread.h>
+#include <string.h>
+#include <unistd.h>
 
 template <typename FunctionType>
 static void netdClientInitFunction(void* handle, const char* symbol, FunctionType* function) {
@@ -35,6 +37,14 @@
 }
 
 static void netdClientInitImpl() {
+    // Prevent netd from looping back fwmarkd connections to itself. It would work, but it's
+    // a deadlock hazard and unnecessary overhead for the resolver.
+    if (getuid() == 0 && strcmp(getprogname(), "netd") == 0) {
+        async_safe_format_log(ANDROID_LOG_INFO, "netdClient",
+                              "Skipping libnetd_client init since *we* are netd");
+        return;
+    }
+
     void* netdClientHandle = dlopen("libnetd_client.so", RTLD_NOW);
     if (netdClientHandle == NULL) {
         // If the library is not available, it's not an error. We'll just use
@@ -54,6 +64,6 @@
 
 extern "C" __LIBC_HIDDEN__ void netdClientInit() {
     if (pthread_once(&netdClientInitOnce, netdClientInitImpl)) {
-        async_safe_format_log(ANDROID_LOG_ERROR, "netdClient", "Failed to initialize netd_client");
+        async_safe_format_log(ANDROID_LOG_ERROR, "netdClient", "Failed to initialize libnetd_client");
     }
 }