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 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 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 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 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 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 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 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 120 TEST(pwd, getpwnam_system_id_root) { 121 check_get_passwd("root", 0, TYPE_SYSTEM); 122 } 123 124 TEST(pwd, getpwnam_system_id_system) { 125 check_get_passwd("system", 1000, TYPE_SYSTEM); 126 } 127 128 TEST(pwd, getpwnam_app_id_radio) { 129 check_get_passwd("radio", 1001, TYPE_SYSTEM); 130 } 131 132 TEST(pwd, getpwnam_oem_id_5000) { 133 check_get_passwd("oem_5000", 5000, TYPE_SYSTEM); 134 } 135 136 TEST(pwd, getpwnam_oem_id_5999) { 137 check_get_passwd("oem_5999", 5999, TYPE_SYSTEM); 138 } 139 140 TEST(pwd, getpwnam_oem_id_2900) { 141 check_get_passwd("oem_2900", 2900, TYPE_SYSTEM); 142 } 143 144 TEST(pwd, getpwnam_oem_id_2999) { 145 check_get_passwd("oem_2999", 2999, TYPE_SYSTEM); 146 } 147 148 TEST(pwd, getpwnam_app_id_nobody) { 149 check_get_passwd("nobody", 9999, TYPE_SYSTEM); 150 } 151 152 TEST(pwd, getpwnam_app_id_u0_a0) { 153 check_get_passwd("u0_a0", 10000, TYPE_APP); 154 } 155 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. 161 TEST(pwd, getpwnam_app_id_u0_a49999) { 162 check_get_passwd("u0_a49999", 59999, TYPE_APP); 163 } 164 165 TEST(pwd, getpwnam_app_id_u0_i1) { 166 check_get_passwd("u0_i1", 99001, TYPE_APP); 167 } 168 169 TEST(pwd, getpwnam_app_id_u1_root) { 170 check_get_passwd("u1_root", 100000, TYPE_SYSTEM); 171 } 172 173 TEST(pwd, getpwnam_app_id_u1_radio) { 174 check_get_passwd("u1_radio", 101001, TYPE_SYSTEM); 175 } 176 177 TEST(pwd, getpwnam_app_id_u1_a0) { 178 check_get_passwd("u1_a0", 110000, TYPE_APP); 179 } 180 181 TEST(pwd, getpwnam_app_id_u1_a40000) { 182 check_get_passwd("u1_a40000", 150000, TYPE_APP); 183 } 184 185 TEST(pwd, getpwnam_app_id_u1_i0) { 186 check_get_passwd("u1_i0", 199000, TYPE_APP); 187 } 188 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 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 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 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 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 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 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 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 302 static void check_get_group(const char*, gid_t) { 303 print_no_getgrnam_test_info(); 304 } 305 306 #endif 307 308 TEST(grp, getgrnam_system_id_root) { 309 check_get_group("root", 0); 310 } 311 312 TEST(grp, getgrnam_system_id_system) { 313 check_get_group("system", 1000); 314 } 315 316 TEST(grp, getgrnam_app_id_radio) { 317 check_get_group("radio", 1001); 318 } 319 320 TEST(grp, getgrnam_oem_id_5000) { 321 check_get_group("oem_5000", 5000); 322 } 323 324 TEST(grp, getgrnam_oem_id_5999) { 325 check_get_group("oem_5999", 5999); 326 } 327 328 TEST(grp, getgrnam_oem_id_2900) { 329 check_get_group("oem_2900", 2900); 330 } 331 332 TEST(grp, getgrnam_oem_id_2999) { 333 check_get_group("oem_2999", 2999); 334 } 335 336 TEST(grp, getgrnam_app_id_nobody) { 337 check_get_group("nobody", 9999); 338 } 339 340 TEST(grp, getgrnam_app_id_u0_a0) { 341 check_get_group("u0_a0", 10000); 342 } 343 344 TEST(grp, getgrnam_app_id_u0_a1234) { 345 check_get_group("u0_a1234", 11234); 346 } 347 348 TEST(grp, getgrnam_app_id_u0_a9999) { 349 check_get_group("u0_a9999", 19999); 350 } 351 352 TEST(getgrnam, app_id_u0_a0_cache) { 353 check_get_group("u0_a0_cache", 20000); 354 } 355 356 TEST(getgrnam, app_id_u0_a1234_cache) { 357 check_get_group("u0_a1234_cache", 21234); 358 } 359 360 TEST(getgrnam, app_id_u0_a9999_cache) { 361 check_get_group("u0_a9999_cache", 29999); 362 } 363 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. 369 TEST(grp, getgrnam_app_id_all_a9999) { 370 check_get_group("all_a9999", 59999); 371 } 372 373 TEST(grp, getgrnam_app_id_u0_i1) { 374 check_get_group("u0_i1", 99001); 375 } 376 377 TEST(grp, getgrnam_app_id_u1_root) { 378 check_get_group("u1_root", 100000); 379 } 380 381 TEST(grp, getgrnam_app_id_u1_radio) { 382 check_get_group("u1_radio", 101001); 383 } 384 385 TEST(grp, getgrnam_app_id_u1_a0) { 386 check_get_group("u1_a0", 110000); 387 } 388 389 TEST(grp, getgrnam_app_id_u1_a40000) { 390 check_get_group("u1_a40000", 150000); 391 } 392 393 TEST(grp, getgrnam_app_id_u1_i0) { 394 check_get_group("u1_i0", 199000); 395 } 396 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 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 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 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