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