1 /* 2 * Copyright (C) 2017 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 #define LOG_TAG "hwservicemanager" 18 19 #include <android-base/logging.h> 20 #include <hidl-util/FQName.h> 21 #include <log/log.h> 22 23 #include "AccessControl.h" 24 25 namespace android { 26 27 static const char *kPermissionAdd = "add"; 28 static const char *kPermissionGet = "find"; 29 static const char *kPermissionList = "list"; 30 31 struct audit_data { 32 const char* interfaceName; 33 const char* sid; 34 pid_t pid; 35 }; 36 37 using android::FQName; 38 39 AccessControl::AccessControl() { 40 mSeHandle = selinux_android_hw_service_context_handle(); 41 LOG_ALWAYS_FATAL_IF(mSeHandle == nullptr, "Failed to acquire SELinux handle."); 42 43 if (getcon(&mSeContext) != 0) { 44 LOG_ALWAYS_FATAL("Failed to acquire hwservicemanager context."); 45 } 46 47 selinux_status_open(true); 48 49 mSeCallbacks.func_audit = AccessControl::auditCallback; 50 selinux_set_callback(SELINUX_CB_AUDIT, mSeCallbacks); 51 52 mSeCallbacks.func_log = selinux_log_callback; /* defined in libselinux */ 53 selinux_set_callback(SELINUX_CB_LOG, mSeCallbacks); 54 } 55 56 bool AccessControl::canAdd(const std::string& fqName, const CallingContext& callingContext) { 57 FQName fqIface; 58 59 if (!FQName::parse(fqName, &fqIface)) { 60 return false; 61 } 62 const std::string checkName = fqIface.package() + "::" + fqIface.name(); 63 64 return checkPermission(callingContext, kPermissionAdd, checkName.c_str()); 65 } 66 67 bool AccessControl::canGet(const std::string& fqName, const CallingContext& callingContext) { 68 FQName fqIface; 69 70 if (!FQName::parse(fqName, &fqIface)) { 71 return false; 72 } 73 const std::string checkName = fqIface.package() + "::" + fqIface.name(); 74 75 return checkPermission(callingContext, kPermissionGet, checkName.c_str()); 76 } 77 78 bool AccessControl::canList(const CallingContext& callingContext) { 79 return checkPermission(callingContext, mSeContext, kPermissionList, nullptr); 80 } 81 82 AccessControl::CallingContext AccessControl::getCallingContext(pid_t sourcePid) { 83 char *sourceContext = nullptr; 84 85 if (getpidcon(sourcePid, &sourceContext) < 0) { 86 ALOGE("SELinux: failed to retrieve process context for pid %d", sourcePid); 87 return { false, "", sourcePid }; 88 } 89 90 std::string context = sourceContext; 91 freecon(sourceContext); 92 return { true, context, sourcePid }; 93 } 94 95 bool AccessControl::checkPermission(const CallingContext& source, const char *targetContext, const char *perm, const char *interface) { 96 if (!source.sidPresent) { 97 return false; 98 } 99 100 bool allowed = false; 101 102 struct audit_data ad; 103 ad.pid = source.pid; 104 ad.sid = source.sid.c_str(); 105 ad.interfaceName = interface; 106 107 allowed = (selinux_check_access(source.sid.c_str(), targetContext, "hwservice_manager", 108 perm, (void *) &ad) == 0); 109 110 return allowed; 111 } 112 113 bool AccessControl::checkPermission(const CallingContext& source, const char *perm, const char *interface) { 114 char *targetContext = nullptr; 115 bool allowed = false; 116 117 // Lookup service in hwservice_contexts 118 if (selabel_lookup(mSeHandle, &targetContext, interface, 0) != 0) { 119 ALOGE("No match for interface %s in hwservice_contexts", interface); 120 return false; 121 } 122 123 allowed = checkPermission(source, targetContext, perm, interface); 124 125 freecon(targetContext); 126 127 return allowed; 128 } 129 130 int AccessControl::auditCallback(void *data, security_class_t /*cls*/, char *buf, size_t len) { 131 struct audit_data *ad = (struct audit_data *)data; 132 133 if (!ad || !ad->interfaceName) { 134 ALOGE("No valid hwservicemanager audit data"); 135 return 0; 136 } 137 138 const char* sid = ad->sid ? ad->sid : "N/A"; 139 140 snprintf(buf, len, "interface=%s sid=%s pid=%d", ad->interfaceName, sid, ad->pid); 141 return 0; 142 } 143 144 } // namespace android 145