Merge changes from topic "sharedlib_in_recovery" am: 2583b0adb2
am: bbf6d709d4

Change-Id: Ia4f7085b1e9da70668655516501759ca68893877
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 9503a49..9094b0a 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -1489,6 +1489,11 @@
 static void soinfo_unload(soinfo* si);
 
 static void shuffle(std::vector<LoadTask*>* v) {
+  if (is_init()) {
+    // arc4random* is not available in init because /dev/random hasn't yet been
+    // created.
+    return;
+  }
   for (size_t i = 0, size = v->size(); i < size; ++i) {
     size_t n = size - i;
     size_t r = arc4random_uniform(n);
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index 1a0d164..a874152 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -197,12 +197,16 @@
 static const char* get_executable_path() {
   static std::string executable_path;
   if (executable_path.empty()) {
-    char path[PATH_MAX];
-    ssize_t path_len = readlink("/proc/self/exe", path, sizeof(path));
-    if (path_len == -1 || path_len >= static_cast<ssize_t>(sizeof(path))) {
-      async_safe_fatal("readlink('/proc/self/exe') failed: %s", strerror(errno));
+    if (!is_init()) {
+      char path[PATH_MAX];
+      ssize_t path_len = readlink("/proc/self/exe", path, sizeof(path));
+      if (path_len == -1 || path_len >= static_cast<ssize_t>(sizeof(path))) {
+        async_safe_fatal("readlink('/proc/self/exe') failed: %s", strerror(errno));
+      }
+      executable_path = std::string(path, path_len);
+    } else {
+      executable_path = "/init";
     }
-    executable_path = std::string(path, path_len);
   }
 
   return executable_path.c_str();
@@ -288,8 +292,14 @@
   // Stat "/proc/self/exe" instead of executable_path because
   // the executable could be unlinked by this point and it should
   // not cause a crash (see http://b/31084669)
-  if (TEMP_FAILURE_RETRY(stat("/proc/self/exe", &file_stat)) != 0) {
-    async_safe_fatal("unable to stat \"/proc/self/exe\": %s", strerror(errno));
+  if (!is_init()) {
+    if (TEMP_FAILURE_RETRY(stat("/proc/self/exe", &file_stat)) != 0) {
+      async_safe_fatal("unable to stat \"/proc/self/exe\": %s", strerror(errno));
+    }
+  } else {
+    // /proc fs is not mounted when init starts. Therefore we can't use
+    // /proc/self/exe for init.
+    stat("/init", &file_stat);
   }
 
   const char* executable_path = get_executable_path();
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index a5eab44..b24be92 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -547,7 +547,10 @@
 
   uint8_t* first = align_up(mmap_ptr, align);
   uint8_t* last = align_down(mmap_ptr + mmap_size, align) - size;
-  size_t n = arc4random_uniform((last - first) / PAGE_SIZE + 1);
+
+  // arc4random* is not available in init because /dev/urandom hasn't yet been
+  // created. Don't randomize then.
+  size_t n = is_init() ? 0 : arc4random_uniform((last - first) / PAGE_SIZE + 1);
   uint8_t* start = first + n * PAGE_SIZE;
   munmap(mmap_ptr, start - mmap_ptr);
   munmap(start + size, mmap_ptr + mmap_size - (start + size));
diff --git a/linker/linker_soinfo.cpp b/linker/linker_soinfo.cpp
index 3191ac7..795b01d 100644
--- a/linker/linker_soinfo.cpp
+++ b/linker/linker_soinfo.cpp
@@ -748,7 +748,14 @@
   // Make sure the handle is unique and does not collide
   // with special values which are RTLD_DEFAULT and RTLD_NEXT.
   do {
-    arc4random_buf(&handle_, sizeof(handle_));
+    if (!is_init()) {
+      arc4random_buf(&handle_, sizeof(handle_));
+    } else {
+      // arc4random* is not available in init because /dev/urandom hasn't yet been
+      // created. So, when running with init, use the monotonically increasing
+      // numbers as handles
+      handle_ += 2;
+    }
     // the least significant bit for the handle is always 1
     // making it easy to test the type of handle passed to
     // dl* functions.
diff --git a/linker/linker_utils.cpp b/linker/linker_utils.cpp
index 661e7cb..789d5c1 100644
--- a/linker/linker_utils.cpp
+++ b/linker/linker_utils.cpp
@@ -239,3 +239,8 @@
     }
   }
 }
+
+bool is_init() {
+  static bool ret = (getpid() == 1);
+  return ret;
+}
diff --git a/linker/linker_utils.h b/linker/linker_utils.h
index 214646c..b15082d 100644
--- a/linker/linker_utils.h
+++ b/linker/linker_utils.h
@@ -55,3 +55,4 @@
 off64_t page_start(off64_t offset);
 size_t page_offset(off64_t offset);
 bool safe_add(off64_t* out, off64_t a, size_t b);
+bool is_init();