Home | History | Annotate | Download | only in bionic
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *  * Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  *  * Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in
     12  *    the documentation and/or other materials provided with the
     13  *    distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
     22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include <ctype.h>
     30 #include <errno.h>
     31 #include <grp.h>
     32 #include <mntent.h>
     33 #include <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 
     54 struct group_state_t {
     55   group group_;
     56   char* group_members_[2];
     57   char group_name_buffer_[32];
     58 };
     59 
     60 struct passwd_state_t {
     61   passwd passwd_;
     62   char name_buffer_[32];
     63   char dir_buffer_[32];
     64   char sh_buffer_[32];
     65 };
     66 
     67 static ThreadLocalBuffer<group_state_t> g_group_tls_buffer;
     68 static ThreadLocalBuffer<passwd_state_t> g_passwd_tls_buffer;
     69 
     70 static 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 
     75 static 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 
     83 static 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 
    133 int 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 
    138 int 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 
    143 static 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 
    158 static 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 
    169 static 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 
    178 static 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 
    187 static 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 
    196 static 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.
    211 static 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 
    280 static 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 
    297 static 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.
    318 static 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 
    330 static 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 
    349 static 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).
    370 static 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).
    398 static 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 
    413 passwd* 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 
    431 passwd* 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.
    450 int 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 
    459 char* 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 
    464 static 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 
    477 group* 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 
    485 static 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 
    498 group* 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 
    506 static 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 
    526 int 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 
    530 int 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.
    536 netent* getnetbyname(const char* /*name*/) {
    537   return NULL;
    538 }
    539 
    540 // We don't have an /etc/networks, so all inputs return NULL.
    541 netent* getnetbyaddr(uint32_t /*net*/, int /*type*/) {
    542   return NULL;
    543 }
    544 
    545 // We don't have an /etc/protocols, so all inputs return NULL.
    546 protoent* getprotobyname(const char* /*name*/) {
    547   return NULL;
    548 }
    549 
    550 // We don't have an /etc/protocols, so all inputs return NULL.
    551 protoent* getprotobynumber(int /*proto*/) {
    552   return NULL;
    553 }
    554 
    555 // Portable code should use sysconf(_SC_PAGE_SIZE) directly instead.
    556 int getpagesize() {
    557   // We dont use sysconf(3) here because that drags in stdio, which makes static binaries fat.
    558   return PAGE_SIZE;
    559 }
    560