Home | History | Annotate | Download | only in tests
      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