diff --git a/libc/bionic/stubs.cpp b/libc/bionic/stubs.cpp index 41c78bc99..0340f0ea2 100644 --- a/libc/bionic/stubs.cpp +++ b/libc/bionic/stubs.cpp @@ -206,7 +206,7 @@ static group* android_name_to_group(group_state_t* state, const char* name) { // u0_a1234 -> 0 * AID_USER + AID_APP + 1234 // u2_i1000 -> 2 * AID_USER + AID_ISOLATED_START + 1000 // u1_system -> 1 * AID_USER + android_ids['system'] -// returns 0 and sets errno to ENOENT in case of error +// returns 0 and sets errno to ENOENT in case of error. static id_t app_id_from_name(const char* name, bool is_group) { char* end; unsigned long userid; @@ -312,6 +312,54 @@ static void print_app_name_from_gid(const gid_t gid, char* buffer, const int buf } } +// Translate an OEM name to the corresponding user/group id. +// oem_XXX -> AID_OEM_RESERVED_2_START + XXX, iff XXX is within range. +static id_t oem_id_from_name(const char* name) { + unsigned int id; + if (sscanf(name, "oem_%u", &id) != 1) { + return 0; + } + // Check OEM id is within range. + if (id > (AID_OEM_RESERVED_2_END - AID_OEM_RESERVED_2_START)) { + return 0; + } + return AID_OEM_RESERVED_2_START + static_cast(id); +} + +static passwd* oem_id_to_passwd(uid_t uid, passwd_state_t* state) { + if (uid < AID_OEM_RESERVED_2_START || uid > AID_OEM_RESERVED_2_END) { + return NULL; + } + + snprintf(state->name_buffer_, sizeof(state->name_buffer_), "oem_%u", + uid - AID_OEM_RESERVED_2_START); + snprintf(state->dir_buffer_, sizeof(state->dir_buffer_), "/"); + snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/system/bin/sh"); + + passwd* pw = &state->passwd_; + pw->pw_name = state->name_buffer_; + pw->pw_dir = state->dir_buffer_; + pw->pw_shell = state->sh_buffer_; + pw->pw_uid = uid; + pw->pw_gid = uid; + return pw; +} + +static group* oem_id_to_group(gid_t gid, group_state_t* state) { + if (gid < AID_OEM_RESERVED_2_START || gid > AID_OEM_RESERVED_2_END) { + return NULL; + } + + snprintf(state->group_name_buffer_, sizeof(state->group_name_buffer_), + "oem_%u", gid - AID_OEM_RESERVED_2_START); + + group* gr = &state->group_; + gr->gr_name = state->group_name_buffer_; + gr->gr_gid = gid; + gr->gr_mem[0] = gr->gr_name; + return gr; +} + // Translate a uid into the corresponding name. // 0 to AID_APP-1 -> "system", "radio", etc. // AID_APP to AID_ISOLATED_START-1 -> u0_a1234 @@ -371,6 +419,11 @@ passwd* getpwuid(uid_t uid) { // NOLINT: implementing bad function. if (pw != NULL) { return pw; } + // Handle OEM range. + pw = oem_id_to_passwd(uid, state); + if (pw != NULL) { + return pw; + } return app_id_to_passwd(uid, state); } @@ -384,6 +437,11 @@ passwd* getpwnam(const char* login) { // NOLINT: implementing bad function. if (pw != NULL) { return pw; } + // Handle OEM range. + pw = oem_id_to_passwd(oem_id_from_name(login), state); + if (pw != NULL) { + return pw; + } return app_id_to_passwd(app_id_from_name(login, false), state); } @@ -407,6 +465,11 @@ static group* getgrgid_internal(gid_t gid, group_state_t* state) { if (grp != NULL) { return grp; } + // Handle OEM range. + grp = oem_id_to_group(gid, state); + if (grp != NULL) { + return grp; + } return app_id_to_group(gid, state); } @@ -423,6 +486,11 @@ static group* getgrnam_internal(const char* name, group_state_t* state) { if (grp != NULL) { return grp; } + // Handle OEM range. + grp = oem_id_to_group(oem_id_from_name(name), state); + if (grp != NULL) { + return grp; + } return app_id_to_group(app_id_from_name(name, true), state); } diff --git a/tests/stubs_test.cpp b/tests/stubs_test.cpp index 2d1bdeee6..c81ca5803 100644 --- a/tests/stubs_test.cpp +++ b/tests/stubs_test.cpp @@ -122,6 +122,14 @@ TEST(getpwnam, app_id_radio) { check_get_passwd("radio", 1001, TYPE_SYSTEM); } +TEST(getpwnam, oem_id_0) { + check_get_passwd("oem_0", 5000, TYPE_SYSTEM); +} + +TEST(getpwnam, oem_id_999) { + check_get_passwd("oem_999", 5999, TYPE_SYSTEM); +} + TEST(getpwnam, app_id_nobody) { check_get_passwd("nobody", 9999, TYPE_SYSTEM); } @@ -247,6 +255,14 @@ TEST(getgrnam, app_id_radio) { check_get_group("radio", 1001); } +TEST(getgrnam, oem_id_0) { + check_get_group("oem_0", 5000); +} + +TEST(getgrnam, oem_id_999) { + check_get_group("oem_999", 5999); +} + TEST(getgrnam, app_id_nobody) { check_get_group("nobody", 9999); }