Merge "linker: disallow W + E PT_LOAD segments"
diff --git a/libc/bionic/sysinfo.cpp b/libc/bionic/sysinfo.cpp
index 1cb5c79..304634a 100644
--- a/libc/bionic/sysinfo.cpp
+++ b/libc/bionic/sysinfo.cpp
@@ -76,29 +76,14 @@
   return cpu_count;
 }
 
-static int __get_meminfo_page_count(const char* pattern) {
-  FILE* fp = fopen("/proc/meminfo", "re");
-  if (fp == NULL) {
-    return -1;
-  }
-
-  int page_count = -1;
-  char buf[256];
-  while (fgets(buf, sizeof(buf), fp) != NULL) {
-    long total;
-    if (sscanf(buf, pattern, &total) == 1) {
-      page_count = static_cast<int>(total / (sysconf(_SC_PAGE_SIZE) / 1024));
-      break;
-    }
-  }
-  fclose(fp);
-  return page_count;
-}
-
 long get_phys_pages() {
-  return __get_meminfo_page_count("MemTotal: %ld kB");
+  struct sysinfo si;
+  sysinfo(&si);
+  return (si.totalram * si.mem_unit) / sysconf(_SC_PAGE_SIZE);
 }
 
 long get_avphys_pages() {
-  return __get_meminfo_page_count("MemFree: %ld kB");
+  struct sysinfo si;
+  sysinfo(&si);
+  return ((si.freeram + si.bufferram) * si.mem_unit) / sysconf(_SC_PAGE_SIZE);
 }
diff --git a/libc/include/cpio.h b/libc/include/cpio.h
new file mode 100644
index 0000000..ceeeb87
--- /dev/null
+++ b/libc/include/cpio.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef _CPIO_H_
+#define _CPIO_H_
+
+#include <sys/cdefs.h>
+
+#define C_IRUSR 0000400
+#define C_IWUSR 0000200
+#define C_IXUSR 0000100
+#define C_IRGRP 0000040
+#define C_IWGRP 0000020
+#define C_IXGRP 0000010
+#define C_IROTH 0000004
+#define C_IWOTH 0000002
+#define C_IXOTH 0000001
+#define C_ISUID 0004000
+#define C_ISGID 0002000
+#define C_ISVTX 0001000
+#define C_ISDIR 0040000
+#define C_ISFIFO 0010000
+#define C_ISREG 0100000
+#define C_ISBLK 0060000
+#define C_ISCHR 0020000
+#define C_ISCTG 0110000
+#define C_ISLNK 0120000
+#define C_ISSOCK 0140000
+
+#define MAGIC "070707"
+
+#endif /* _CPIO_H_ */
diff --git a/libc/include/dlfcn.h b/libc/include/dlfcn.h
index a53f664..9aa4a1f 100644
--- a/libc/include/dlfcn.h
+++ b/libc/include/dlfcn.h
@@ -51,7 +51,7 @@
 
 void* dlopen(const char* filename, int flag);
 int dlclose(void* _Nonnull handle);
-const char* dlerror(void);
+char* dlerror(void);
 void* dlsym(void* handle, const char* _Nonnull symbol);
 void* dlvsym(void* handle, const char* _Nonnull symbol, const char* _Nonnull version) __INTRODUCED_IN(24);
 int dladdr(const void* addr, Dl_info* _Nonnull info);
diff --git a/libc/include/tar.h b/libc/include/tar.h
new file mode 100644
index 0000000..a5d7a36
--- /dev/null
+++ b/libc/include/tar.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef _TAR_H_
+#define _TAR_H_
+
+#include <sys/cdefs.h>
+
+#define TMAGIC "ustar"
+#define TMAGLEN 6
+#define TVERSION "00"
+#define TVERSLEN 2
+
+#define REGTYPE '0'
+#define AREGTYPE '\0'
+#define LNKTYPE '1'
+#define SYMTYPE '2'
+#define CHRTYPE '3'
+#define BLKTYPE '4'
+#define DIRTYPE '5'
+#define FIFOTYPE '6'
+#define CONTTYPE '7'
+
+#define TSUID 04000
+#define TSGID 02000
+#define TSVTX 01000
+#define TUREAD 00400
+#define TUWRITE 00200
+#define TUEXEC 00100
+#define TGREAD 00040
+#define TGWRITE 00020
+#define TGEXEC 00010
+#define TOREAD 00004
+#define TOWRITE 00002
+#define TOEXEC 00001
+
+#endif /* _TAR_H_ */
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index c792289..86949de 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -97,9 +97,10 @@
 int execvp(const char* __file, char* const* __argv);
 int execvpe(const char* __file, char* const* __argv, char* const* __envp) __INTRODUCED_IN(21);
 int execve(const char* __file, char* const* __argv, char* const* __envp);
-int execl(const char* __path, const char* __arg0, ...);
-int execlp(const char* __file, const char* __arg0, ...);
-int execle(const char* __path, const char* __arg0, ...);
+int execl(const char* __path, const char* __arg0, ...) __attribute__((__sentinel__));
+int execlp(const char* __file, const char* __arg0, ...) __attribute__((__sentinel__));
+int execle(const char* __path, const char* __arg0, ... /*,  char* const* __envp */)
+    __attribute__((__sentinel__(1)));
 
 int nice(int __incr);
 
diff --git a/libdl/Android.bp b/libdl/Android.bp
index 84561d9..273a887 100644
--- a/libdl/Android.bp
+++ b/libdl/Android.bp
@@ -60,3 +60,9 @@
         never: true,
     },
 }
+
+ndk_library {
+    name: "libdl.ndk",
+    symbol_file: "libdl.map.txt",
+    first_version: "9",
+}
diff --git a/libdl/libdl.c b/libdl/libdl.c
index b62ee5c..4cc4dea 100644
--- a/libdl/libdl.c
+++ b/libdl/libdl.c
@@ -25,7 +25,7 @@
 
 void* dlopen(const char* filename __unused, int flag __unused) { return 0; }
 
-const char* dlerror(void) { return 0; }
+char* dlerror(void) { return 0; }
 
 void* dlsym(void* handle __unused, const char* symbol __unused) { return 0; }
 
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index 4d9a218..3ac61d7 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -33,10 +33,10 @@
 
 static pthread_mutex_t g_dl_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
 
-static const char* __bionic_set_dlerror(char* new_value) {
+static char* __bionic_set_dlerror(char* new_value) {
   char** dlerror_slot = &reinterpret_cast<char**>(__get_tls())[TLS_SLOT_DLERROR];
 
-  const char* old_value = *dlerror_slot;
+  char* old_value = *dlerror_slot;
   *dlerror_slot = new_value;
   return old_value;
 }
@@ -52,8 +52,8 @@
   __bionic_set_dlerror(buffer);
 }
 
-const char* dlerror() {
-  const char* old_value = __bionic_set_dlerror(nullptr);
+char* dlerror() {
+  char* old_value = __bionic_set_dlerror(nullptr);
   return old_value;
 }
 
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 9b90028..d2a6e7d 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -91,32 +91,35 @@
 static soinfo* sonext;
 static soinfo* somain; // main process, always the one after libdl_info
 
-static const char* const kDefaultLdPaths[] = {
 #if defined(__LP64__)
-  "/system/lib64",
-  "/vendor/lib64",
+static const char* const kSystemLibDir     = "/system/lib64";
+static const char* const kVendorLibDir     = "/vendor/lib64";
+static const char* const kAsanSystemLibDir = "/data/lib64";
+static const char* const kAsanVendorLibDir = "/data/vendor/lib64";
 #else
-  "/system/lib",
-  "/vendor/lib",
+static const char* const kSystemLibDir     = "/system/lib";
+static const char* const kVendorLibDir     = "/vendor/lib";
+static const char* const kAsanSystemLibDir = "/data/lib";
+static const char* const kAsanVendorLibDir = "/data/vendor/lib";
 #endif
+
+static const char* const kDefaultLdPaths[] = {
+  kSystemLibDir,
+  kVendorLibDir,
   nullptr
 };
 
 static const char* const kAsanDefaultLdPaths[] = {
-#if defined(__LP64__)
-  "/data/lib64",
-  "/system/lib64",
-  "/data/vendor/lib64",
-  "/vendor/lib64",
-#else
-  "/data/lib",
-  "/system/lib",
-  "/data/vendor/lib",
-  "/vendor/lib",
-#endif
+  kAsanSystemLibDir,
+  kSystemLibDir,
+  kAsanVendorLibDir,
+  kVendorLibDir,
   nullptr
 };
 
+// Is ASAN enabled?
+static bool g_is_asan = false;
+
 static bool is_system_library(const std::string& realpath) {
   for (const auto& dir : g_default_namespace.get_default_library_paths()) {
     if (file_is_in_dir(realpath, dir)) {
@@ -126,11 +129,16 @@
   return false;
 }
 
-#if defined(__LP64__)
-static const char* const kSystemLibDir = "/system/lib64";
-#else
-static const char* const kSystemLibDir = "/system/lib";
-#endif
+// Checks if the file exists and not a directory.
+static bool file_exists(const char* path) {
+  struct stat s;
+
+  if (stat(path, &s) != 0) {
+    return false;
+  }
+
+  return S_ISREG(s.st_mode);
+}
 
 // TODO(dimitry): The grey-list is a workaround for http://b/26394120 ---
 // gradually remove libraries from this list until it is gone.
@@ -1828,8 +1836,27 @@
     }
   }
 
+  std::string asan_name_holder;
+
+  const char* translated_name = name;
+  if (g_is_asan) {
+    if (file_is_in_dir(name, kSystemLibDir)) {
+      asan_name_holder = std::string(kAsanSystemLibDir) + "/" + basename(name);
+      if (file_exists(asan_name_holder.c_str())) {
+        translated_name = asan_name_holder.c_str();
+        PRINT("linker_asan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
+      }
+    } else if (file_is_in_dir(name, kVendorLibDir)) {
+      asan_name_holder = std::string(kAsanVendorLibDir) + "/" + basename(name);
+      if (file_exists(asan_name_holder.c_str())) {
+        translated_name = asan_name_holder.c_str();
+        PRINT("linker_asan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
+      }
+    }
+  }
+
   ProtectedDataGuard guard;
-  soinfo* si = find_library(ns, name, flags, extinfo, caller);
+  soinfo* si = find_library(ns, translated_name, flags, extinfo, caller);
   if (si != nullptr) {
     failure_guard.disable();
     si->call_constructors();
@@ -3283,6 +3310,7 @@
   const char* bname = basename(interp);
   if (bname && (strcmp(bname, "linker_asan") == 0 || strcmp(bname, "linker_asan64") == 0)) {
     g_default_ld_paths = kAsanDefaultLdPaths;
+    g_is_asan = true;
   } else {
     g_default_ld_paths = kDefaultLdPaths;
   }
diff --git a/tests/sys_sysinfo_test.cpp b/tests/sys_sysinfo_test.cpp
index b00e13f..d7d0f6e 100644
--- a/tests/sys_sysinfo_test.cpp
+++ b/tests/sys_sysinfo_test.cpp
@@ -17,17 +17,28 @@
 #include <gtest/gtest.h>
 
 #include <sys/sysinfo.h>
+#include <unistd.h>
 
 TEST(sys_sysinfo, smoke) {
-  int nprocessor = get_nprocs();
-  ASSERT_GT(nprocessor, 0);
+  int nprocs = get_nprocs();
+  ASSERT_GT(nprocs, 0);
+  ASSERT_EQ(sysconf(_SC_NPROCESSORS_ONLN), nprocs);
 
-  int nprocessor_conf = get_nprocs_conf();
-  ASSERT_GE(nprocessor_conf, nprocessor);
+  int nprocs_conf = get_nprocs_conf();
+  ASSERT_GE(nprocs_conf, nprocs);
+  ASSERT_EQ(sysconf(_SC_NPROCESSORS_CONF), nprocs_conf);
 
   long avail_phys_pages = get_avphys_pages();
   ASSERT_GT(avail_phys_pages, 0);
+  ASSERT_EQ(sysconf(_SC_AVPHYS_PAGES), avail_phys_pages);
 
   long phys_pages = get_phys_pages();
   ASSERT_GE(phys_pages, avail_phys_pages);
+  ASSERT_EQ(sysconf(_SC_PHYS_PAGES), phys_pages);
+}
+
+TEST(sys_sysinfo, sysinfo) {
+  struct sysinfo si;
+  memset(&si, 0, sizeof(si));
+  ASSERT_EQ(0, sysinfo(&si));
 }