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 <netdb.h> 34#include <pthread.h> 35#include <pwd.h> 36#include <stdio.h> 37#include <stdlib.h> 38#include <string.h> 39#include <unistd.h> 40 41#include "private/android_filesystem_config.h" 42#include "private/bionic_macros.h" 43#include "private/ErrnoRestorer.h" 44#include "private/libc_logging.h" 45#include "private/ThreadLocalBuffer.h" 46 47// POSIX seems to envisage an implementation where the <pwd.h> functions are 48// implemented by brute-force searching with getpwent(3), and the <grp.h> 49// functions are implemented similarly with getgrent(3). This means that it's 50// okay for all the <grp.h> functions to share state, and all the <passwd.h> 51// functions to share state, but <grp.h> functions can't clobber <passwd.h> 52// functions' state and vice versa. 53 54struct group_state_t { 55 group group_; 56 char* group_members_[2]; 57 char group_name_buffer_[32]; 58}; 59 60struct passwd_state_t { 61 passwd passwd_; 62 char name_buffer_[32]; 63 char dir_buffer_[32]; 64 char sh_buffer_[32]; 65}; 66 67static ThreadLocalBuffer<group_state_t> g_group_tls_buffer; 68static ThreadLocalBuffer<passwd_state_t> g_passwd_tls_buffer; 69 70static void init_group_state(group_state_t* state) { 71 memset(state, 0, sizeof(group_state_t)); 72 state->group_.gr_mem = state->group_members_; 73} 74 75static group_state_t* __group_state() { 76 group_state_t* result = g_group_tls_buffer.get(); 77 if (result != nullptr) { 78 init_group_state(result); 79 } 80 return result; 81} 82 83static int do_getpw_r(int by_name, const char* name, uid_t uid, 84 passwd* dst, char* buf, size_t byte_count, 85 passwd** result) { 86 // getpwnam_r and getpwuid_r don't modify errno, but library calls we 87 // make might. 88 ErrnoRestorer errno_restorer; 89 *result = NULL; 90 91 // Our implementation of getpwnam(3) and getpwuid(3) use thread-local 92 // storage, so we can call them as long as we copy everything out 93 // before returning. 94 const passwd* src = by_name ? getpwnam(name) : getpwuid(uid); // NOLINT: see above. 95 96 // POSIX allows failure to find a match to be considered a non-error. 97 // Reporting success (0) but with *result NULL is glibc's behavior. 98 if (src == NULL) { 99 return (errno == ENOENT) ? 0 : errno; 100 } 101 102 // Work out where our strings will go in 'buf', and whether we've got 103 // enough space. 104 size_t required_byte_count = 0; 105 dst->pw_name = buf; 106 required_byte_count += strlen(src->pw_name) + 1; 107 dst->pw_dir = buf + required_byte_count; 108 required_byte_count += strlen(src->pw_dir) + 1; 109 dst->pw_shell = buf + required_byte_count; 110 required_byte_count += strlen(src->pw_shell) + 1; 111 if (byte_count < required_byte_count) { 112 return ERANGE; 113 } 114 115 // Copy the strings. 116 snprintf(buf, byte_count, "%s%c%s%c%s", src->pw_name, 0, src->pw_dir, 0, src->pw_shell); 117 118 // pw_passwd and pw_gecos are non-POSIX and unused (always NULL) in bionic. 119 // Note: On LP32, we define pw_gecos to pw_passwd since they're both NULL. 120 dst->pw_passwd = NULL; 121#if defined(__LP64__) 122 dst->pw_gecos = NULL; 123#endif 124 125 // Copy the integral fields. 126 dst->pw_gid = src->pw_gid; 127 dst->pw_uid = src->pw_uid; 128 129 *result = dst; 130 return 0; 131} 132 133int getpwnam_r(const char* name, passwd* pwd, 134 char* buf, size_t byte_count, passwd** result) { 135 return do_getpw_r(1, name, -1, pwd, buf, byte_count, result); 136} 137 138int getpwuid_r(uid_t uid, passwd* pwd, 139 char* buf, size_t byte_count, passwd** result) { 140 return do_getpw_r(0, NULL, uid, pwd, buf, byte_count, result); 141} 142 143static passwd* android_iinfo_to_passwd(passwd_state_t* state, 144 const android_id_info* iinfo) { 145 snprintf(state->name_buffer_, sizeof(state->name_buffer_), "%s", iinfo->name); 146 snprintf(state->dir_buffer_, sizeof(state->dir_buffer_), "/"); 147 snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/system/bin/sh"); 148 149 passwd* pw = &state->passwd_; 150 pw->pw_name = state->name_buffer_; 151 pw->pw_uid = iinfo->aid; 152 pw->pw_gid = iinfo->aid; 153 pw->pw_dir = state->dir_buffer_; 154 pw->pw_shell = state->sh_buffer_; 155 return pw; 156} 157 158static group* android_iinfo_to_group(group_state_t* state, 159 const android_id_info* iinfo) { 160 snprintf(state->group_name_buffer_, sizeof(state->group_name_buffer_), "%s", iinfo->name); 161 162 group* gr = &state->group_; 163 gr->gr_name = state->group_name_buffer_; 164 gr->gr_gid = iinfo->aid; 165 gr->gr_mem[0] = gr->gr_name; 166 return gr; 167} 168 169static passwd* android_id_to_passwd(passwd_state_t* state, unsigned id) { 170 for (size_t n = 0; n < android_id_count; ++n) { 171 if (android_ids[n].aid == id) { 172 return android_iinfo_to_passwd(state, android_ids + n); 173 } 174 } 175 return NULL; 176} 177 178static passwd* android_name_to_passwd(passwd_state_t* state, const char* name) { 179 for (size_t n = 0; n < android_id_count; ++n) { 180 if (!strcmp(android_ids[n].name, name)) { 181 return android_iinfo_to_passwd(state, android_ids + n); 182 } 183 } 184 return NULL; 185} 186 187static group* android_id_to_group(group_state_t* state, unsigned id) { 188 for (size_t n = 0; n < android_id_count; ++n) { 189 if (android_ids[n].aid == id) { 190 return android_iinfo_to_group(state, android_ids + n); 191 } 192 } 193 return NULL; 194} 195 196static group* android_name_to_group(group_state_t* state, const char* name) { 197 for (size_t n = 0; n < android_id_count; ++n) { 198 if (!strcmp(android_ids[n].name, name)) { 199 return android_iinfo_to_group(state, android_ids + n); 200 } 201 } 202 return NULL; 203} 204 205// Translate a user/group name to the corresponding user/group id. 206// all_a1234 -> 0 * AID_USER + AID_SHARED_GID_START + 1234 (group name only) 207// u0_a1234 -> 0 * AID_USER + AID_APP + 1234 208// u2_i1000 -> 2 * AID_USER + AID_ISOLATED_START + 1000 209// u1_system -> 1 * AID_USER + android_ids['system'] 210// returns 0 and sets errno to ENOENT in case of error. 211static id_t app_id_from_name(const char* name, bool is_group) { 212 char* end; 213 unsigned long userid; 214 bool is_shared_gid = false; 215 216 if (is_group && name[0] == 'a' && name[1] == 'l' && name[2] == 'l') { 217 end = const_cast<char*>(name+3); 218 userid = 0; 219 is_shared_gid = true; 220 } else if (name[0] == 'u' && isdigit(name[1])) { 221 userid = strtoul(name+1, &end, 10); 222 } else { 223 errno = ENOENT; 224 return 0; 225 } 226 227 if (end[0] != '_' || end[1] == 0) { 228 errno = ENOENT; 229 return 0; 230 } 231 232 unsigned long appid = 0; 233 if (end[1] == 'a' && isdigit(end[2])) { 234 if (is_shared_gid) { 235 // end will point to \0 if the strtoul below succeeds. 236 appid = strtoul(end+2, &end, 10) + AID_SHARED_GID_START; 237 if (appid > AID_SHARED_GID_END) { 238 errno = ENOENT; 239 return 0; 240 } 241 } else { 242 // end will point to \0 if the strtoul below succeeds. 243 appid = strtoul(end+2, &end, 10) + AID_APP; 244 } 245 } else if (end[1] == 'i' && isdigit(end[2])) { 246 // end will point to \0 if the strtoul below succeeds. 247 appid = strtoul(end+2, &end, 10) + AID_ISOLATED_START; 248 } else { 249 for (size_t n = 0; n < android_id_count; n++) { 250 if (!strcmp(android_ids[n].name, end + 1)) { 251 appid = android_ids[n].aid; 252 // Move the end pointer to the null terminator. 253 end += strlen(android_ids[n].name) + 1; 254 break; 255 } 256 } 257 } 258 259 // Check that the entire string was consumed by one of the 3 cases above. 260 if (end[0] != 0) { 261 errno = ENOENT; 262 return 0; 263 } 264 265 // Check that user id won't overflow. 266 if (userid > 1000) { 267 errno = ENOENT; 268 return 0; 269 } 270 271 // Check that app id is within range. 272 if (appid >= AID_USER) { 273 errno = ENOENT; 274 return 0; 275 } 276 277 return (appid + userid*AID_USER); 278} 279 280static void print_app_name_from_uid(const uid_t uid, char* buffer, const int bufferlen) { 281 const uid_t appid = uid % AID_USER; 282 const uid_t userid = uid / AID_USER; 283 if (appid >= AID_ISOLATED_START) { 284 snprintf(buffer, bufferlen, "u%u_i%u", userid, appid - AID_ISOLATED_START); 285 } else if (appid < AID_APP) { 286 for (size_t n = 0; n < android_id_count; n++) { 287 if (android_ids[n].aid == appid) { 288 snprintf(buffer, bufferlen, "u%u_%s", userid, android_ids[n].name); 289 return; 290 } 291 } 292 } else { 293 snprintf(buffer, bufferlen, "u%u_a%u", userid, appid - AID_APP); 294 } 295} 296 297static void print_app_name_from_gid(const gid_t gid, char* buffer, const int bufferlen) { 298 const uid_t appid = gid % AID_USER; 299 const uid_t userid = gid / AID_USER; 300 if (appid >= AID_ISOLATED_START) { 301 snprintf(buffer, bufferlen, "u%u_i%u", userid, appid - AID_ISOLATED_START); 302 } else if (userid == 0 && appid >= AID_SHARED_GID_START && appid <= AID_SHARED_GID_END) { 303 snprintf(buffer, bufferlen, "all_a%u", appid - AID_SHARED_GID_START); 304 } else if (appid < AID_APP) { 305 for (size_t n = 0; n < android_id_count; n++) { 306 if (android_ids[n].aid == appid) { 307 snprintf(buffer, bufferlen, "u%u_%s", userid, android_ids[n].name); 308 return; 309 } 310 } 311 } else { 312 snprintf(buffer, bufferlen, "u%u_a%u", userid, appid - AID_APP); 313 } 314} 315 316// Translate an OEM name to the corresponding user/group id. 317// oem_XXX -> AID_OEM_RESERVED_2_START + XXX, iff XXX is within range. 318static id_t oem_id_from_name(const char* name) { 319 unsigned int id; 320 if (sscanf(name, "oem_%u", &id) != 1) { 321 return 0; 322 } 323 // Check OEM id is within range. 324 if (id > (AID_OEM_RESERVED_2_END - AID_OEM_RESERVED_2_START)) { 325 return 0; 326 } 327 return AID_OEM_RESERVED_2_START + static_cast<id_t>(id); 328} 329 330static passwd* oem_id_to_passwd(uid_t uid, passwd_state_t* state) { 331 if (uid < AID_OEM_RESERVED_2_START || uid > AID_OEM_RESERVED_2_END) { 332 return NULL; 333 } 334 335 snprintf(state->name_buffer_, sizeof(state->name_buffer_), "oem_%u", 336 uid - AID_OEM_RESERVED_2_START); 337 snprintf(state->dir_buffer_, sizeof(state->dir_buffer_), "/"); 338 snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/system/bin/sh"); 339 340 passwd* pw = &state->passwd_; 341 pw->pw_name = state->name_buffer_; 342 pw->pw_dir = state->dir_buffer_; 343 pw->pw_shell = state->sh_buffer_; 344 pw->pw_uid = uid; 345 pw->pw_gid = uid; 346 return pw; 347} 348 349static group* oem_id_to_group(gid_t gid, group_state_t* state) { 350 if (gid < AID_OEM_RESERVED_2_START || gid > AID_OEM_RESERVED_2_END) { 351 return NULL; 352 } 353 354 snprintf(state->group_name_buffer_, sizeof(state->group_name_buffer_), 355 "oem_%u", gid - AID_OEM_RESERVED_2_START); 356 357 group* gr = &state->group_; 358 gr->gr_name = state->group_name_buffer_; 359 gr->gr_gid = gid; 360 gr->gr_mem[0] = gr->gr_name; 361 return gr; 362} 363 364// Translate a uid into the corresponding name. 365// 0 to AID_APP-1 -> "system", "radio", etc. 366// AID_APP to AID_ISOLATED_START-1 -> u0_a1234 367// AID_ISOLATED_START to AID_USER-1 -> u0_i1234 368// AID_USER+ -> u1_radio, u1_a1234, u2_i1234, etc. 369// returns a passwd structure (sets errno to ENOENT on failure). 370static passwd* app_id_to_passwd(uid_t uid, passwd_state_t* state) { 371 if (uid < AID_APP) { 372 errno = ENOENT; 373 return NULL; 374 } 375 376 print_app_name_from_uid(uid, state->name_buffer_, sizeof(state->name_buffer_)); 377 378 const uid_t appid = uid % AID_USER; 379 if (appid < AID_APP) { 380 snprintf(state->dir_buffer_, sizeof(state->dir_buffer_), "/"); 381 } else { 382 snprintf(state->dir_buffer_, sizeof(state->dir_buffer_), "/data"); 383 } 384 385 snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/system/bin/sh"); 386 387 passwd* pw = &state->passwd_; 388 pw->pw_name = state->name_buffer_; 389 pw->pw_dir = state->dir_buffer_; 390 pw->pw_shell = state->sh_buffer_; 391 pw->pw_uid = uid; 392 pw->pw_gid = uid; 393 return pw; 394} 395 396// Translate a gid into the corresponding app_<gid> 397// group structure (sets errno to ENOENT on failure). 398static group* app_id_to_group(gid_t gid, group_state_t* state) { 399 if (gid < AID_APP) { 400 errno = ENOENT; 401 return NULL; 402 } 403 404 print_app_name_from_gid(gid, state->group_name_buffer_, sizeof(state->group_name_buffer_)); 405 406 group* gr = &state->group_; 407 gr->gr_name = state->group_name_buffer_; 408 gr->gr_gid = gid; 409 gr->gr_mem[0] = gr->gr_name; 410 return gr; 411} 412 413passwd* getpwuid(uid_t uid) { // NOLINT: implementing bad function. 414 passwd_state_t* state = g_passwd_tls_buffer.get(); 415 if (state == NULL) { 416 return NULL; 417 } 418 419 passwd* pw = android_id_to_passwd(state, uid); 420 if (pw != NULL) { 421 return pw; 422 } 423 // Handle OEM range. 424 pw = oem_id_to_passwd(uid, state); 425 if (pw != NULL) { 426 return pw; 427 } 428 return app_id_to_passwd(uid, state); 429} 430 431passwd* getpwnam(const char* login) { // NOLINT: implementing bad function. 432 passwd_state_t* state = g_passwd_tls_buffer.get(); 433 if (state == NULL) { 434 return NULL; 435 } 436 437 passwd* pw = android_name_to_passwd(state, login); 438 if (pw != NULL) { 439 return pw; 440 } 441 // Handle OEM range. 442 pw = oem_id_to_passwd(oem_id_from_name(login), state); 443 if (pw != NULL) { 444 return pw; 445 } 446 return app_id_to_passwd(app_id_from_name(login, false), state); 447} 448 449// All users are in just one group, the one passed in. 450int getgrouplist(const char* /*user*/, gid_t group, gid_t* groups, int* ngroups) { 451 if (*ngroups < 1) { 452 *ngroups = 1; 453 return -1; 454 } 455 groups[0] = group; 456 return (*ngroups = 1); 457} 458 459char* getlogin() { // NOLINT: implementing bad function. 460 passwd *pw = getpwuid(getuid()); // NOLINT: implementing bad function in terms of bad function. 461 return (pw != NULL) ? pw->pw_name : NULL; 462} 463 464static group* getgrgid_internal(gid_t gid, group_state_t* state) { 465 group* grp = android_id_to_group(state, gid); 466 if (grp != NULL) { 467 return grp; 468 } 469 // Handle OEM range. 470 grp = oem_id_to_group(gid, state); 471 if (grp != NULL) { 472 return grp; 473 } 474 return app_id_to_group(gid, state); 475} 476 477group* getgrgid(gid_t gid) { // NOLINT: implementing bad function. 478 group_state_t* state = __group_state(); 479 if (state == NULL) { 480 return NULL; 481 } 482 return getgrgid_internal(gid, state); 483} 484 485static group* getgrnam_internal(const char* name, group_state_t* state) { 486 group* grp = android_name_to_group(state, name); 487 if (grp != NULL) { 488 return grp; 489 } 490 // Handle OEM range. 491 grp = oem_id_to_group(oem_id_from_name(name), state); 492 if (grp != NULL) { 493 return grp; 494 } 495 return app_id_to_group(app_id_from_name(name, true), state); 496} 497 498group* getgrnam(const char* name) { // NOLINT: implementing bad function. 499 group_state_t* state = __group_state(); 500 if (state == NULL) { 501 return NULL; 502 } 503 return getgrnam_internal(name, state); 504} 505 506static int getgroup_r(bool by_name, const char* name, gid_t gid, struct group* grp, char* buf, 507 size_t buflen, struct group** result) { 508 ErrnoRestorer errno_restorer; 509 *result = NULL; 510 char* p = reinterpret_cast<char*>( 511 BIONIC_ALIGN(reinterpret_cast<uintptr_t>(buf), sizeof(uintptr_t))); 512 if (p + sizeof(group_state_t) > buf + buflen) { 513 return ERANGE; 514 } 515 group_state_t* state = reinterpret_cast<group_state_t*>(p); 516 init_group_state(state); 517 group* retval = (by_name ? getgrnam_internal(name, state) : getgrgid_internal(gid, state)); 518 if (retval != NULL) { 519 *grp = *retval; 520 *result = grp; 521 return 0; 522 } 523 return errno; 524} 525 526int getgrgid_r(gid_t gid, struct group* grp, char* buf, size_t buflen, struct group** result) { 527 return getgroup_r(false, NULL, gid, grp, buf, buflen, result); 528} 529 530int getgrnam_r(const char* name, struct group* grp, char* buf, size_t buflen, 531 struct group **result) { 532 return getgroup_r(true, name, 0, grp, buf, buflen, result); 533} 534 535// We don't have an /etc/networks, so all inputs return NULL. 536netent* getnetbyname(const char* /*name*/) { 537 return NULL; 538} 539 540// We don't have an /etc/networks, so all inputs return NULL. 541netent* getnetbyaddr(uint32_t /*net*/, int /*type*/) { 542 return NULL; 543} 544 545// We don't have an /etc/protocols, so all inputs return NULL. 546protoent* getprotobyname(const char* /*name*/) { 547 return NULL; 548} 549 550// We don't have an /etc/protocols, so all inputs return NULL. 551protoent* getprotobynumber(int /*proto*/) { 552 return NULL; 553} 554 555// Portable code should use sysconf(_SC_PAGE_SIZE) directly instead. 556int getpagesize() { 557 // We dont use sysconf(3) here because that drags in stdio, which makes static binaries fat. 558 return PAGE_SIZE; 559} 560