Merge changes Iefdc1662,I8ee9ce62

* changes:
  Don't define IN_CLOEXEC/IN_NONBLOCK for pre-L.
  Undef EPOLL_CLOEXEC for pre-L.
diff --git a/libc/bionic/exec.cpp b/libc/bionic/exec.cpp
index c43eb90..2001106 100644
--- a/libc/bionic/exec.cpp
+++ b/libc/bionic/exec.cpp
@@ -72,19 +72,25 @@
 int execl(const char* name, const char* arg, ...) {
   va_list ap;
   va_start(ap, arg);
-  return __execl(name, arg, kIsExecL, ap);
+  int result = __execl(name, arg, kIsExecL, ap);
+  va_end(ap);
+  return result;
 }
 
 int execle(const char* name, const char* arg, ...) {
   va_list ap;
   va_start(ap, arg);
-  return __execl(name, arg, kIsExecLE, ap);
+  int result = __execl(name, arg, kIsExecLE, ap);
+  va_end(ap);
+  return result;
 }
 
 int execlp(const char* name, const char* arg, ...) {
   va_list ap;
   va_start(ap, arg);
-  return __execl(name, arg, kIsExecLP, ap);
+  int result = __execl(name, arg, kIsExecLP, ap);
+  va_end(ap);
+  return result;
 }
 
 int execv(const char* name, char* const* argv) {
diff --git a/libc/dns/include/resolv_netid.h b/libc/dns/include/resolv_netid.h
index 37c1891..3b2f4da 100644
--- a/libc/dns/include/resolv_netid.h
+++ b/libc/dns/include/resolv_netid.h
@@ -34,6 +34,7 @@
  */
 #include <sys/cdefs.h>
 #include <netinet/in.h>
+#include "resolv_params.h"
 #include <stdio.h>
 
 /*
@@ -71,6 +72,7 @@
     unsigned dns_netid;
     unsigned dns_mark;
     uid_t uid;
+    res_send_qhook qhook;
 };
 
 #define NET_CONTEXT_INVALID_UID ((uid_t)-1)
@@ -83,6 +85,8 @@
  * TODO: consider refactoring android_getaddrinfo_proxy() to serve as an
  * explore_fqdn() dispatch table method, with the below function only making DNS calls.
  */
+struct hostent *android_gethostbyaddrfornetcontext(const void *, socklen_t, int, const struct android_net_context *) __used_in_netd;
+struct hostent *android_gethostbynamefornetcontext(const char *, int, const struct android_net_context *) __used_in_netd;
 int android_getaddrinfofornetcontext(const char *, const char *, const struct addrinfo *,
     const struct android_net_context *, struct addrinfo **) __used_in_netd;
 
@@ -97,7 +101,7 @@
 extern void _resolv_delete_cache_for_net(unsigned netid) __used_in_netd;
 
 /* Internal use only. */
-struct hostent *android_gethostbyaddrfornet_proxy(const void *, socklen_t, int , unsigned, unsigned) __LIBC_HIDDEN__;
+struct hostent *android_gethostbyaddrfornetcontext_proxy(const void *, socklen_t, int , const struct android_net_context *) __LIBC_HIDDEN__;
 int android_getnameinfofornet(const struct sockaddr *, socklen_t, char *, size_t, char *, size_t, int, unsigned, unsigned) __LIBC_HIDDEN__;
 FILE* android_open_proxy(void) __LIBC_HIDDEN__;
 
diff --git a/libc/dns/include/resolv_params.h b/libc/dns/include/resolv_params.h
index 49ae691..1b9d433 100644
--- a/libc/dns/include/resolv_params.h
+++ b/libc/dns/include/resolv_params.h
@@ -43,4 +43,15 @@
     uint8_t max_samples; // max # samples taken into account for statistics
 };
 
+typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error }
+	res_sendhookact;
+
+typedef res_sendhookact (*res_send_qhook)(struct sockaddr * const *,
+					      const u_char **, int *,
+					      u_char *, int, int *);
+
+typedef res_sendhookact (*res_send_rhook)(const struct sockaddr *,
+					      const u_char *, int, u_char *,
+					      int, int *);
+
 #endif // _RESOLV_PARAMS_H
diff --git a/libc/dns/include/resolv_private.h b/libc/dns/include/resolv_private.h
index 54b9626..284270c 100644
--- a/libc/dns/include/resolv_private.h
+++ b/libc/dns/include/resolv_private.h
@@ -116,17 +116,6 @@
 #endif
 #endif
 
-typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error }
-	res_sendhookact;
-
-typedef res_sendhookact (*res_send_qhook)(struct sockaddr * const *,
-					      const u_char **, int *,
-					      u_char *, int, int *);
-
-typedef res_sendhookact (*res_send_rhook)(const struct sockaddr *,
-					      const u_char *, int, u_char *,
-					      int, int *);
-
 struct res_sym {
 	int		number;	   /* Identifying number, like T_MX */
 	const char *	name;	   /* Its symbolic name, like "MX" */
diff --git a/libc/dns/net/gethnamaddr.c b/libc/dns/net/gethnamaddr.c
index 75cb2b3..a22d718 100644
--- a/libc/dns/net/gethnamaddr.c
+++ b/libc/dns/net/gethnamaddr.c
@@ -119,6 +119,14 @@
 static const char AskedForGot[] =
 			  "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
 
+static const struct android_net_context NETCONTEXT_UNSET = {
+	.app_mark = MARK_UNSET,
+	.app_netid = NETID_UNSET,
+	.dns_mark = MARK_UNSET,
+	.dns_netid = NETID_UNSET,
+	.uid = NET_CONTEXT_INVALID_UID
+};
+
 #define	MAXPACKET	(64*1024)
 
 typedef union {
@@ -152,9 +160,9 @@
 static int _dns_gethtbyname(void *, void *, va_list);
 
 static struct hostent *gethostbyname_internal(const char *, int, res_state,
-    struct hostent *, char *, size_t, int *, unsigned, unsigned);
-static struct hostent* android_gethostbyaddrfornet_proxy_internal(const void*, socklen_t,
-    int, struct hostent *, char *, size_t, int *, unsigned, unsigned);
+    struct hostent *, char *, size_t, int *, const struct android_net_context *);
+static struct hostent* android_gethostbyaddrfornetcontext_proxy_internal(const void*, socklen_t,
+    int, struct hostent *, char *, size_t, int *, const struct android_net_context *);
 
 static const ns_src default_dns_files[] = {
 	{ NSSRC_FILES, 	NS_SUCCESS },
@@ -521,15 +529,15 @@
 	_DIAGASSERT(name != NULL);
 
 	if (res->options & RES_USE_INET6) {
-		*result = gethostbyname_internal(name, AF_INET6, res, hp, buf, buflen, errorp, NETID_UNSET,
-		                                 MARK_UNSET);
+		*result = gethostbyname_internal(name, AF_INET6, res, hp, buf, buflen, errorp,
+		                                 &NETCONTEXT_UNSET);
 		if (*result) {
 			__res_put_state(res);
 			return 0;
 		}
 	}
-	*result = gethostbyname_internal(name, AF_INET, res, hp, buf, buflen, errorp, NETID_UNSET,
-	                                 MARK_UNSET);
+	*result = gethostbyname_internal(name, AF_INET, res, hp, buf, buflen, errorp,
+	                                 &NETCONTEXT_UNSET);
 	__res_put_state(res);
 	if (!*result && errno == ENOSPC) {
 	  errno = ERANGE;
@@ -550,8 +558,8 @@
 		*errorp = NETDB_INTERNAL;
 		return -1;
 	}
-	*result = gethostbyname_internal(name, af, res, hp, buf, buflen, errorp, NETID_UNSET,
-	                                 MARK_UNSET);
+	*result = gethostbyname_internal(name, af, res, hp, buf, buflen, errorp,
+	                                 &NETCONTEXT_UNSET);
 	__res_put_state(res);
 	if (!*result && errno == ENOSPC) {
 		errno = ERANGE;
@@ -814,17 +822,17 @@
 // very similar in proxy-ness to android_getaddrinfo_proxy
 static struct hostent *
 gethostbyname_internal(const char *name, int af, res_state res, struct hostent *hp, char *hbuf,
-                       size_t hbuflen, int *errorp, unsigned netid, unsigned mark)
+                       size_t hbuflen, int *errorp, const struct android_net_context *netcontext)
 {
 	FILE* proxy = android_open_proxy();
 	if (proxy == NULL) {
 		// Either we're not supposed to be using the proxy or the proxy is unavailable.
-		res_setnetid(res, netid);
-		res_setmark(res, mark);
+		res_setnetid(res, netcontext->dns_netid);
+		res_setmark(res, netcontext->dns_mark);
 		return gethostbyname_internal_real(name, af, res, hp, hbuf, hbuflen, errorp);
 	}
 
-	netid = __netdClientDispatch.netIdForResolv(netid);
+	unsigned netid = __netdClientDispatch.netIdForResolv(netcontext->app_netid);
 
 	// This is writing to system/netd/server/DnsProxyListener.cpp and changes
 	// here need to be matched there.
@@ -850,8 +858,8 @@
 int gethostbyaddr_r(const void *addr, socklen_t len, int af, struct hostent *hp, char *buf,
                     size_t buflen, struct hostent **result, int *h_errnop)
 {
-	*result = android_gethostbyaddrfornet_proxy_internal(addr, len, af, hp, buf, buflen, h_errnop,
-                                                       NETID_UNSET, MARK_UNSET);
+	*result = android_gethostbyaddrfornetcontext_proxy_internal(
+		addr, len, af, hp, buf, buflen, h_errnop, &NETCONTEXT_UNSET);
 	if (!*result && errno == ENOSPC) {
 		errno = ERANGE;
 		return ERANGE;
@@ -860,8 +868,9 @@
 }
 
 static struct hostent *
-android_gethostbyaddrfornet_real(const void *addr, socklen_t len, int af, struct hostent *hp,
-                                 char *buf, size_t buflen, int *he, unsigned netid, unsigned mark)
+android_gethostbyaddrfornetcontext_real(const void *addr, socklen_t len, int af, struct hostent *hp,
+                                 char *buf, size_t buflen, int *he,
+				 const struct android_net_context *netcontext)
 {
 	const u_char *uaddr = (const u_char *)addr;
 	socklen_t size;
@@ -913,21 +922,21 @@
 	info.he = he;
 	*he = NETDB_INTERNAL;
 	if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyaddr",
-	    default_dns_files, uaddr, len, af, netid, mark) != NS_SUCCESS)
+	    default_dns_files, uaddr, len, af, netcontext) != NS_SUCCESS)
 		return NULL;
 	*he = NETDB_SUCCESS;
 	return hp;
 }
 
 static struct hostent*
-android_gethostbyaddrfornet_proxy_internal(const void* addr, socklen_t len, int af,
+android_gethostbyaddrfornetcontext_proxy_internal(const void* addr, socklen_t len, int af,
                              struct hostent *hp, char *hbuf, size_t hbuflen, int *he,
-                             unsigned netid, unsigned mark)
+                             const struct android_net_context *netcontext)
 {
 	FILE* proxy = android_open_proxy();
 	if (proxy == NULL) {
 		// Either we're not supposed to be using the proxy or the proxy is unavailable.
-		return android_gethostbyaddrfornet_real(addr,len, af, hp, hbuf, hbuflen, he, netid, mark);
+		return android_gethostbyaddrfornetcontext_real(addr,len, af, hp, hbuf, hbuflen, he, netcontext);
 	}
 
 	char buf[INET6_ADDRSTRLEN];  //big enough for IPv4 and IPv6
@@ -937,7 +946,7 @@
 		return NULL;
 	}
 
-	netid = __netdClientDispatch.netIdForResolv(netid);
+	unsigned netid = __netdClientDispatch.netIdForResolv(netcontext->app_netid);
 
 	if (fprintf(proxy, "gethostbyaddr %s %d %d %u",
 			addrStr, len, af, netid) < 0) {
@@ -1238,15 +1247,14 @@
 	char *bf;
 	size_t blen;
 	struct getnamaddr *info = rv;
-	unsigned netid, mark;
+	const struct android_net_context *netcontext;
 
 	_DIAGASSERT(rv != NULL);
 
 	uaddr = va_arg(ap, unsigned char *);
 	info->hp->h_length = va_arg(ap, int);
 	info->hp->h_addrtype = va_arg(ap, int);
-	netid = va_arg(ap, unsigned);
-	mark = va_arg(ap, unsigned);
+	netcontext = va_arg(ap, const struct android_net_context *);
 
 	switch (info->hp->h_addrtype) {
 	case AF_INET:
@@ -1288,8 +1296,8 @@
 		free(buf);
 		return NS_NOTFOUND;
 	}
-	res_setnetid(res, netid);
-	res_setmark(res, mark);
+	res_setnetid(res, netcontext->dns_netid);
+	res_setmark(res, netcontext->dns_mark);
 	n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, (int)sizeof(buf->buf));
 	if (n < 0) {
 		free(buf);
@@ -1585,16 +1593,39 @@
 	return result;
 }
 
+// android_gethostby*fornet can be called in two different contexts.
+//  - In the proxy client context (proxy != NULL), |netid| is |app_netid|.
+//  - In the proxy listener context (proxy == NULL), |netid| is |dns_netid|.
+// The netcontext is constructed before checking which context we are in.
+// Therefore, we have to populate both fields, and rely on the downstream code to check whether
+// |proxy == NULL|, and use that info to query the field that matches the caller's intent.
+static struct android_net_context make_context(unsigned netid, unsigned mark) {
+	struct android_net_context netcontext = NETCONTEXT_UNSET;
+	netcontext.app_netid = netid;
+	netcontext.app_mark = mark;
+	netcontext.dns_netid = netid;
+	netcontext.dns_mark = mark;
+	return netcontext;
+}
+
 struct hostent *
 android_gethostbynamefornet(const char *name, int af, unsigned netid, unsigned mark)
 {
+	const struct android_net_context netcontext = make_context(netid, mark);
+	return android_gethostbynamefornetcontext(name, af, &netcontext);
+}
+
+struct hostent *
+android_gethostbynamefornetcontext(const char *name, int af,
+	const struct android_net_context *netcontext)
+{
 	struct hostent *hp;
 	res_state res = __res_get_state();
 	if (res == NULL)
 		return NULL;
 	res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */
 	hp = gethostbyname_internal(name, af, res, &rs->host, rs->hostbuf, sizeof(rs->hostbuf),
-	                            &h_errno, netid, mark);
+	                            &h_errno, netcontext);
 	__res_put_state(res);
 	return hp;
 }
@@ -1602,22 +1633,30 @@
 struct hostent *
 gethostbyaddr(const void *addr, socklen_t len, int af)
 {
-	return android_gethostbyaddrfornet_proxy(addr, len, af, NETID_UNSET, MARK_UNSET);
+	return android_gethostbyaddrfornetcontext_proxy(addr, len, af, &NETCONTEXT_UNSET);
 }
 
 struct hostent *
 android_gethostbyaddrfornet(const void *addr, socklen_t len, int af, unsigned netid, unsigned mark)
 {
-	return android_gethostbyaddrfornet_proxy(addr, len, af, netid, mark);
+	const struct android_net_context netcontext = make_context(netid, mark);
+	return android_gethostbyaddrfornetcontext(addr, len, af, &netcontext);
+}
+
+struct hostent *
+android_gethostbyaddrfornetcontext(const void *addr, socklen_t len, int af,
+	const struct android_net_context *netcontext)
+{
+	return android_gethostbyaddrfornetcontext_proxy(addr, len, af, netcontext);
 }
 
 __LIBC_HIDDEN__ struct hostent*
-android_gethostbyaddrfornet_proxy(const void* addr, socklen_t len, int af,
-                                  unsigned netid, unsigned mark)
+android_gethostbyaddrfornetcontext_proxy(const void* addr, socklen_t len, int af,
+                                  const struct android_net_context *netcontext)
 {
 	res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */
-	return android_gethostbyaddrfornet_proxy_internal(addr, len, af, &rs->host, rs->hostbuf,
-                                                    sizeof(rs->hostbuf), &h_errno, netid, mark);
+	return android_gethostbyaddrfornetcontext_proxy_internal(addr, len, af, &rs->host, rs->hostbuf,
+                                                    sizeof(rs->hostbuf), &h_errno, netcontext);
 }
 
 struct hostent *
diff --git a/libc/dns/net/getnameinfo.c b/libc/dns/net/getnameinfo.c
index 236e7f2..5fa4e37 100644
--- a/libc/dns/net/getnameinfo.c
+++ b/libc/dns/net/getnameinfo.c
@@ -300,7 +300,10 @@
 			break;
 		}
 	} else {
-		hp = android_gethostbyaddrfornet_proxy(addr, afd->a_addrlen, afd->a_af, netid, mark);
+		// This code should only run in the app context, not inside netd, so netid is
+		// the app's netid.  netd doesn't use getnameinfo for network requests.
+		const struct android_net_context netcontext = { .app_netid = netid, .app_mark = mark };
+		hp = android_gethostbyaddrfornetcontext_proxy(addr, afd->a_addrlen, afd->a_af, &netcontext);
 		if (hp) {
 #if 0
 			/*
diff --git a/libc/dns/resolv/res_send.c b/libc/dns/resolv/res_send.c
index 586bb8f..3b94fcf 100644
--- a/libc/dns/resolv/res_send.c
+++ b/libc/dns/resolv/res_send.c
@@ -523,6 +523,10 @@
 					res_nclose(statp);
 					goto next_ns;
 				case res_done:
+					if (cache_status == RESOLV_CACHE_NOTFOUND) {
+						_resolv_cache_add(statp->netid, buf, buflen,
+								ans, resplen);
+					}
 					return (resplen);
 				case res_modified:
 					/* give the hook another try */
diff --git a/libc/include/sys/sem.h b/libc/include/sys/sem.h
index 904c334..be0e22d 100644
--- a/libc/include/sys/sem.h
+++ b/libc/include/sys/sem.h
@@ -39,9 +39,17 @@
 
 #include <linux/sem.h>
 
+__BEGIN_DECLS
+
 #define semid_ds semid64_ds
 
-__BEGIN_DECLS
+union semun {
+  int val;
+  struct semid_ds* buf;
+  unsigned short* array;
+  struct seminfo* __buf;
+  void* __pad;
+};
 
 int semctl(int, int, int, ...) __INTRODUCED_IN(26);
 int semget(key_t, int, int) __INTRODUCED_IN(26);
diff --git a/libc/kernel/tools/defaults.py b/libc/kernel/tools/defaults.py
index c22f684..5198dbe 100644
--- a/libc/kernel/tools/defaults.py
+++ b/libc/kernel/tools/defaults.py
@@ -70,6 +70,8 @@
     "semid_ds": "__kernel_legacy_semid_ds",
     "shmid_ds": "__kernel_legacy_shmid_ds",
     "ipc_perm": "__kernel_legacy_ipc_perm",
+    # The kernel semun isn't usable (https://github.com/android-ndk/ndk/issues/400).
+    "semun": "__kernel_legacy_semun",
     # The kernel's _NSIG/NSIG are one less than the userspace value, so we need to move them aside.
     "_NSIG": "_KERNEL__NSIG",
     "NSIG": "_KERNEL_NSIG",
diff --git a/libc/kernel/uapi/linux/sem.h b/libc/kernel/uapi/linux/sem.h
index 6916556..df815db 100644
--- a/libc/kernel/uapi/linux/sem.h
+++ b/libc/kernel/uapi/linux/sem.h
@@ -52,7 +52,7 @@
   short sem_flg;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 };
-union semun {
+union __kernel_legacy_semun {
   int val;
   struct __kernel_legacy_semid_ds __user * buf;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
diff --git a/libc/libc.arm.map b/libc/libc.arm.map
index 4654f99..b32f769 100644
--- a/libc/libc.arm.map
+++ b/libc/libc.arm.map
@@ -1494,7 +1494,9 @@
     android_getaddrinfofornet;
     android_getaddrinfofornetcontext;
     android_gethostbyaddrfornet;
+    android_gethostbyaddrfornetcontext;
     android_gethostbynamefornet;
+    android_gethostbynamefornetcontext;
     arc4random_addrandom; # arm x86 mips
     arc4random_stir; # arm x86 mips
     atexit; # arm
diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map
index 2c04e4d..afcf8bb 100644
--- a/libc/libc.arm64.map
+++ b/libc/libc.arm64.map
@@ -1242,7 +1242,9 @@
     android_getaddrinfofornet;
     android_getaddrinfofornetcontext;
     android_gethostbyaddrfornet;
+    android_gethostbyaddrfornetcontext;
     android_gethostbynamefornet;
+    android_gethostbynamefornetcontext;
     free_malloc_leak_info;
     get_malloc_leak_info;
     gMallocLeakZygoteChild;
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index c4bc262..f05e7eb 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1520,7 +1520,9 @@
     android_getaddrinfofornet;
     android_getaddrinfofornetcontext;
     android_gethostbyaddrfornet;
+    android_gethostbyaddrfornetcontext;
     android_gethostbynamefornet;
+    android_gethostbynamefornetcontext;
     arc4random_addrandom; # arm x86 mips
     arc4random_stir; # arm x86 mips
     atexit; # arm
diff --git a/libc/libc.mips.map b/libc/libc.mips.map
index f68f1c5..a472214 100644
--- a/libc/libc.mips.map
+++ b/libc/libc.mips.map
@@ -1337,7 +1337,9 @@
     android_getaddrinfofornet;
     android_getaddrinfofornetcontext;
     android_gethostbyaddrfornet;
+    android_gethostbyaddrfornetcontext;
     android_gethostbynamefornet;
+    android_gethostbynamefornetcontext;
     arc4random_addrandom; # arm x86 mips
     arc4random_stir; # arm x86 mips
     bcopy; # arm x86 mips
diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map
index 2c04e4d..afcf8bb 100644
--- a/libc/libc.mips64.map
+++ b/libc/libc.mips64.map
@@ -1242,7 +1242,9 @@
     android_getaddrinfofornet;
     android_getaddrinfofornetcontext;
     android_gethostbyaddrfornet;
+    android_gethostbyaddrfornetcontext;
     android_gethostbynamefornet;
+    android_gethostbynamefornetcontext;
     free_malloc_leak_info;
     get_malloc_leak_info;
     gMallocLeakZygoteChild;
diff --git a/libc/libc.x86.map b/libc/libc.x86.map
index bea2fe9..27a597f 100644
--- a/libc/libc.x86.map
+++ b/libc/libc.x86.map
@@ -1336,7 +1336,9 @@
     android_getaddrinfofornet;
     android_getaddrinfofornetcontext;
     android_gethostbyaddrfornet;
+    android_gethostbyaddrfornetcontext;
     android_gethostbynamefornet;
+    android_gethostbynamefornetcontext;
     arc4random_addrandom; # arm x86 mips
     arc4random_stir; # arm x86 mips
     bcopy; # arm x86 mips
diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map
index 2c04e4d..afcf8bb 100644
--- a/libc/libc.x86_64.map
+++ b/libc/libc.x86_64.map
@@ -1242,7 +1242,9 @@
     android_getaddrinfofornet;
     android_getaddrinfofornetcontext;
     android_gethostbyaddrfornet;
+    android_gethostbyaddrfornetcontext;
     android_gethostbynamefornet;
+    android_gethostbynamefornetcontext;
     free_malloc_leak_info;
     get_malloc_leak_info;
     gMallocLeakZygoteChild;
diff --git a/libc/malloc_debug/exported32.map b/libc/malloc_debug/exported32.map
index a985ef9..59bb102 100644
--- a/libc/malloc_debug/exported32.map
+++ b/libc/malloc_debug/exported32.map
@@ -13,6 +13,7 @@
     debug_malloc_disable;
     debug_malloc_enable;
     debug_malloc_usable_size;
+    debug_mallopt;
     debug_memalign;
     debug_posix_memalign;
     debug_pvalloc;
diff --git a/libc/malloc_debug/exported64.map b/libc/malloc_debug/exported64.map
index 1a6b30f..ec9d840 100644
--- a/libc/malloc_debug/exported64.map
+++ b/libc/malloc_debug/exported64.map
@@ -13,6 +13,7 @@
     debug_malloc_disable;
     debug_malloc_enable;
     debug_malloc_usable_size;
+    debug_mallopt;
     debug_memalign;
     debug_posix_memalign;
     debug_realloc;
diff --git a/tests/sys_sem_test.cpp b/tests/sys_sem_test.cpp
index d8d83c5..eaf2b8f 100644
--- a/tests/sys_sem_test.cpp
+++ b/tests/sys_sem_test.cpp
@@ -98,3 +98,19 @@
   ASSERT_EQ(-1, semtimedop(-1, nullptr, 0, nullptr));
   ASSERT_TRUE(errno == EINVAL || errno == ENOSYS);
 }
+
+TEST(sys_sem, union_semun) {
+  // https://github.com/android-ndk/ndk/issues/400
+#if defined(__BIONIC__)
+  semun arg;
+  semid_ds i1;
+  seminfo i2;
+  unsigned short a[] = { 1u, 2u };
+  arg.val = 123;
+  arg.buf = &i1;
+  arg.array = a;
+  arg.__buf = &i2;
+#else
+  // glibc already mostly removed this cruft (although it's still in <linux/sem.h>).
+#endif
+}