• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "private/grp_pwd.h"
30 
31 #include <android/api-level.h>
32 #include <ctype.h>
33 #include <errno.h>
34 #include <grp.h>
35 #include <mntent.h>
36 #include <pthread.h>
37 #include <pwd.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <sys/system_properties.h>
42 #include <sys/types.h>
43 #include <unistd.h>
44 
45 #include "private/ErrnoRestorer.h"
46 #include "private/android_filesystem_config.h"
47 #include "platform/bionic/macros.h"
48 
49 #if defined(__ANDROID__)
50 // Generated android_ids array
51 #include "generated_android_ids.h"
52 #else
53 // Empty array for host; everything is from the database files
54 #include "empty_android_ids.h"
55 #endif
56 
57 #include "grp_pwd_file.h"
58 
59 static PasswdFile passwd_files[] = {
60     {"/etc/passwd", "system_"},  // symlinks to /system/etc/passwd in Android
61     {"/vendor/etc/passwd", "vendor_"},
62     {"/odm/etc/passwd", "odm_"},
63     {"/product/etc/passwd", "product_"},
64     {"/system_ext/etc/passwd", "system_ext_"},
65 };
66 
67 static GroupFile group_files[] = {
68     {"/etc/group", "system_"},  // symlinks to /system/etc/group in Android
69     {"/vendor/etc/group", "vendor_"},
70     {"/odm/etc/group", "odm_"},
71     {"/product/etc/group", "product_"},
72     {"/system_ext/etc/group", "system_ext_"},
73 };
74 
75 // POSIX seems to envisage an implementation where the <pwd.h> functions are
76 // implemented by brute-force searching with getpwent(3), and the <grp.h>
77 // functions are implemented similarly with getgrent(3). This means that it's
78 // okay for all the <grp.h> functions to share state, and all the <passwd.h>
79 // functions to share state, but <grp.h> functions can't clobber <passwd.h>
80 // functions' state and vice versa.
81 #include "bionic/pthread_internal.h"
82 
init_group_state(group_state_t * state)83 static void init_group_state(group_state_t* state) {
84   memset(state, 0, sizeof(group_state_t) - sizeof(state->getgrent_idx));
85   state->group_.gr_name = state->group_name_buffer_;
86   state->group_.gr_mem = state->group_members_;
87   state->group_.gr_mem[0] = state->group_.gr_name;
88 }
89 
get_group_tls_buffer()90 static group_state_t* get_group_tls_buffer() {
91   auto result = &__get_bionic_tls().group;
92   init_group_state(result);
93   return result;
94 }
95 
init_passwd_state(passwd_state_t * state)96 static void init_passwd_state(passwd_state_t* state) {
97   memset(state, 0, sizeof(passwd_state_t) - sizeof(state->getpwent_idx));
98   state->passwd_.pw_name = state->name_buffer_;
99   state->passwd_.pw_dir = state->dir_buffer_;
100   state->passwd_.pw_shell = state->sh_buffer_;
101 }
102 
get_passwd_tls_buffer()103 static passwd_state_t* get_passwd_tls_buffer() {
104   auto result = &__get_bionic_tls().passwd;
105   init_passwd_state(result);
106   return result;
107 }
108 
android_iinfo_to_passwd(passwd_state_t * state,const android_id_info * iinfo)109 static passwd* android_iinfo_to_passwd(passwd_state_t* state,
110                                        const android_id_info* iinfo) {
111   snprintf(state->name_buffer_, sizeof(state->name_buffer_), "%s", iinfo->name);
112   snprintf(state->dir_buffer_, sizeof(state->dir_buffer_), "/");
113   snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/bin/sh");
114 
115   passwd* pw = &state->passwd_;
116   pw->pw_uid   = iinfo->aid;
117   pw->pw_gid   = iinfo->aid;
118   return pw;
119 }
120 
android_iinfo_to_group(group_state_t * state,const android_id_info * iinfo)121 static group* android_iinfo_to_group(group_state_t* state,
122                                      const android_id_info* iinfo) {
123   snprintf(state->group_name_buffer_, sizeof(state->group_name_buffer_), "%s", iinfo->name);
124 
125   group* gr = &state->group_;
126   gr->gr_gid = iinfo->aid;
127   return gr;
128 }
129 
find_android_id_info(unsigned id)130 static const android_id_info* find_android_id_info(unsigned id) {
131   for (size_t n = 0; n < android_id_count; ++n) {
132     if (android_ids[n].aid == id) {
133       return &android_ids[n];
134     }
135   }
136   return nullptr;
137 }
138 
find_android_id_info(const char * name)139 static const android_id_info* find_android_id_info(const char* name) {
140   for (size_t n = 0; n < android_id_count; ++n) {
141     if (!strcmp(android_ids[n].name, name)) {
142       return &android_ids[n];
143     }
144   }
145   return nullptr;
146 }
147 
148 // These are a list of the reserved app ranges, and should never contain anything below
149 // AID_APP_START.  They exist per user, so a given uid/gid modulo AID_USER_OFFSET will map
150 // to these ranges.
151 struct IdRange {
152   id_t start;
153   id_t end;
154 };
155 
156 static constexpr IdRange user_ranges[] = {
157   { AID_APP_START, AID_APP_END },
158   { AID_ISOLATED_START, AID_ISOLATED_END },
159 };
160 
161 static constexpr IdRange group_ranges[] = {
162   { AID_APP_START, AID_APP_END },
163   { AID_CACHE_GID_START, AID_CACHE_GID_END },
164   { AID_EXT_GID_START, AID_EXT_GID_END },
165   { AID_EXT_CACHE_GID_START, AID_EXT_CACHE_GID_END },
166   { AID_SHARED_GID_START, AID_SHARED_GID_END },
167   { AID_ISOLATED_START, AID_ISOLATED_END },
168 };
169 
170 template <class T, size_t N>
verify_user_ranges_ascending(T (& ranges)[N])171 static constexpr bool verify_user_ranges_ascending(T (&ranges)[N]) {
172   auto array_size = N;
173   if (array_size < 2) return false;
174 
175   if (ranges[0].start > ranges[0].end) return false;
176 
177   for (size_t i = 1; i < array_size; ++i) {
178     if (ranges[i].start > ranges[i].end) return false;
179     if (ranges[i - 1].end > ranges[i].start) return false;
180   }
181   return true;
182 }
183 
184 static_assert(verify_user_ranges_ascending(user_ranges), "user_ranges must have ascending ranges");
185 static_assert(verify_user_ranges_ascending(group_ranges), "user_ranges must have ascending ranges");
186 
187 // This list comes from PackageManagerService.java, where platform AIDs are added to list of valid
188 // AIDs for packages via addSharedUserLPw().
189 static constexpr const id_t secondary_user_platform_ids[] = {
190   AID_SYSTEM, AID_RADIO,          AID_LOG,           AID_NFC, AID_BLUETOOTH,
191   AID_SHELL,  AID_SECURE_ELEMENT, AID_NETWORK_STACK,
192 };
193 
platform_id_secondary_user_allowed(id_t id)194 static bool platform_id_secondary_user_allowed(id_t id) {
195   for (const auto& allowed_id : secondary_user_platform_ids) {
196     if (allowed_id == id) {
197       return true;
198     }
199   }
200   return false;
201 }
202 
203 #if defined(__ANDROID__)
is_valid_app_id(id_t id,bool is_group)204 static bool is_valid_app_id(id_t id, bool is_group) {
205   id_t appid = id % AID_USER_OFFSET;
206 
207   // AID_OVERFLOWUID is never a valid app id, so we explicitly return false to ensure this.
208   // This is true across all users, as there is no reason to ever map this id into any user range.
209   if (appid == AID_OVERFLOWUID) {
210     return false;
211   }
212 
213   auto ranges_size = is_group ? arraysize(group_ranges) : arraysize(user_ranges);
214   auto ranges = is_group ? group_ranges : user_ranges;
215 
216   // If we're checking an appid that resolves below the user range, then it's a platform AID for a
217   // seconary user. We only allow a reduced set of these, so we must check that it is allowed.
218   if (appid < ranges[0].start && platform_id_secondary_user_allowed(appid)) {
219     return true;
220   }
221 
222   // The shared GID range is only valid for the first user.
223   if (appid >= AID_SHARED_GID_START && appid <= AID_SHARED_GID_END && appid != id) {
224     return false;
225   }
226 
227   // Otherwise check that the appid is in one of the reserved ranges.
228   for (size_t i = 0; i < ranges_size; ++i) {
229     if (appid >= ranges[i].start && appid <= ranges[i].end) {
230       return true;
231     }
232   }
233 
234   return false;
235 }
236 #else
is_valid_app_id(id_t,bool)237 static bool is_valid_app_id(id_t, bool) {
238   // Host doesn't have the concept of app_id
239   return false;
240 }
241 #endif  // if defined(__ANDROID__)
242 
243 // This provides an iterater for app_ids within the first user's app id's.
get_next_app_id(id_t current_id,bool is_group)244 static id_t get_next_app_id(id_t current_id, bool is_group) {
245   auto ranges_size = is_group ? arraysize(group_ranges) : arraysize(user_ranges);
246   auto ranges = is_group ? group_ranges : user_ranges;
247 
248   // If current_id is below the first of the ranges, then we're uninitialized, and return the first
249   // valid id.
250   if (current_id < ranges[0].start) {
251     return ranges[0].start;
252   }
253 
254   id_t incremented_id = current_id + 1;
255 
256   // Check to see if our incremented_id is between two ranges, and if so, return the beginning of
257   // the next valid range.
258   for (size_t i = 1; i < ranges_size; ++i) {
259     if (incremented_id > ranges[i - 1].end && incremented_id < ranges[i].start) {
260       return ranges[i].start;
261     }
262   }
263 
264   // Check to see if our incremented_id is above final range, and return -1 to indicate that we've
265   // completed if so.
266   if (incremented_id > ranges[ranges_size - 1].end) {
267     return -1;
268   }
269 
270   // Otherwise the incremented_id is valid, so return it.
271   return incremented_id;
272 }
273 
274 // Translate a user/group name to the corresponding user/group id.
275 // all_a1234 -> 0 * AID_USER_OFFSET + AID_SHARED_GID_START + 1234 (group name only)
276 // u0_a1234_ext_cache -> 0 * AID_USER_OFFSET + AID_EXT_CACHE_GID_START + 1234 (group name only)
277 // u0_a1234_ext -> 0 * AID_USER_OFFSET + AID_EXT_GID_START + 1234 (group name only)
278 // u0_a1234_cache -> 0 * AID_USER_OFFSET + AID_CACHE_GID_START + 1234 (group name only)
279 // u0_a1234 -> 0 * AID_USER_OFFSET + AID_APP_START + 1234
280 // u2_i1000 -> 2 * AID_USER_OFFSET + AID_ISOLATED_START + 1000
281 // u1_system -> 1 * AID_USER_OFFSET + android_ids['system']
282 // returns 0 and sets errno to ENOENT in case of error.
app_id_from_name(const char * name,bool is_group)283 static id_t app_id_from_name(const char* name, bool is_group) {
284   char* end;
285   unsigned long userid;
286   bool is_shared_gid = false;
287 
288   if (is_group && name[0] == 'a' && name[1] == 'l' && name[2] == 'l') {
289     end = const_cast<char*>(name+3);
290     userid = 0;
291     is_shared_gid = true;
292   } else if (name[0] == 'u' && isdigit(name[1])) {
293     userid = strtoul(name+1, &end, 10);
294   } else {
295     errno = ENOENT;
296     return 0;
297   }
298 
299   if (end[0] != '_' || end[1] == 0) {
300     errno = ENOENT;
301     return 0;
302   }
303 
304   unsigned long appid = 0;
305   if (end[1] == 'a' && isdigit(end[2])) {
306     if (is_shared_gid) {
307       // end will point to \0 if the strtoul below succeeds.
308       appid = strtoul(end+2, &end, 10) + AID_SHARED_GID_START;
309       if (appid > AID_SHARED_GID_END) {
310         errno = ENOENT;
311         return 0;
312       }
313     } else {
314       // end will point to \0 if the strtoul below succeeds.
315       appid = strtoul(end+2, &end, 10);
316       if (is_group) {
317         if (!strcmp(end, "_ext_cache")) {
318           end += 10;
319           appid += AID_EXT_CACHE_GID_START;
320         } else if (!strcmp(end, "_ext")) {
321           end += 4;
322           appid += AID_EXT_GID_START;
323         } else if (!strcmp(end, "_cache")) {
324           end += 6;
325           appid += AID_CACHE_GID_START;
326         } else {
327           appid += AID_APP_START;
328         }
329       } else {
330         appid += AID_APP_START;
331       }
332     }
333   } else if (end[1] == 'i' && isdigit(end[2])) {
334     // end will point to \0 if the strtoul below succeeds.
335     appid = strtoul(end+2, &end, 10) + AID_ISOLATED_START;
336   } else if (auto* android_id_info = find_android_id_info(end + 1); android_id_info != nullptr) {
337     appid = android_id_info->aid;
338     end += strlen(android_id_info->name) + 1;
339     if (!platform_id_secondary_user_allowed(appid)) {
340       errno = ENOENT;
341       return 0;
342     }
343   }
344 
345   // Check that the entire string was consumed by one of the 3 cases above.
346   if (end[0] != 0) {
347     errno = ENOENT;
348     return 0;
349   }
350 
351   // Check that user id won't overflow.
352   if (userid > 1000) {
353     errno = ENOENT;
354     return 0;
355   }
356 
357   // Check that app id is within range.
358   if (appid >= AID_USER_OFFSET) {
359     errno = ENOENT;
360     return 0;
361   }
362 
363   return (appid + userid*AID_USER_OFFSET);
364 }
365 
print_app_name_from_uid(const uid_t uid,char * buffer,const int bufferlen)366 static void print_app_name_from_uid(const uid_t uid, char* buffer, const int bufferlen) {
367   const uid_t appid = uid % AID_USER_OFFSET;
368   const uid_t userid = uid / AID_USER_OFFSET;
369   if (appid >= AID_ISOLATED_START) {
370     snprintf(buffer, bufferlen, "u%u_i%u", userid, appid - AID_ISOLATED_START);
371   } else if (appid < AID_APP_START) {
372     if (auto* android_id_info = find_android_id_info(appid); android_id_info != nullptr) {
373       snprintf(buffer, bufferlen, "u%u_%s", userid, android_id_info->name);
374     }
375   } else {
376     snprintf(buffer, bufferlen, "u%u_a%u", userid, appid - AID_APP_START);
377   }
378 }
379 
print_app_name_from_gid(const gid_t gid,char * buffer,const int bufferlen)380 static void print_app_name_from_gid(const gid_t gid, char* buffer, const int bufferlen) {
381   const uid_t appid = gid % AID_USER_OFFSET;
382   const uid_t userid = gid / AID_USER_OFFSET;
383   if (appid >= AID_ISOLATED_START) {
384     snprintf(buffer, bufferlen, "u%u_i%u", userid, appid - AID_ISOLATED_START);
385   } else if (userid == 0 && appid >= AID_SHARED_GID_START && appid <= AID_SHARED_GID_END) {
386     snprintf(buffer, bufferlen, "all_a%u", appid - AID_SHARED_GID_START);
387   } else if (appid >= AID_EXT_CACHE_GID_START && appid <= AID_EXT_CACHE_GID_END) {
388     snprintf(buffer, bufferlen, "u%u_a%u_ext_cache", userid, appid - AID_EXT_CACHE_GID_START);
389   } else if (appid >= AID_EXT_GID_START && appid <= AID_EXT_GID_END) {
390     snprintf(buffer, bufferlen, "u%u_a%u_ext", userid, appid - AID_EXT_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     if (auto* android_id_info = find_android_id_info(appid); android_id_info != nullptr) {
395       snprintf(buffer, bufferlen, "u%u_%s", userid, android_id_info->name);
396     }
397   } else {
398     snprintf(buffer, bufferlen, "u%u_a%u", userid, appid - AID_APP_START);
399   }
400 }
401 
402 #if defined(__ANDROID__)
device_launched_before_api_29()403 static bool device_launched_before_api_29() {
404   // Check if ro.product.first_api_level is set to a value > 0 and < 29, if so, this device was
405   // launched before API 29 (Q). Any other value is considered to be either in development or
406   // launched after.
407   // Cache the value as __system_property_get() is expensive and this may be called often.
408   static bool result = [] {
409     char value[PROP_VALUE_MAX] = { 0 };
410     if (__system_property_get("ro.product.first_api_level", value) == 0) {
411       return false;
412     }
413     int value_int = atoi(value);
414     return value_int != 0 && value_int < 29;
415   }();
416   return result;
417 }
418 
419 // oem_XXXX -> uid
420 //  Supported ranges:
421 //   AID_OEM_RESERVED_START to AID_OEM_RESERVED_END (2900-2999)
422 //   AID_OEM_RESERVED_2_START to AID_OEM_RESERVED_2_END (5000-5999)
423 // Check OEM id is within range.
is_oem_id(id_t id)424 static bool is_oem_id(id_t id) {
425   // Upgrading devices launched before API level 29 may not comply with the below check.
426   // Due to the difficulty in changing uids after launch, it is waived for these devices.
427   // The legacy range:
428   // AID_OEM_RESERVED_START to AID_EVERYBODY (2900-9996), excluding builtin AIDs.
429   if (device_launched_before_api_29() && id >= AID_OEM_RESERVED_START && id < AID_EVERYBODY &&
430       find_android_id_info(id) == nullptr) {
431     return true;
432   }
433 
434   return (id >= AID_OEM_RESERVED_START && id <= AID_OEM_RESERVED_END) ||
435          (id >= AID_OEM_RESERVED_2_START && id <= AID_OEM_RESERVED_2_END);
436 }
437 #else
is_oem_id(id_t)438 static bool is_oem_id(id_t) {
439   // no OEM ids in host
440   return false;
441 }
442 #endif  // if defined(__ANDROID__)
443 
444 // Translate an OEM name to the corresponding user/group id.
oem_id_from_name(const char * name)445 static id_t oem_id_from_name(const char* name) {
446   unsigned int id;
447   if (sscanf(name, "oem_%u", &id) != 1) {
448     return 0;
449   }
450   if (!is_oem_id(id)) {
451     return 0;
452   }
453   return static_cast<id_t>(id);
454 }
455 
oem_id_to_passwd(uid_t uid,passwd_state_t * state)456 static passwd* oem_id_to_passwd(uid_t uid, passwd_state_t* state) {
457   for (auto& passwd_file : passwd_files) {
458     if (passwd_file.FindById(uid, state)) {
459       return &state->passwd_;
460     }
461   }
462 
463   if (!is_oem_id(uid)) {
464     return nullptr;
465   }
466 
467   snprintf(state->name_buffer_, sizeof(state->name_buffer_), "oem_%u", uid);
468   snprintf(state->dir_buffer_, sizeof(state->dir_buffer_), "/");
469   snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/bin/sh");
470 
471   passwd* pw = &state->passwd_;
472   pw->pw_uid   = uid;
473   pw->pw_gid   = uid;
474   return pw;
475 }
476 
oem_id_to_group(gid_t gid,group_state_t * state)477 static group* oem_id_to_group(gid_t gid, group_state_t* state) {
478   for (auto& group_file : group_files) {
479     if (group_file.FindById(gid, state)) {
480       return &state->group_;
481     }
482   }
483 
484   if (!is_oem_id(gid)) {
485     return nullptr;
486   }
487 
488   snprintf(state->group_name_buffer_, sizeof(state->group_name_buffer_),
489            "oem_%u", gid);
490 
491   group* gr = &state->group_;
492   gr->gr_gid = gid;
493   return gr;
494 }
495 
496 // Translate a uid into the corresponding name.
497 // 0 to AID_APP_START-1                    -> "system", "radio", etc.
498 // AID_APP_START to AID_ISOLATED_START-1   -> u0_a1234
499 // AID_ISOLATED_START to AID_USER_OFFSET-1 -> u0_i1234
500 // AID_USER_OFFSET+                        -> u1_radio, u1_a1234, u2_i1234, etc.
501 // returns a passwd structure (sets errno to ENOENT on failure).
app_id_to_passwd(uid_t uid,passwd_state_t * state)502 static passwd* app_id_to_passwd(uid_t uid, passwd_state_t* state) {
503   if (uid < AID_APP_START || !is_valid_app_id(uid, false)) {
504     errno = ENOENT;
505     return nullptr;
506   }
507 
508   print_app_name_from_uid(uid, state->name_buffer_, sizeof(state->name_buffer_));
509 
510   const uid_t appid = uid % AID_USER_OFFSET;
511   if (appid < AID_APP_START) {
512       snprintf(state->dir_buffer_, sizeof(state->dir_buffer_), "/");
513   } else {
514       snprintf(state->dir_buffer_, sizeof(state->dir_buffer_), "/data");
515   }
516 
517   snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/bin/sh");
518 
519   passwd* pw = &state->passwd_;
520   pw->pw_uid   = uid;
521   pw->pw_gid   = uid;
522   return pw;
523 }
524 
525 // Translate a gid into the corresponding app_<gid>
526 // group structure (sets errno to ENOENT on failure).
app_id_to_group(gid_t gid,group_state_t * state)527 static group* app_id_to_group(gid_t gid, group_state_t* state) {
528   if (gid < AID_APP_START || !is_valid_app_id(gid, true)) {
529     errno = ENOENT;
530     return nullptr;
531   }
532 
533   print_app_name_from_gid(gid, state->group_name_buffer_, sizeof(state->group_name_buffer_));
534 
535   group* gr = &state->group_;
536   gr->gr_gid = gid;
537   return gr;
538 }
539 
getpwuid_internal(uid_t uid,passwd_state_t * state)540 passwd* getpwuid_internal(uid_t uid, passwd_state_t* state) {
541   if (auto* android_id_info = find_android_id_info(uid); android_id_info != nullptr) {
542     return android_iinfo_to_passwd(state, android_id_info);
543   }
544 
545   // Find an entry from the database file
546   passwd* pw = oem_id_to_passwd(uid, state);
547   if (pw != nullptr) {
548     return pw;
549   }
550   return app_id_to_passwd(uid, state);
551 }
552 
getpwuid(uid_t uid)553 passwd* getpwuid(uid_t uid) {  // NOLINT: implementing bad function.
554   passwd_state_t* state = get_passwd_tls_buffer();
555   return getpwuid_internal(uid, state);
556 }
557 
getpwnam_internal(const char * login,passwd_state_t * state)558 passwd* getpwnam_internal(const char* login, passwd_state_t* state) {
559   if (auto* android_id_info = find_android_id_info(login); android_id_info != nullptr) {
560     return android_iinfo_to_passwd(state, android_id_info);
561   }
562 
563   // Find an entry from the database file
564   for (auto& passwd_file : passwd_files) {
565     if (passwd_file.FindByName(login, state)) {
566       return &state->passwd_;
567     }
568   }
569 
570   // Handle OEM range.
571   passwd* pw = oem_id_to_passwd(oem_id_from_name(login), state);
572   if (pw != nullptr) {
573     return pw;
574   }
575   return app_id_to_passwd(app_id_from_name(login, false), state);
576 }
577 
getpwnam(const char * login)578 passwd* getpwnam(const char* login) {  // NOLINT: implementing bad function.
579   passwd_state_t* state = get_passwd_tls_buffer();
580   return getpwnam_internal(login, state);
581 }
582 
getpasswd_r(bool by_name,const char * name,uid_t uid,struct passwd * pwd,char * buf,size_t buflen,struct passwd ** result)583 static int getpasswd_r(bool by_name, const char* name, uid_t uid, struct passwd* pwd, char* buf,
584                        size_t buflen, struct passwd** result) {
585   ErrnoRestorer errno_restorer;
586   *result = nullptr;
587   char* p =
588       reinterpret_cast<char*>(__BIONIC_ALIGN(reinterpret_cast<uintptr_t>(buf), sizeof(uintptr_t)));
589   if (p + sizeof(passwd_state_t) > buf + buflen) {
590     return ERANGE;
591   }
592   passwd_state_t* state = reinterpret_cast<passwd_state_t*>(p);
593   init_passwd_state(state);
594   passwd* retval = (by_name ? getpwnam_internal(name, state) : getpwuid_internal(uid, state));
595   if (retval != nullptr) {
596     *pwd = *retval;
597     *result = pwd;
598     return 0;
599   }
600   return errno;
601 }
602 
getpwnam_r(const char * name,passwd * pwd,char * buf,size_t byte_count,passwd ** result)603 int getpwnam_r(const char* name, passwd* pwd, char* buf, size_t byte_count, passwd** result) {
604   return getpasswd_r(true, name, -1, pwd, buf, byte_count, result);
605 }
606 
getpwuid_r(uid_t uid,passwd * pwd,char * buf,size_t byte_count,passwd ** result)607 int getpwuid_r(uid_t uid, passwd* pwd, char* buf, size_t byte_count, passwd** result) {
608   return getpasswd_r(false, nullptr, uid, pwd, buf, byte_count, result);
609 }
610 
611 // All users are in just one group, the one passed in.
getgrouplist(const char *,gid_t group,gid_t * groups,int * ngroups)612 int getgrouplist(const char* /*user*/, gid_t group, gid_t* groups, int* ngroups) {
613   if (*ngroups < 1) {
614     *ngroups = 1;
615     return -1;
616   }
617   groups[0] = group;
618   return (*ngroups = 1);
619 }
620 
getlogin()621 char* getlogin() { // NOLINT: implementing bad function.
622   passwd *pw = getpwuid(getuid()); // NOLINT: implementing bad function in terms of bad function.
623   return pw ? pw->pw_name : nullptr;
624 }
625 
getlogin_r(char * buf,size_t size)626 int getlogin_r(char* buf, size_t size) {
627   char* login = getlogin();
628   if (login == nullptr) return errno;
629   size_t login_length = strlen(login) + 1;
630   if (login_length > size) return ERANGE;
631   memcpy(buf, login, login_length);
632   return 0;
633 }
634 
setpwent()635 void setpwent() {
636   passwd_state_t* state = get_passwd_tls_buffer();
637   if (state) {
638     state->getpwent_idx = 0;
639   }
640 }
641 
endpwent()642 void endpwent() {
643   setpwent();
644 }
645 
getpwent()646 passwd* getpwent() {
647   passwd_state_t* state = get_passwd_tls_buffer();
648   if (state->getpwent_idx < 0) {
649     return nullptr;
650   }
651 
652   size_t start = 0;
653   ssize_t end = android_id_count;
654   if (state->getpwent_idx < end) {
655     return android_iinfo_to_passwd(state, android_ids + state->getpwent_idx++);
656   }
657 
658   start = end;
659   end += AID_OEM_RESERVED_END - AID_OEM_RESERVED_START + 1;
660 
661   if (state->getpwent_idx < end) {
662     return oem_id_to_passwd(
663         state->getpwent_idx++ - start + AID_OEM_RESERVED_START, state);
664   }
665 
666   start = end;
667   end += AID_OEM_RESERVED_2_END - AID_OEM_RESERVED_2_START + 1;
668 
669   if (state->getpwent_idx < end) {
670     return oem_id_to_passwd(
671         state->getpwent_idx++ - start + AID_OEM_RESERVED_2_START, state);
672   }
673 
674   start = end;
675   end += AID_SYSTEM_EXT_RESERVED_END - AID_SYSTEM_RESERVED_START + 1;
676 
677   if (state->getpwent_idx < end) {
678     // No one calls this enough to worry about how inefficient the below is.
679     auto* oem_passwd =
680         oem_id_to_passwd(state->getpwent_idx++ - start + AID_SYSTEM_RESERVED_START, state);
681     while (oem_passwd == nullptr && state->getpwent_idx < end) {
682       oem_passwd =
683           oem_id_to_passwd(state->getpwent_idx++ - start + AID_SYSTEM_RESERVED_START, state);
684     }
685     if (oem_passwd != nullptr) {
686       return oem_passwd;
687     }
688   }
689 
690   state->getpwent_idx = get_next_app_id(state->getpwent_idx, false);
691 
692   if (state->getpwent_idx != -1) {
693     return app_id_to_passwd(state->getpwent_idx, state);
694   }
695 
696   // We are not reporting u1_a* and higher or we will be here forever
697   return nullptr;
698 }
699 
getgrgid_internal(gid_t gid,group_state_t * state)700 static group* getgrgid_internal(gid_t gid, group_state_t* state) {
701   if (auto* android_id_info = find_android_id_info(gid); android_id_info != nullptr) {
702     return android_iinfo_to_group(state, android_id_info);
703   }
704 
705   // Find an entry from the database file
706   group* grp = oem_id_to_group(gid, state);
707   if (grp != nullptr) {
708     return grp;
709   }
710   return app_id_to_group(gid, state);
711 }
712 
getgrgid(gid_t gid)713 group* getgrgid(gid_t gid) { // NOLINT: implementing bad function.
714   group_state_t* state = get_group_tls_buffer();
715   return getgrgid_internal(gid, state);
716 }
717 
getgrnam_internal(const char * name,group_state_t * state)718 static group* getgrnam_internal(const char* name, group_state_t* state) {
719   if (auto* android_id_info = find_android_id_info(name); android_id_info != nullptr) {
720     return android_iinfo_to_group(state, android_id_info);
721   }
722 
723   // Find an entry from the database file
724   for (auto& group_file : group_files) {
725     if (group_file.FindByName(name, state)) {
726       return &state->group_;
727     }
728   }
729 
730   // Handle OEM range.
731   group* grp = oem_id_to_group(oem_id_from_name(name), state);
732   if (grp != nullptr) {
733     return grp;
734   }
735   return app_id_to_group(app_id_from_name(name, true), state);
736 }
737 
getgrnam(const char * name)738 group* getgrnam(const char* name) { // NOLINT: implementing bad function.
739   group_state_t* state = get_group_tls_buffer();
740   return getgrnam_internal(name, state);
741 }
742 
getgroup_r(bool by_name,const char * name,gid_t gid,struct group * grp,char * buf,size_t buflen,struct group ** result)743 static int getgroup_r(bool by_name, const char* name, gid_t gid, struct group* grp, char* buf,
744                       size_t buflen, struct group** result) {
745   ErrnoRestorer errno_restorer;
746   *result = nullptr;
747   char* p = reinterpret_cast<char*>(
748       __BIONIC_ALIGN(reinterpret_cast<uintptr_t>(buf), sizeof(uintptr_t)));
749   if (p + sizeof(group_state_t) > buf + buflen) {
750     return ERANGE;
751   }
752   group_state_t* state = reinterpret_cast<group_state_t*>(p);
753   init_group_state(state);
754   group* retval = (by_name ? getgrnam_internal(name, state) : getgrgid_internal(gid, state));
755   if (retval != nullptr) {
756     *grp = *retval;
757     *result = grp;
758     return 0;
759   }
760   return errno;
761 }
762 
getgrgid_r(gid_t gid,struct group * grp,char * buf,size_t buflen,struct group ** result)763 int getgrgid_r(gid_t gid, struct group* grp, char* buf, size_t buflen, struct group** result) {
764   return getgroup_r(false, nullptr, gid, grp, buf, buflen, result);
765 }
766 
getgrnam_r(const char * name,struct group * grp,char * buf,size_t buflen,struct group ** result)767 int getgrnam_r(const char* name, struct group* grp, char* buf, size_t buflen,
768                struct group **result) {
769   return getgroup_r(true, name, 0, grp, buf, buflen, result);
770 }
771 
setgrent()772 void setgrent() {
773   group_state_t* state = get_group_tls_buffer();
774   if (state) {
775     state->getgrent_idx = 0;
776   }
777 }
778 
endgrent()779 void endgrent() {
780   setgrent();
781 }
782 
getgrent()783 group* getgrent() {
784   group_state_t* state = get_group_tls_buffer();
785   if (state->getgrent_idx < 0) {
786     return nullptr;
787   }
788 
789   size_t start = 0;
790   ssize_t end = android_id_count;
791   if (state->getgrent_idx < end) {
792     return android_iinfo_to_group(state, android_ids + state->getgrent_idx++);
793   }
794 
795   start = end;
796   end += AID_OEM_RESERVED_END - AID_OEM_RESERVED_START + 1;
797 
798   if (state->getgrent_idx < end) {
799     return oem_id_to_group(
800         state->getgrent_idx++ - start + AID_OEM_RESERVED_START, state);
801   }
802 
803   start = end;
804   end += AID_OEM_RESERVED_2_END - AID_OEM_RESERVED_2_START + 1;
805 
806   if (state->getgrent_idx < end) {
807     return oem_id_to_group(
808         state->getgrent_idx++ - start + AID_OEM_RESERVED_2_START, state);
809   }
810 
811   start = end;
812   end += AID_SYSTEM_EXT_RESERVED_END - AID_SYSTEM_RESERVED_START + 1;
813 
814   if (state->getgrent_idx < end) {
815     // No one calls this enough to worry about how inefficient the below is.
816     init_group_state(state);
817     auto* oem_group =
818         oem_id_to_group(state->getgrent_idx++ - start + AID_SYSTEM_RESERVED_START, state);
819     while (oem_group == nullptr && state->getgrent_idx < end) {
820       oem_group = oem_id_to_group(state->getgrent_idx++ - start + AID_SYSTEM_RESERVED_START, state);
821     }
822     if (oem_group != nullptr) {
823       return oem_group;
824     }
825   }
826 
827   start = end;
828   end += AID_USER_OFFSET - AID_APP_START; // Do not expose higher groups
829 
830   state->getgrent_idx = get_next_app_id(state->getgrent_idx, true);
831 
832   if (state->getgrent_idx != -1) {
833     return app_id_to_group(state->getgrent_idx, state);
834   }
835 
836   // We are not reporting u1_a* and higher or we will be here forever
837   return nullptr;
838 }
839