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