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/types.h> 16#include <sys/capability.h> 17#include <unistd.h> 18 19#include <libminijail.h> 20 21#include <android-base/logging.h> 22 23const uid_t kSystemUid = 1000U; 24 25gid_t groups[] = { kSystemUid + 1, kSystemUid + 2 }; 26 27size_t getgroups_with_alloc(gid_t **plist) { 28 *plist = NULL; 29 30 int nsupp_groups = getgroups(0, NULL); 31 if (nsupp_groups < 0) { 32 PLOG(ERROR) << "getgroups(0)"; 33 return 0; 34 } 35 if (nsupp_groups == 0) { 36 LOG(INFO) << "No supplementary groups."; 37 return 0; 38 } 39 40 *plist = (gid_t*)calloc((size_t)nsupp_groups, sizeof(gid_t)); 41 nsupp_groups = getgroups(nsupp_groups, *plist); 42 if (nsupp_groups < 0) { 43 PLOG(ERROR) << "getgroups(nsupp_groups)"; 44 free(*plist); 45 return 0; 46 } 47 return nsupp_groups; 48} 49 50bool check_ugid(uid_t expected_id) { 51 bool success = true; 52 53 uid_t ruid = getuid(); 54 if (ruid != expected_id) { 55 LOG(ERROR) << "rUID " << ruid << " is not " << expected_id; 56 success = false; 57 } 58 gid_t rgid = getgid(); 59 if (rgid != expected_id) { 60 LOG(ERROR) << "rGID " << ruid << " is not " << expected_id; 61 success = false; 62 } 63 return success; 64} 65 66bool check_groups(size_t expected_size, gid_t *expected_list) { 67 bool success = true; 68 69 gid_t *actual_list; 70 size_t actual_size = getgroups_with_alloc(&actual_list); 71 72 if (expected_size != actual_size) { 73 LOG(ERROR) << "Mismatched supplementary group list size: expected " 74 << expected_size << ", actual " << actual_size; 75 success = false; 76 } 77 78 for (size_t i = 0; i < expected_size; i++) { 79 bool found = false; 80 for (size_t j = 0; j < actual_size; j++) { 81 if (expected_list[i] == actual_list[j]) { 82 // Test next expected GID. 83 found = true; 84 break; 85 } 86 } 87 if (!found) { 88 LOG(ERROR) << "Expected GID " << expected_list[i] << " not found."; 89 success = false; 90 } 91 } 92 free(actual_list); 93 return success; 94} 95 96void log_resugid() { 97 uid_t ruid, euid, suid; 98 gid_t rgid, egid, sgid; 99 getresuid(&ruid, &euid, &suid); 100 getresgid(&rgid, &egid, &sgid); 101 102 LOG(INFO) << "ruid " << ruid << " euid " << euid << " suid " << suid; 103 LOG(INFO) << "rgid " << rgid << " egid " << egid << " sgid " << sgid; 104 105 gid_t *list; 106 size_t nsupp_groups = getgroups_with_alloc(&list); 107 for (size_t i = 0; i < (size_t)nsupp_groups; i++) { 108 LOG(INFO) << "supp gid " << i + 1 << " " << list[i]; 109 } 110 free(list); 111} 112 113int main(void) { 114 minijail *j = minijail_new(); 115 minijail_change_user(j, "system"); 116 minijail_change_group(j, "system"); 117 size_t num_groups = sizeof(groups) / sizeof(groups[0]); 118 minijail_set_supplementary_gids(j, num_groups, groups); 119 minijail_use_caps(j, CAP_TO_MASK(CAP_SETUID) | CAP_TO_MASK(CAP_SETGID)); 120 minijail_enter(j); 121 122 bool success = check_ugid(kSystemUid); 123 success = success && check_groups(num_groups, groups); 124 125 minijail_destroy(j); 126 minijail *j2 = minijail_new(); 127 minijail_change_uid(j2, 5 * kSystemUid); 128 minijail_change_gid(j2, 5 * kSystemUid); 129 minijail_enter(j2); 130 131 success = success && check_ugid(5 * kSystemUid); 132 133 return success? 0 : 1; 134} 135