Merge "Respect caller DT_RUNPATH in dlopen()."
diff --git a/libc/arch-arm/cortex-a9/bionic/memcpy_base.S b/libc/arch-arm/cortex-a9/bionic/memcpy_base.S
index bb08b94..966b9b3 100644
--- a/libc/arch-arm/cortex-a9/bionic/memcpy_base.S
+++ b/libc/arch-arm/cortex-a9/bionic/memcpy_base.S
@@ -133,8 +133,7 @@
         strbcs      ip, [r0], #1
         strbcs      lr, [r0], #1
 
-        ldmfd       sp!, {r0, lr}
-        bx          lr
+        ldmfd       sp!, {r0, pc}
 END(MEMCPY_BASE)
 
 ENTRY_PRIVATE(MEMCPY_BASE_ALIGNED)
diff --git a/libc/arch-arm/cortex-a9/bionic/memset.S b/libc/arch-arm/cortex-a9/bionic/memset.S
index 8ee6ac2..48ba815 100644
--- a/libc/arch-arm/cortex-a9/bionic/memset.S
+++ b/libc/arch-arm/cortex-a9/bionic/memset.S
@@ -136,8 +136,7 @@
         strbcs      r1, [r0], #1
         strbmi      r1, [r0], #1
         subs        r2, r2, r3
-        popls       {r0, r4-r7, lr}   /* return */
-        bxls        lr
+        popls       {r0, r4-r7, pc}   /* return */
 
         /* align the destination to a cache-line */
         mov         r12, r1
@@ -180,8 +179,7 @@
         strhmi      r1, [r0], #2
         movs        r2, r2, lsl #2
         strbcs      r1, [r0]
-        ldmfd       sp!, {r0, r4-r7, lr}
-        bx          lr
+        ldmfd       sp!, {r0, r4-r7, pc}
 END(__memset_large_copy)
 
         .data
diff --git a/libc/arch-arm/generic/bionic/memcmp.S b/libc/arch-arm/generic/bionic/memcmp.S
index c78dbd4..6643d55 100644
--- a/libc/arch-arm/generic/bionic/memcmp.S
+++ b/libc/arch-arm/generic/bionic/memcmp.S
@@ -221,8 +221,7 @@
         bne         8b
 
 9:      /* restore registers and return */
-        ldmfd       sp!, {r4, lr}
-        bx          lr
+        ldmfd       sp!, {r4, pc}
 
 10:     /* process less than 12 bytes */
         cmp         r2, #0
diff --git a/libc/arch-arm/generic/bionic/memcpy.S b/libc/arch-arm/generic/bionic/memcpy.S
index ea5a399..65cba4c 100644
--- a/libc/arch-arm/generic/bionic/memcpy.S
+++ b/libc/arch-arm/generic/bionic/memcpy.S
@@ -194,8 +194,7 @@
 
         /* we're done! restore everything and return */
 1:      ldmfd       sp!, {r5-r11}
-        ldmfd       sp!, {r0, r4, lr}
-        bx          lr
+        ldmfd       sp!, {r0, r4, pc}
 
         /********************************************************************/
 
@@ -385,8 +384,7 @@
 
         /* we're done! restore sp and spilled registers and return */
         add         sp,  sp, #28
-        ldmfd       sp!, {r0, r4, lr}
-        bx          lr
+        ldmfd       sp!, {r0, r4, pc}
 END(memcpy)
 
         // Only reached when the __memcpy_chk check fails.
diff --git a/libc/arch-arm/generic/bionic/memset.S b/libc/arch-arm/generic/bionic/memset.S
index d17a9c4..b8eabbf 100644
--- a/libc/arch-arm/generic/bionic/memset.S
+++ b/libc/arch-arm/generic/bionic/memset.S
@@ -82,8 +82,7 @@
         strbcs      r1, [r0], #1
         strbmi      r1, [r0], #1
         subs        r2, r2, r3
-        popls       {r0, r4-r7, lr}    /* return */
-        bxls        lr
+        popls       {r0, r4-r7, pc}    /* return */
 
         /* align the destination to a cache-line */
         mov         r12, r1
@@ -126,8 +125,7 @@
         strhmi      r1, [r0], #2
         movs        r2, r2, lsl #2
         strbcs      r1, [r0]
-        ldmfd       sp!, {r0, r4-r7, lr}
-        bx          lr
+        ldmfd       sp!, {r0, r4-r7, pc}
 END(memset)
 
         .data
diff --git a/libc/arch-arm/krait/bionic/memcpy_base.S b/libc/arch-arm/krait/bionic/memcpy_base.S
index 035dcf1..6c098ac 100644
--- a/libc/arch-arm/krait/bionic/memcpy_base.S
+++ b/libc/arch-arm/krait/bionic/memcpy_base.S
@@ -118,6 +118,5 @@
         strbcs      ip, [r0], #1
         strbcs      lr, [r0], #1
 
-        ldmfd       sp!, {r0, lr}
-        bx          lr
+        ldmfd       sp!, {r0, pc}
 END(MEMCPY_BASE)
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index 9b23ece..bd71628 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -37,6 +37,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/auxv.h>
+#include <sys/personality.h>
 #include <sys/time.h>
 #include <unistd.h>
 
@@ -44,6 +45,7 @@
 #include "private/bionic_ssp.h"
 #include "private/bionic_tls.h"
 #include "private/KernelArgumentBlock.h"
+#include "private/libc_logging.h"
 #include "pthread_internal.h"
 
 extern "C" abort_msg_t** __abort_message_ptr;
@@ -289,6 +291,19 @@
   dst[0] = nullptr;
 }
 
+static void __initialize_personality() {
+#if !defined(__LP64__)
+  int old_value = personality(0xffffffff);
+  if (old_value == -1) {
+    __libc_fatal("error getting old personality value: %s", strerror(errno));
+  }
+
+  if (personality((static_cast<unsigned int>(old_value) & ~PER_MASK) | PER_LINUX32) == -1) {
+    __libc_fatal("error setting PER_LINUX32 personality: %s", strerror(errno));
+  }
+#endif
+}
+
 void __libc_init_AT_SECURE(KernelArgumentBlock& args) {
   __libc_auxv = args.auxv;
 
@@ -312,6 +327,8 @@
 
   // Now the environment has been sanitized, make it available.
   environ = args.envp;
+
+  __initialize_personality();
 }
 
 /* This function will be called during normal program termination
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index dbdb180..e260e97 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -87,6 +87,7 @@
     // We can only use const static allocated string for mapped region name, as Android kernel
     // uses the string pointer directly when dumping /proc/pid/maps.
     prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, ss.ss_sp, ss.ss_size, "thread signal stack");
+    prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, stack_base, PAGE_SIZE, "thread signal stack guard page");
   }
 }
 
@@ -140,6 +141,7 @@
     munmap(space, mmap_size);
     return NULL;
   }
+  prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, space, stack_guard_size, "thread stack guard page");
 
   return space;
 }
diff --git a/libc/dns/include/resolv_netid.h b/libc/dns/include/resolv_netid.h
index 1d0f869..d364645 100644
--- a/libc/dns/include/resolv_netid.h
+++ b/libc/dns/include/resolv_netid.h
@@ -53,10 +53,37 @@
 
 #define __used_in_netd __attribute__((visibility ("default")))
 
+/*
+ * A struct to capture context relevant to network operations.
+ *
+ * Application and DNS netids/marks can differ from one another under certain
+ * circumstances, notably when a VPN applies to the given uid's traffic but the
+ * VPN network does not have its own DNS servers explicitly provisioned.
+ *
+ * The introduction of per-UID routing means the uid is also an essential part
+ * of the evaluation context. Its proper uninitialized value is
+ * NET_CONTEXT_INVALID_UID.
+ */
+struct android_net_context {
+    unsigned app_netid;
+    unsigned app_mark;
+    unsigned dns_netid;
+    unsigned dns_mark;
+    uid_t uid;
+} __attribute__((packed));
+
+#define NET_CONTEXT_INVALID_UID ((uid_t)-1)
+
 struct hostent *android_gethostbyaddrfornet(const void *, socklen_t, int, unsigned, unsigned) __used_in_netd;
 struct hostent *android_gethostbynamefornet(const char *, int, unsigned, unsigned) __used_in_netd;
 int android_getaddrinfofornet(const char *, const char *, const struct addrinfo *, unsigned,
-		unsigned, struct addrinfo **) __used_in_netd;
+    unsigned, struct addrinfo **) __used_in_netd;
+/*
+ * TODO: consider refactoring android_getaddrinfo_proxy() to serve as an
+ * explore_fqdn() dispatch table method, with the below function only making DNS calls.
+ */
+int android_getaddrinfofornetcontext(const char *, const char *, const struct addrinfo *,
+    const struct android_net_context *, struct addrinfo **) __used_in_netd;
 
 /* set name servers for a network */
 extern void _resolv_set_nameservers_for_net(unsigned netid,
diff --git a/libc/dns/net/getaddrinfo.c b/libc/dns/net/getaddrinfo.c
index c73c085..829b679 100644
--- a/libc/dns/net/getaddrinfo.c
+++ b/libc/dns/net/getaddrinfo.c
@@ -218,7 +218,7 @@
 
 static int str2number(const char *);
 static int explore_fqdn(const struct addrinfo *, const char *,
-	const char *, struct addrinfo **, unsigned netid, unsigned mark);
+	const char *, struct addrinfo **, const struct android_net_context *);
 static int explore_null(const struct addrinfo *,
 	const char *, struct addrinfo **);
 static int explore_numeric(const struct addrinfo *, const char *,
@@ -244,6 +244,7 @@
 static struct addrinfo *_gethtent(FILE **, const char *,
     const struct addrinfo *);
 static int _files_getaddrinfo(void *, void *, va_list);
+static int _find_src_addr(const struct sockaddr *, struct sockaddr *, unsigned , uid_t);
 
 static int res_queryN(const char *, struct res_target *, res_state);
 static int res_searchN(const char *, struct res_target *, res_state);
@@ -360,29 +361,6 @@
 }
 
 /*
- * Connect a UDP socket to a given unicast address. This will cause no network
- * traffic, but will fail fast if the system has no or limited reachability to
- * the destination (e.g., no IPv4 address, no IPv6 default route, ...).
- */
-static int
-_test_connect(int pf, struct sockaddr *addr, size_t addrlen, unsigned mark) {
-	int s = socket(pf, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
-	if (s < 0)
-		return 0;
-	if (mark != MARK_UNSET && setsockopt(s, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0)
-		return 0;
-	int ret;
-	do {
-		ret = __connect(s, addr, addrlen);
-	} while (ret < 0 && errno == EINTR);
-	int success = (ret == 0);
-	do {
-		ret = close(s);
-	} while (ret < 0 && errno == EINTR);
-	return success;
-}
-
-/*
  * The following functions determine whether IPv4 or IPv6 connectivity is
  * available in order to implement AI_ADDRCONFIG.
  *
@@ -392,24 +370,24 @@
  * so checking for connectivity is the next best thing.
  */
 static int
-_have_ipv6(unsigned mark) {
+_have_ipv6(unsigned mark, uid_t uid) {
 	static const struct sockaddr_in6 sin6_test = {
 		.sin6_family = AF_INET6,
 		.sin6_addr.s6_addr = {  // 2000::
 			0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
 		};
 	sockaddr_union addr = { .in6 = sin6_test };
-	return _test_connect(PF_INET6, &addr.generic, sizeof(addr.in6), mark);
+	return _find_src_addr(&addr.generic, NULL, mark, uid) == 1;
 }
 
 static int
-_have_ipv4(unsigned mark) {
+_have_ipv4(unsigned mark, uid_t uid) {
 	static const struct sockaddr_in sin_test = {
 		.sin_family = AF_INET,
 		.sin_addr.s_addr = __constant_htonl(0x08080808L)  // 8.8.8.8
 	};
 	sockaddr_union addr = { .in = sin_test };
-	return _test_connect(PF_INET, &addr.generic, sizeof(addr.in), mark);
+	return _find_src_addr(&addr.generic, NULL, mark, uid) == 1;
 }
 
 bool readBE32(FILE* fp, int32_t* result) {
@@ -474,7 +452,7 @@
 
 	int result_code = (int)strtol(buf, NULL, 10);
 	// verify the code itself
-	if (result_code != DnsProxyQueryResult ) {
+	if (result_code != DnsProxyQueryResult) {
 		fread(buf, 1, sizeof(buf), proxy);
 		goto exit;
 	}
@@ -589,6 +567,21 @@
 android_getaddrinfofornet(const char *hostname, const char *servname,
     const struct addrinfo *hints, unsigned netid, unsigned mark, struct addrinfo **res)
 {
+	struct android_net_context netcontext = {
+		.app_netid = netid,
+		.app_mark = mark,
+		.dns_netid = netid,
+		.dns_mark = mark,
+		.uid = NET_CONTEXT_INVALID_UID,
+        };
+	return android_getaddrinfofornetcontext(hostname, servname, hints, &netcontext, res);
+}
+
+int
+android_getaddrinfofornetcontext(const char *hostname, const char *servname,
+    const struct addrinfo *hints, const struct android_net_context *netcontext,
+    struct addrinfo **res)
+{
 	struct addrinfo sentinel;
 	struct addrinfo *cur;
 	int error = 0;
@@ -601,6 +594,7 @@
 	/* servname is allowed to be NULL */
 	/* hints is allowed to be NULL */
 	assert(res != NULL);
+	assert(netcontext != NULL);
 	memset(&sentinel, 0, sizeof(sentinel));
 	cur = &sentinel;
 	pai = &ai;
@@ -731,7 +725,8 @@
 		ERR(EAI_NONAME);
 
 #if defined(__ANDROID__)
-	int gai_error = android_getaddrinfo_proxy(hostname, servname, hints, res, netid);
+	int gai_error = android_getaddrinfo_proxy(
+		hostname, servname, hints, res, netcontext->app_netid);
 	if (gai_error != EAI_SYSTEM) {
 		return gai_error;
 	}
@@ -763,8 +758,8 @@
 		if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
 			pai->ai_protocol = ex->e_protocol;
 
-		error = explore_fqdn(pai, hostname, servname,
-			&cur->ai_next, netid, mark);
+		error = explore_fqdn(
+			pai, hostname, servname, &cur->ai_next, netcontext);
 
 		while (cur && cur->ai_next)
 			cur = cur->ai_next;
@@ -797,7 +792,8 @@
  */
 static int
 explore_fqdn(const struct addrinfo *pai, const char *hostname,
-    const char *servname, struct addrinfo **res, unsigned netid, unsigned mark)
+    const char *servname, struct addrinfo **res,
+    const struct android_net_context *netcontext)
 {
 	struct addrinfo *result;
 	struct addrinfo *cur;
@@ -823,7 +819,7 @@
 		return 0;
 
 	switch (nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo",
-			default_dns_files, hostname, pai, netid, mark)) {
+			default_dns_files, hostname, pai, netcontext)) {
 	case NS_TRYAGAIN:
 		error = EAI_AGAIN;
 		goto free;
@@ -1763,13 +1759,13 @@
  * address. src_addr must be large enough to hold a struct sockaddr_in6.
  *
  * Returns 1 if a source address was found, 0 if the address is unreachable,
- * and -1 if a fatal error occurred. If 0 or 1, the contents of src_addr are
+ * and -1 if a fatal error occurred. If 0 or -1, the contents of src_addr are
  * undefined.
  */
 
 /*ARGSUSED*/
 static int
-_find_src_addr(const struct sockaddr *addr, struct sockaddr *src_addr, unsigned mark)
+_find_src_addr(const struct sockaddr *addr, struct sockaddr *src_addr, unsigned mark, uid_t uid)
 {
 	int sock;
 	int ret;
@@ -1797,6 +1793,8 @@
 	}
 	if (mark != MARK_UNSET && setsockopt(sock, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0)
 		return 0;
+	if (uid > 0 && uid != NET_CONTEXT_INVALID_UID && fchown(sock, uid, (gid_t)-1) < 0)
+		return 0;
 	do {
 		ret = __connect(sock, addr, len);
 	} while (ret == -1 && errno == EINTR);
@@ -1806,7 +1804,7 @@
 		return 0;
 	}
 
-	if (getsockname(sock, src_addr, &len) == -1) {
+	if (src_addr && getsockname(sock, src_addr, &len) == -1) {
 		close(sock);
 		return -1;
 	}
@@ -1821,7 +1819,7 @@
 
 /*ARGSUSED*/
 static void
-_rfc6724_sort(struct addrinfo *list_sentinel, unsigned mark)
+_rfc6724_sort(struct addrinfo *list_sentinel, unsigned mark, uid_t uid)
 {
 	struct addrinfo *cur;
 	int nelem = 0, i;
@@ -1848,7 +1846,7 @@
 		elems[i].ai = cur;
 		elems[i].original_order = i;
 
-		has_src_addr = _find_src_addr(cur->ai_addr, &elems[i].src_addr.generic, mark);
+		has_src_addr = _find_src_addr(cur->ai_addr, &elems[i].src_addr.generic, mark, uid);
 		if (has_src_addr == -1) {
 			goto error;
 		}
@@ -1879,12 +1877,11 @@
 	struct addrinfo sentinel, *cur;
 	struct res_target q, q2;
 	res_state res;
-	unsigned netid, mark;
+	const struct android_net_context *netcontext;
 
 	name = va_arg(ap, char *);
 	pai = va_arg(ap, const struct addrinfo *);
-	netid = va_arg(ap, unsigned);
-	mark = va_arg(ap, unsigned);
+	netcontext = va_arg(ap, const struct android_net_context *);
 	//fprintf(stderr, "_dns_getaddrinfo() name = '%s'\n", name);
 
 	memset(&q, 0, sizeof(q));
@@ -1913,8 +1910,8 @@
 		q.anslen = sizeof(buf->buf);
 		int query_ipv6 = 1, query_ipv4 = 1;
 		if (pai->ai_flags & AI_ADDRCONFIG) {
-			query_ipv6 = _have_ipv6(mark);
-			query_ipv4 = _have_ipv4(mark);
+			query_ipv6 = _have_ipv6(netcontext->app_mark, netcontext->uid);
+			query_ipv4 = _have_ipv4(netcontext->app_mark, netcontext->uid);
 		}
 		if (query_ipv6) {
 			q.qtype = T_AAAA;
@@ -1966,8 +1963,8 @@
 	 * fully populate the thread private data here, but if we get down there
 	 * and have a cache hit that would be wasted, so we do the rest there on miss
 	 */
-	res_setnetid(res, netid);
-	res_setmark(res, mark);
+	res_setnetid(res, netcontext->dns_netid);
+	res_setmark(res, netcontext->dns_mark);
 	if (res_searchN(name, &q, res) < 0) {
 		__res_put_state(res);
 		free(buf);
@@ -1999,7 +1996,7 @@
 		}
 	}
 
-	_rfc6724_sort(&sentinel, netid);
+	_rfc6724_sort(&sentinel, netcontext->app_mark, netcontext->uid);
 
 	__res_put_state(res);
 
diff --git a/libc/dns/net/gethnamaddr.c b/libc/dns/net/gethnamaddr.c
index 8f5800a..42f0d0a 100644
--- a/libc/dns/net/gethnamaddr.c
+++ b/libc/dns/net/gethnamaddr.c
@@ -640,6 +640,9 @@
 		ptr += size;
 	}
 
+	// Fix alignment after variable-length data.
+	ptr = (char*)ALIGN(ptr);
+
 	int aliases_len = ((int)(aliases - aliases_ptrs) + 1) * sizeof(*hp->h_aliases);
 	if (ptr + aliases_len > hbuf_end) {
 		goto nospc;
@@ -674,6 +677,9 @@
 		ptr += size;
 	}
 
+	// Fix alignment after variable-length data.
+	ptr = (char*)ALIGN(ptr);
+
 	int addrs_len = ((int)(addr_p - addr_ptrs) + 1) * sizeof(*hp->h_addr_list);
 	if (ptr + addrs_len > hbuf_end) {
 		goto nospc;
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index 04613f4..7df8b60 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -520,6 +520,11 @@
 #include <android/api-level.h>
 
 /* glibc compatibility. */
+#if __POSIX_VISIBLE >= 200809
+#define __USE_ISOC99 1
+#define __USE_XOPEN2K 1
+#define __USE_XOPEN2K8 1
+#endif
 #if __LP64__
 #define __WORDSIZE 64
 #else
diff --git a/libc/include/sys/personality.h b/libc/include/sys/personality.h
index 8a023f9..7764468 100644
--- a/libc/include/sys/personality.h
+++ b/libc/include/sys/personality.h
@@ -34,7 +34,7 @@
 
 __BEGIN_DECLS
 
-extern int personality (unsigned long persona);
+extern int personality (unsigned int persona);
 
 __END_DECLS
 
diff --git a/libc/include/uchar.h b/libc/include/uchar.h
index 0ec9d2e..a5e72ea 100644
--- a/libc/include/uchar.h
+++ b/libc/include/uchar.h
@@ -34,7 +34,7 @@
 
 __BEGIN_DECLS
 
-#if defined(__GNUC__) && __GNUC__ >= 5 && !defined(__cplusplus)
+#if __STDC_VERSION__ >= 201112L && !defined(__cplusplus)
 typedef __CHAR16_TYPE__ char16_t;
 typedef __CHAR32_TYPE__ char32_t;
 #endif
diff --git a/libc/libc.map b/libc/libc.map
index 4e17515..47c52a4 100644
--- a/libc/libc.map
+++ b/libc/libc.map
@@ -306,6 +306,7 @@
     alphasort;
     alphasort64;
     android_getaddrinfofornet;
+    android_getaddrinfofornetcontext;
     android_gethostbyaddrfornet;
     android_gethostbynamefornet;
     android_set_abort_message;
diff --git a/libc/zoneinfo/tzdata b/libc/zoneinfo/tzdata
index 2c734fa..4e4f6a7 100644
--- a/libc/zoneinfo/tzdata
+++ b/libc/zoneinfo/tzdata
Binary files differ
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 54fada1..f71e5e0 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -37,7 +37,6 @@
 #include <string.h>
 #include <sys/mman.h>
 #include <sys/param.h>
-#include <sys/personality.h>
 #include <unistd.h>
 
 #include <new>
@@ -3192,12 +3191,6 @@
     ldpreload_env = getenv("LD_PRELOAD");
   }
 
-#if !defined(__LP64__)
-  if (personality(PER_LINUX32) == -1) {
-    __libc_fatal("error setting PER_LINUX32 personality: %s", strerror(errno));
-  }
-#endif
-
   INFO("[ android linker & debugger ]");
 
   soinfo* si = soinfo_alloc(args.argv[0], nullptr, 0, RTLD_GLOBAL);
diff --git a/tests/sys_personality_test.cpp b/tests/sys_personality_test.cpp
index 55a023d..2dfaa65 100644
--- a/tests/sys_personality_test.cpp
+++ b/tests/sys_personality_test.cpp
@@ -19,7 +19,7 @@
 #include <sys/personality.h>
 
 TEST(sys_personality, current_persona) {
-  int persona = personality(0xffffffff);
+  int persona = personality(0xffffffff) & PER_MASK;
 #if defined(__BIONIC__)
 #if defined(__LP64__)
   ASSERT_EQ(PER_LINUX, persona);