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