xref: /aosp_15_r20/frameworks/native/cmds/servicemanager/Access.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker  * Copyright (C) 2019 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker  *
4*38e8c45fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker  *
8*38e8c45fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker  *
10*38e8c45fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker  * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker  */
16*38e8c45fSAndroid Build Coastguard Worker 
17*38e8c45fSAndroid Build Coastguard Worker #include "Access.h"
18*38e8c45fSAndroid Build Coastguard Worker 
19*38e8c45fSAndroid Build Coastguard Worker #include <android-base/logging.h>
20*38e8c45fSAndroid Build Coastguard Worker #include <binder/IPCThreadState.h>
21*38e8c45fSAndroid Build Coastguard Worker #include <log/log_safetynet.h>
22*38e8c45fSAndroid Build Coastguard Worker #include <selinux/android.h>
23*38e8c45fSAndroid Build Coastguard Worker #include <selinux/avc.h>
24*38e8c45fSAndroid Build Coastguard Worker 
25*38e8c45fSAndroid Build Coastguard Worker #include <sstream>
26*38e8c45fSAndroid Build Coastguard Worker 
27*38e8c45fSAndroid Build Coastguard Worker namespace android {
28*38e8c45fSAndroid Build Coastguard Worker 
29*38e8c45fSAndroid Build Coastguard Worker #ifdef VENDORSERVICEMANAGER
30*38e8c45fSAndroid Build Coastguard Worker constexpr bool kIsVendor = true;
31*38e8c45fSAndroid Build Coastguard Worker #else
32*38e8c45fSAndroid Build Coastguard Worker constexpr bool kIsVendor = false;
33*38e8c45fSAndroid Build Coastguard Worker #endif
34*38e8c45fSAndroid Build Coastguard Worker 
35*38e8c45fSAndroid Build Coastguard Worker #ifdef __ANDROID__
getPidcon(pid_t pid)36*38e8c45fSAndroid Build Coastguard Worker static std::string getPidcon(pid_t pid) {
37*38e8c45fSAndroid Build Coastguard Worker     android_errorWriteLog(0x534e4554, "121035042");
38*38e8c45fSAndroid Build Coastguard Worker 
39*38e8c45fSAndroid Build Coastguard Worker     char* lookup = nullptr;
40*38e8c45fSAndroid Build Coastguard Worker     if (getpidcon(pid, &lookup) < 0) {
41*38e8c45fSAndroid Build Coastguard Worker         LOG(ERROR) << "SELinux: getpidcon(pid=" << pid << ") failed to retrieve pid context";
42*38e8c45fSAndroid Build Coastguard Worker         return "";
43*38e8c45fSAndroid Build Coastguard Worker     }
44*38e8c45fSAndroid Build Coastguard Worker     std::string result = lookup;
45*38e8c45fSAndroid Build Coastguard Worker     freecon(lookup);
46*38e8c45fSAndroid Build Coastguard Worker     return result;
47*38e8c45fSAndroid Build Coastguard Worker }
48*38e8c45fSAndroid Build Coastguard Worker 
getSehandle()49*38e8c45fSAndroid Build Coastguard Worker static struct selabel_handle* getSehandle() {
50*38e8c45fSAndroid Build Coastguard Worker     static struct selabel_handle* gSehandle = nullptr;
51*38e8c45fSAndroid Build Coastguard Worker     if (gSehandle != nullptr && selinux_status_updated()) {
52*38e8c45fSAndroid Build Coastguard Worker         selabel_close(gSehandle);
53*38e8c45fSAndroid Build Coastguard Worker         gSehandle = nullptr;
54*38e8c45fSAndroid Build Coastguard Worker     }
55*38e8c45fSAndroid Build Coastguard Worker 
56*38e8c45fSAndroid Build Coastguard Worker     if (gSehandle == nullptr) {
57*38e8c45fSAndroid Build Coastguard Worker         gSehandle = kIsVendor
58*38e8c45fSAndroid Build Coastguard Worker             ? selinux_android_vendor_service_context_handle()
59*38e8c45fSAndroid Build Coastguard Worker             : selinux_android_service_context_handle();
60*38e8c45fSAndroid Build Coastguard Worker     }
61*38e8c45fSAndroid Build Coastguard Worker 
62*38e8c45fSAndroid Build Coastguard Worker     CHECK(gSehandle != nullptr);
63*38e8c45fSAndroid Build Coastguard Worker     return gSehandle;
64*38e8c45fSAndroid Build Coastguard Worker }
65*38e8c45fSAndroid Build Coastguard Worker 
66*38e8c45fSAndroid Build Coastguard Worker struct AuditCallbackData {
67*38e8c45fSAndroid Build Coastguard Worker     const Access::CallingContext* context;
68*38e8c45fSAndroid Build Coastguard Worker     const std::string* tname;
69*38e8c45fSAndroid Build Coastguard Worker };
70*38e8c45fSAndroid Build Coastguard Worker 
auditCallback(void * data,security_class_t,char * buf,size_t len)71*38e8c45fSAndroid Build Coastguard Worker static int auditCallback(void *data, security_class_t /*cls*/, char *buf, size_t len) {
72*38e8c45fSAndroid Build Coastguard Worker     const AuditCallbackData* ad = reinterpret_cast<AuditCallbackData*>(data);
73*38e8c45fSAndroid Build Coastguard Worker 
74*38e8c45fSAndroid Build Coastguard Worker     if (!ad) {
75*38e8c45fSAndroid Build Coastguard Worker         LOG(ERROR) << "No service manager audit data";
76*38e8c45fSAndroid Build Coastguard Worker         return 0;
77*38e8c45fSAndroid Build Coastguard Worker     }
78*38e8c45fSAndroid Build Coastguard Worker 
79*38e8c45fSAndroid Build Coastguard Worker     snprintf(buf, len, "pid=%d uid=%d name=%s", ad->context->debugPid, ad->context->uid,
80*38e8c45fSAndroid Build Coastguard Worker         ad->tname->c_str());
81*38e8c45fSAndroid Build Coastguard Worker     return 0;
82*38e8c45fSAndroid Build Coastguard Worker }
83*38e8c45fSAndroid Build Coastguard Worker #endif
84*38e8c45fSAndroid Build Coastguard Worker 
toDebugString() const85*38e8c45fSAndroid Build Coastguard Worker std::string Access::CallingContext::toDebugString() const {
86*38e8c45fSAndroid Build Coastguard Worker     std::stringstream ss;
87*38e8c45fSAndroid Build Coastguard Worker     ss << "Caller(pid=" << debugPid << ",uid=" << uid << ",sid=" << sid << ")";
88*38e8c45fSAndroid Build Coastguard Worker     return ss.str();
89*38e8c45fSAndroid Build Coastguard Worker }
90*38e8c45fSAndroid Build Coastguard Worker 
Access()91*38e8c45fSAndroid Build Coastguard Worker Access::Access() {
92*38e8c45fSAndroid Build Coastguard Worker #ifdef __ANDROID__
93*38e8c45fSAndroid Build Coastguard Worker     union selinux_callback cb;
94*38e8c45fSAndroid Build Coastguard Worker 
95*38e8c45fSAndroid Build Coastguard Worker     cb.func_audit = auditCallback;
96*38e8c45fSAndroid Build Coastguard Worker     selinux_set_callback(SELINUX_CB_AUDIT, cb);
97*38e8c45fSAndroid Build Coastguard Worker 
98*38e8c45fSAndroid Build Coastguard Worker     cb.func_log = kIsVendor ? selinux_vendor_log_callback : selinux_log_callback;
99*38e8c45fSAndroid Build Coastguard Worker     selinux_set_callback(SELINUX_CB_LOG, cb);
100*38e8c45fSAndroid Build Coastguard Worker 
101*38e8c45fSAndroid Build Coastguard Worker     CHECK(selinux_status_open(true /*fallback*/) >= 0);
102*38e8c45fSAndroid Build Coastguard Worker 
103*38e8c45fSAndroid Build Coastguard Worker     CHECK(getcon(&mThisProcessContext) == 0);
104*38e8c45fSAndroid Build Coastguard Worker #endif
105*38e8c45fSAndroid Build Coastguard Worker }
106*38e8c45fSAndroid Build Coastguard Worker 
~Access()107*38e8c45fSAndroid Build Coastguard Worker Access::~Access() {
108*38e8c45fSAndroid Build Coastguard Worker     freecon(mThisProcessContext);
109*38e8c45fSAndroid Build Coastguard Worker }
110*38e8c45fSAndroid Build Coastguard Worker 
getCallingContext()111*38e8c45fSAndroid Build Coastguard Worker Access::CallingContext Access::getCallingContext() {
112*38e8c45fSAndroid Build Coastguard Worker #ifdef __ANDROID__
113*38e8c45fSAndroid Build Coastguard Worker     IPCThreadState* ipc = IPCThreadState::self();
114*38e8c45fSAndroid Build Coastguard Worker 
115*38e8c45fSAndroid Build Coastguard Worker     const char* callingSid = ipc->getCallingSid();
116*38e8c45fSAndroid Build Coastguard Worker     pid_t callingPid = ipc->getCallingPid();
117*38e8c45fSAndroid Build Coastguard Worker 
118*38e8c45fSAndroid Build Coastguard Worker     return CallingContext {
119*38e8c45fSAndroid Build Coastguard Worker         .debugPid = callingPid,
120*38e8c45fSAndroid Build Coastguard Worker         .uid = ipc->getCallingUid(),
121*38e8c45fSAndroid Build Coastguard Worker         .sid = callingSid ? std::string(callingSid) : getPidcon(callingPid),
122*38e8c45fSAndroid Build Coastguard Worker     };
123*38e8c45fSAndroid Build Coastguard Worker #else
124*38e8c45fSAndroid Build Coastguard Worker     return CallingContext();
125*38e8c45fSAndroid Build Coastguard Worker #endif
126*38e8c45fSAndroid Build Coastguard Worker }
127*38e8c45fSAndroid Build Coastguard Worker 
canFind(const CallingContext & ctx,const std::string & name)128*38e8c45fSAndroid Build Coastguard Worker bool Access::canFind(const CallingContext& ctx,const std::string& name) {
129*38e8c45fSAndroid Build Coastguard Worker     return actionAllowedFromLookup(ctx, name, "find");
130*38e8c45fSAndroid Build Coastguard Worker }
131*38e8c45fSAndroid Build Coastguard Worker 
canAdd(const CallingContext & ctx,const std::string & name)132*38e8c45fSAndroid Build Coastguard Worker bool Access::canAdd(const CallingContext& ctx, const std::string& name) {
133*38e8c45fSAndroid Build Coastguard Worker     return actionAllowedFromLookup(ctx, name, "add");
134*38e8c45fSAndroid Build Coastguard Worker }
135*38e8c45fSAndroid Build Coastguard Worker 
canList(const CallingContext & ctx)136*38e8c45fSAndroid Build Coastguard Worker bool Access::canList(const CallingContext& ctx) {
137*38e8c45fSAndroid Build Coastguard Worker     return actionAllowed(ctx, mThisProcessContext, "list", "service_manager");
138*38e8c45fSAndroid Build Coastguard Worker }
139*38e8c45fSAndroid Build Coastguard Worker 
actionAllowed(const CallingContext & sctx,const char * tctx,const char * perm,const std::string & tname)140*38e8c45fSAndroid Build Coastguard Worker bool Access::actionAllowed(const CallingContext& sctx, const char* tctx, const char* perm,
141*38e8c45fSAndroid Build Coastguard Worker         const std::string& tname) {
142*38e8c45fSAndroid Build Coastguard Worker #ifdef __ANDROID__
143*38e8c45fSAndroid Build Coastguard Worker     const char* tclass = "service_manager";
144*38e8c45fSAndroid Build Coastguard Worker 
145*38e8c45fSAndroid Build Coastguard Worker     AuditCallbackData data = {
146*38e8c45fSAndroid Build Coastguard Worker         .context = &sctx,
147*38e8c45fSAndroid Build Coastguard Worker         .tname = &tname,
148*38e8c45fSAndroid Build Coastguard Worker     };
149*38e8c45fSAndroid Build Coastguard Worker 
150*38e8c45fSAndroid Build Coastguard Worker     return 0 == selinux_check_access(sctx.sid.c_str(), tctx, tclass, perm,
151*38e8c45fSAndroid Build Coastguard Worker         reinterpret_cast<void*>(&data));
152*38e8c45fSAndroid Build Coastguard Worker #else
153*38e8c45fSAndroid Build Coastguard Worker     (void)sctx;
154*38e8c45fSAndroid Build Coastguard Worker     (void)tctx;
155*38e8c45fSAndroid Build Coastguard Worker     (void)perm;
156*38e8c45fSAndroid Build Coastguard Worker     (void)tname;
157*38e8c45fSAndroid Build Coastguard Worker 
158*38e8c45fSAndroid Build Coastguard Worker     return true;
159*38e8c45fSAndroid Build Coastguard Worker #endif
160*38e8c45fSAndroid Build Coastguard Worker }
161*38e8c45fSAndroid Build Coastguard Worker 
actionAllowedFromLookup(const CallingContext & sctx,const std::string & name,const char * perm)162*38e8c45fSAndroid Build Coastguard Worker bool Access::actionAllowedFromLookup(const CallingContext& sctx, const std::string& name, const char *perm) {
163*38e8c45fSAndroid Build Coastguard Worker #ifdef __ANDROID__
164*38e8c45fSAndroid Build Coastguard Worker     char *tctx = nullptr;
165*38e8c45fSAndroid Build Coastguard Worker     if (selabel_lookup(getSehandle(), &tctx, name.c_str(), SELABEL_CTX_ANDROID_SERVICE) != 0) {
166*38e8c45fSAndroid Build Coastguard Worker         LOG(ERROR) << "SELinux: No match for " << name << " in service_contexts.\n";
167*38e8c45fSAndroid Build Coastguard Worker         return false;
168*38e8c45fSAndroid Build Coastguard Worker     }
169*38e8c45fSAndroid Build Coastguard Worker 
170*38e8c45fSAndroid Build Coastguard Worker     bool allowed = actionAllowed(sctx, tctx, perm, name);
171*38e8c45fSAndroid Build Coastguard Worker     freecon(tctx);
172*38e8c45fSAndroid Build Coastguard Worker     return allowed;
173*38e8c45fSAndroid Build Coastguard Worker #else
174*38e8c45fSAndroid Build Coastguard Worker     (void)sctx;
175*38e8c45fSAndroid Build Coastguard Worker     (void)name;
176*38e8c45fSAndroid Build Coastguard Worker     (void)perm;
177*38e8c45fSAndroid Build Coastguard Worker     (void)kIsVendor;
178*38e8c45fSAndroid Build Coastguard Worker 
179*38e8c45fSAndroid Build Coastguard Worker     return true;
180*38e8c45fSAndroid Build Coastguard Worker #endif
181*38e8c45fSAndroid Build Coastguard Worker }
182*38e8c45fSAndroid Build Coastguard Worker 
183*38e8c45fSAndroid Build Coastguard Worker }  // android
184