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