1 #include <android-base/logging.h>
2 #include <hidl-util/FQName.h>
3 #include <log/log.h>
4
5 #include "AccessControl.h"
6
7 namespace android {
8
9 static const char *kPermissionAdd = "add";
10 static const char *kPermissionGet = "find";
11 static const char *kPermissionList = "list";
12
13 struct audit_data {
14 const char* interfaceName;
15 pid_t pid;
16 };
17
18 using android::FQName;
19
AccessControl()20 AccessControl::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
canAdd(const std::string & fqName,pid_t pid)37 bool 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
canGet(const std::string & fqName,pid_t pid)48 bool 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
canList(pid_t pid)59 bool AccessControl::canList(pid_t pid) {
60 return checkPermission(pid, mSeContext, kPermissionList, nullptr);
61 }
62
checkPermission(pid_t sourcePid,const char * targetContext,const char * perm,const char * interface)63 bool 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
checkPermission(pid_t sourcePid,const char * perm,const char * interface)85 bool 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
auditCallback(void * data,security_class_t,char * buf,size_t len)102 int 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
115