• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <gtest/gtest.h>
18 
19 // Below are the header files we want to test.
20 #include <grp.h>
21 #include <pwd.h>
22 
23 #include <errno.h>
24 #include <limits.h>
25 #include <sys/cdefs.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28 
29 #include <bitset>
30 
31 #include <private/android_filesystem_config.h>
32 
33 // Generated android_ids array
34 #include "generated_android_ids.h"
35 
36 enum uid_type_t {
37   TYPE_SYSTEM,
38   TYPE_APP
39 };
40 
41 #if defined(__BIONIC__)
42 
check_passwd(const passwd * pwd,const char * username,uid_t uid,uid_type_t uid_type)43 static void check_passwd(const passwd* pwd, const char* username, uid_t uid, uid_type_t uid_type) {
44   ASSERT_TRUE(pwd != NULL);
45   ASSERT_STREQ(username, pwd->pw_name);
46   ASSERT_EQ(uid, pwd->pw_uid);
47   ASSERT_EQ(uid, pwd->pw_gid);
48   ASSERT_EQ(NULL, pwd->pw_passwd);
49 #ifdef __LP64__
50   ASSERT_EQ(NULL, pwd->pw_gecos);
51 #endif
52 
53   if (uid_type == TYPE_SYSTEM) {
54     ASSERT_STREQ("/", pwd->pw_dir);
55   } else {
56     ASSERT_STREQ("/data", pwd->pw_dir);
57   }
58   ASSERT_STREQ("/system/bin/sh", pwd->pw_shell);
59 }
60 
check_getpwuid(const char * username,uid_t uid,uid_type_t uid_type)61 static void check_getpwuid(const char* username, uid_t uid, uid_type_t uid_type) {
62   errno = 0;
63   passwd* pwd = getpwuid(uid);
64   ASSERT_EQ(0, errno);
65   SCOPED_TRACE("getpwuid");
66   check_passwd(pwd, username, uid, uid_type);
67 }
68 
check_getpwnam(const char * username,uid_t uid,uid_type_t uid_type)69 static void check_getpwnam(const char* username, uid_t uid, uid_type_t uid_type) {
70   errno = 0;
71   passwd* pwd = getpwnam(username);
72   ASSERT_EQ(0, errno);
73   SCOPED_TRACE("getpwnam");
74   check_passwd(pwd, username, uid, uid_type);
75 }
76 
check_getpwuid_r(const char * username,uid_t uid,uid_type_t uid_type)77 static void check_getpwuid_r(const char* username, uid_t uid, uid_type_t uid_type) {
78   passwd pwd_storage;
79   char buf[512];
80   int result;
81 
82   errno = 0;
83   passwd* pwd = NULL;
84   result = getpwuid_r(uid, &pwd_storage, buf, sizeof(buf), &pwd);
85   ASSERT_EQ(0, result);
86   ASSERT_EQ(0, errno);
87   SCOPED_TRACE("getpwuid_r");
88   check_passwd(pwd, username, uid, uid_type);
89 }
90 
check_getpwnam_r(const char * username,uid_t uid,uid_type_t uid_type)91 static void check_getpwnam_r(const char* username, uid_t uid, uid_type_t uid_type) {
92   passwd pwd_storage;
93   char buf[512];
94   int result;
95 
96   errno = 0;
97   passwd* pwd = NULL;
98   result = getpwnam_r(username, &pwd_storage, buf, sizeof(buf), &pwd);
99   ASSERT_EQ(0, result);
100   ASSERT_EQ(0, errno);
101   SCOPED_TRACE("getpwnam_r");
102   check_passwd(pwd, username, uid, uid_type);
103 }
104 
check_get_passwd(const char * username,uid_t uid,uid_type_t uid_type)105 static void check_get_passwd(const char* username, uid_t uid, uid_type_t uid_type) {
106   check_getpwuid(username, uid, uid_type);
107   check_getpwnam(username, uid, uid_type);
108   check_getpwuid_r(username, uid, uid_type);
109   check_getpwnam_r(username, uid, uid_type);
110 }
111 
112 #else // !defined(__BIONIC__)
113 
check_get_passwd(const char *,uid_t,uid_type_t)114 static void check_get_passwd(const char* /* username */, uid_t /* uid */, uid_type_t /* uid_type */) {
115   GTEST_LOG_(INFO) << "This test is about uid/username translation for Android, which does nothing on libc other than bionic.\n";
116 }
117 
118 #endif
119 
TEST(pwd,getpwnam_system_id_root)120 TEST(pwd, getpwnam_system_id_root) {
121   check_get_passwd("root", 0, TYPE_SYSTEM);
122 }
123 
TEST(pwd,getpwnam_system_id_system)124 TEST(pwd, getpwnam_system_id_system) {
125   check_get_passwd("system", 1000, TYPE_SYSTEM);
126 }
127 
TEST(pwd,getpwnam_app_id_radio)128 TEST(pwd, getpwnam_app_id_radio) {
129   check_get_passwd("radio", 1001, TYPE_SYSTEM);
130 }
131 
TEST(pwd,getpwnam_oem_id_5000)132 TEST(pwd, getpwnam_oem_id_5000) {
133   check_get_passwd("oem_5000", 5000, TYPE_SYSTEM);
134 }
135 
TEST(pwd,getpwnam_oem_id_5999)136 TEST(pwd, getpwnam_oem_id_5999) {
137   check_get_passwd("oem_5999", 5999, TYPE_SYSTEM);
138 }
139 
TEST(pwd,getpwnam_oem_id_2900)140 TEST(pwd, getpwnam_oem_id_2900) {
141   check_get_passwd("oem_2900", 2900, TYPE_SYSTEM);
142 }
143 
TEST(pwd,getpwnam_oem_id_2999)144 TEST(pwd, getpwnam_oem_id_2999) {
145   check_get_passwd("oem_2999", 2999, TYPE_SYSTEM);
146 }
147 
TEST(pwd,getpwnam_app_id_nobody)148 TEST(pwd, getpwnam_app_id_nobody) {
149   check_get_passwd("nobody", 9999, TYPE_SYSTEM);
150 }
151 
TEST(pwd,getpwnam_app_id_u0_a0)152 TEST(pwd, getpwnam_app_id_u0_a0) {
153   check_get_passwd("u0_a0", 10000, TYPE_APP);
154 }
155 
TEST(pwd,getpwnam_app_id_u0_a1234)156 TEST(pwd, getpwnam_app_id_u0_a1234) {
157   check_get_passwd("u0_a1234", 11234, TYPE_APP);
158 }
159 
160 // Test the difference between uid and shared gid.
TEST(pwd,getpwnam_app_id_u0_a49999)161 TEST(pwd, getpwnam_app_id_u0_a49999) {
162   check_get_passwd("u0_a49999", 59999, TYPE_APP);
163 }
164 
TEST(pwd,getpwnam_app_id_u0_i1)165 TEST(pwd, getpwnam_app_id_u0_i1) {
166   check_get_passwd("u0_i1", 99001, TYPE_APP);
167 }
168 
TEST(pwd,getpwnam_app_id_u1_root)169 TEST(pwd, getpwnam_app_id_u1_root) {
170   check_get_passwd("u1_root", 100000, TYPE_SYSTEM);
171 }
172 
TEST(pwd,getpwnam_app_id_u1_radio)173 TEST(pwd, getpwnam_app_id_u1_radio) {
174   check_get_passwd("u1_radio", 101001, TYPE_SYSTEM);
175 }
176 
TEST(pwd,getpwnam_app_id_u1_a0)177 TEST(pwd, getpwnam_app_id_u1_a0) {
178   check_get_passwd("u1_a0", 110000, TYPE_APP);
179 }
180 
TEST(pwd,getpwnam_app_id_u1_a40000)181 TEST(pwd, getpwnam_app_id_u1_a40000) {
182   check_get_passwd("u1_a40000", 150000, TYPE_APP);
183 }
184 
TEST(pwd,getpwnam_app_id_u1_i0)185 TEST(pwd, getpwnam_app_id_u1_i0) {
186   check_get_passwd("u1_i0", 199000, TYPE_APP);
187 }
188 
TEST(pwd,getpwent_iterate)189 TEST(pwd, getpwent_iterate) {
190   passwd* pwd;
191   std::bitset<10000> exist;
192   bool application = false;
193 
194   exist.reset();
195 
196   setpwent();
197   while ((pwd = getpwent()) != NULL) {
198     ASSERT_TRUE(NULL != pwd->pw_name);
199     ASSERT_EQ(pwd->pw_gid, pwd->pw_uid);
200     ASSERT_EQ(NULL, pwd->pw_passwd);
201 #ifdef __LP64__
202     ASSERT_TRUE(NULL == pwd->pw_gecos);
203 #endif
204     ASSERT_TRUE(NULL != pwd->pw_shell);
205     if (pwd->pw_uid >= exist.size()) {
206       ASSERT_STREQ("/data", pwd->pw_dir);
207       application = true;
208     } else {
209       ASSERT_STREQ("/", pwd->pw_dir);
210       // TODO(b/27999086): fix this check with the OEM range
211       // If OEMs add their own AIDs to private/android_filesystem_config.h, this check will fail.
212       // Long term we want to create a better solution for OEMs adding AIDs, but we're not there
213       // yet, so therefore we do not check for uid's in the OEM range.
214       if (!(pwd->pw_uid >= 2900 && pwd->pw_uid <= 2999) &&
215           !(pwd->pw_uid >= 5000 && pwd->pw_uid <= 5999)) {
216         ASSERT_FALSE(exist[pwd->pw_uid]);
217       }
218       exist[pwd->pw_uid] = true;
219     }
220   }
221   endpwent();
222 
223   // Required content
224   for (size_t n = 0; n < android_id_count; ++n) {
225     ASSERT_TRUE(exist[android_ids[n].aid]);
226   }
227   for (size_t n = 2900; n < 2999; ++n) {
228     ASSERT_TRUE(exist[n]);
229   }
230   for (size_t n = 5000; n < 5999; ++n) {
231     ASSERT_TRUE(exist[n]);
232   }
233   ASSERT_TRUE(application);
234 }
235 
check_group(const group * grp,const char * group_name,gid_t gid)236 static void check_group(const group* grp, const char* group_name, gid_t gid) {
237   ASSERT_TRUE(grp != NULL);
238   ASSERT_STREQ(group_name, grp->gr_name);
239   ASSERT_EQ(gid, grp->gr_gid);
240   ASSERT_TRUE(grp->gr_mem != NULL);
241   ASSERT_STREQ(group_name, grp->gr_mem[0]);
242   ASSERT_TRUE(grp->gr_mem[1] == NULL);
243 }
244 
245 #if defined(__BIONIC__)
246 
check_getgrgid(const char * group_name,gid_t gid)247 static void check_getgrgid(const char* group_name, gid_t gid) {
248   errno = 0;
249   group* grp = getgrgid(gid);
250   ASSERT_EQ(0, errno);
251   SCOPED_TRACE("getgrgid");
252   check_group(grp, group_name, gid);
253 }
254 
check_getgrnam(const char * group_name,gid_t gid)255 static void check_getgrnam(const char* group_name, gid_t gid) {
256   errno = 0;
257   group* grp = getgrnam(group_name);
258   ASSERT_EQ(0, errno);
259   SCOPED_TRACE("getgrnam");
260   check_group(grp, group_name, gid);
261 }
262 
check_getgrgid_r(const char * group_name,gid_t gid)263 static void check_getgrgid_r(const char* group_name, gid_t gid) {
264   group grp_storage;
265   char buf[512];
266   group* grp;
267 
268   errno = 0;
269   int result = getgrgid_r(gid, &grp_storage, buf, sizeof(buf), &grp);
270   ASSERT_EQ(0, result);
271   ASSERT_EQ(0, errno);
272   SCOPED_TRACE("getgrgid_r");
273   check_group(grp, group_name, gid);
274 }
275 
check_getgrnam_r(const char * group_name,gid_t gid)276 static void check_getgrnam_r(const char* group_name, gid_t gid) {
277   group grp_storage;
278   char buf[512];
279   group* grp;
280 
281   errno = 0;
282   int result = getgrnam_r(group_name, &grp_storage, buf, sizeof(buf), &grp);
283   ASSERT_EQ(0, result);
284   ASSERT_EQ(0, errno);
285   SCOPED_TRACE("getgrnam_r");
286   check_group(grp, group_name, gid);
287 }
288 
check_get_group(const char * group_name,gid_t gid)289 static void check_get_group(const char* group_name, gid_t gid) {
290   check_getgrgid(group_name, gid);
291   check_getgrnam(group_name, gid);
292   check_getgrgid_r(group_name, gid);
293   check_getgrnam_r(group_name, gid);
294 }
295 
296 #else // !defined(__BIONIC__)
297 
print_no_getgrnam_test_info()298 static void print_no_getgrnam_test_info() {
299   GTEST_LOG_(INFO) << "This test is about gid/group_name translation for Android, which does nothing on libc other than bionic.\n";
300 }
301 
check_get_group(const char *,gid_t)302 static void check_get_group(const char*, gid_t) {
303   print_no_getgrnam_test_info();
304 }
305 
306 #endif
307 
TEST(grp,getgrnam_system_id_root)308 TEST(grp, getgrnam_system_id_root) {
309   check_get_group("root", 0);
310 }
311 
TEST(grp,getgrnam_system_id_system)312 TEST(grp, getgrnam_system_id_system) {
313   check_get_group("system", 1000);
314 }
315 
TEST(grp,getgrnam_app_id_radio)316 TEST(grp, getgrnam_app_id_radio) {
317   check_get_group("radio", 1001);
318 }
319 
TEST(grp,getgrnam_oem_id_5000)320 TEST(grp, getgrnam_oem_id_5000) {
321   check_get_group("oem_5000", 5000);
322 }
323 
TEST(grp,getgrnam_oem_id_5999)324 TEST(grp, getgrnam_oem_id_5999) {
325   check_get_group("oem_5999", 5999);
326 }
327 
TEST(grp,getgrnam_oem_id_2900)328 TEST(grp, getgrnam_oem_id_2900) {
329   check_get_group("oem_2900", 2900);
330 }
331 
TEST(grp,getgrnam_oem_id_2999)332 TEST(grp, getgrnam_oem_id_2999) {
333   check_get_group("oem_2999", 2999);
334 }
335 
TEST(grp,getgrnam_app_id_nobody)336 TEST(grp, getgrnam_app_id_nobody) {
337   check_get_group("nobody", 9999);
338 }
339 
TEST(grp,getgrnam_app_id_u0_a0)340 TEST(grp, getgrnam_app_id_u0_a0) {
341   check_get_group("u0_a0", 10000);
342 }
343 
TEST(grp,getgrnam_app_id_u0_a1234)344 TEST(grp, getgrnam_app_id_u0_a1234) {
345   check_get_group("u0_a1234", 11234);
346 }
347 
TEST(grp,getgrnam_app_id_u0_a9999)348 TEST(grp, getgrnam_app_id_u0_a9999) {
349   check_get_group("u0_a9999", 19999);
350 }
351 
TEST(getgrnam,app_id_u0_a0_cache)352 TEST(getgrnam, app_id_u0_a0_cache) {
353   check_get_group("u0_a0_cache", 20000);
354 }
355 
TEST(getgrnam,app_id_u0_a1234_cache)356 TEST(getgrnam, app_id_u0_a1234_cache) {
357   check_get_group("u0_a1234_cache", 21234);
358 }
359 
TEST(getgrnam,app_id_u0_a9999_cache)360 TEST(getgrnam, app_id_u0_a9999_cache) {
361   check_get_group("u0_a9999_cache", 29999);
362 }
363 
TEST(getgrnam,app_id_u10_a1234_cache)364 TEST(getgrnam, app_id_u10_a1234_cache) {
365   check_get_group("u10_a1234_cache", 1021234);
366 }
367 
368 // Test the difference between uid and shared gid.
TEST(grp,getgrnam_app_id_all_a9999)369 TEST(grp, getgrnam_app_id_all_a9999) {
370   check_get_group("all_a9999", 59999);
371 }
372 
TEST(grp,getgrnam_app_id_u0_i1)373 TEST(grp, getgrnam_app_id_u0_i1) {
374   check_get_group("u0_i1", 99001);
375 }
376 
TEST(grp,getgrnam_app_id_u1_root)377 TEST(grp, getgrnam_app_id_u1_root) {
378   check_get_group("u1_root", 100000);
379 }
380 
TEST(grp,getgrnam_app_id_u1_radio)381 TEST(grp, getgrnam_app_id_u1_radio) {
382   check_get_group("u1_radio", 101001);
383 }
384 
TEST(grp,getgrnam_app_id_u1_a0)385 TEST(grp, getgrnam_app_id_u1_a0) {
386   check_get_group("u1_a0", 110000);
387 }
388 
TEST(grp,getgrnam_app_id_u1_a40000)389 TEST(grp, getgrnam_app_id_u1_a40000) {
390   check_get_group("u1_a40000", 150000);
391 }
392 
TEST(grp,getgrnam_app_id_u1_i0)393 TEST(grp, getgrnam_app_id_u1_i0) {
394   check_get_group("u1_i0", 199000);
395 }
396 
TEST(grp,getgrnam_r_reentrancy)397 TEST(grp, getgrnam_r_reentrancy) {
398 #if defined(__BIONIC__)
399   group grp_storage[2];
400   char buf[2][512];
401   group* grp[3];
402   int result = getgrnam_r("root", &grp_storage[0], buf[0], sizeof(buf[0]), &grp[0]);
403   ASSERT_EQ(0, result);
404   check_group(grp[0], "root", 0);
405   grp[1] = getgrnam("system");
406   check_group(grp[1], "system", 1000);
407   result = getgrnam_r("radio", &grp_storage[1], buf[1], sizeof(buf[1]), &grp[2]);
408   ASSERT_EQ(0, result);
409   check_group(grp[2], "radio", 1001);
410   check_group(grp[0], "root", 0);
411   check_group(grp[1], "system", 1000);
412 #else
413   print_no_getgrnam_test_info();
414 #endif
415 }
416 
TEST(grp,getgrgid_r_reentrancy)417 TEST(grp, getgrgid_r_reentrancy) {
418 #if defined(__BIONIC__)
419   group grp_storage[2];
420   char buf[2][512];
421   group* grp[3];
422   int result = getgrgid_r(0, &grp_storage[0], buf[0], sizeof(buf[0]), &grp[0]);
423   ASSERT_EQ(0, result);
424   check_group(grp[0], "root", 0);
425   grp[1] = getgrgid(1000);
426   check_group(grp[1], "system", 1000);
427   result = getgrgid_r(1001, &grp_storage[1], buf[1], sizeof(buf[1]), &grp[2]);
428   ASSERT_EQ(0, result);
429   check_group(grp[2], "radio", 1001);
430   check_group(grp[0], "root", 0);
431   check_group(grp[1], "system", 1000);
432 #else
433   print_no_getgrnam_test_info();
434 #endif
435 }
436 
TEST(grp,getgrnam_r_large_enough_suggested_buffer_size)437 TEST(grp, getgrnam_r_large_enough_suggested_buffer_size) {
438   long size = sysconf(_SC_GETGR_R_SIZE_MAX);
439   ASSERT_GT(size, 0);
440   char buf[size];
441   group grp_storage;
442   group* grp;
443   ASSERT_EQ(0, getgrnam_r("root", &grp_storage, buf, size, &grp));
444   check_group(grp, "root", 0);
445 }
446 
TEST(grp,getgrent_iterate)447 TEST(grp, getgrent_iterate) {
448   group* grp;
449   std::bitset<10000> exist;
450   bool application = false;
451 
452   exist.reset();
453 
454   setgrent();
455   while ((grp = getgrent()) != NULL) {
456     ASSERT_TRUE(grp->gr_name != NULL);
457     ASSERT_TRUE(grp->gr_mem != NULL);
458     ASSERT_STREQ(grp->gr_name, grp->gr_mem[0]);
459     ASSERT_TRUE(grp->gr_mem[1] == NULL);
460     if (grp->gr_gid >= exist.size()) {
461       application = true;
462     } else {
463       // TODO(b/27999086): fix this check with the OEM range
464       // If OEMs add their own AIDs to private/android_filesystem_config.h, this check will fail.
465       // Long term we want to create a better solution for OEMs adding AIDs, but we're not there
466       // yet, so therefore we do not check for gid's in the OEM range.
467       if (!(grp->gr_gid >= 2900 && grp->gr_gid <= 2999) &&
468           !(grp->gr_gid >= 5000 && grp->gr_gid <= 5999)) {
469         ASSERT_FALSE(exist[grp->gr_gid]);
470       }
471       exist[grp->gr_gid] = true;
472     }
473   }
474   endgrent();
475 
476   // Required content
477   for (size_t n = 0; n < android_id_count; ++n) {
478     ASSERT_TRUE(exist[android_ids[n].aid]);
479   }
480   for (size_t n = 2900; n < 2999; ++n) {
481     ASSERT_TRUE(exist[n]);
482   }
483   for (size_t n = 5000; n < 5999; ++n) {
484     ASSERT_TRUE(exist[n]);
485   }
486   ASSERT_TRUE(application);
487 }
488