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 <private/android_filesystem_config.h>
     35 #include <private/logd.h>
     36 #include <pthread.h>
     37 #include <pwd.h>
     38 #include <stdio.h>
     39 #include <stdlib.h>
     40 #include <unistd.h>
     41 
     42 // Thread-specific state for the non-reentrant functions.
     43 static pthread_once_t stubs_once = PTHREAD_ONCE_INIT;
     44 static pthread_key_t stubs_key;
     45 struct stubs_state_t {
     46   passwd passwd_;
     47   group group_;
     48   char* group_members_[2];
     49   char app_name_buffer_[32];
     50   char group_name_buffer_[32];
     51   char dir_buffer_[32];
     52   char sh_buffer_[32];
     53 };
     54 
     55 static int do_getpw_r(int by_name, const char* name, uid_t uid,
     56                       passwd* dst, char* buf, size_t byte_count,
     57                       passwd** result) {
     58   // getpwnam_r and getpwuid_r don't modify errno, but library calls we
     59   // make might.
     60   int old_errno = errno;
     61   *result = NULL;
     62 
     63   // Our implementation of getpwnam(3) and getpwuid(3) use thread-local
     64   // storage, so we can call them as long as we copy everything out
     65   // before returning.
     66   const passwd* src = by_name ? getpwnam(name) : getpwuid(uid); // NOLINT: see above.
     67 
     68   // POSIX allows failure to find a match to be considered a non-error.
     69   // Reporting success (0) but with *result NULL is glibc's behavior.
     70   if (src == NULL) {
     71     int rc = (errno == ENOENT) ? 0 : errno;
     72     errno = old_errno;
     73     return rc;
     74   }
     75 
     76   // Work out where our strings will go in 'buf', and whether we've got
     77   // enough space.
     78   size_t required_byte_count = 0;
     79   dst->pw_name = buf;
     80   required_byte_count += strlen(src->pw_name) + 1;
     81   dst->pw_dir = buf + required_byte_count;
     82   required_byte_count += strlen(src->pw_dir) + 1;
     83   dst->pw_shell = buf + required_byte_count;
     84   required_byte_count += strlen(src->pw_shell) + 1;
     85   if (byte_count < required_byte_count) {
     86     errno = old_errno;
     87     return ERANGE;
     88   }
     89 
     90   // Copy the strings.
     91   snprintf(buf, byte_count, "%s%c%s%c%s",
     92            src->pw_name, 0, src->pw_dir, 0, src->pw_shell);
     93 
     94   // pw_passwd is non-POSIX and unused (always NULL) in bionic.
     95   // pw_gecos is non-POSIX and missing in bionic.
     96   dst->pw_passwd = NULL;
     97 
     98   // Copy the integral fields.
     99   dst->pw_gid = src->pw_gid;
    100   dst->pw_uid = src->pw_uid;
    101 
    102   *result = dst;
    103   errno = old_errno;
    104   return 0;
    105 }
    106 
    107 int getpwnam_r(const char* name, passwd* pwd,
    108                char* buf, size_t byte_count, passwd** result) {
    109   return do_getpw_r(1, name, -1, pwd, buf, byte_count, result);
    110 }
    111 
    112 int getpwuid_r(uid_t uid, passwd* pwd,
    113                char* buf, size_t byte_count, passwd** result) {
    114   return do_getpw_r(0, NULL, uid, pwd, buf, byte_count, result);
    115 }
    116 
    117 static stubs_state_t* stubs_state_alloc() {
    118   stubs_state_t*  s = static_cast<stubs_state_t*>(calloc(1, sizeof(*s)));
    119   if (s != NULL) {
    120     s->group_.gr_mem = s->group_members_;
    121   }
    122   return s;
    123 }
    124 
    125 static void stubs_state_free(void* ptr) {
    126   stubs_state_t* state = static_cast<stubs_state_t*>(ptr);
    127   free(state);
    128 }
    129 
    130 static void __stubs_key_init() {
    131   pthread_key_create(&stubs_key, stubs_state_free);
    132 }
    133 
    134 static stubs_state_t* __stubs_state() {
    135   pthread_once(&stubs_once, __stubs_key_init);
    136   stubs_state_t* s = static_cast<stubs_state_t*>(pthread_getspecific(stubs_key));
    137   if (s == NULL) {
    138     s = stubs_state_alloc();
    139     if (s == NULL) {
    140       errno = ENOMEM;  // Just in case.
    141     } else {
    142       if (pthread_setspecific(stubs_key, s) != 0) {
    143         stubs_state_free(s);
    144         errno = ENOMEM;
    145         s = NULL;
    146       }
    147     }
    148   }
    149   return s;
    150 }
    151 
    152 static passwd* android_iinfo_to_passwd(stubs_state_t* state,
    153                                        const android_id_info* iinfo) {
    154   snprintf(state->dir_buffer_, sizeof(state->dir_buffer_), "/");
    155   snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/system/bin/sh");
    156 
    157   passwd* pw = &state->passwd_;
    158   pw->pw_name  = (char*) iinfo->name;
    159   pw->pw_uid   = iinfo->aid;
    160   pw->pw_gid   = iinfo->aid;
    161   pw->pw_dir   = state->dir_buffer_;
    162   pw->pw_shell = state->sh_buffer_;
    163   return pw;
    164 }
    165 
    166 static group* android_iinfo_to_group(group* gr,
    167                                      const android_id_info* iinfo) {
    168   gr->gr_name   = (char*) iinfo->name;
    169   gr->gr_gid    = iinfo->aid;
    170   gr->gr_mem[0] = gr->gr_name;
    171   gr->gr_mem[1] = NULL;
    172   return gr;
    173 }
    174 
    175 static passwd* android_id_to_passwd(stubs_state_t* state, unsigned id) {
    176   for (size_t n = 0; n < android_id_count; ++n) {
    177     if (android_ids[n].aid == id) {
    178       return android_iinfo_to_passwd(state, android_ids + n);
    179     }
    180   }
    181   return NULL;
    182 }
    183 
    184 static passwd* android_name_to_passwd(stubs_state_t* state, const char* name) {
    185   for (size_t n = 0; n < android_id_count; ++n) {
    186     if (!strcmp(android_ids[n].name, name)) {
    187       return android_iinfo_to_passwd(state, android_ids + n);
    188     }
    189   }
    190   return NULL;
    191 }
    192 
    193 static group* android_id_to_group(group* gr, unsigned id) {
    194   for (size_t n = 0; n < android_id_count; ++n) {
    195     if (android_ids[n].aid == id) {
    196       return android_iinfo_to_group(gr, android_ids + n);
    197     }
    198   }
    199   return NULL;
    200 }
    201 
    202 static group* android_name_to_group(group* gr, const char* name) {
    203   for (size_t n = 0; n < android_id_count; ++n) {
    204     if (!strcmp(android_ids[n].name, name)) {
    205       return android_iinfo_to_group(gr, android_ids + n);
    206     }
    207   }
    208   return NULL;
    209 }
    210 
    211 // Translate a user/group name to the corresponding user/group id.
    212 // u0_a1234 -> 0 * AID_USER + AID_APP + 1234
    213 // u2_i1000 -> 2 * AID_USER + AID_ISOLATED_START + 1000
    214 // u1_system -> 1 * AID_USER + android_ids['system']
    215 // returns 0 and sets errno to ENOENT in case of error
    216 static unsigned app_id_from_name(const char* name) {
    217   if (name[0] != 'u' || !isdigit(name[1])) {
    218     errno = ENOENT;
    219     return 0;
    220   }
    221 
    222   char* end;
    223   unsigned long userid = strtoul(name+1, &end, 10);
    224   if (end[0] != '_' || end[1] == 0) {
    225     errno = ENOENT;
    226     return 0;
    227   }
    228 
    229   unsigned long appid = 0;
    230   if (end[1] == 'a' && isdigit(end[2])) {
    231     // end will point to \0 if the strtoul below succeeds.
    232     appid = strtoul(end+2, &end, 10) + AID_APP;
    233   } else if (end[1] == 'i' && isdigit(end[2])) {
    234     // end will point to \0 if the strtoul below succeeds.
    235     appid = strtoul(end+2, &end, 10) + AID_ISOLATED_START;
    236   } else {
    237     for (size_t n = 0; n < android_id_count; n++) {
    238       if (!strcmp(android_ids[n].name, end + 1)) {
    239         appid = android_ids[n].aid;
    240         // Move the end pointer to the null terminator.
    241         end += strlen(android_ids[n].name) + 1;
    242       }
    243     }
    244   }
    245 
    246   // Check that the entire string was consumed by one of the 3 cases above.
    247   if (end[0] != 0) {
    248     errno = ENOENT;
    249     return 0;
    250   }
    251 
    252   // Check that user id won't overflow.
    253   if (userid > 1000) {
    254     errno = ENOENT;
    255     return 0;
    256   }
    257 
    258   // Check that app id is within range.
    259   if (appid >= AID_USER) {
    260     errno = ENOENT;
    261     return 0;
    262   }
    263 
    264   return (unsigned)(appid + userid*AID_USER);
    265 }
    266 
    267 static void print_app_name_from_appid_userid(const uid_t appid,
    268     const uid_t userid, char* buffer, const int bufferlen) {
    269   if (appid >= AID_ISOLATED_START) {
    270     snprintf(buffer, bufferlen, "u%u_i%u", userid, appid - AID_ISOLATED_START);
    271   } else if (userid == 0 && appid >= AID_SHARED_GID_START) {
    272     snprintf(buffer, bufferlen, "all_a%u", appid - AID_SHARED_GID_START);
    273   } else if (appid < AID_APP) {
    274     for (size_t n = 0; n < android_id_count; n++) {
    275       if (android_ids[n].aid == appid) {
    276         snprintf(buffer, bufferlen, "u%u_%s", userid, android_ids[n].name);
    277         return;
    278       }
    279     }
    280   } else {
    281     snprintf(buffer, bufferlen, "u%u_a%u", userid, appid - AID_APP);
    282   }
    283 }
    284 
    285 static void print_app_name_from_uid(const uid_t uid, char* buffer, const int bufferlen) {
    286   const uid_t appid = uid % AID_USER;
    287   const uid_t userid = uid / AID_USER;
    288   return print_app_name_from_appid_userid(appid, userid, buffer, bufferlen);
    289 }
    290 
    291 // Translate a uid into the corresponding name.
    292 // 0 to AID_APP-1                   -> "system", "radio", etc.
    293 // AID_APP to AID_ISOLATED_START-1  -> u0_a1234
    294 // AID_ISOLATED_START to AID_USER-1 -> u0_i1234
    295 // AID_USER+                        -> u1_radio, u1_a1234, u2_i1234, etc.
    296 // returns a passwd structure (sets errno to ENOENT on failure).
    297 static passwd* app_id_to_passwd(uid_t uid, stubs_state_t* state) {
    298   passwd* pw = &state->passwd_;
    299 
    300   if (uid < AID_APP) {
    301     errno = ENOENT;
    302     return NULL;
    303   }
    304 
    305   const uid_t appid = uid % AID_USER;
    306   const uid_t userid = uid / AID_USER;
    307 
    308   print_app_name_from_appid_userid(appid, userid, state->app_name_buffer_,
    309                                    sizeof(state->app_name_buffer_));
    310 
    311   if (appid < AID_APP) {
    312       snprintf(state->dir_buffer_, sizeof(state->dir_buffer_), "/");
    313   } else {
    314       snprintf(state->dir_buffer_, sizeof(state->dir_buffer_), "/data");
    315   }
    316 
    317   snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/system/bin/sh");
    318 
    319   pw->pw_name  = state->app_name_buffer_;
    320   pw->pw_dir   = state->dir_buffer_;
    321   pw->pw_shell = state->sh_buffer_;
    322   pw->pw_uid   = uid;
    323   pw->pw_gid   = uid;
    324 
    325   return pw;
    326 }
    327 
    328 // Translate a gid into the corresponding app_<gid>
    329 // group structure (sets errno to ENOENT on failure).
    330 static group* app_id_to_group(gid_t gid, stubs_state_t* state) {
    331   if (gid < AID_APP) {
    332     errno = ENOENT;
    333     return NULL;
    334   }
    335 
    336   print_app_name_from_uid(gid, state->group_name_buffer_,
    337                           sizeof(state->group_name_buffer_));
    338 
    339   group* gr = &state->group_;
    340   gr->gr_name   = state->group_name_buffer_;
    341   gr->gr_gid    = gid;
    342   gr->gr_mem[0] = gr->gr_name;
    343   gr->gr_mem[1] = NULL;
    344   return gr;
    345 }
    346 
    347 
    348 passwd* getpwuid(uid_t uid) { // NOLINT: implementing bad function.
    349   stubs_state_t* state = __stubs_state();
    350   if (state == NULL) {
    351     return NULL;
    352   }
    353 
    354   passwd* pw = android_id_to_passwd(state, uid);
    355   if (pw != NULL) {
    356     return pw;
    357   }
    358   return app_id_to_passwd(uid, state);
    359 }
    360 
    361 passwd* getpwnam(const char* login) { // NOLINT: implementing bad function.
    362   stubs_state_t* state = __stubs_state();
    363   if (state == NULL) {
    364     return NULL;
    365   }
    366 
    367   passwd* pw = android_name_to_passwd(state, login);
    368   if (pw != NULL) {
    369     return pw;
    370   }
    371   return app_id_to_passwd(app_id_from_name(login), state);
    372 }
    373 
    374 int getgrouplist(const char* user, gid_t group, gid_t* groups, int* ngroups) {
    375     if (*ngroups < 1) {
    376         *ngroups = 1;
    377         return -1;
    378     }
    379     groups[0] = group;
    380     return (*ngroups = 1);
    381 }
    382 
    383 char* getlogin() { // NOLINT: implementing bad function.
    384   passwd *pw = getpwuid(getuid()); // NOLINT: implementing bad function in terms of bad function.
    385   return (pw != NULL) ? pw->pw_name : NULL;
    386 }
    387 
    388 group* getgrgid(gid_t gid) { // NOLINT: implementing bad function.
    389   stubs_state_t* state = __stubs_state();
    390   if (state == NULL) {
    391     return NULL;
    392   }
    393 
    394   group* gr = android_id_to_group(&state->group_, gid);
    395   if (gr != NULL) {
    396     return gr;
    397   }
    398 
    399   return app_id_to_group(gid, state);
    400 }
    401 
    402 group* getgrnam(const char* name) { // NOLINT: implementing bad function.
    403   stubs_state_t* state = __stubs_state();
    404   if (state == NULL) {
    405     return NULL;
    406   }
    407 
    408   if (android_name_to_group(&state->group_, name) != 0) {
    409     return &state->group_;
    410   }
    411 
    412   return app_id_to_group(app_id_from_name(name), state);
    413 }
    414 
    415 static void unimplemented_stub(const char* function) {
    416   const char* fmt = "%s(3) is not implemented on Android\n";
    417   __libc_android_log_print(ANDROID_LOG_WARN, "libc", fmt, function);
    418   fprintf(stderr, fmt, function);
    419 }
    420 
    421 #define UNIMPLEMENTED unimplemented_stub(__PRETTY_FUNCTION__)
    422 
    423 netent* getnetbyname(const char* name) {
    424   UNIMPLEMENTED;
    425   return NULL;
    426 }
    427 
    428 void endpwent() {
    429   UNIMPLEMENTED;
    430 }
    431 
    432 mntent* getmntent(FILE* f) {
    433   UNIMPLEMENTED;
    434   return NULL;
    435 }
    436 
    437 char* ttyname(int fd) { // NOLINT: implementing bad function.
    438   UNIMPLEMENTED;
    439   return NULL;
    440 }
    441 
    442 int ttyname_r(int fd, char* buf, size_t buflen) {
    443   UNIMPLEMENTED;
    444   return -ERANGE;
    445 }
    446 
    447 netent* getnetbyaddr(uint32_t net, int type) {
    448   UNIMPLEMENTED;
    449   return NULL;
    450 }
    451 
    452 protoent* getprotobyname(const char* name) {
    453   UNIMPLEMENTED;
    454   return NULL;
    455 }
    456 
    457 protoent* getprotobynumber(int proto) {
    458   UNIMPLEMENTED;
    459   return NULL;
    460 }
    461 
    462 char* getusershell() {
    463   UNIMPLEMENTED;
    464   return NULL;
    465 }
    466 
    467 void setusershell() {
    468   UNIMPLEMENTED;
    469 }
    470 
    471 void endusershell() {
    472   UNIMPLEMENTED;
    473 }
    474