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