blob: aa5d43e65509d9ad0d1d084211445f21b6f9f44c [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;
Steven Moreland7185a892019-01-09 18:00:05 -080017 const char* sid;
Martijn Coenen7ce83be2017-04-07 16:19:32 -070018 pid_t pid;
19};
20
21using android::FQName;
22
23AccessControl::AccessControl() {
24 mSeHandle = selinux_android_hw_service_context_handle();
Yi Kong00892ee2018-07-31 16:50:28 -070025 LOG_ALWAYS_FATAL_IF(mSeHandle == nullptr, "Failed to acquire SELinux handle.");
Martijn Coenen7ce83be2017-04-07 16:19:32 -070026
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 Moreland7185a892019-01-09 18:00:05 -080040bool AccessControl::canAdd(const std::string& fqName, const CallingContext& callingContext) {
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 Moreland7185a892019-01-09 18:00:05 -080048 return checkPermission(callingContext, kPermissionAdd, checkName.c_str());
Martijn Coenen7ce83be2017-04-07 16:19:32 -070049}
50
Steven Moreland7185a892019-01-09 18:00:05 -080051bool AccessControl::canGet(const std::string& fqName, const CallingContext& callingContext) {
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 Moreland7185a892019-01-09 18:00:05 -080059 return checkPermission(callingContext, kPermissionGet, checkName.c_str());
Martijn Coenen7ce83be2017-04-07 16:19:32 -070060}
61
Steven Moreland7185a892019-01-09 18:00:05 -080062bool AccessControl::canList(const CallingContext& callingContext) {
63 return checkPermission(callingContext, mSeContext, kPermissionList, nullptr);
Martijn Coenen7ce83be2017-04-07 16:19:32 -070064}
65
Steven Moreland7185a892019-01-09 18:00:05 -080066AccessControl::CallingContext AccessControl::getCallingContext(pid_t sourcePid) {
Yi Kong00892ee2018-07-31 16:50:28 -070067 char *sourceContext = nullptr;
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 Moreland7185a892019-01-09 18:00:05 -080071 return { false, "", sourcePid };
Steven Moreland4034c1c2017-11-03 17:42:27 -070072 }
73
Steven Moreland7185a892019-01-09 18:00:05 -080074 std::string context = sourceContext;
75 freecon(sourceContext);
76 return { true, context, sourcePid };
Steven Moreland4034c1c2017-11-03 17:42:27 -070077}
78
Steven Moreland7185a892019-01-09 18:00:05 -080079bool AccessControl::checkPermission(const CallingContext& source, const char *targetContext, const char *perm, const char *interface) {
80 if (!source.sidPresent) {
Martijn Coenen7ce83be2017-04-07 16:19:32 -070081 return false;
82 }
83
Steven Moreland4034c1c2017-11-03 17:42:27 -070084 bool allowed = false;
Steven Moreland4034c1c2017-11-03 17:42:27 -070085
Steven Moreland7185a892019-01-09 18:00:05 -080086 struct audit_data ad;
87 ad.pid = source.pid;
88 ad.sid = source.sid.c_str();
Martijn Coenen7ce83be2017-04-07 16:19:32 -070089 ad.interfaceName = interface;
90
Steven Moreland7185a892019-01-09 18:00:05 -080091 allowed = (selinux_check_access(source.sid.c_str(), targetContext, "hwservice_manager",
Martijn Coenen7ce83be2017-04-07 16:19:32 -070092 perm, (void *) &ad) == 0);
93
Martijn Coenen7ce83be2017-04-07 16:19:32 -070094 return allowed;
95}
96
Steven Moreland7185a892019-01-09 18:00:05 -080097bool AccessControl::checkPermission(const CallingContext& source, const char *perm, const char *interface) {
Yi Kong00892ee2018-07-31 16:50:28 -070098 char *targetContext = nullptr;
Martijn Coenen7ce83be2017-04-07 16:19:32 -070099 bool allowed = false;
100
101 // Lookup service in hwservice_contexts
102 if (selabel_lookup(mSeHandle, &targetContext, interface, 0) != 0) {
103 ALOGE("No match for interface %s in hwservice_contexts", interface);
104 return false;
105 }
106
Steven Moreland7185a892019-01-09 18:00:05 -0800107 allowed = checkPermission(source, targetContext, perm, interface);
Martijn Coenen7ce83be2017-04-07 16:19:32 -0700108
109 freecon(targetContext);
110
111 return allowed;
112}
113
114int AccessControl::auditCallback(void *data, security_class_t /*cls*/, char *buf, size_t len) {
115 struct audit_data *ad = (struct audit_data *)data;
116
117 if (!ad || !ad->interfaceName) {
118 ALOGE("No valid hwservicemanager audit data");
119 return 0;
120 }
121
Steven Moreland7185a892019-01-09 18:00:05 -0800122 const char* sid = ad->sid ? ad->sid : "N/A";
123
124 snprintf(buf, len, "interface=%s sid=%s pid=%d", ad->interfaceName, sid, ad->pid);
Martijn Coenen7ce83be2017-04-07 16:19:32 -0700125 return 0;
126}
127
128} // namespace android