• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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