xref: /aosp_15_r20/system/hwservicemanager/AccessControl.cpp (revision ee3b7b6295061e544d3520b965ea91a90424af41)
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