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 enum uid_type_t {
     30   TYPE_SYSTEM,
     31   TYPE_APP
     32 };
     33 
     34 #if defined(__BIONIC__)
     35 
     36 static void check_passwd(const passwd* pwd, const char* username, uid_t uid, uid_type_t uid_type) {
     37   ASSERT_TRUE(pwd != NULL);
     38   ASSERT_STREQ(username, pwd->pw_name);
     39   ASSERT_EQ(uid, pwd->pw_uid);
     40   ASSERT_EQ(uid, pwd->pw_gid);
     41   ASSERT_EQ(NULL, pwd->pw_passwd);
     42 #ifdef __LP64__
     43   ASSERT_EQ(NULL, pwd->pw_gecos);
     44 #endif
     45 
     46   if (uid_type == TYPE_SYSTEM) {
     47     ASSERT_STREQ("/", pwd->pw_dir);
     48   } else {
     49     ASSERT_STREQ("/data", pwd->pw_dir);
     50   }
     51   ASSERT_STREQ("/system/bin/sh", pwd->pw_shell);
     52 }
     53 
     54 static void check_getpwuid(const char* username, uid_t uid, uid_type_t uid_type) {
     55   errno = 0;
     56   passwd* pwd = getpwuid(uid);
     57   ASSERT_EQ(0, errno);
     58   SCOPED_TRACE("getpwuid");
     59   check_passwd(pwd, username, uid, uid_type);
     60 }
     61 
     62 static void check_getpwnam(const char* username, uid_t uid, uid_type_t uid_type) {
     63   errno = 0;
     64   passwd* pwd = getpwnam(username);
     65   ASSERT_EQ(0, errno);
     66   SCOPED_TRACE("getpwnam");
     67   check_passwd(pwd, username, uid, uid_type);
     68 }
     69 
     70 static void check_getpwuid_r(const char* username, uid_t uid, uid_type_t uid_type) {
     71   passwd pwd_storage;
     72   char buf[512];
     73   int result;
     74 
     75   errno = 0;
     76   passwd* pwd = NULL;
     77   result = getpwuid_r(uid, &pwd_storage, buf, sizeof(buf), &pwd);
     78   ASSERT_EQ(0, result);
     79   ASSERT_EQ(0, errno);
     80   SCOPED_TRACE("getpwuid_r");
     81   check_passwd(pwd, username, uid, uid_type);
     82 }
     83 
     84 static void check_getpwnam_r(const char* username, uid_t uid, uid_type_t uid_type) {
     85   passwd pwd_storage;
     86   char buf[512];
     87   int result;
     88 
     89   errno = 0;
     90   passwd* pwd = NULL;
     91   result = getpwnam_r(username, &pwd_storage, buf, sizeof(buf), &pwd);
     92   ASSERT_EQ(0, result);
     93   ASSERT_EQ(0, errno);
     94   SCOPED_TRACE("getpwnam_r");
     95   check_passwd(pwd, username, uid, uid_type);
     96 }
     97 
     98 static void check_get_passwd(const char* username, uid_t uid, uid_type_t uid_type) {
     99   check_getpwuid(username, uid, uid_type);
    100   check_getpwnam(username, uid, uid_type);
    101   check_getpwuid_r(username, uid, uid_type);
    102   check_getpwnam_r(username, uid, uid_type);
    103 }
    104 
    105 #else // !defined(__BIONIC__)
    106 
    107 static void check_get_passwd(const char* /* username */, uid_t /* uid */, uid_type_t /* uid_type */) {
    108   GTEST_LOG_(INFO) << "This test is about uid/username translation for Android, which does nothing on libc other than bionic.\n";
    109 }
    110 
    111 #endif
    112 
    113 TEST(getpwnam, system_id_root) {
    114   check_get_passwd("root", 0, TYPE_SYSTEM);
    115 }
    116 
    117 TEST(getpwnam, system_id_system) {
    118   check_get_passwd("system", 1000, TYPE_SYSTEM);
    119 }
    120 
    121 TEST(getpwnam, app_id_radio) {
    122   check_get_passwd("radio", 1001, TYPE_SYSTEM);
    123 }
    124 
    125 TEST(getpwnam, oem_id_0) {
    126   check_get_passwd("oem_0", 5000, TYPE_SYSTEM);
    127 }
    128 
    129 TEST(getpwnam, oem_id_999) {
    130   check_get_passwd("oem_999", 5999, TYPE_SYSTEM);
    131 }
    132 
    133 TEST(getpwnam, app_id_nobody) {
    134   check_get_passwd("nobody", 9999, TYPE_SYSTEM);
    135 }
    136 
    137 TEST(getpwnam, app_id_u0_a0) {
    138   check_get_passwd("u0_a0", 10000, TYPE_APP);
    139 }
    140 
    141 TEST(getpwnam, app_id_u0_a1234) {
    142   check_get_passwd("u0_a1234", 11234, TYPE_APP);
    143 }
    144 
    145 // Test the difference between uid and shared gid.
    146 TEST(getpwnam, app_id_u0_a49999) {
    147   check_get_passwd("u0_a49999", 59999, TYPE_APP);
    148 }
    149 
    150 TEST(getpwnam, app_id_u0_i1) {
    151   check_get_passwd("u0_i1", 99001, TYPE_APP);
    152 }
    153 
    154 TEST(getpwnam, app_id_u1_root) {
    155   check_get_passwd("u1_root", 100000, TYPE_SYSTEM);
    156 }
    157 
    158 TEST(getpwnam, app_id_u1_radio) {
    159   check_get_passwd("u1_radio", 101001, TYPE_SYSTEM);
    160 }
    161 
    162 TEST(getpwnam, app_id_u1_a0) {
    163   check_get_passwd("u1_a0", 110000, TYPE_APP);
    164 }
    165 
    166 TEST(getpwnam, app_id_u1_a40000) {
    167   check_get_passwd("u1_a40000", 150000, TYPE_APP);
    168 }
    169 
    170 TEST(getpwnam, app_id_u1_i0) {
    171   check_get_passwd("u1_i0", 199000, TYPE_APP);
    172 }
    173 
    174 static void check_group(const group* grp, const char* group_name, gid_t gid) {
    175   ASSERT_TRUE(grp != NULL);
    176   ASSERT_STREQ(group_name, grp->gr_name);
    177   ASSERT_EQ(gid, grp->gr_gid);
    178   ASSERT_TRUE(grp->gr_mem != NULL);
    179   ASSERT_STREQ(group_name, grp->gr_mem[0]);
    180   ASSERT_TRUE(grp->gr_mem[1] == NULL);
    181 }
    182 
    183 #if defined(__BIONIC__)
    184 
    185 static void check_getgrgid(const char* group_name, gid_t gid) {
    186   errno = 0;
    187   group* grp = getgrgid(gid);
    188   ASSERT_EQ(0, errno);
    189   SCOPED_TRACE("getgrgid");
    190   check_group(grp, group_name, gid);
    191 }
    192 
    193 static void check_getgrnam(const char* group_name, gid_t gid) {
    194   errno = 0;
    195   group* grp = getgrnam(group_name);
    196   ASSERT_EQ(0, errno);
    197   SCOPED_TRACE("getgrnam");
    198   check_group(grp, group_name, gid);
    199 }
    200 
    201 static void check_getgrgid_r(const char* group_name, gid_t gid) {
    202   group grp_storage;
    203   char buf[512];
    204   group* grp;
    205 
    206   errno = 0;
    207   int result = getgrgid_r(gid, &grp_storage, buf, sizeof(buf), &grp);
    208   ASSERT_EQ(0, result);
    209   ASSERT_EQ(0, errno);
    210   SCOPED_TRACE("getgrgid_r");
    211   check_group(grp, group_name, gid);
    212 }
    213 
    214 static void check_getgrnam_r(const char* group_name, gid_t gid) {
    215   group grp_storage;
    216   char buf[512];
    217   group* grp;
    218 
    219   errno = 0;
    220   int result = getgrnam_r(group_name, &grp_storage, buf, sizeof(buf), &grp);
    221   ASSERT_EQ(0, result);
    222   ASSERT_EQ(0, errno);
    223   SCOPED_TRACE("getgrnam_r");
    224   check_group(grp, group_name, gid);
    225 }
    226 
    227 static void check_get_group(const char* group_name, gid_t gid) {
    228   check_getgrgid(group_name, gid);
    229   check_getgrnam(group_name, gid);
    230   check_getgrgid_r(group_name, gid);
    231   check_getgrnam_r(group_name, gid);
    232 }
    233 
    234 #else // !defined(__BIONIC__)
    235 
    236 static void print_no_getgrnam_test_info() {
    237   GTEST_LOG_(INFO) << "This test is about gid/group_name translation for Android, which does nothing on libc other than bionic.\n";
    238 }
    239 
    240 static void check_get_group(const char*, gid_t) {
    241   print_no_getgrnam_test_info();
    242 }
    243 
    244 #endif
    245 
    246 TEST(getgrnam, system_id_root) {
    247   check_get_group("root", 0);
    248 }
    249 
    250 TEST(getgrnam, system_id_system) {
    251   check_get_group("system", 1000);
    252 }
    253 
    254 TEST(getgrnam, app_id_radio) {
    255   check_get_group("radio", 1001);
    256 }
    257 
    258 TEST(getgrnam, oem_id_0) {
    259   check_get_group("oem_0", 5000);
    260 }
    261 
    262 TEST(getgrnam, oem_id_999) {
    263   check_get_group("oem_999", 5999);
    264 }
    265 
    266 TEST(getgrnam, app_id_nobody) {
    267   check_get_group("nobody", 9999);
    268 }
    269 
    270 TEST(getgrnam, app_id_u0_a0) {
    271   check_get_group("u0_a0", 10000);
    272 }
    273 
    274 TEST(getgrnam, app_id_u0_a1234) {
    275   check_get_group("u0_a1234", 11234);
    276 }
    277 
    278 TEST(getgrnam, app_id_u0_a9999) {
    279   check_get_group("u0_a9999", 19999);
    280 }
    281 
    282 // Test the difference between uid and shared gid.
    283 TEST(getgrnam, app_id_all_a9999) {
    284   check_get_group("all_a9999", 59999);
    285 }
    286 
    287 TEST(getgrnam, app_id_u0_i1) {
    288   check_get_group("u0_i1", 99001);
    289 }
    290 
    291 TEST(getgrnam, app_id_u1_root) {
    292   check_get_group("u1_root", 100000);
    293 }
    294 
    295 TEST(getgrnam, app_id_u1_radio) {
    296   check_get_group("u1_radio", 101001);
    297 }
    298 
    299 TEST(getgrnam, app_id_u1_a0) {
    300   check_get_group("u1_a0", 110000);
    301 }
    302 
    303 TEST(getgrnam, app_id_u1_a40000) {
    304   check_get_group("u1_a40000", 150000);
    305 }
    306 
    307 TEST(getgrnam, app_id_u1_i0) {
    308   check_get_group("u1_i0", 199000);
    309 }
    310 
    311 TEST(getgrnam_r, reentrancy) {
    312 #if defined(__BIONIC__)
    313   group grp_storage[2];
    314   char buf[2][512];
    315   group* grp[3];
    316   int result = getgrnam_r("root", &grp_storage[0], buf[0], sizeof(buf[0]), &grp[0]);
    317   ASSERT_EQ(0, result);
    318   check_group(grp[0], "root", 0);
    319   grp[1] = getgrnam("system");
    320   check_group(grp[1], "system", 1000);
    321   result = getgrnam_r("radio", &grp_storage[1], buf[1], sizeof(buf[1]), &grp[2]);
    322   ASSERT_EQ(0, result);
    323   check_group(grp[2], "radio", 1001);
    324   check_group(grp[0], "root", 0);
    325   check_group(grp[1], "system", 1000);
    326 #else
    327   print_no_getgrnam_test_info();
    328 #endif
    329 }
    330 
    331 TEST(getgrgid_r, reentrancy) {
    332 #if defined(__BIONIC__)
    333   group grp_storage[2];
    334   char buf[2][512];
    335   group* grp[3];
    336   int result = getgrgid_r(0, &grp_storage[0], buf[0], sizeof(buf[0]), &grp[0]);
    337   ASSERT_EQ(0, result);
    338   check_group(grp[0], "root", 0);
    339   grp[1] = getgrgid(1000);
    340   check_group(grp[1], "system", 1000);
    341   result = getgrgid_r(1001, &grp_storage[1], buf[1], sizeof(buf[1]), &grp[2]);
    342   ASSERT_EQ(0, result);
    343   check_group(grp[2], "radio", 1001);
    344   check_group(grp[0], "root", 0);
    345   check_group(grp[1], "system", 1000);
    346 #else
    347   print_no_getgrnam_test_info();
    348 #endif
    349 }
    350 
    351 TEST(getgrnam_r, large_enough_suggested_buffer_size) {
    352   long size = sysconf(_SC_GETGR_R_SIZE_MAX);
    353   ASSERT_GT(size, 0);
    354   char buf[size];
    355   group grp_storage;
    356   group* grp;
    357   ASSERT_EQ(0, getgrnam_r("root", &grp_storage, buf, size, &grp));
    358   check_group(grp, "root", 0);
    359 }
    360