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       ASSERT_FALSE(exist[pwd->pw_uid]);
211       exist[pwd->pw_uid] = true;
212     }
213   }
214   endpwent();
215 
216   // Required content
217   for (size_t n = 0; n < android_id_count; ++n) {
218     ASSERT_TRUE(exist[android_ids[n].aid]);
219   }
220   for (size_t n = 2900; n < 2999; ++n) {
221     ASSERT_TRUE(exist[n]);
222   }
223   for (size_t n = 5000; n < 5999; ++n) {
224     ASSERT_TRUE(exist[n]);
225   }
226   ASSERT_TRUE(application);
227 }
228 
check_group(const group * grp,const char * group_name,gid_t gid)229 static void check_group(const group* grp, const char* group_name, gid_t gid) {
230   ASSERT_TRUE(grp != NULL);
231   ASSERT_STREQ(group_name, grp->gr_name);
232   ASSERT_EQ(gid, grp->gr_gid);
233   ASSERT_TRUE(grp->gr_mem != NULL);
234   ASSERT_STREQ(group_name, grp->gr_mem[0]);
235   ASSERT_TRUE(grp->gr_mem[1] == NULL);
236 }
237 
238 #if defined(__BIONIC__)
239 
check_getgrgid(const char * group_name,gid_t gid)240 static void check_getgrgid(const char* group_name, gid_t gid) {
241   errno = 0;
242   group* grp = getgrgid(gid);
243   ASSERT_EQ(0, errno);
244   SCOPED_TRACE("getgrgid");
245   check_group(grp, group_name, gid);
246 }
247 
check_getgrnam(const char * group_name,gid_t gid)248 static void check_getgrnam(const char* group_name, gid_t gid) {
249   errno = 0;
250   group* grp = getgrnam(group_name);
251   ASSERT_EQ(0, errno);
252   SCOPED_TRACE("getgrnam");
253   check_group(grp, group_name, gid);
254 }
255 
check_getgrgid_r(const char * group_name,gid_t gid)256 static void check_getgrgid_r(const char* group_name, gid_t gid) {
257   group grp_storage;
258   char buf[512];
259   group* grp;
260 
261   errno = 0;
262   int result = getgrgid_r(gid, &grp_storage, buf, sizeof(buf), &grp);
263   ASSERT_EQ(0, result);
264   ASSERT_EQ(0, errno);
265   SCOPED_TRACE("getgrgid_r");
266   check_group(grp, group_name, gid);
267 }
268 
check_getgrnam_r(const char * group_name,gid_t gid)269 static void check_getgrnam_r(const char* group_name, gid_t gid) {
270   group grp_storage;
271   char buf[512];
272   group* grp;
273 
274   errno = 0;
275   int result = getgrnam_r(group_name, &grp_storage, buf, sizeof(buf), &grp);
276   ASSERT_EQ(0, result);
277   ASSERT_EQ(0, errno);
278   SCOPED_TRACE("getgrnam_r");
279   check_group(grp, group_name, gid);
280 }
281 
check_get_group(const char * group_name,gid_t gid)282 static void check_get_group(const char* group_name, gid_t gid) {
283   check_getgrgid(group_name, gid);
284   check_getgrnam(group_name, gid);
285   check_getgrgid_r(group_name, gid);
286   check_getgrnam_r(group_name, gid);
287 }
288 
289 #else // !defined(__BIONIC__)
290 
print_no_getgrnam_test_info()291 static void print_no_getgrnam_test_info() {
292   GTEST_LOG_(INFO) << "This test is about gid/group_name translation for Android, which does nothing on libc other than bionic.\n";
293 }
294 
check_get_group(const char *,gid_t)295 static void check_get_group(const char*, gid_t) {
296   print_no_getgrnam_test_info();
297 }
298 
299 #endif
300 
TEST(grp,getgrnam_system_id_root)301 TEST(grp, getgrnam_system_id_root) {
302   check_get_group("root", 0);
303 }
304 
TEST(grp,getgrnam_system_id_system)305 TEST(grp, getgrnam_system_id_system) {
306   check_get_group("system", 1000);
307 }
308 
TEST(grp,getgrnam_app_id_radio)309 TEST(grp, getgrnam_app_id_radio) {
310   check_get_group("radio", 1001);
311 }
312 
TEST(grp,getgrnam_oem_id_5000)313 TEST(grp, getgrnam_oem_id_5000) {
314   check_get_group("oem_5000", 5000);
315 }
316 
TEST(grp,getgrnam_oem_id_5999)317 TEST(grp, getgrnam_oem_id_5999) {
318   check_get_group("oem_5999", 5999);
319 }
320 
TEST(grp,getgrnam_oem_id_2900)321 TEST(grp, getgrnam_oem_id_2900) {
322   check_get_group("oem_2900", 2900);
323 }
324 
TEST(grp,getgrnam_oem_id_2999)325 TEST(grp, getgrnam_oem_id_2999) {
326   check_get_group("oem_2999", 2999);
327 }
328 
TEST(grp,getgrnam_app_id_nobody)329 TEST(grp, getgrnam_app_id_nobody) {
330   check_get_group("nobody", 9999);
331 }
332 
TEST(grp,getgrnam_app_id_u0_a0)333 TEST(grp, getgrnam_app_id_u0_a0) {
334   check_get_group("u0_a0", 10000);
335 }
336 
TEST(grp,getgrnam_app_id_u0_a1234)337 TEST(grp, getgrnam_app_id_u0_a1234) {
338   check_get_group("u0_a1234", 11234);
339 }
340 
TEST(grp,getgrnam_app_id_u0_a9999)341 TEST(grp, getgrnam_app_id_u0_a9999) {
342   check_get_group("u0_a9999", 19999);
343 }
344 
TEST(getgrnam,app_id_u0_a0_cache)345 TEST(getgrnam, app_id_u0_a0_cache) {
346   check_get_group("u0_a0_cache", 20000);
347 }
348 
TEST(getgrnam,app_id_u0_a1234_cache)349 TEST(getgrnam, app_id_u0_a1234_cache) {
350   check_get_group("u0_a1234_cache", 21234);
351 }
352 
TEST(getgrnam,app_id_u0_a9999_cache)353 TEST(getgrnam, app_id_u0_a9999_cache) {
354   check_get_group("u0_a9999_cache", 29999);
355 }
356 
TEST(getgrnam,app_id_u10_a1234_cache)357 TEST(getgrnam, app_id_u10_a1234_cache) {
358   check_get_group("u10_a1234_cache", 1021234);
359 }
360 
361 // Test the difference between uid and shared gid.
TEST(grp,getgrnam_app_id_all_a9999)362 TEST(grp, getgrnam_app_id_all_a9999) {
363   check_get_group("all_a9999", 59999);
364 }
365 
TEST(grp,getgrnam_app_id_u0_i1)366 TEST(grp, getgrnam_app_id_u0_i1) {
367   check_get_group("u0_i1", 99001);
368 }
369 
TEST(grp,getgrnam_app_id_u1_root)370 TEST(grp, getgrnam_app_id_u1_root) {
371   check_get_group("u1_root", 100000);
372 }
373 
TEST(grp,getgrnam_app_id_u1_radio)374 TEST(grp, getgrnam_app_id_u1_radio) {
375   check_get_group("u1_radio", 101001);
376 }
377 
TEST(grp,getgrnam_app_id_u1_a0)378 TEST(grp, getgrnam_app_id_u1_a0) {
379   check_get_group("u1_a0", 110000);
380 }
381 
TEST(grp,getgrnam_app_id_u1_a40000)382 TEST(grp, getgrnam_app_id_u1_a40000) {
383   check_get_group("u1_a40000", 150000);
384 }
385 
TEST(grp,getgrnam_app_id_u1_i0)386 TEST(grp, getgrnam_app_id_u1_i0) {
387   check_get_group("u1_i0", 199000);
388 }
389 
TEST(grp,getgrnam_r_reentrancy)390 TEST(grp, getgrnam_r_reentrancy) {
391 #if defined(__BIONIC__)
392   group grp_storage[2];
393   char buf[2][512];
394   group* grp[3];
395   int result = getgrnam_r("root", &grp_storage[0], buf[0], sizeof(buf[0]), &grp[0]);
396   ASSERT_EQ(0, result);
397   check_group(grp[0], "root", 0);
398   grp[1] = getgrnam("system");
399   check_group(grp[1], "system", 1000);
400   result = getgrnam_r("radio", &grp_storage[1], buf[1], sizeof(buf[1]), &grp[2]);
401   ASSERT_EQ(0, result);
402   check_group(grp[2], "radio", 1001);
403   check_group(grp[0], "root", 0);
404   check_group(grp[1], "system", 1000);
405 #else
406   print_no_getgrnam_test_info();
407 #endif
408 }
409 
TEST(grp,getgrgid_r_reentrancy)410 TEST(grp, getgrgid_r_reentrancy) {
411 #if defined(__BIONIC__)
412   group grp_storage[2];
413   char buf[2][512];
414   group* grp[3];
415   int result = getgrgid_r(0, &grp_storage[0], buf[0], sizeof(buf[0]), &grp[0]);
416   ASSERT_EQ(0, result);
417   check_group(grp[0], "root", 0);
418   grp[1] = getgrgid(1000);
419   check_group(grp[1], "system", 1000);
420   result = getgrgid_r(1001, &grp_storage[1], buf[1], sizeof(buf[1]), &grp[2]);
421   ASSERT_EQ(0, result);
422   check_group(grp[2], "radio", 1001);
423   check_group(grp[0], "root", 0);
424   check_group(grp[1], "system", 1000);
425 #else
426   print_no_getgrnam_test_info();
427 #endif
428 }
429 
TEST(grp,getgrnam_r_large_enough_suggested_buffer_size)430 TEST(grp, getgrnam_r_large_enough_suggested_buffer_size) {
431   long size = sysconf(_SC_GETGR_R_SIZE_MAX);
432   ASSERT_GT(size, 0);
433   char buf[size];
434   group grp_storage;
435   group* grp;
436   ASSERT_EQ(0, getgrnam_r("root", &grp_storage, buf, size, &grp));
437   check_group(grp, "root", 0);
438 }
439 
TEST(grp,getgrent_iterate)440 TEST(grp, getgrent_iterate) {
441   group* grp;
442   std::bitset<10000> exist;
443   bool application = false;
444 
445   exist.reset();
446 
447   setgrent();
448   while ((grp = getgrent()) != NULL) {
449     ASSERT_TRUE(grp->gr_name != NULL);
450     ASSERT_TRUE(grp->gr_mem != NULL);
451     ASSERT_STREQ(grp->gr_name, grp->gr_mem[0]);
452     ASSERT_TRUE(grp->gr_mem[1] == NULL);
453     if (grp->gr_gid >= exist.size()) {
454       application = true;
455     } else {
456       ASSERT_FALSE(exist[grp->gr_gid]);
457       exist[grp->gr_gid] = true;
458     }
459   }
460   endgrent();
461 
462   // Required content
463   for (size_t n = 0; n < android_id_count; ++n) {
464     ASSERT_TRUE(exist[android_ids[n].aid]);
465   }
466   for (size_t n = 2900; n < 2999; ++n) {
467     ASSERT_TRUE(exist[n]);
468   }
469   for (size_t n = 5000; n < 5999; ++n) {
470     ASSERT_TRUE(exist[n]);
471   }
472   ASSERT_TRUE(application);
473 }
474