diff --git a/libc/bionic/grp_pwd.cpp b/libc/bionic/grp_pwd.cpp index d37fadd38..6f8c07e48 100644 --- a/libc/bionic/grp_pwd.cpp +++ b/libc/bionic/grp_pwd.cpp @@ -50,8 +50,21 @@ #include "generated_android_ids.h" #include "grp_pwd_file.h" -static PasswdFile vendor_passwd("/vendor/etc/passwd", "vendor_"); -static GroupFile vendor_group("/vendor/etc/group", "vendor_"); +static PasswdFile passwd_files[] = { + { "/system/etc/passwd", "system_" }, + { "/vendor/etc/passwd", "vendor_" }, + { "/odm/etc/passwd", "odm_" }, + { "/product/etc/passwd", "product_" }, + { "/system_ext/etc/passwd", "system_ext_" }, +}; + +static GroupFile group_files[] = { + { "/system/etc/group", "system_" }, + { "/vendor/etc/group", "vendor_" }, + { "/odm/etc/group", "odm_" }, + { "/product/etc/group", "product_" }, + { "/system_ext/etc/group", "system_ext_" }, +}; // POSIX seems to envisage an implementation where the functions are // implemented by brute-force searching with getpwent(3), and the @@ -91,7 +104,7 @@ static passwd* android_iinfo_to_passwd(passwd_state_t* state, const android_id_info* iinfo) { snprintf(state->name_buffer_, sizeof(state->name_buffer_), "%s", iinfo->name); snprintf(state->dir_buffer_, sizeof(state->dir_buffer_), "/"); - snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/system/bin/sh"); + snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/bin/sh"); passwd* pw = &state->passwd_; pw->pw_uid = iinfo->aid; @@ -421,17 +434,19 @@ static id_t oem_id_from_name(const char* name) { } static passwd* oem_id_to_passwd(uid_t uid, passwd_state_t* state) { + for (auto& passwd_file : passwd_files) { + if (passwd_file.FindById(uid, state)) { + return &state->passwd_; + } + } + if (!is_oem_id(uid)) { return nullptr; } - if (vendor_passwd.FindById(uid, state)) { - return &state->passwd_; - } - snprintf(state->name_buffer_, sizeof(state->name_buffer_), "oem_%u", uid); snprintf(state->dir_buffer_, sizeof(state->dir_buffer_), "/"); - snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/vendor/bin/sh"); + snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/bin/sh"); passwd* pw = &state->passwd_; pw->pw_uid = uid; @@ -440,12 +455,14 @@ static passwd* oem_id_to_passwd(uid_t uid, passwd_state_t* state) { } static group* oem_id_to_group(gid_t gid, group_state_t* state) { - if (!is_oem_id(gid)) { - return nullptr; + for (auto& group_file : group_files) { + if (group_file.FindById(gid, state)) { + return &state->group_; + } } - if (vendor_group.FindById(gid, state)) { - return &state->group_; + if (!is_oem_id(gid)) { + return nullptr; } snprintf(state->group_name_buffer_, sizeof(state->group_name_buffer_), @@ -477,7 +494,7 @@ static passwd* app_id_to_passwd(uid_t uid, passwd_state_t* state) { snprintf(state->dir_buffer_, sizeof(state->dir_buffer_), "/data"); } - snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/system/bin/sh"); + snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/bin/sh"); passwd* pw = &state->passwd_; pw->pw_uid = uid; @@ -523,8 +540,8 @@ passwd* getpwnam_internal(const char* login, passwd_state_t* state) { return android_iinfo_to_passwd(state, android_id_info); } - if (vendor_passwd.FindByName(login, state)) { - if (is_oem_id(state->passwd_.pw_uid)) { + for (auto& passwd_file : passwd_files) { + if (passwd_file.FindByName(login, state)) { return &state->passwd_; } } @@ -633,6 +650,22 @@ passwd* getpwent() { state->getpwent_idx++ - start + AID_OEM_RESERVED_2_START, state); } + start = end; + end += AID_SYSTEM_EXT_RESERVED_END - AID_SYSTEM_RESERVED_START + 1; + + if (state->getpwent_idx < end) { + // No one calls this enough to worry about how inefficient the below is. + auto* oem_passwd = + oem_id_to_passwd(state->getpwent_idx++ - start + AID_SYSTEM_RESERVED_START, state); + while (oem_passwd == nullptr && state->getpwent_idx < end) { + oem_passwd = + oem_id_to_passwd(state->getpwent_idx++ - start + AID_SYSTEM_RESERVED_START, state); + } + if (oem_passwd != nullptr) { + return oem_passwd; + } + } + state->getpwent_idx = get_next_app_id(state->getpwent_idx, false); if (state->getpwent_idx != -1) { @@ -666,8 +699,8 @@ static group* getgrnam_internal(const char* name, group_state_t* state) { return android_iinfo_to_group(state, android_id_info); } - if (vendor_group.FindByName(name, state)) { - if (is_oem_id(state->group_.gr_gid)) { + for (auto& group_file : group_files) { + if (group_file.FindByName(name, state)) { return &state->group_; } } @@ -753,6 +786,22 @@ group* getgrent() { state->getgrent_idx++ - start + AID_OEM_RESERVED_2_START, state); } + start = end; + end += AID_SYSTEM_EXT_RESERVED_END - AID_SYSTEM_RESERVED_START + 1; + + if (state->getgrent_idx < end) { + // No one calls this enough to worry about how inefficient the below is. + init_group_state(state); + auto* oem_group = + oem_id_to_group(state->getgrent_idx++ - start + AID_SYSTEM_RESERVED_START, state); + while (oem_group == nullptr && state->getgrent_idx < end) { + oem_group = oem_id_to_group(state->getgrent_idx++ - start + AID_SYSTEM_RESERVED_START, state); + } + if (oem_group != nullptr) { + return oem_group; + } + } + start = end; end += AID_USER_OFFSET - AID_APP_START; // Do not expose higher groups diff --git a/libc/bionic/grp_pwd_file.cpp b/libc/bionic/grp_pwd_file.cpp index 201c9d084..e13604e68 100644 --- a/libc/bionic/grp_pwd_file.cpp +++ b/libc/bionic/grp_pwd_file.cpp @@ -270,8 +270,8 @@ bool MmapFile::Find(Line* line, Predicate predicate) { 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_. + // To comply with Treble, users/groups from each partition need to be prefixed with + // the partition name. if (required_prefix_ != nullptr) { if (strncmp(line->fields[0], required_prefix_, strlen(required_prefix_)) != 0) { char name[kGrpPwdBufferSize]; diff --git a/libc/symbol_ordering b/libc/symbol_ordering index c04692bca..679d461bb 100644 --- a/libc/symbol_ordering +++ b/libc/symbol_ordering @@ -176,8 +176,6 @@ __p_type.typebuf __sym_ntop.unname __sym_ntos.unname _ZL10gFunctions -_ZL12vendor_group -_ZL13vendor_passwd freelist __p_option.nbuf __p_time.nbuf diff --git a/tests/grp_pwd_test.cpp b/tests/grp_pwd_test.cpp index 5b6eed863..6b49e298e 100644 --- a/tests/grp_pwd_test.cpp +++ b/tests/grp_pwd_test.cpp @@ -75,11 +75,7 @@ static void check_passwd(const passwd* pwd, const char* username, uid_t uid, uid EXPECT_STREQ("/", pwd->pw_dir); } - if (uid_type == TYPE_VENDOR) { - EXPECT_STREQ("/vendor/bin/sh", pwd->pw_shell); - } else { - EXPECT_STREQ("/system/bin/sh", pwd->pw_shell); - } + EXPECT_STREQ("/bin/sh", pwd->pw_shell); } static void check_getpwuid(const char* username, uid_t uid, uid_type_t uid_type, @@ -382,7 +378,7 @@ TEST(pwd, getpwnam_r_large_enough_suggested_buffer_size) { #if defined(__BIONIC__) template -static void expect_ids(const T& ids, bool is_group) { +static void expect_ids(T ids, bool is_group) { std::set expected_ids; // Ensure that all android_ids are iterated through. for (size_t n = 0; n < android_id_count; ++n) { @@ -415,6 +411,14 @@ static void expect_ids(const T& ids, bool is_group) { return; } + auto allow_range = [&ids](uid_t start, uid_t end) { + for (size_t n = start; n <= end; ++n) { + ids.erase(n); + } + }; + + allow_range(AID_SYSTEM_RESERVED_START, AID_SYSTEM_EXT_RESERVED_END); + // Ensure that no other ids were returned. auto return_differences = [&ids, &expected_ids] { std::vector missing_from_ids;