• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
do_getpw_r(int by_name,const char * name,uid_t uid,struct passwd * dst,char * buf,size_t byte_count,struct passwd ** result)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 
getpwnam_r(const char * name,struct passwd * pwd,char * buf,size_t byte_count,struct passwd ** result)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 
getpwuid_r(uid_t uid,struct passwd * pwd,char * buf,size_t byte_count,struct passwd ** result)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
stubs_state_free(void * _s)127 stubs_state_free( void*  _s )
128 {
129     stubs_state_t*  s = _s;
130     free(s);
131 }
132 
133 static stubs_state_t*
stubs_state_alloc(void)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 
__stubs_key_init(void)144 static void __stubs_key_init(void)
145 {
146     pthread_key_create( &the_key, stubs_state_free );
147 }
148 
149 static stubs_state_t*
__stubs_state(void)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*
android_iinfo_to_passwd(struct passwd * pw,struct android_id_info * iinfo)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*
android_iinfo_to_group(struct group * gr,struct android_id_info * iinfo)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 *
android_id_to_passwd(struct passwd * pw,unsigned id)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*
android_name_to_passwd(struct passwd * pw,const char * name)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*
android_id_to_group(struct group * gr,unsigned id)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*
android_name_to_group(struct group * gr,const char * name)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
app_id_from_name(const char * name)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
print_app_uid_name(uid_t uid,char * buffer,int bufferlen)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*
app_id_to_passwd(uid_t uid,stubs_state_t * state)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*
app_id_to_group(gid_t gid,stubs_state_t * state)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*
getpwuid(uid_t uid)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*
getpwnam(const char * login)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
getgrouplist(const char * user,gid_t group,gid_t * groups,int * ngroups)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*
getlogin(void)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*
getgrgid(gid_t gid)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*
getgrnam(const char * name)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 
getnetbyname(const char * name)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 
endpwent(void)448 void endpwent(void)
449 {
450 }
451 
getmntent(FILE * f)452 struct mntent* getmntent(FILE* f)
453 {
454     fprintf(stderr, "FIX ME! implement getmntent() %s:%d\n", __FILE__, __LINE__);
455     return NULL;
456 }
457 
ttyname(int fd)458 char* ttyname(int fd)
459 {
460     fprintf(stderr, "FIX ME! implement ttyname() %s:%d\n", __FILE__, __LINE__);
461     return NULL;
462 }
463 
ttyname_r(int fd,char * buf,size_t buflen)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 
getnetbyaddr(uint32_t net,int type)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 
getprotobyname(const char * name)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 
getprotobynumber(int proto)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 
getusershell(void)488 char* getusershell(void)
489 {
490     fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
491     return NULL;
492 }
493 
setusershell(void)494 void setusershell(void)
495 {
496     fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
497 }
498 
endusershell(void)499 void endusershell(void)
500 {
501     fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
502 }
503