Home | History | Annotate | Download | only in test
      1 // Copyright (C) 2016 The Android Open Source Project
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //      http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include <sys/capability.h>
     16 #include <sys/types.h>
     17 #include <unistd.h>
     18 
     19 #include <libminijail.h>
     20 
     21 #include <android-base/logging.h>
     22 #include <android-base/macros.h>
     23 
     24 const uid_t kSystemUid = 1000U;
     25 
     26 gid_t groups[] = {kSystemUid + 1, kSystemUid + 2};
     27 
     28 size_t getgroups_with_alloc(gid_t** plist) {
     29   *plist = NULL;
     30 
     31   int nsupp_groups = getgroups(0, NULL);
     32   if (nsupp_groups < 0) {
     33     PLOG(ERROR) << "getgroups(0)";
     34     return 0;
     35   }
     36   if (nsupp_groups == 0) {
     37     LOG(INFO) << "No supplementary groups.";
     38     return 0;
     39   }
     40 
     41   *plist = (gid_t*)calloc((size_t)nsupp_groups, sizeof(gid_t));
     42   nsupp_groups = getgroups(nsupp_groups, *plist);
     43   if (nsupp_groups < 0) {
     44     PLOG(ERROR) << "getgroups(nsupp_groups)";
     45     free(*plist);
     46     return 0;
     47   }
     48   return nsupp_groups;
     49 }
     50 
     51 bool check_ugid(uid_t expected_id) {
     52   bool success = true;
     53 
     54   uid_t ruid = getuid();
     55   if (ruid != expected_id) {
     56     LOG(ERROR) << "rUID " << ruid << " is not " << expected_id;
     57     success = false;
     58   }
     59   gid_t rgid = getgid();
     60   if (rgid != expected_id) {
     61     LOG(ERROR) << "rGID " << ruid << " is not " << expected_id;
     62     success = false;
     63   }
     64   return success;
     65 }
     66 
     67 bool check_groups(size_t expected_size, gid_t* expected_list) {
     68   bool success = true;
     69 
     70   gid_t* actual_list;
     71   size_t actual_size = getgroups_with_alloc(&actual_list);
     72 
     73   if (expected_size != actual_size) {
     74     LOG(ERROR) << "Mismatched supplementary group list size: expected "
     75                << expected_size << ", actual " << actual_size;
     76     success = false;
     77   }
     78 
     79   for (size_t i = 0; i < expected_size; i++) {
     80     bool found = false;
     81     for (size_t j = 0; j < actual_size; j++) {
     82       if (expected_list[i] == actual_list[j]) {
     83         // Test next expected GID.
     84         found = true;
     85         break;
     86       }
     87     }
     88     if (!found) {
     89       LOG(ERROR) << "Expected GID " << expected_list[i] << " not found.";
     90       success = false;
     91     }
     92   }
     93   free(actual_list);
     94   return success;
     95 }
     96 
     97 void log_resugid() {
     98   uid_t ruid, euid, suid;
     99   gid_t rgid, egid, sgid;
    100   getresuid(&ruid, &euid, &suid);
    101   getresgid(&rgid, &egid, &sgid);
    102 
    103   LOG(INFO) << "ruid " << ruid << " euid " << euid << " suid " << suid;
    104   LOG(INFO) << "rgid " << rgid << " egid " << egid << " sgid " << sgid;
    105 
    106   gid_t* list;
    107   size_t nsupp_groups = getgroups_with_alloc(&list);
    108   for (size_t i = 0; i < (size_t)nsupp_groups; i++) {
    109     LOG(INFO) << "supp gid " << i + 1 << " " << list[i];
    110   }
    111   free(list);
    112 }
    113 
    114 int main(void) {
    115   minijail* j = minijail_new();
    116   minijail_change_user(j, "system");
    117   minijail_change_group(j, "system");
    118   size_t num_groups = arraysize(groups);
    119   minijail_set_supplementary_gids(j, num_groups, groups);
    120   minijail_use_caps(j, CAP_TO_MASK(CAP_SETUID) | CAP_TO_MASK(CAP_SETGID));
    121   minijail_enter(j);
    122 
    123   bool success = check_ugid(kSystemUid);
    124   success = success && check_groups(num_groups, groups);
    125 
    126   minijail_destroy(j);
    127   minijail* j2 = minijail_new();
    128   minijail_change_uid(j2, 5 * kSystemUid);
    129   minijail_change_gid(j2, 5 * kSystemUid);
    130   minijail_enter(j2);
    131 
    132   success = success && check_ugid(5 * kSystemUid);
    133 
    134   return success ? 0 : 1;
    135 }
    136