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