Snap for 4787078 from 7b405f8b983fe43401fa9f6c75671b73203b71b0 to pi-release

Change-Id: I8aea358b26f1ad7c96bb0961e536696dedc84c9f
diff --git a/libc/bionic/grp_pwd.cpp b/libc/bionic/grp_pwd.cpp
index 952058f..1de8fc5 100644
--- a/libc/bionic/grp_pwd.cpp
+++ b/libc/bionic/grp_pwd.cpp
@@ -46,8 +46,8 @@
 #include "generated_android_ids.h"
 #include "grp_pwd_file.h"
 
-static PasswdFile vendor_passwd("/vendor/etc/passwd");
-static GroupFile vendor_group("/vendor/etc/group");
+static PasswdFile vendor_passwd("/vendor/etc/passwd", "vendor_");
+static GroupFile vendor_group("/vendor/etc/group", "vendor_");
 
 // POSIX seems to envisage an implementation where the <pwd.h> functions are
 // implemented by brute-force searching with getpwent(3), and the <grp.h>
diff --git a/libc/bionic/grp_pwd_file.cpp b/libc/bionic/grp_pwd_file.cpp
index 37493a7..d19b41e 100644
--- a/libc/bionic/grp_pwd_file.cpp
+++ b/libc/bionic/grp_pwd_file.cpp
@@ -30,9 +30,12 @@
 
 #include <fcntl.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
 
+#include <async_safe/log.h>
+
 #include "private/ErrnoRestorer.h"
 
 // This file mmap's /*/etc/passwd and /*/etc/group in order to return their contents without any
@@ -189,7 +192,8 @@
 
 }  // namespace
 
-MmapFile::MmapFile(const char* filename) : filename_(filename) {
+MmapFile::MmapFile(const char* filename, const char* required_prefix)
+    : filename_(filename), required_prefix_(required_prefix) {
   lock_.init(false);
 }
 
@@ -266,6 +270,18 @@
 
   while (line_beginning < end) {
     line_beginning = ParseLine(line_beginning, end, line->fields, line->kNumFields);
+    // To comply with Treble, users/groups from the vendor partition need to be prefixed with
+    // vendor_.
+    if (required_prefix_ != nullptr) {
+      if (strncmp(line->fields[0], required_prefix_, strlen(required_prefix_)) != 0) {
+        char name[kGrpPwdBufferSize];
+        CopyFieldToString(name, line->fields[0], sizeof(name));
+        async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+                              "Found user/group name '%s' in '%s' without required prefix '%s'",
+                              name, filename_, required_prefix_);
+        continue;
+      }
+    }
     if (predicate(line)) return true;
   }
 
@@ -303,7 +319,8 @@
   });
 }
 
-PasswdFile::PasswdFile(const char* filename) : mmap_file_(filename) {
+PasswdFile::PasswdFile(const char* filename, const char* required_prefix)
+    : mmap_file_(filename, required_prefix) {
 }
 
 bool PasswdFile::FindById(uid_t id, passwd_state_t* passwd_state) {
@@ -318,7 +335,8 @@
   return mmap_file_.FindByName(name, &passwd_line) && passwd_line.ToPasswdState(passwd_state);
 }
 
-GroupFile::GroupFile(const char* filename) : mmap_file_(filename) {
+GroupFile::GroupFile(const char* filename, const char* required_prefix)
+    : mmap_file_(filename, required_prefix) {
 }
 
 bool GroupFile::FindById(gid_t id, group_state_t* group_state) {
diff --git a/libc/bionic/grp_pwd_file.h b/libc/bionic/grp_pwd_file.h
index 048cd82..29d75f4 100644
--- a/libc/bionic/grp_pwd_file.h
+++ b/libc/bionic/grp_pwd_file.h
@@ -37,7 +37,7 @@
 
 class MmapFile {
  public:
-  MmapFile(const char* filename);
+  MmapFile(const char* filename, const char* required_prefix);
 
   template <typename Line>
   bool FindById(uid_t uid, Line* line);
@@ -65,11 +65,12 @@
   const char* filename_ = nullptr;
   const char* start_ = nullptr;
   const char* end_ = nullptr;
+  const char* required_prefix_;
 };
 
 class PasswdFile {
  public:
-  PasswdFile(const char* filename);
+  PasswdFile(const char* filename, const char* required_prefix);
 
   bool FindById(uid_t id, passwd_state_t* passwd_state);
   bool FindByName(const char* name, passwd_state_t* passwd_state);
@@ -85,7 +86,7 @@
 
 class GroupFile {
  public:
-  GroupFile(const char* filename);
+  GroupFile(const char* filename, const char* required_prefix);
 
   bool FindById(gid_t id, group_state_t* group_state);
   bool FindByName(const char* name, group_state_t* group_state);
diff --git a/libc/private/grp_pwd.h b/libc/private/grp_pwd.h
index e1aff4f..ab79586 100644
--- a/libc/private/grp_pwd.h
+++ b/libc/private/grp_pwd.h
@@ -31,18 +31,20 @@
 #include <grp.h>
 #include <pwd.h>
 
+static constexpr size_t kGrpPwdBufferSize = 32;
+
 struct group_state_t {
   group group_;
   char* group_members_[2];
-  char group_name_buffer_[32];
+  char group_name_buffer_[kGrpPwdBufferSize];
   // Must be last so init_group_state can run a simple memset for the above
   ssize_t getgrent_idx;
 };
 
 struct passwd_state_t {
   passwd passwd_;
-  char name_buffer_[32];
-  char dir_buffer_[32];
-  char sh_buffer_[32];
+  char name_buffer_[kGrpPwdBufferSize];
+  char dir_buffer_[kGrpPwdBufferSize];
+  char sh_buffer_[kGrpPwdBufferSize];
   ssize_t getpwent_idx;
 };
diff --git a/linker/linker.cpp b/linker/linker.cpp
index a0205dc..c78b9ab 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -44,6 +44,7 @@
 #include <unordered_map>
 #include <vector>
 
+#include <android-base/properties.h>
 #include <android-base/scopeguard.h>
 
 #include <async_safe/log.h>
@@ -89,6 +90,7 @@
 static const char* const kLdConfigArchFilePath = "/system/etc/ld.config." ABI_STRING ".txt";
 
 static const char* const kLdConfigFilePath = "/system/etc/ld.config.txt";
+static const char* const kLdConfigVndkLiteFilePath = "/system/etc/ld.config.vndk_lite.txt";
 
 #if defined(__LP64__)
 static const char* const kSystemLibDir     = "/system/lib64";
@@ -3721,6 +3723,42 @@
   return namespaces;
 }
 
+static std::string get_ld_config_file_vndk_path() {
+  if (android::base::GetBoolProperty("ro.vndk.lite", false)) {
+    return kLdConfigVndkLiteFilePath;
+  }
+
+  std::string ld_config_file_vndk = kLdConfigFilePath;
+  size_t insert_pos = ld_config_file_vndk.find_last_of('.');
+  if (insert_pos == std::string::npos) {
+    insert_pos = ld_config_file_vndk.length();
+  }
+  ld_config_file_vndk.insert(insert_pos, Config::get_vndk_version_string('.'));
+  return ld_config_file_vndk;
+}
+
+static std::string get_ld_config_file_path() {
+#ifdef USE_LD_CONFIG_FILE
+  // This is a debugging/testing only feature. Must not be available on
+  // production builds.
+  const char* ld_config_file_env = getenv("LD_CONFIG_FILE");
+  if (ld_config_file_env != nullptr && file_exists(ld_config_file_env)) {
+    return ld_config_file_env;
+  }
+#endif
+
+  if (file_exists(kLdConfigArchFilePath)) {
+    return kLdConfigArchFilePath;
+  }
+
+  std::string ld_config_file_vndk = get_ld_config_file_vndk_path();
+  if (file_exists(ld_config_file_vndk.c_str())) {
+    return ld_config_file_vndk;
+  }
+
+  return kLdConfigFilePath;
+}
+
 std::vector<android_namespace_t*> init_default_namespaces(const char* executable_path) {
   g_default_namespace.set_name("(default)");
 
@@ -3738,31 +3776,16 @@
 
   std::string error_msg;
 
-  std::string ld_config_vndk = kLdConfigFilePath;
-  size_t insert_pos = ld_config_vndk.find_last_of('.');
-  if (insert_pos == std::string::npos) {
-    insert_pos = ld_config_vndk.length();
-  }
-  ld_config_vndk.insert(insert_pos, Config::get_vndk_version_string('.'));
-  const char* ld_config_txt = file_exists(ld_config_vndk.c_str()) ? ld_config_vndk.c_str() : kLdConfigFilePath;
-  const char* config_file = file_exists(kLdConfigArchFilePath) ? kLdConfigArchFilePath : ld_config_txt;
-#ifdef USE_LD_CONFIG_FILE
-  // This is a debugging/testing only feature. Must not be available on
-  // production builds.
-  const char* ld_config_file = getenv("LD_CONFIG_FILE");
-  if (ld_config_file != nullptr && file_exists(ld_config_file)) {
-    config_file = ld_config_file;
-  }
-#endif
+  std::string ld_config_file_path = get_ld_config_file_path();
 
-  if (!Config::read_binary_config(config_file,
+  if (!Config::read_binary_config(ld_config_file_path.c_str(),
                                   executable_path,
                                   g_is_asan,
                                   &config,
                                   &error_msg)) {
     if (!error_msg.empty()) {
       DL_WARN("Warning: couldn't read \"%s\" for \"%s\" (using default configuration instead): %s",
-              config_file,
+              ld_config_file_path.c_str(),
               executable_path,
               error_msg.c_str());
     }
diff --git a/tests/grp_pwd_file_test.cpp b/tests/grp_pwd_file_test.cpp
index d6f3c9f..8721805 100644
--- a/tests/grp_pwd_file_test.cpp
+++ b/tests/grp_pwd_file_test.cpp
@@ -94,7 +94,7 @@
   static const char test_string[] = "name:password:1:2:user_info:dir:shell\n";
   write(file.fd, test_string, sizeof(test_string) - 1);
 
-  PasswdFile passwd_file(file.filename);
+  PasswdFile passwd_file(file.filename, nullptr);
   FileUnmapper unmapper(passwd_file);
 
   FindAndCheckPasswdEntry(&passwd_file, "name", 1, 2, "dir", "shell");
@@ -114,7 +114,7 @@
   static const char test_string[] = "name:password:1:one,two,three\n";
   write(file.fd, test_string, sizeof(test_string) - 1);
 
-  GroupFile group_file(file.filename);
+  GroupFile group_file(file.filename, nullptr);
   FileUnmapper unmapper(group_file);
 
   FindAndCheckGroupEntry(&group_file, "name", 1);
@@ -150,7 +150,7 @@
 
   write(file.fd, test_string, sizeof(test_string) - 1);
 
-  PasswdFile passwd_file(file.filename);
+  PasswdFile passwd_file(file.filename, nullptr);
   FileUnmapper unmapper(passwd_file);
 
   FindAndCheckPasswdEntry(&passwd_file, "first", 1, 2, "dir", "shell");
@@ -186,7 +186,7 @@
 
   write(file.fd, test_string, sizeof(test_string) - 1);
 
-  GroupFile group_file(file.filename);
+  GroupFile group_file(file.filename, nullptr);
   FileUnmapper unmapper(group_file);
 
   FindAndCheckGroupEntry(&group_file, "first", 1);
@@ -200,3 +200,47 @@
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif  // __BIONIC__
 }
+
+TEST(grp_pwd_file, passwd_file_required_prefix) {
+#if defined(__BIONIC__)
+  TemporaryFile file;
+  ASSERT_NE(-1, file.fd);
+  static const char test_string[] =
+      "name:password:1:2:user_info:dir:shell\n"
+      "vendor_name:password:3:4:user_info:dir:shell\n";
+  write(file.fd, test_string, sizeof(test_string) - 1);
+
+  PasswdFile passwd_file(file.filename, "vendor_");
+  FileUnmapper unmapper(passwd_file);
+
+  EXPECT_FALSE(passwd_file.FindByName("name", nullptr));
+  EXPECT_FALSE(passwd_file.FindById(1, nullptr));
+
+  FindAndCheckPasswdEntry(&passwd_file, "vendor_name", 3, 4, "dir", "shell");
+
+#else   // __BIONIC__
+  GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif  // __BIONIC__
+}
+
+TEST(grp_pwd_file, group_file_required_prefix) {
+#if defined(__BIONIC__)
+  TemporaryFile file;
+  ASSERT_NE(-1, file.fd);
+  static const char test_string[] =
+      "name:password:1:one,two,three\n"
+      "vendor_name:password:2:one,two,three\n";
+  write(file.fd, test_string, sizeof(test_string) - 1);
+
+  GroupFile group_file(file.filename, "vendor_");
+  FileUnmapper unmapper(group_file);
+
+  EXPECT_FALSE(group_file.FindByName("name", nullptr));
+  EXPECT_FALSE(group_file.FindById(1, nullptr));
+
+  FindAndCheckGroupEntry(&group_file, "vendor_name", 2);
+
+#else   // __BIONIC__
+  GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif  // __BIONIC__
+}