blob: abcb569c0a3ec439d5ba883cbe40728bc52278cf [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;
21
22AccessControl::AccessControl() {
23 mSeHandle = selinux_android_hw_service_context_handle();
24 LOG_ALWAYS_FATAL_IF(mSeHandle == NULL, "Failed to acquire SELinux handle.");
25
26 if (getcon(&mSeContext) != 0) {
27 LOG_ALWAYS_FATAL("Failed to acquire hwservicemanager context.");
28 }
29
30 selinux_status_open(true);
31
32 mSeCallbacks.func_audit = AccessControl::auditCallback;
33 selinux_set_callback(SELINUX_CB_AUDIT, mSeCallbacks);
34
35 mSeCallbacks.func_log = selinux_log_callback; /* defined in libselinux */
36 selinux_set_callback(SELINUX_CB_LOG, mSeCallbacks);
37}
38
39bool AccessControl::canAdd(const std::string& fqName, pid_t pid) {
40 FQName fqIface(fqName);
41
42 if (!fqIface.isValid()) {
43 return false;
44 }
45 const std::string checkName = fqIface.package() + "::" + fqIface.name();
46
47 return checkPermission(pid, kPermissionAdd, checkName.c_str());
48}
49
50bool AccessControl::canGet(const std::string& fqName, pid_t pid) {
51 FQName fqIface(fqName);
52
53 if (!fqIface.isValid()) {
54 return false;
55 }
56 const std::string checkName = fqIface.package() + "::" + fqIface.name();
57
58 return checkPermission(pid, kPermissionGet, checkName.c_str());
59}
60
61bool AccessControl::canList(pid_t pid) {
62 return checkPermission(pid, mSeContext, kPermissionList, nullptr);
63}
64
65bool AccessControl::checkPermission(pid_t sourcePid, const char *targetContext,
66 const char *perm, const char *interface) {
67 char *sourceContext = NULL;
68 bool allowed = false;
69 struct audit_data ad;
70
71 if (getpidcon(sourcePid, &sourceContext) < 0) {
Martijn Coenen39247422017-09-25 15:29:06 +020072 ALOGE("SELinux: failed to retrieve process context for pid %d", sourcePid);
Martijn Coenen7ce83be2017-04-07 16:19:32 -070073 return false;
74 }
75
76 ad.pid = sourcePid;
77 ad.interfaceName = interface;
78
79 allowed = (selinux_check_access(sourceContext, targetContext, "hwservice_manager",
80 perm, (void *) &ad) == 0);
81
82 freecon(sourceContext);
83
84 return allowed;
85}
86
87bool AccessControl::checkPermission(pid_t sourcePid, const char *perm, const char *interface) {
88 char *targetContext = NULL;
89 bool allowed = false;
90
91 // Lookup service in hwservice_contexts
92 if (selabel_lookup(mSeHandle, &targetContext, interface, 0) != 0) {
93 ALOGE("No match for interface %s in hwservice_contexts", interface);
94 return false;
95 }
96
97 allowed = checkPermission(sourcePid, targetContext, perm, interface);
98
99 freecon(targetContext);
100
101 return allowed;
102}
103
104int AccessControl::auditCallback(void *data, security_class_t /*cls*/, char *buf, size_t len) {
105 struct audit_data *ad = (struct audit_data *)data;
106
107 if (!ad || !ad->interfaceName) {
108 ALOGE("No valid hwservicemanager audit data");
109 return 0;
110 }
111
112 snprintf(buf, len, "interface=%s pid=%d", ad->interfaceName, ad->pid);
113 return 0;
114}
115
116} // namespace android