Home | History | Annotate | Download | only in bionic
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *  * Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  *  * Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in
     12  *    the documentation and/or other materials provided with the
     13  *    distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
     22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include <ctype.h>
     30 #include <errno.h>
     31 #include <grp.h>
     32 #include <mntent.h>
     33 #include <pthread.h>
     34 #include <pwd.h>
     35 #include <stdio.h>
     36 #include <stdlib.h>
     37 #include <string.h>
     38 #include <unistd.h>
     39 
     40 #include "private/android_filesystem_config.h"
     41 #include "private/bionic_macros.h"
     42 #include "private/grp_pwd.h"
     43 #include "private/ErrnoRestorer.h"
     44 
     45 // Generated android_ids array
     46 #include "generated_android_ids.h"
     47 #include "grp_pwd_file.h"
     48 
     49 static PasswdFile vendor_passwd("/vendor/etc/passwd", "vendor_");
     50 static GroupFile vendor_group("/vendor/etc/group", "vendor_");
     51 
     52 // POSIX seems to envisage an implementation where the <pwd.h> functions are
     53 // implemented by brute-force searching with getpwent(3), and the <grp.h>
     54 // functions are implemented similarly with getgrent(3). This means that it's
     55 // okay for all the <grp.h> functions to share state, and all the <passwd.h>
     56 // functions to share state, but <grp.h> functions can't clobber <passwd.h>
     57 // functions' state and vice versa.
     58 #include "bionic/pthread_internal.h"
     59 static group_state_t* get_group_tls_buffer() {
     60   return &__get_bionic_tls().group;
     61 }
     62 
     63 static passwd_state_t* get_passwd_tls_buffer() {
     64   return &__get_bionic_tls().passwd;
     65 }
     66 
     67 static void init_group_state(group_state_t* state) {
     68   memset(state, 0, sizeof(group_state_t) - sizeof(state->getgrent_idx));
     69   state->group_.gr_mem = state->group_members_;
     70 }
     71 
     72 static group_state_t* __group_state() {
     73   group_state_t* result = get_group_tls_buffer();
     74   if (result != nullptr) {
     75     init_group_state(result);
     76   }
     77   return result;
     78 }
     79 
     80 static int do_getpw_r(int by_name, const char* name, uid_t uid,
     81                       passwd* dst, char* buf, size_t byte_count,
     82                       passwd** result) {
     83   // getpwnam_r and getpwuid_r don't modify errno, but library calls we
     84   // make might.
     85   ErrnoRestorer errno_restorer;
     86   *result = nullptr;
     87 
     88   // Our implementation of getpwnam(3) and getpwuid(3) use thread-local
     89   // storage, so we can call them as long as we copy everything out
     90   // before returning.
     91   const passwd* src = by_name ? getpwnam(name) : getpwuid(uid); // NOLINT: see above.
     92 
     93   // POSIX allows failure to find a match to be considered a non-error.
     94   // Reporting success (0) but with *result NULL is glibc's behavior.
     95   if (src == nullptr) {
     96     return (errno == ENOENT) ? 0 : errno;
     97   }
     98 
     99   // Work out where our strings will go in 'buf', and whether we've got
    100   // enough space.
    101   size_t required_byte_count = 0;
    102   dst->pw_name = buf;
    103   required_byte_count += strlen(src->pw_name) + 1;
    104   dst->pw_dir = buf + required_byte_count;
    105   required_byte_count += strlen(src->pw_dir) + 1;
    106   dst->pw_shell = buf + required_byte_count;
    107   required_byte_count += strlen(src->pw_shell) + 1;
    108   if (byte_count < required_byte_count) {
    109     return ERANGE;
    110   }
    111 
    112   // Copy the strings.
    113   snprintf(buf, byte_count, "%s%c%s%c%s", src->pw_name, 0, src->pw_dir, 0, src->pw_shell);
    114 
    115   // pw_passwd and pw_gecos are non-POSIX and unused (always NULL) in bionic.
    116   // Note: On LP32, we define pw_gecos to pw_passwd since they're both NULL.
    117   dst->pw_passwd = nullptr;
    118 #if defined(__LP64__)
    119   dst->pw_gecos = nullptr;
    120 #endif
    121 
    122   // Copy the integral fields.
    123   dst->pw_gid = src->pw_gid;
    124   dst->pw_uid = src->pw_uid;
    125 
    126   *result = dst;
    127   return 0;
    128 }
    129 
    130 int getpwnam_r(const char* name, passwd* pwd,
    131                char* buf, size_t byte_count, passwd** result) {
    132   return do_getpw_r(1, name, -1, pwd, buf, byte_count, result);
    133 }
    134 
    135 int getpwuid_r(uid_t uid, passwd* pwd,
    136                char* buf, size_t byte_count, passwd** result) {
    137   return do_getpw_r(0, nullptr, uid, pwd, buf, byte_count, result);
    138 }
    139 
    140 static passwd* android_iinfo_to_passwd(passwd_state_t* state,
    141                                        const android_id_info* iinfo) {
    142   snprintf(state->name_buffer_, sizeof(state->name_buffer_), "%s", iinfo->name);
    143   snprintf(state->dir_buffer_, sizeof(state->dir_buffer_), "/");
    144   snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/system/bin/sh");
    145 
    146   passwd* pw = &state->passwd_;
    147   pw->pw_name  = state->name_buffer_;
    148   pw->pw_uid   = iinfo->aid;
    149   pw->pw_gid   = iinfo->aid;
    150   pw->pw_dir   = state->dir_buffer_;
    151   pw->pw_shell = state->sh_buffer_;
    152   return pw;
    153 }
    154 
    155 static group* android_iinfo_to_group(group_state_t* state,
    156                                      const android_id_info* iinfo) {
    157   snprintf(state->group_name_buffer_, sizeof(state->group_name_buffer_), "%s", iinfo->name);
    158 
    159   group* gr = &state->group_;
    160   gr->gr_name   = state->group_name_buffer_;
    161   gr->gr_gid    = iinfo->aid;
    162   gr->gr_mem[0] = gr->gr_name;
    163   return gr;
    164 }
    165 
    166 static passwd* android_id_to_passwd(passwd_state_t* state, unsigned id) {
    167   for (size_t n = 0; n < android_id_count; ++n) {
    168     if (android_ids[n].aid == id) {
    169       return android_iinfo_to_passwd(state, android_ids + n);
    170     }
    171   }
    172   return nullptr;
    173 }
    174 
    175 static passwd* android_name_to_passwd(passwd_state_t* state, const char* name) {
    176   for (size_t n = 0; n < android_id_count; ++n) {
    177     if (!strcmp(android_ids[n].name, name)) {
    178       return android_iinfo_to_passwd(state, android_ids + n);
    179     }
    180   }
    181   return nullptr;
    182 }
    183 
    184 static group* android_id_to_group(group_state_t* state, unsigned id) {
    185   for (size_t n = 0; n < android_id_count; ++n) {
    186     if (android_ids[n].aid == id) {
    187       return android_iinfo_to_group(state, android_ids + n);
    188     }
    189   }
    190   return nullptr;
    191 }
    192 
    193 static group* android_name_to_group(group_state_t* state, const char* name) {
    194   for (size_t n = 0; n < android_id_count; ++n) {
    195     if (!strcmp(android_ids[n].name, name)) {
    196       return android_iinfo_to_group(state, android_ids + n);
    197     }
    198   }
    199   return nullptr;
    200 }
    201 
    202 // These are a list of the reserved app ranges, and should never contain anything below
    203 // AID_APP_START.  They exist per user, so a given uid/gid modulo AID_USER_OFFSET will map
    204 // to these ranges.
    205 static constexpr struct {
    206   uid_t start;
    207   uid_t end;
    208 } user_ranges[] = {
    209   { AID_APP_START, AID_APP_END },
    210   { AID_CACHE_GID_START, AID_CACHE_GID_END },
    211   { AID_EXT_GID_START, AID_EXT_GID_END },
    212   { AID_EXT_CACHE_GID_START, AID_EXT_CACHE_GID_END },
    213   { AID_SHARED_GID_START, AID_SHARED_GID_END },
    214   { AID_ISOLATED_START, AID_ISOLATED_END },
    215 };
    216 
    217 static constexpr bool verify_user_ranges_ascending() {
    218   auto array_size = arraysize(user_ranges);
    219   if (array_size < 2) return false;
    220 
    221   if (user_ranges[0].start > user_ranges[0].end) return false;
    222 
    223   for (size_t i = 1; i < array_size; ++i) {
    224     if (user_ranges[i].start > user_ranges[i].end) return false;
    225     if (user_ranges[i - 1].end > user_ranges[i].start) return false;
    226   }
    227   return true;
    228 }
    229 
    230 static_assert(verify_user_ranges_ascending(), "user_ranges must have ascending ranges");
    231 
    232 static bool is_valid_app_id(id_t id) {
    233   id_t appid = id % AID_USER_OFFSET;
    234 
    235   // AID_OVERFLOWUID is never a valid app id, so we explicitly return false to ensure this.
    236   // This is true across all users, as there is no reason to ever map this id into any user range.
    237   if (appid == AID_OVERFLOWUID) {
    238     return false;
    239   }
    240 
    241   // If we've resolved to something before app_start, we have already checked against
    242   // android_ids, so no need to check again.
    243   if (appid < user_ranges[0].start) {
    244     return true;
    245   }
    246 
    247   // Otherwise check that the appid is in one of the reserved ranges.
    248   for (size_t i = 0; i < arraysize(user_ranges); ++i) {
    249     if (appid >= user_ranges[i].start && appid <= user_ranges[i].end) {
    250       return true;
    251     }
    252   }
    253 
    254   return false;
    255 }
    256 
    257 // This provides an iterater for app_ids within the first user's app id's.
    258 static uid_t get_next_app_id(uid_t current_id) {
    259   // If current_id is below the first of the user_ranges, then we're uninitialized, and return the
    260   // first valid id.
    261   if (current_id < user_ranges[0].start) {
    262     return user_ranges[0].start;
    263   }
    264 
    265   uid_t incremented_id = current_id + 1;
    266 
    267   // Check to see if our incremented_id is between two ranges, and if so, return the beginning of
    268   // the next valid range.
    269   for (size_t i = 1; i < arraysize(user_ranges); ++i) {
    270     if (incremented_id > user_ranges[i - 1].end && incremented_id < user_ranges[i].start) {
    271       return user_ranges[i].start;
    272     }
    273   }
    274 
    275   // Check to see if our incremented_id is above final range, and return -1 to indicate that we've
    276   // completed if so.
    277   if (incremented_id > user_ranges[arraysize(user_ranges) - 1].end) {
    278     return -1;
    279   }
    280 
    281   // Otherwise the incremented_id is valid, so return it.
    282   return incremented_id;
    283 }
    284 
    285 // Translate a user/group name to the corresponding user/group id.
    286 // all_a1234 -> 0 * AID_USER_OFFSET + AID_SHARED_GID_START + 1234 (group name only)
    287 // u0_a1234_cache -> 0 * AID_USER_OFFSET + AID_CACHE_GID_START + 1234 (group name only)
    288 // u0_a1234 -> 0 * AID_USER_OFFSET + AID_APP_START + 1234
    289 // u2_i1000 -> 2 * AID_USER_OFFSET + AID_ISOLATED_START + 1000
    290 // u1_system -> 1 * AID_USER_OFFSET + android_ids['system']
    291 // returns 0 and sets errno to ENOENT in case of error.
    292 static id_t app_id_from_name(const char* name, bool is_group) {
    293   char* end;
    294   unsigned long userid;
    295   bool is_shared_gid = false;
    296 
    297   if (is_group && name[0] == 'a' && name[1] == 'l' && name[2] == 'l') {
    298     end = const_cast<char*>(name+3);
    299     userid = 0;
    300     is_shared_gid = true;
    301   } else if (name[0] == 'u' && isdigit(name[1])) {
    302     userid = strtoul(name+1, &end, 10);
    303   } else {
    304     errno = ENOENT;
    305     return 0;
    306   }
    307 
    308   if (end[0] != '_' || end[1] == 0) {
    309     errno = ENOENT;
    310     return 0;
    311   }
    312 
    313   unsigned long appid = 0;
    314   if (end[1] == 'a' && isdigit(end[2])) {
    315     if (is_shared_gid) {
    316       // end will point to \0 if the strtoul below succeeds.
    317       appid = strtoul(end+2, &end, 10) + AID_SHARED_GID_START;
    318       if (appid > AID_SHARED_GID_END) {
    319         errno = ENOENT;
    320         return 0;
    321       }
    322     } else {
    323       // end will point to \0 if the strtoul below succeeds.
    324       appid = strtoul(end+2, &end, 10);
    325       if (is_group && !strcmp(end, "_cache")) {
    326         end += 6;
    327         appid += AID_CACHE_GID_START;
    328       } else {
    329         appid += AID_APP_START;
    330       }
    331     }
    332   } else if (end[1] == 'i' && isdigit(end[2])) {
    333     // end will point to \0 if the strtoul below succeeds.
    334     appid = strtoul(end+2, &end, 10) + AID_ISOLATED_START;
    335   } else {
    336     for (size_t n = 0; n < android_id_count; n++) {
    337       if (!strcmp(android_ids[n].name, end + 1)) {
    338         appid = android_ids[n].aid;
    339         // Move the end pointer to the null terminator.
    340         end += strlen(android_ids[n].name) + 1;
    341         break;
    342       }
    343     }
    344   }
    345 
    346   // Check that the entire string was consumed by one of the 3 cases above.
    347   if (end[0] != 0) {
    348     errno = ENOENT;
    349     return 0;
    350   }
    351 
    352   // Check that user id won't overflow.
    353   if (userid > 1000) {
    354     errno = ENOENT;
    355     return 0;
    356   }
    357 
    358   // Check that app id is within range.
    359   if (appid >= AID_USER_OFFSET) {
    360     errno = ENOENT;
    361     return 0;
    362   }
    363 
    364   return (appid + userid*AID_USER_OFFSET);
    365 }
    366 
    367 static void print_app_name_from_uid(const uid_t uid, char* buffer, const int bufferlen) {
    368   const uid_t appid = uid % AID_USER_OFFSET;
    369   const uid_t userid = uid / AID_USER_OFFSET;
    370   if (appid >= AID_ISOLATED_START) {
    371     snprintf(buffer, bufferlen, "u%u_i%u", userid, appid - AID_ISOLATED_START);
    372   } else if (appid < AID_APP_START) {
    373     for (size_t n = 0; n < android_id_count; n++) {
    374       if (android_ids[n].aid == appid) {
    375         snprintf(buffer, bufferlen, "u%u_%s", userid, android_ids[n].name);
    376         return;
    377       }
    378     }
    379   } else {
    380     snprintf(buffer, bufferlen, "u%u_a%u", userid, appid - AID_APP_START);
    381   }
    382 }
    383 
    384 static void print_app_name_from_gid(const gid_t gid, char* buffer, const int bufferlen) {
    385   const uid_t appid = gid % AID_USER_OFFSET;
    386   const uid_t userid = gid / AID_USER_OFFSET;
    387   if (appid >= AID_ISOLATED_START) {
    388     snprintf(buffer, bufferlen, "u%u_i%u", userid, appid - AID_ISOLATED_START);
    389   } else if (userid == 0 && appid >= AID_SHARED_GID_START && appid <= AID_SHARED_GID_END) {
    390     snprintf(buffer, bufferlen, "all_a%u", appid - AID_SHARED_GID_START);
    391   } else if (appid >= AID_CACHE_GID_START && appid <= AID_CACHE_GID_END) {
    392     snprintf(buffer, bufferlen, "u%u_a%u_cache", userid, appid - AID_CACHE_GID_START);
    393   } else if (appid < AID_APP_START) {
    394     for (size_t n = 0; n < android_id_count; n++) {
    395       if (android_ids[n].aid == appid) {
    396         snprintf(buffer, bufferlen, "u%u_%s", userid, android_ids[n].name);
    397         return;
    398       }
    399     }
    400   } else {
    401     snprintf(buffer, bufferlen, "u%u_a%u", userid, appid - AID_APP_START);
    402   }
    403 }
    404 
    405 // oem_XXXX -> uid
    406 //  Supported ranges:
    407 //   AID_OEM_RESERVED_START to AID_OEM_RESERVED_END (2900-2999)
    408 //   AID_OEM_RESERVED_2_START to AID_OEM_RESERVED_2_END (5000-5999)
    409 // Check OEM id is within range.
    410 static bool is_oem_id(id_t id) {
    411   return (((id >= AID_OEM_RESERVED_START) && (id <= AID_OEM_RESERVED_END)) ||
    412       ((id >= AID_OEM_RESERVED_2_START) && (id <= AID_OEM_RESERVED_2_END)));
    413 }
    414 
    415 // Translate an OEM name to the corresponding user/group id.
    416 static id_t oem_id_from_name(const char* name) {
    417   unsigned int id;
    418   if (sscanf(name, "oem_%u", &id) != 1) {
    419     return 0;
    420   }
    421   if (!is_oem_id(id)) {
    422     return 0;
    423   }
    424   return static_cast<id_t>(id);
    425 }
    426 
    427 static passwd* oem_id_to_passwd(uid_t uid, passwd_state_t* state) {
    428   if (!is_oem_id(uid)) {
    429     return nullptr;
    430   }
    431 
    432   if (vendor_passwd.FindById(uid, state)) {
    433     return &state->passwd_;
    434   }
    435 
    436   snprintf(state->name_buffer_, sizeof(state->name_buffer_), "oem_%u", uid);
    437   snprintf(state->dir_buffer_, sizeof(state->dir_buffer_), "/");
    438   snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/vendor/bin/sh");
    439 
    440   passwd* pw = &state->passwd_;
    441   pw->pw_name  = state->name_buffer_;
    442   pw->pw_dir   = state->dir_buffer_;
    443   pw->pw_shell = state->sh_buffer_;
    444   pw->pw_uid   = uid;
    445   pw->pw_gid   = uid;
    446   return pw;
    447 }
    448 
    449 static group* oem_id_to_group(gid_t gid, group_state_t* state) {
    450   if (!is_oem_id(gid)) {
    451     return nullptr;
    452   }
    453 
    454   if (vendor_group.FindById(gid, state)) {
    455     return &state->group_;
    456   }
    457 
    458   snprintf(state->group_name_buffer_, sizeof(state->group_name_buffer_),
    459            "oem_%u", gid);
    460 
    461   group* gr = &state->group_;
    462   gr->gr_name   = state->group_name_buffer_;
    463   gr->gr_gid    = gid;
    464   gr->gr_mem[0] = gr->gr_name;
    465   return gr;
    466 }
    467 
    468 // Translate a uid into the corresponding name.
    469 // 0 to AID_APP_START-1                    -> "system", "radio", etc.
    470 // AID_APP_START to AID_ISOLATED_START-1   -> u0_a1234
    471 // AID_ISOLATED_START to AID_USER_OFFSET-1 -> u0_i1234
    472 // AID_USER_OFFSET+                        -> u1_radio, u1_a1234, u2_i1234, etc.
    473 // returns a passwd structure (sets errno to ENOENT on failure).
    474 static passwd* app_id_to_passwd(uid_t uid, passwd_state_t* state) {
    475   if (uid < AID_APP_START || !is_valid_app_id(uid)) {
    476     errno = ENOENT;
    477     return nullptr;
    478   }
    479 
    480   print_app_name_from_uid(uid, state->name_buffer_, sizeof(state->name_buffer_));
    481 
    482   const uid_t appid = uid % AID_USER_OFFSET;
    483   if (appid < AID_APP_START) {
    484       snprintf(state->dir_buffer_, sizeof(state->dir_buffer_), "/");
    485   } else {
    486       snprintf(state->dir_buffer_, sizeof(state->dir_buffer_), "/data");
    487   }
    488 
    489   snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/system/bin/sh");
    490 
    491   passwd* pw = &state->passwd_;
    492   pw->pw_name  = state->name_buffer_;
    493   pw->pw_dir   = state->dir_buffer_;
    494   pw->pw_shell = state->sh_buffer_;
    495   pw->pw_uid   = uid;
    496   pw->pw_gid   = uid;
    497   return pw;
    498 }
    499 
    500 // Translate a gid into the corresponding app_<gid>
    501 // group structure (sets errno to ENOENT on failure).
    502 static group* app_id_to_group(gid_t gid, group_state_t* state) {
    503   if (gid < AID_APP_START || !is_valid_app_id(gid)) {
    504     errno = ENOENT;
    505     return nullptr;
    506   }
    507 
    508   print_app_name_from_gid(gid, state->group_name_buffer_, sizeof(state->group_name_buffer_));
    509 
    510   group* gr = &state->group_;
    511   gr->gr_name   = state->group_name_buffer_;
    512   gr->gr_gid    = gid;
    513   gr->gr_mem[0] = gr->gr_name;
    514   return gr;
    515 }
    516 
    517 passwd* getpwuid(uid_t uid) { // NOLINT: implementing bad function.
    518   passwd_state_t* state = get_passwd_tls_buffer();
    519   if (state == nullptr) {
    520     return nullptr;
    521   }
    522 
    523   passwd* pw = android_id_to_passwd(state, uid);
    524   if (pw != nullptr) {
    525     return pw;
    526   }
    527   // Handle OEM range.
    528   pw = oem_id_to_passwd(uid, state);
    529   if (pw != nullptr) {
    530     return pw;
    531   }
    532   return app_id_to_passwd(uid, state);
    533 }
    534 
    535 passwd* getpwnam(const char* login) { // NOLINT: implementing bad function.
    536   passwd_state_t* state = get_passwd_tls_buffer();
    537   if (state == nullptr) {
    538     return nullptr;
    539   }
    540 
    541   passwd* pw = android_name_to_passwd(state, login);
    542   if (pw != nullptr) {
    543     return pw;
    544   }
    545 
    546   if (vendor_passwd.FindByName(login, state)) {
    547     if (is_oem_id(state->passwd_.pw_uid)) {
    548       return &state->passwd_;
    549     }
    550   }
    551 
    552   // Handle OEM range.
    553   pw = oem_id_to_passwd(oem_id_from_name(login), state);
    554   if (pw != nullptr) {
    555     return pw;
    556   }
    557   return app_id_to_passwd(app_id_from_name(login, false), state);
    558 }
    559 
    560 // All users are in just one group, the one passed in.
    561 int getgrouplist(const char* /*user*/, gid_t group, gid_t* groups, int* ngroups) {
    562   if (*ngroups < 1) {
    563     *ngroups = 1;
    564     return -1;
    565   }
    566   groups[0] = group;
    567   return (*ngroups = 1);
    568 }
    569 
    570 char* getlogin() { // NOLINT: implementing bad function.
    571   passwd *pw = getpwuid(getuid()); // NOLINT: implementing bad function in terms of bad function.
    572   return pw ? pw->pw_name : nullptr;
    573 }
    574 
    575 int getlogin_r(char* buf, size_t size) {
    576   char* login = getlogin();
    577   if (login == nullptr) return errno;
    578   size_t login_length = strlen(login) + 1;
    579   if (login_length > size) return ERANGE;
    580   memcpy(buf, login, login_length);
    581   return 0;
    582 }
    583 
    584 void setpwent() {
    585   passwd_state_t* state = get_passwd_tls_buffer();
    586   if (state) {
    587     state->getpwent_idx = 0;
    588   }
    589 }
    590 
    591 void endpwent() {
    592   setpwent();
    593 }
    594 
    595 passwd* getpwent() {
    596   passwd_state_t* state = get_passwd_tls_buffer();
    597   if (state == nullptr) {
    598     return nullptr;
    599   }
    600   if (state->getpwent_idx < 0) {
    601     return nullptr;
    602   }
    603 
    604   size_t start = 0;
    605   ssize_t end = android_id_count;
    606   if (state->getpwent_idx < end) {
    607     return android_iinfo_to_passwd(state, android_ids + state->getpwent_idx++);
    608   }
    609 
    610   start = end;
    611   end += AID_OEM_RESERVED_END - AID_OEM_RESERVED_START + 1;
    612 
    613   if (state->getpwent_idx < end) {
    614     return oem_id_to_passwd(
    615         state->getpwent_idx++ - start + AID_OEM_RESERVED_START, state);
    616   }
    617 
    618   start = end;
    619   end += AID_OEM_RESERVED_2_END - AID_OEM_RESERVED_2_START + 1;
    620 
    621   if (state->getpwent_idx < end) {
    622     return oem_id_to_passwd(
    623         state->getpwent_idx++ - start + AID_OEM_RESERVED_2_START, state);
    624   }
    625 
    626   state->getpwent_idx = get_next_app_id(state->getpwent_idx);
    627 
    628   if (state->getpwent_idx != -1) {
    629     return app_id_to_passwd(state->getpwent_idx, state);
    630   }
    631 
    632   // We are not reporting u1_a* and higher or we will be here forever
    633   return nullptr;
    634 }
    635 
    636 static group* getgrgid_internal(gid_t gid, group_state_t* state) {
    637   group* grp = android_id_to_group(state, gid);
    638   if (grp != nullptr) {
    639     return grp;
    640   }
    641   // Handle OEM range.
    642   grp = oem_id_to_group(gid, state);
    643   if (grp != nullptr) {
    644     return grp;
    645   }
    646   return app_id_to_group(gid, state);
    647 }
    648 
    649 group* getgrgid(gid_t gid) { // NOLINT: implementing bad function.
    650   group_state_t* state = __group_state();
    651   if (state == nullptr) {
    652     return nullptr;
    653   }
    654   return getgrgid_internal(gid, state);
    655 }
    656 
    657 static group* getgrnam_internal(const char* name, group_state_t* state) {
    658   group* grp = android_name_to_group(state, name);
    659   if (grp != nullptr) {
    660     return grp;
    661   }
    662 
    663   if (vendor_group.FindByName(name, state)) {
    664     if (is_oem_id(state->group_.gr_gid)) {
    665       return &state->group_;
    666     }
    667   }
    668 
    669   // Handle OEM range.
    670   grp = oem_id_to_group(oem_id_from_name(name), state);
    671   if (grp != nullptr) {
    672     return grp;
    673   }
    674   return app_id_to_group(app_id_from_name(name, true), state);
    675 }
    676 
    677 group* getgrnam(const char* name) { // NOLINT: implementing bad function.
    678   group_state_t* state = __group_state();
    679   if (state == nullptr) {
    680     return nullptr;
    681   }
    682   return getgrnam_internal(name, state);
    683 }
    684 
    685 static int getgroup_r(bool by_name, const char* name, gid_t gid, struct group* grp, char* buf,
    686                       size_t buflen, struct group** result) {
    687   ErrnoRestorer errno_restorer;
    688   *result = nullptr;
    689   char* p = reinterpret_cast<char*>(
    690       __BIONIC_ALIGN(reinterpret_cast<uintptr_t>(buf), sizeof(uintptr_t)));
    691   if (p + sizeof(group_state_t) > buf + buflen) {
    692     return ERANGE;
    693   }
    694   group_state_t* state = reinterpret_cast<group_state_t*>(p);
    695   init_group_state(state);
    696   group* retval = (by_name ? getgrnam_internal(name, state) : getgrgid_internal(gid, state));
    697   if (retval != nullptr) {
    698     *grp = *retval;
    699     *result = grp;
    700     return 0;
    701   }
    702   return errno;
    703 }
    704 
    705 int getgrgid_r(gid_t gid, struct group* grp, char* buf, size_t buflen, struct group** result) {
    706   return getgroup_r(false, nullptr, gid, grp, buf, buflen, result);
    707 }
    708 
    709 int getgrnam_r(const char* name, struct group* grp, char* buf, size_t buflen,
    710                struct group **result) {
    711   return getgroup_r(true, name, 0, grp, buf, buflen, result);
    712 }
    713 
    714 void setgrent() {
    715   group_state_t* state = get_group_tls_buffer();
    716   if (state) {
    717     state->getgrent_idx = 0;
    718   }
    719 }
    720 
    721 void endgrent() {
    722   setgrent();
    723 }
    724 
    725 group* getgrent() {
    726   group_state_t* state = get_group_tls_buffer();
    727   if (state == nullptr) {
    728     return nullptr;
    729   }
    730   if (state->getgrent_idx < 0) {
    731     return nullptr;
    732   }
    733 
    734   size_t start = 0;
    735   ssize_t end = android_id_count;
    736   if (state->getgrent_idx < end) {
    737     init_group_state(state);
    738     return android_iinfo_to_group(state, android_ids + state->getgrent_idx++);
    739   }
    740 
    741   start = end;
    742   end += AID_OEM_RESERVED_END - AID_OEM_RESERVED_START + 1;
    743 
    744   if (state->getgrent_idx < end) {
    745     init_group_state(state);
    746     return oem_id_to_group(
    747         state->getgrent_idx++ - start + AID_OEM_RESERVED_START, state);
    748   }
    749 
    750   start = end;
    751   end += AID_OEM_RESERVED_2_END - AID_OEM_RESERVED_2_START + 1;
    752 
    753   if (state->getgrent_idx < end) {
    754     init_group_state(state);
    755     return oem_id_to_group(
    756         state->getgrent_idx++ - start + AID_OEM_RESERVED_2_START, state);
    757   }
    758 
    759   start = end;
    760   end += AID_USER_OFFSET - AID_APP_START; // Do not expose higher groups
    761 
    762   state->getgrent_idx = get_next_app_id(state->getgrent_idx);
    763 
    764   if (state->getgrent_idx != -1) {
    765     return app_id_to_group(state->getgrent_idx, state);
    766   }
    767 
    768   // We are not reporting u1_a* and higher or we will be here forever
    769   return nullptr;
    770 }
    771