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 /** Thread-specific state for the stubs functions
     41  **/
     42 
     43 pthread_once_t   the_once = PTHREAD_ONCE_INIT;
     44 pthread_key_t    the_key;
     45 
     46 typedef struct {
     47     struct passwd  passwd;
     48     struct group   group;
     49     char*          group_members[2];
     50     char           app_name_buffer[32];
     51     char           group_name_buffer[32];
     52 } stubs_state_t;
     53 
     54 static void
     55 stubs_state_free( void*  _s )
     56 {
     57     stubs_state_t*  s = _s;
     58     free(s);
     59 }
     60 
     61 static stubs_state_t*
     62 stubs_state_alloc( void )
     63 {
     64     stubs_state_t*  s = calloc(1, sizeof *s);
     65 
     66     if (s != NULL) {
     67         s->group.gr_mem = s->group_members;
     68     }
     69     return s;
     70 }
     71 
     72 static void __stubs_key_init(void)
     73 {
     74     pthread_key_create( &the_key, stubs_state_free );
     75 }
     76 
     77 static stubs_state_t*
     78 __stubs_state(void)
     79 {
     80     stubs_state_t*  s;
     81 
     82     pthread_once(&the_once, __stubs_key_init);
     83     s = pthread_getspecific(the_key);
     84     if (s == NULL) {
     85         s = stubs_state_alloc();
     86         if (s == NULL) {
     87             errno = ENOMEM;  /* just in case */
     88         } else {
     89             if ( pthread_setspecific(the_key, s) != 0 ) {
     90                 stubs_state_free(s);
     91                 errno = ENOMEM;
     92                 s     = NULL;
     93             }
     94         }
     95     }
     96     return s;
     97 }
     98 
     99 static struct passwd*
    100 android_iinfo_to_passwd( struct passwd          *pw,
    101                          struct android_id_info *iinfo )
    102 {
    103     pw->pw_name  = (char*)iinfo->name;
    104     pw->pw_uid   = iinfo->aid;
    105     pw->pw_gid   = iinfo->aid;
    106     pw->pw_dir   = "/";
    107     pw->pw_shell = "/system/bin/sh";
    108     return pw;
    109 }
    110 
    111 static struct group*
    112 android_iinfo_to_group( struct group *gr,
    113                         struct android_id_info *iinfo )
    114 {
    115     gr->gr_name   = (char*) iinfo->name;
    116     gr->gr_gid    = iinfo->aid;
    117     gr->gr_mem[0] = gr->gr_name;
    118     gr->gr_mem[1] = NULL;
    119     return gr;
    120 }
    121 
    122 static struct passwd *
    123 android_id_to_passwd( struct passwd *pw, unsigned id)
    124 {
    125     struct android_id_info *iinfo = android_ids;
    126     unsigned n;
    127     for (n = 0; n < android_id_count; n++) {
    128         if (iinfo[n].aid == id) {
    129             return android_iinfo_to_passwd(pw, iinfo + n);
    130         }
    131     }
    132     return NULL;
    133 }
    134 
    135 static struct passwd*
    136 android_name_to_passwd(struct passwd *pw, const char *name)
    137 {
    138     struct android_id_info *iinfo = android_ids;
    139     unsigned n;
    140     for (n = 0; n < android_id_count; n++) {
    141         if (!strcmp(iinfo[n].name, name)) {
    142             return android_iinfo_to_passwd(pw, iinfo + n);
    143         }
    144     }
    145     return NULL;
    146 }
    147 
    148 static struct group*
    149 android_id_to_group( struct group *gr, unsigned id )
    150 {
    151     struct android_id_info *iinfo = android_ids;
    152     unsigned n;
    153     for (n = 0; n < android_id_count; n++) {
    154         if (iinfo[n].aid == id) {
    155             return android_iinfo_to_group(gr, iinfo + n);
    156         }
    157     }
    158     return NULL;
    159 }
    160 
    161 static struct group*
    162 android_name_to_group( struct group *gr, const char *name )
    163 {
    164     struct android_id_info *iinfo = android_ids;
    165     unsigned n;
    166     for (n = 0; n < android_id_count; n++) {
    167         if (!strcmp(iinfo[n].name, name)) {
    168             return android_iinfo_to_group(gr, iinfo + n);
    169         }
    170     }
    171     return NULL;
    172 }
    173 
    174 /* translate a user/group name like app_1234 into the
    175  * corresponding user/group id (AID_APP + 1234)
    176  * returns 0 and sets errno to ENOENT in case of error
    177  */
    178 static unsigned
    179 app_id_from_name( const char*  name )
    180 {
    181     unsigned long  id;
    182     char*          end;
    183 
    184     if (memcmp(name, "app_", 4) != 0 || !isdigit(name[4]))
    185         goto FAIL;
    186 
    187     id = strtoul(name+4, &end, 10);
    188     if (*end != '\0')
    189         goto FAIL;
    190 
    191     id += AID_APP;
    192 
    193     /* check for overflow and that the value can be
    194      * stored in our 32-bit uid_t/gid_t */
    195     if (id < AID_APP || (unsigned)id != id)
    196         goto FAIL;
    197 
    198     return (unsigned)id;
    199 
    200 FAIL:
    201     errno = ENOENT;
    202     return 0;
    203 }
    204 
    205 /* translate a uid into the corresponding app_<uid>
    206  * passwd structure (sets errno to ENOENT on failure)
    207  */
    208 static struct passwd*
    209 app_id_to_passwd(uid_t  uid, stubs_state_t*  state)
    210 {
    211     struct passwd*  pw = &state->passwd;
    212 
    213     if (uid < AID_APP) {
    214         errno = ENOENT;
    215         return NULL;
    216     }
    217 
    218     snprintf( state->app_name_buffer, sizeof state->app_name_buffer,
    219               "app_%u", uid - AID_APP );
    220 
    221     pw->pw_name  = state->app_name_buffer;
    222     pw->pw_dir   = "/data";
    223     pw->pw_shell = "/system/bin/sh";
    224     pw->pw_uid   = uid;
    225     pw->pw_gid   = uid;
    226 
    227     return pw;
    228 }
    229 
    230 /* translate a gid into the corresponding app_<gid>
    231  * group structure (sets errno to ENOENT on failure)
    232  */
    233 static struct group*
    234 app_id_to_group(gid_t  gid, stubs_state_t*  state)
    235 {
    236     struct group*  gr = &state->group;
    237 
    238     if (gid < AID_APP) {
    239         errno = ENOENT;
    240         return NULL;
    241     }
    242 
    243     snprintf(state->group_name_buffer, sizeof state->group_name_buffer,
    244              "app_%u", gid - AID_APP);
    245 
    246     gr->gr_name   = state->group_name_buffer;
    247     gr->gr_gid    = gid;
    248     gr->gr_mem[0] = gr->gr_name;
    249     gr->gr_mem[1] = NULL;
    250 
    251     return gr;
    252 }
    253 
    254 
    255 struct passwd*
    256 getpwuid(uid_t uid)
    257 {
    258     stubs_state_t*  state = __stubs_state();
    259     struct passwd*  pw;
    260 
    261     if (state == NULL)
    262         return NULL;
    263 
    264     pw = &state->passwd;
    265 
    266     if ( android_id_to_passwd(pw, uid) != NULL )
    267         return pw;
    268 
    269     return app_id_to_passwd(uid, state);
    270 }
    271 
    272 struct passwd*
    273 getpwnam(const char *login)
    274 {
    275     stubs_state_t*  state = __stubs_state();
    276 
    277     if (state == NULL)
    278         return NULL;
    279 
    280     if (android_name_to_passwd(&state->passwd, login) != NULL)
    281         return &state->passwd;
    282 
    283     return app_id_to_passwd( app_id_from_name(login), state );
    284 }
    285 
    286 int
    287 getgrouplist (const char *user, gid_t group,
    288               gid_t *groups, int *ngroups)
    289 {
    290     if (*ngroups < 1) {
    291         *ngroups = 1;
    292         return -1;
    293     }
    294     groups[0] = group;
    295     return (*ngroups = 1);
    296 }
    297 
    298 char*
    299 getlogin(void)
    300 {
    301     struct passwd *pw = getpwuid(getuid());
    302 
    303     if(pw) {
    304         return pw->pw_name;
    305     } else {
    306         return NULL;
    307     }
    308 }
    309 
    310 struct group*
    311 getgrgid(gid_t gid)
    312 {
    313     stubs_state_t*  state = __stubs_state();
    314     struct group*   gr;
    315 
    316     if (state == NULL)
    317         return NULL;
    318 
    319     gr = android_id_to_group(&state->group, gid);
    320     if (gr != NULL)
    321         return gr;
    322 
    323     return app_id_to_group(gid, state);
    324 }
    325 
    326 struct group*
    327 getgrnam(const char *name)
    328 {
    329     stubs_state_t*  state = __stubs_state();
    330     unsigned        id;
    331 
    332     if (state == NULL)
    333         return NULL;
    334 
    335     if (android_name_to_group(&state->group, name) != 0)
    336         return &state->group;
    337 
    338     return app_id_to_group( app_id_from_name(name), state );
    339 }
    340 
    341 
    342 struct netent* getnetbyname(const char *name)
    343 {
    344     fprintf(stderr, "FIX ME! implement getgrnam() %s:%d\n", __FILE__, __LINE__);
    345     return NULL;
    346 }
    347 
    348 void endpwent(void)
    349 {
    350 }
    351 
    352 struct mntent* getmntent(FILE* f)
    353 {
    354     fprintf(stderr, "FIX ME! implement getmntent() %s:%d\n", __FILE__, __LINE__);
    355     return NULL;
    356 }
    357 
    358 char* ttyname(int fd)
    359 {
    360     fprintf(stderr, "FIX ME! implement ttyname() %s:%d\n", __FILE__, __LINE__);
    361     return NULL;
    362 }
    363 
    364 int ttyname_r(int fd, char *buf, size_t buflen)
    365 {
    366     fprintf(stderr, "FIX ME! implement ttyname_r() %s:%d\n", __FILE__, __LINE__);
    367     return -ERANGE;
    368 }
    369 
    370 struct netent *getnetbyaddr(uint32_t net, int type)
    371 {
    372     fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
    373     return NULL;
    374 }
    375 
    376 struct protoent *getprotobyname(const char *name)
    377 {
    378     fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
    379     return NULL;
    380 }
    381 
    382 struct protoent *getprotobynumber(int proto)
    383 {
    384     fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
    385     return NULL;
    386 }
    387 
    388 char* getusershell(void)
    389 {
    390     fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
    391     return NULL;
    392 }
    393 
    394 void setusershell(void)
    395 {
    396     fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
    397 }
    398 
    399 void endusershell(void)
    400 {
    401     fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
    402 }
    403 
    404