1*ee3b7b62SAndroid Build Coastguard Worker /*
2*ee3b7b62SAndroid Build Coastguard Worker * Copyright (C) 2017 The Android Open Source Project
3*ee3b7b62SAndroid Build Coastguard Worker *
4*ee3b7b62SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*ee3b7b62SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*ee3b7b62SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*ee3b7b62SAndroid Build Coastguard Worker *
8*ee3b7b62SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*ee3b7b62SAndroid Build Coastguard Worker *
10*ee3b7b62SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*ee3b7b62SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*ee3b7b62SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ee3b7b62SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*ee3b7b62SAndroid Build Coastguard Worker * limitations under the License.
15*ee3b7b62SAndroid Build Coastguard Worker */
16*ee3b7b62SAndroid Build Coastguard Worker
17*ee3b7b62SAndroid Build Coastguard Worker #define LOG_TAG "hwservicemanager"
18*ee3b7b62SAndroid Build Coastguard Worker
19*ee3b7b62SAndroid Build Coastguard Worker #include <android-base/logging.h>
20*ee3b7b62SAndroid Build Coastguard Worker #include <hidl-util/FQName.h>
21*ee3b7b62SAndroid Build Coastguard Worker #include <log/log.h>
22*ee3b7b62SAndroid Build Coastguard Worker
23*ee3b7b62SAndroid Build Coastguard Worker #include "AccessControl.h"
24*ee3b7b62SAndroid Build Coastguard Worker
25*ee3b7b62SAndroid Build Coastguard Worker namespace android {
26*ee3b7b62SAndroid Build Coastguard Worker
27*ee3b7b62SAndroid Build Coastguard Worker static const char *kPermissionAdd = "add";
28*ee3b7b62SAndroid Build Coastguard Worker static const char *kPermissionGet = "find";
29*ee3b7b62SAndroid Build Coastguard Worker static const char *kPermissionList = "list";
30*ee3b7b62SAndroid Build Coastguard Worker
31*ee3b7b62SAndroid Build Coastguard Worker struct audit_data {
32*ee3b7b62SAndroid Build Coastguard Worker const char* interfaceName;
33*ee3b7b62SAndroid Build Coastguard Worker const char* sid;
34*ee3b7b62SAndroid Build Coastguard Worker pid_t pid;
35*ee3b7b62SAndroid Build Coastguard Worker };
36*ee3b7b62SAndroid Build Coastguard Worker
37*ee3b7b62SAndroid Build Coastguard Worker using android::FQName;
38*ee3b7b62SAndroid Build Coastguard Worker
AccessControl()39*ee3b7b62SAndroid Build Coastguard Worker AccessControl::AccessControl() {
40*ee3b7b62SAndroid Build Coastguard Worker mSeHandle = selinux_android_hw_service_context_handle();
41*ee3b7b62SAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mSeHandle == nullptr, "Failed to acquire SELinux handle.");
42*ee3b7b62SAndroid Build Coastguard Worker
43*ee3b7b62SAndroid Build Coastguard Worker if (getcon(&mSeContext) != 0) {
44*ee3b7b62SAndroid Build Coastguard Worker LOG_ALWAYS_FATAL("Failed to acquire hwservicemanager context.");
45*ee3b7b62SAndroid Build Coastguard Worker }
46*ee3b7b62SAndroid Build Coastguard Worker
47*ee3b7b62SAndroid Build Coastguard Worker selinux_status_open(true);
48*ee3b7b62SAndroid Build Coastguard Worker
49*ee3b7b62SAndroid Build Coastguard Worker mSeCallbacks.func_audit = AccessControl::auditCallback;
50*ee3b7b62SAndroid Build Coastguard Worker selinux_set_callback(SELINUX_CB_AUDIT, mSeCallbacks);
51*ee3b7b62SAndroid Build Coastguard Worker
52*ee3b7b62SAndroid Build Coastguard Worker mSeCallbacks.func_log = selinux_log_callback; /* defined in libselinux */
53*ee3b7b62SAndroid Build Coastguard Worker selinux_set_callback(SELINUX_CB_LOG, mSeCallbacks);
54*ee3b7b62SAndroid Build Coastguard Worker }
55*ee3b7b62SAndroid Build Coastguard Worker
canAdd(const std::string & fqName,const CallingContext & callingContext)56*ee3b7b62SAndroid Build Coastguard Worker bool AccessControl::canAdd(const std::string& fqName, const CallingContext& callingContext) {
57*ee3b7b62SAndroid Build Coastguard Worker FQName fqIface;
58*ee3b7b62SAndroid Build Coastguard Worker
59*ee3b7b62SAndroid Build Coastguard Worker if (!FQName::parse(fqName, &fqIface)) {
60*ee3b7b62SAndroid Build Coastguard Worker return false;
61*ee3b7b62SAndroid Build Coastguard Worker }
62*ee3b7b62SAndroid Build Coastguard Worker const std::string checkName = fqIface.package() + "::" + fqIface.name();
63*ee3b7b62SAndroid Build Coastguard Worker
64*ee3b7b62SAndroid Build Coastguard Worker return checkPermission(callingContext, kPermissionAdd, checkName.c_str());
65*ee3b7b62SAndroid Build Coastguard Worker }
66*ee3b7b62SAndroid Build Coastguard Worker
canGet(const std::string & fqName,const CallingContext & callingContext)67*ee3b7b62SAndroid Build Coastguard Worker bool AccessControl::canGet(const std::string& fqName, const CallingContext& callingContext) {
68*ee3b7b62SAndroid Build Coastguard Worker FQName fqIface;
69*ee3b7b62SAndroid Build Coastguard Worker
70*ee3b7b62SAndroid Build Coastguard Worker if (!FQName::parse(fqName, &fqIface)) {
71*ee3b7b62SAndroid Build Coastguard Worker return false;
72*ee3b7b62SAndroid Build Coastguard Worker }
73*ee3b7b62SAndroid Build Coastguard Worker const std::string checkName = fqIface.package() + "::" + fqIface.name();
74*ee3b7b62SAndroid Build Coastguard Worker
75*ee3b7b62SAndroid Build Coastguard Worker return checkPermission(callingContext, kPermissionGet, checkName.c_str());
76*ee3b7b62SAndroid Build Coastguard Worker }
77*ee3b7b62SAndroid Build Coastguard Worker
canList(const CallingContext & callingContext)78*ee3b7b62SAndroid Build Coastguard Worker bool AccessControl::canList(const CallingContext& callingContext) {
79*ee3b7b62SAndroid Build Coastguard Worker return checkPermission(callingContext, mSeContext, kPermissionList, nullptr);
80*ee3b7b62SAndroid Build Coastguard Worker }
81*ee3b7b62SAndroid Build Coastguard Worker
getCallingContext(pid_t sourcePid)82*ee3b7b62SAndroid Build Coastguard Worker AccessControl::CallingContext AccessControl::getCallingContext(pid_t sourcePid) {
83*ee3b7b62SAndroid Build Coastguard Worker char *sourceContext = nullptr;
84*ee3b7b62SAndroid Build Coastguard Worker
85*ee3b7b62SAndroid Build Coastguard Worker if (getpidcon(sourcePid, &sourceContext) < 0) {
86*ee3b7b62SAndroid Build Coastguard Worker ALOGE("SELinux: failed to retrieve process context for pid %d", sourcePid);
87*ee3b7b62SAndroid Build Coastguard Worker return { false, "", sourcePid };
88*ee3b7b62SAndroid Build Coastguard Worker }
89*ee3b7b62SAndroid Build Coastguard Worker
90*ee3b7b62SAndroid Build Coastguard Worker std::string context = sourceContext;
91*ee3b7b62SAndroid Build Coastguard Worker freecon(sourceContext);
92*ee3b7b62SAndroid Build Coastguard Worker return { true, context, sourcePid };
93*ee3b7b62SAndroid Build Coastguard Worker }
94*ee3b7b62SAndroid Build Coastguard Worker
checkPermission(const CallingContext & source,const char * targetContext,const char * perm,const char * interface)95*ee3b7b62SAndroid Build Coastguard Worker bool AccessControl::checkPermission(const CallingContext& source, const char *targetContext, const char *perm, const char *interface) {
96*ee3b7b62SAndroid Build Coastguard Worker if (!source.sidPresent) {
97*ee3b7b62SAndroid Build Coastguard Worker return false;
98*ee3b7b62SAndroid Build Coastguard Worker }
99*ee3b7b62SAndroid Build Coastguard Worker
100*ee3b7b62SAndroid Build Coastguard Worker bool allowed = false;
101*ee3b7b62SAndroid Build Coastguard Worker
102*ee3b7b62SAndroid Build Coastguard Worker struct audit_data ad;
103*ee3b7b62SAndroid Build Coastguard Worker ad.pid = source.pid;
104*ee3b7b62SAndroid Build Coastguard Worker ad.sid = source.sid.c_str();
105*ee3b7b62SAndroid Build Coastguard Worker ad.interfaceName = interface;
106*ee3b7b62SAndroid Build Coastguard Worker
107*ee3b7b62SAndroid Build Coastguard Worker allowed = (selinux_check_access(source.sid.c_str(), targetContext, "hwservice_manager",
108*ee3b7b62SAndroid Build Coastguard Worker perm, (void *) &ad) == 0);
109*ee3b7b62SAndroid Build Coastguard Worker
110*ee3b7b62SAndroid Build Coastguard Worker return allowed;
111*ee3b7b62SAndroid Build Coastguard Worker }
112*ee3b7b62SAndroid Build Coastguard Worker
checkPermission(const CallingContext & source,const char * perm,const char * interface)113*ee3b7b62SAndroid Build Coastguard Worker bool AccessControl::checkPermission(const CallingContext& source, const char *perm, const char *interface) {
114*ee3b7b62SAndroid Build Coastguard Worker char *targetContext = nullptr;
115*ee3b7b62SAndroid Build Coastguard Worker bool allowed = false;
116*ee3b7b62SAndroid Build Coastguard Worker
117*ee3b7b62SAndroid Build Coastguard Worker // Lookup service in hwservice_contexts
118*ee3b7b62SAndroid Build Coastguard Worker if (selabel_lookup(mSeHandle, &targetContext, interface, 0) != 0) {
119*ee3b7b62SAndroid Build Coastguard Worker ALOGE("No match for interface %s in hwservice_contexts", interface);
120*ee3b7b62SAndroid Build Coastguard Worker return false;
121*ee3b7b62SAndroid Build Coastguard Worker }
122*ee3b7b62SAndroid Build Coastguard Worker
123*ee3b7b62SAndroid Build Coastguard Worker allowed = checkPermission(source, targetContext, perm, interface);
124*ee3b7b62SAndroid Build Coastguard Worker
125*ee3b7b62SAndroid Build Coastguard Worker freecon(targetContext);
126*ee3b7b62SAndroid Build Coastguard Worker
127*ee3b7b62SAndroid Build Coastguard Worker return allowed;
128*ee3b7b62SAndroid Build Coastguard Worker }
129*ee3b7b62SAndroid Build Coastguard Worker
auditCallback(void * data,security_class_t,char * buf,size_t len)130*ee3b7b62SAndroid Build Coastguard Worker int AccessControl::auditCallback(void *data, security_class_t /*cls*/, char *buf, size_t len) {
131*ee3b7b62SAndroid Build Coastguard Worker struct audit_data *ad = (struct audit_data *)data;
132*ee3b7b62SAndroid Build Coastguard Worker
133*ee3b7b62SAndroid Build Coastguard Worker if (!ad || !ad->interfaceName) {
134*ee3b7b62SAndroid Build Coastguard Worker ALOGE("No valid hwservicemanager audit data");
135*ee3b7b62SAndroid Build Coastguard Worker return 0;
136*ee3b7b62SAndroid Build Coastguard Worker }
137*ee3b7b62SAndroid Build Coastguard Worker
138*ee3b7b62SAndroid Build Coastguard Worker const char* sid = ad->sid ? ad->sid : "N/A";
139*ee3b7b62SAndroid Build Coastguard Worker
140*ee3b7b62SAndroid Build Coastguard Worker snprintf(buf, len, "interface=%s sid=%s pid=%d", ad->interfaceName, sid, ad->pid);
141*ee3b7b62SAndroid Build Coastguard Worker return 0;
142*ee3b7b62SAndroid Build Coastguard Worker }
143*ee3b7b62SAndroid Build Coastguard Worker
144*ee3b7b62SAndroid Build Coastguard Worker } // namespace android
145