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