blob: 711038ce636c241e5a836c351896f8d1cf031d03 [file] [log] [blame]
Steven Moreland80e1e6d2019-06-21 12:35:59 -07001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "Access.h"
18
19#include <android-base/logging.h>
20#include <binder/IPCThreadState.h>
21#include <log/log_safetynet.h>
22#include <selinux/android.h>
23#include <selinux/avc.h>
24
25namespace android {
26
27#ifdef VENDORSERVICEMANAGER
28constexpr bool kIsVendor = true;
29#else
30constexpr bool kIsVendor = false;
31#endif
32
Pawanab56a472022-07-26 17:06:25 +000033#ifdef __ANDROID__
Steven Moreland80e1e6d2019-06-21 12:35:59 -070034static std::string getPidcon(pid_t pid) {
Yifan Hongba7fcc32020-06-03 16:53:07 +000035 android_errorWriteLog(0x534e4554, "121035042");
Steven Moreland80e1e6d2019-06-21 12:35:59 -070036
37 char* lookup = nullptr;
38 if (getpidcon(pid, &lookup) < 0) {
39 LOG(ERROR) << "SELinux: getpidcon(pid=" << pid << ") failed to retrieve pid context";
40 return "";
41 }
42 std::string result = lookup;
43 freecon(lookup);
44 return result;
45}
46
47static struct selabel_handle* getSehandle() {
48 static struct selabel_handle* gSehandle = nullptr;
Steven Moreland80e1e6d2019-06-21 12:35:59 -070049 if (gSehandle != nullptr && selinux_status_updated()) {
50 selabel_close(gSehandle);
51 gSehandle = nullptr;
52 }
53
54 if (gSehandle == nullptr) {
55 gSehandle = kIsVendor
56 ? selinux_android_vendor_service_context_handle()
57 : selinux_android_service_context_handle();
58 }
59
60 CHECK(gSehandle != nullptr);
61 return gSehandle;
62}
63
Steven Moreland68039a12019-07-31 19:44:16 -070064struct AuditCallbackData {
65 const Access::CallingContext* context;
66 const std::string* tname;
67};
68
Steven Moreland80e1e6d2019-06-21 12:35:59 -070069static int auditCallback(void *data, security_class_t /*cls*/, char *buf, size_t len) {
Steven Moreland68039a12019-07-31 19:44:16 -070070 const AuditCallbackData* ad = reinterpret_cast<AuditCallbackData*>(data);
Steven Moreland80e1e6d2019-06-21 12:35:59 -070071
72 if (!ad) {
73 LOG(ERROR) << "No service manager audit data";
74 return 0;
75 }
76
Steven Moreland68039a12019-07-31 19:44:16 -070077 snprintf(buf, len, "pid=%d uid=%d name=%s", ad->context->debugPid, ad->context->uid,
78 ad->tname->c_str());
Steven Moreland80e1e6d2019-06-21 12:35:59 -070079 return 0;
80}
Pawanab56a472022-07-26 17:06:25 +000081#endif
Steven Moreland80e1e6d2019-06-21 12:35:59 -070082
83Access::Access() {
Pawanab56a472022-07-26 17:06:25 +000084#ifdef __ANDROID__
Steven Moreland80e1e6d2019-06-21 12:35:59 -070085 union selinux_callback cb;
86
87 cb.func_audit = auditCallback;
88 selinux_set_callback(SELINUX_CB_AUDIT, cb);
89
90 cb.func_log = kIsVendor ? selinux_vendor_log_callback : selinux_log_callback;
91 selinux_set_callback(SELINUX_CB_LOG, cb);
92
93 CHECK(selinux_status_open(true /*fallback*/) >= 0);
94
95 CHECK(getcon(&mThisProcessContext) == 0);
Pawanab56a472022-07-26 17:06:25 +000096#endif
Steven Moreland80e1e6d2019-06-21 12:35:59 -070097}
98
99Access::~Access() {
100 freecon(mThisProcessContext);
101}
102
Steven Morelanda9fe4742019-07-18 14:45:20 -0700103Access::CallingContext Access::getCallingContext() {
Pawanab56a472022-07-26 17:06:25 +0000104#ifdef __ANDROID__
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700105 IPCThreadState* ipc = IPCThreadState::self();
106
107 const char* callingSid = ipc->getCallingSid();
108 pid_t callingPid = ipc->getCallingPid();
109
110 return CallingContext {
111 .debugPid = callingPid,
112 .uid = ipc->getCallingUid(),
113 .sid = callingSid ? std::string(callingSid) : getPidcon(callingPid),
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700114 };
Pawanab56a472022-07-26 17:06:25 +0000115#else
116 return CallingContext();
117#endif
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700118}
119
Steven Morelanda9fe4742019-07-18 14:45:20 -0700120bool Access::canFind(const CallingContext& ctx,const std::string& name) {
121 return actionAllowedFromLookup(ctx, name, "find");
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700122}
123
Steven Morelanda9fe4742019-07-18 14:45:20 -0700124bool Access::canAdd(const CallingContext& ctx, const std::string& name) {
125 return actionAllowedFromLookup(ctx, name, "add");
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700126}
127
128bool Access::canList(const CallingContext& ctx) {
Steven Moreland68039a12019-07-31 19:44:16 -0700129 return actionAllowed(ctx, mThisProcessContext, "list", "service_manager");
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700130}
131
Steven Moreland68039a12019-07-31 19:44:16 -0700132bool Access::actionAllowed(const CallingContext& sctx, const char* tctx, const char* perm,
133 const std::string& tname) {
Pawanab56a472022-07-26 17:06:25 +0000134#ifdef __ANDROID__
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700135 const char* tclass = "service_manager";
136
Steven Moreland68039a12019-07-31 19:44:16 -0700137 AuditCallbackData data = {
138 .context = &sctx,
139 .tname = &tname,
140 };
141
142 return 0 == selinux_check_access(sctx.sid.c_str(), tctx, tclass, perm,
143 reinterpret_cast<void*>(&data));
Pawanab56a472022-07-26 17:06:25 +0000144#else
145 (void)sctx;
146 (void)tctx;
147 (void)perm;
148 (void)tname;
149
150 return true;
151#endif
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700152}
153
Steven Morelanda9fe4742019-07-18 14:45:20 -0700154bool Access::actionAllowedFromLookup(const CallingContext& sctx, const std::string& name, const char *perm) {
Pawanab56a472022-07-26 17:06:25 +0000155#ifdef __ANDROID__
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700156 char *tctx = nullptr;
Tri Vo6ea26982019-10-04 12:34:53 -0700157 if (selabel_lookup(getSehandle(), &tctx, name.c_str(), SELABEL_CTX_ANDROID_SERVICE) != 0) {
Steven Morelanda9fe4742019-07-18 14:45:20 -0700158 LOG(ERROR) << "SELinux: No match for " << name << " in service_contexts.\n";
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700159 return false;
160 }
161
Steven Moreland68039a12019-07-31 19:44:16 -0700162 bool allowed = actionAllowed(sctx, tctx, perm, name);
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700163 freecon(tctx);
164 return allowed;
Pawanab56a472022-07-26 17:06:25 +0000165#else
166 (void)sctx;
167 (void)name;
168 (void)perm;
169 (void)kIsVendor;
170
171 return true;
172#endif
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700173}
174
175} // android