blob: 93d78e2930b367fd3a1f51065c9b657e0096b922 [file] [log] [blame]
Martijn Coenen39247422017-09-25 15:29:06 +02001#define LOG_TAG "hwservicemanager"
2
Martijn Coenen7ce83be2017-04-07 16:19:32 -07003#include <android-base/logging.h>
4#include <hidl-util/FQName.h>
5#include <log/log.h>
6
7#include "AccessControl.h"
8
9namespace android {
10
11static const char *kPermissionAdd = "add";
12static const char *kPermissionGet = "find";
13static const char *kPermissionList = "list";
14
15struct audit_data {
16 const char* interfaceName;
17 pid_t pid;
18};
19
20using android::FQName;
Steven Moreland4034c1c2017-11-03 17:42:27 -070021using Context = AccessControl::Context;
Martijn Coenen7ce83be2017-04-07 16:19:32 -070022
23AccessControl::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
Steven Moreland4034c1c2017-11-03 17:42:27 -070040bool AccessControl::canAdd(const std::string& fqName, const Context &context, pid_t pid) {
Steven Moreland0cd38f02018-03-06 15:09:22 -080041 FQName fqIface;
Martijn Coenen7ce83be2017-04-07 16:19:32 -070042
Steven Moreland0cd38f02018-03-06 15:09:22 -080043 if (!FQName::parse(fqName, &fqIface)) {
Martijn Coenen7ce83be2017-04-07 16:19:32 -070044 return false;
45 }
46 const std::string checkName = fqIface.package() + "::" + fqIface.name();
47
Steven Moreland4034c1c2017-11-03 17:42:27 -070048 return checkPermission(context, pid, kPermissionAdd, checkName.c_str());
Martijn Coenen7ce83be2017-04-07 16:19:32 -070049}
50
51bool AccessControl::canGet(const std::string& fqName, pid_t pid) {
Steven Moreland0cd38f02018-03-06 15:09:22 -080052 FQName fqIface;
Martijn Coenen7ce83be2017-04-07 16:19:32 -070053
Steven Moreland0cd38f02018-03-06 15:09:22 -080054 if (!FQName::parse(fqName, &fqIface)) {
Martijn Coenen7ce83be2017-04-07 16:19:32 -070055 return false;
56 }
57 const std::string checkName = fqIface.package() + "::" + fqIface.name();
58
Steven Moreland4034c1c2017-11-03 17:42:27 -070059 return checkPermission(getContext(pid), pid, kPermissionGet, checkName.c_str());
Martijn Coenen7ce83be2017-04-07 16:19:32 -070060}
61
62bool AccessControl::canList(pid_t pid) {
Steven Moreland4034c1c2017-11-03 17:42:27 -070063 return checkPermission(getContext(pid), pid, mSeContext, kPermissionList, nullptr);
Martijn Coenen7ce83be2017-04-07 16:19:32 -070064}
65
Steven Moreland4034c1c2017-11-03 17:42:27 -070066Context AccessControl::getContext(pid_t sourcePid) {
Martijn Coenen7ce83be2017-04-07 16:19:32 -070067 char *sourceContext = NULL;
Martijn Coenen7ce83be2017-04-07 16:19:32 -070068
69 if (getpidcon(sourcePid, &sourceContext) < 0) {
Martijn Coenen39247422017-09-25 15:29:06 +020070 ALOGE("SELinux: failed to retrieve process context for pid %d", sourcePid);
Steven Moreland4034c1c2017-11-03 17:42:27 -070071 return Context(nullptr, freecon);
72 }
73
74 return Context(sourceContext, freecon);
75}
76
77bool AccessControl::checkPermission(const Context &context, pid_t sourceAuditPid, const char *targetContext, const char *perm, const char *interface) {
78 if (context == nullptr) {
Martijn Coenen7ce83be2017-04-07 16:19:32 -070079 return false;
80 }
81
Steven Moreland4034c1c2017-11-03 17:42:27 -070082 bool allowed = false;
83 struct audit_data ad;
84
85 ad.pid = sourceAuditPid;
Martijn Coenen7ce83be2017-04-07 16:19:32 -070086 ad.interfaceName = interface;
87
Steven Moreland4034c1c2017-11-03 17:42:27 -070088 allowed = (selinux_check_access(context.get(), targetContext, "hwservice_manager",
Martijn Coenen7ce83be2017-04-07 16:19:32 -070089 perm, (void *) &ad) == 0);
90
Martijn Coenen7ce83be2017-04-07 16:19:32 -070091 return allowed;
92}
93
Steven Moreland4034c1c2017-11-03 17:42:27 -070094bool AccessControl::checkPermission(const Context &context, pid_t sourceAuditPid, const char *perm, const char *interface) {
Martijn Coenen7ce83be2017-04-07 16:19:32 -070095 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
Steven Moreland4034c1c2017-11-03 17:42:27 -0700104 allowed = checkPermission(context, sourceAuditPid, targetContext, perm, interface);
Martijn Coenen7ce83be2017-04-07 16:19:32 -0700105
106 freecon(targetContext);
107
108 return allowed;
109}
110
111int 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