Merge "Changes to bionic/libc to demonstrate mixed builds."
diff --git a/libc/Android.bp b/libc/Android.bp
index cfa2182..d739ce6 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1009,7 +1009,9 @@
         "bionic/arpa_inet.cpp",
         "bionic/assert.cpp",
         "bionic/atof.cpp",
+        "bionic/bind.cpp",
         "bionic/bionic_allocator.cpp",
+        "bionic/bionic_appcompat.cpp",
         "bionic/bionic_arc4random.cpp",
         "bionic/bionic_futex.cpp",
         "bionic/bionic_netlink.cpp",
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 6142baf..7cf7a2d 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -244,7 +244,7 @@
 # sockets
 int           __socket:socket(int, int, int)              arm,lp64
 int           __socketpair:socketpair(int, int, int, int*)    arm,lp64
-int           bind(int, struct sockaddr*, socklen_t)  arm,lp64
+int           __bind:bind(int, struct sockaddr*, socklen_t)  arm,lp64
 int           __connect:connect(int, struct sockaddr*, socklen_t)   arm,lp64
 int           listen(int, int)                   arm,lp64
 int           __accept4:accept4(int, struct sockaddr*, socklen_t*, int)  arm,lp64
@@ -262,7 +262,7 @@
 
 # sockets for x86. These are done as an "indexed" call to socketcall syscall.
 int           __socket:socketcall:1(int, int, int) x86
-int           bind:socketcall:2(int, struct sockaddr*, int)  x86
+int           __bind:socketcall:2(int, struct sockaddr*, int)  x86
 int           __connect:socketcall:3(int, struct sockaddr*, socklen_t)   x86
 int           listen:socketcall:4(int, int)                   x86
 int           getsockname:socketcall:6(int, struct sockaddr*, socklen_t*)  x86
diff --git a/libc/bionic/bind.cpp b/libc/bionic/bind.cpp
new file mode 100644
index 0000000..79e8020
--- /dev/null
+++ b/libc/bionic/bind.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+// b/170214442: Intercept bind calls on NETLINK_ROUTE sockets.
+// This entire file will be reverted before release.
+
+#include <async_safe/log.h>
+#include <errno.h>
+#include <linux/rtnetlink.h>
+#include <string.h>
+#include <sys/socket.h>
+
+#include "bionic_appcompat.h"
+
+extern "C" int __bind(int fd, const struct sockaddr* addr, socklen_t addr_length);
+
+int bind(int fd, const struct sockaddr* addr, socklen_t addr_length) {
+  if (should_apply_soft_mac_bind_restrictions()) {
+    int sock_domain, sock_protocol;
+    socklen_t sock_domain_length = sizeof(sock_domain);
+    socklen_t sock_protocol_length = sizeof(sock_protocol);
+    if (getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &sock_domain, &sock_domain_length) < 0 ||
+        getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &sock_protocol, &sock_protocol_length) < 0) {
+      async_safe_format_log(ANDROID_LOG_ERROR, "mac-restrictions",
+                            "Could not get socket type/protocol: %s", strerror(errno));
+    } else if (AF_NETLINK == sock_domain && NETLINK_ROUTE == sock_protocol) {
+      char package_name[MAX_PACKAGE_NAME_LENGTH + 1];
+      get_package_name(package_name, sizeof(package_name));
+      async_safe_format_log(
+          ANDROID_LOG_ERROR, "mac-restrictions",
+          "%s tried to call bind() on a NETLINK_ROUTE socket, which is not allowed. Please follow "
+          "instructions at go/netlink-bug if this app behaves incorrectly.",
+          package_name);
+      errno = EACCES;
+      return -1;
+    }
+  }
+
+  return __bind(fd, addr, addr_length);
+}
diff --git a/libc/bionic/bionic_appcompat.cpp b/libc/bionic/bionic_appcompat.cpp
new file mode 100644
index 0000000..5b31c29
--- /dev/null
+++ b/libc/bionic/bionic_appcompat.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+// b/170214442: Intercept bind calls on NETLINK_ROUTE sockets and getifaddrs() calls.
+// This entire file will be reverted before release.
+
+#include <async_safe/log.h>
+#include <cutils/misc.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "bionic_appcompat.h"
+
+bool should_apply_soft_mac_restrictions(const char* const allowlist[]) {
+  if (getuid() < FIRST_APPLICATION_UID) {
+    // System app. No restrictions should be applied.
+    return false;
+  }
+  if (android_get_application_target_sdk_version() >= __ANDROID_API_R__) {
+    // Restrictions already applied by SELinux. Behave as normally.
+    return false;
+  }
+
+  char package_name[MAX_PACKAGE_NAME_LENGTH + 1];
+  if (get_package_name(package_name, sizeof(package_name)) < 0) {
+    // Error in getting own package name. Apply restrictions by default.
+    async_safe_format_log(ANDROID_LOG_ERROR, "mac-restrictions",
+                          "Could not determine own package name for uid %d", getuid());
+    return true;
+  }
+  for (int i = 0; allowlist[i] != nullptr; i++) {
+    if (strcmp(package_name, allowlist[i]) == 0) {
+      async_safe_format_log(ANDROID_LOG_WARN, "mac-restrictions",
+                            "Temporarily allowing %s to bypass MAC address restrictions.",
+                            package_name);
+      return false;
+    }
+  }
+  return true;
+}
+
+bool should_apply_soft_mac_bind_restrictions() {
+  return should_apply_soft_mac_restrictions(soft_mac_bind_allowlist);
+}
+
+bool should_apply_soft_mac_getlink_restrictions() {
+  return should_apply_soft_mac_restrictions(soft_mac_getlink_allowlist);
+}
+
+int get_package_name(char* buffer, const int bufferlen) {
+  int file = open("/proc/self/cmdline", O_RDONLY | O_CLOEXEC);
+  if (file < 0) {
+    return file;
+  }
+
+  ssize_t len = read(file, buffer, bufferlen - 1);
+  if (len < 0) {
+    close(file);
+    return -1;
+  }
+  buffer[len] = 0;
+
+  close(file);
+  return 0;
+}
\ No newline at end of file
diff --git a/libc/bionic/bionic_appcompat.h b/libc/bionic/bionic_appcompat.h
new file mode 100644
index 0000000..1976e0b
--- /dev/null
+++ b/libc/bionic/bionic_appcompat.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+constexpr int MAX_PACKAGE_NAME_LENGTH = 230;
+
+static inline const char* const soft_mac_bind_allowlist[] = {
+    "com.skype.raider",
+    nullptr,
+};
+
+static inline const char* const soft_mac_getlink_allowlist[] = {
+    nullptr,
+};
+
+int get_package_name(char* buffer, const int bufferlen);
+bool should_apply_soft_mac_bind_restrictions();
+bool should_apply_soft_mac_getlink_restrictions();
\ No newline at end of file
diff --git a/libc/bionic/ifaddrs.cpp b/libc/bionic/ifaddrs.cpp
index 1536333..22ecdb4 100644
--- a/libc/bionic/ifaddrs.cpp
+++ b/libc/bionic/ifaddrs.cpp
@@ -42,6 +42,7 @@
 
 #include "private/ErrnoRestorer.h"
 
+#include "bionic_appcompat.h"
 #include "bionic_netlink.h"
 
 // The public ifaddrs struct is full of pointers. Rather than track several
@@ -310,9 +311,12 @@
   // - System apps
   // - Apps with a target SDK version lower than R
   bool getlink_success = false;
-  if (getuid() < FIRST_APPLICATION_UID ||
-      android_get_application_target_sdk_version() < __ANDROID_API_R__) {
+  if (!should_apply_soft_mac_getlink_restrictions()) {
     getlink_success = nc.SendRequest(RTM_GETLINK) && nc.ReadResponses(__getifaddrs_callback, out);
+  } else if (android_get_application_target_sdk_version() < __ANDROID_API_R__) {
+    async_safe_format_log(ANDROID_LOG_WARN, "mac-restrictions",
+                          "ifaddr no longer returns link info. Please follow instructions at "
+                          "go/netlink-bug if this app behaves incorrectly.");
   }
   bool getaddr_success =
     nc.SendRequest(RTM_GETADDR) && nc.ReadResponses(__getifaddrs_callback, out);