Do not allow System.load() of external libraries

The greylisting mechanism had a bug that allowed
loading any library using absolute path from java code.

It mistakenly assumed they are needed by greylisted
system library when in fact it is dlopen() call from
libnativeloader.

This patch fixes this problem by checking that the library is in
fact dt_needed and it is not a dlopen call.

Bug: http://b/26394120
Bug: http://b/22548808
Change-Id: Ia3d4c19e77b04d09a6c3047d684d0c04bd5c785e
diff --git a/linker/linker.cpp b/linker/linker.cpp
index bb592c8..72e7759 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -1187,6 +1187,14 @@
     extinfo_ = extinfo;
   }
 
+  bool is_dt_needed() const {
+    return is_dt_needed_;
+  }
+
+  void set_dt_needed(bool is_dt_needed) {
+    is_dt_needed_ = is_dt_needed;
+  }
+
   const ElfReader& get_elf_reader() const {
     CHECK(si_ != nullptr);
     return (*elf_readers_map_)[si_];
@@ -1226,7 +1234,8 @@
   LoadTask(const char* name, soinfo* needed_by,
            std::unordered_map<const soinfo*, ElfReader>* readers_map)
     : name_(name), needed_by_(needed_by), si_(nullptr),
-      fd_(-1), close_fd_(false), file_offset_(0), elf_readers_map_(readers_map) {}
+      fd_(-1), close_fd_(false), file_offset_(0), elf_readers_map_(readers_map),
+      is_dt_needed_(false) {}
 
   ~LoadTask() {
     if (fd_ != -1 && close_fd_) {
@@ -1242,6 +1251,9 @@
   bool close_fd_;
   off64_t file_offset_;
   std::unordered_map<const soinfo*, ElfReader>* elf_readers_map_;
+  // TODO(dimitry): workaround for http://b/26394120 - will be removed before the release
+  bool is_dt_needed_;
+  // END OF WORKAROUND
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(LoadTask);
 };
@@ -1772,7 +1784,7 @@
 
   if (!ns->is_accessible(realpath)) {
     // TODO(dimitry): workaround for http://b/26394120 - will be removed before the release
-    const soinfo* needed_by = task->get_needed_by();
+    const soinfo* needed_by = task->is_dt_needed() ? task->get_needed_by() : nullptr;
     if (is_greylisted(name, needed_by)) {
       // print warning only if needed by non-system library
       if (needed_by == nullptr || !is_system_library(needed_by->get_realpath())) {
@@ -2040,6 +2052,7 @@
 
     bool is_dt_needed = needed_by != nullptr && (needed_by != start_with || add_as_children);
     task->set_extinfo(is_dt_needed ? nullptr : extinfo);
+    task->set_dt_needed(is_dt_needed);
 
     if(!find_library_internal(ns, task, &zip_archive_cache, &load_tasks, rtld_flags)) {
       return false;