blob: 6e2abf65e2b0c61251e92b77f75e57584ac5912f [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
Steven Moreland5759db02024-03-27 00:03:05 +000025#include <sstream>
26
Steven Moreland80e1e6d2019-06-21 12:35:59 -070027namespace android {
28
29#ifdef VENDORSERVICEMANAGER
30constexpr bool kIsVendor = true;
31#else
32constexpr bool kIsVendor = false;
33#endif
34
Pawanab56a472022-07-26 17:06:25 +000035#ifdef __ANDROID__
Steven Moreland80e1e6d2019-06-21 12:35:59 -070036static std::string getPidcon(pid_t pid) {
Steven Moreland8a9bb842024-12-05 01:02:53 +000037 CHECK_EQ(nullptr, IPCThreadState::self()->getServingStackPointer())
38 << "Did not get context from PID " << pid
39 << ". We should always get contexts from other processes.";
Steven Moreland80e1e6d2019-06-21 12:35:59 -070040
41 char* lookup = nullptr;
42 if (getpidcon(pid, &lookup) < 0) {
43 LOG(ERROR) << "SELinux: getpidcon(pid=" << pid << ") failed to retrieve pid context";
44 return "";
45 }
46 std::string result = lookup;
47 freecon(lookup);
48 return result;
49}
50
51static struct selabel_handle* getSehandle() {
52 static struct selabel_handle* gSehandle = nullptr;
Steven Moreland80e1e6d2019-06-21 12:35:59 -070053 if (gSehandle != nullptr && selinux_status_updated()) {
54 selabel_close(gSehandle);
55 gSehandle = nullptr;
56 }
57
58 if (gSehandle == nullptr) {
59 gSehandle = kIsVendor
60 ? selinux_android_vendor_service_context_handle()
61 : selinux_android_service_context_handle();
62 }
63
64 CHECK(gSehandle != nullptr);
65 return gSehandle;
66}
67
Steven Moreland68039a12019-07-31 19:44:16 -070068struct AuditCallbackData {
69 const Access::CallingContext* context;
70 const std::string* tname;
71};
72
Steven Moreland80e1e6d2019-06-21 12:35:59 -070073static int auditCallback(void *data, security_class_t /*cls*/, char *buf, size_t len) {
Steven Moreland68039a12019-07-31 19:44:16 -070074 const AuditCallbackData* ad = reinterpret_cast<AuditCallbackData*>(data);
Steven Moreland80e1e6d2019-06-21 12:35:59 -070075
76 if (!ad) {
77 LOG(ERROR) << "No service manager audit data";
78 return 0;
79 }
80
Steven Moreland68039a12019-07-31 19:44:16 -070081 snprintf(buf, len, "pid=%d uid=%d name=%s", ad->context->debugPid, ad->context->uid,
82 ad->tname->c_str());
Steven Moreland80e1e6d2019-06-21 12:35:59 -070083 return 0;
84}
Pawanab56a472022-07-26 17:06:25 +000085#endif
Steven Moreland80e1e6d2019-06-21 12:35:59 -070086
Steven Moreland5759db02024-03-27 00:03:05 +000087std::string Access::CallingContext::toDebugString() const {
88 std::stringstream ss;
89 ss << "Caller(pid=" << debugPid << ",uid=" << uid << ",sid=" << sid << ")";
90 return ss.str();
91}
92
Steven Moreland80e1e6d2019-06-21 12:35:59 -070093Access::Access() {
Pawanab56a472022-07-26 17:06:25 +000094#ifdef __ANDROID__
Steven Moreland80e1e6d2019-06-21 12:35:59 -070095 union selinux_callback cb;
96
97 cb.func_audit = auditCallback;
98 selinux_set_callback(SELINUX_CB_AUDIT, cb);
99
100 cb.func_log = kIsVendor ? selinux_vendor_log_callback : selinux_log_callback;
101 selinux_set_callback(SELINUX_CB_LOG, cb);
102
103 CHECK(selinux_status_open(true /*fallback*/) >= 0);
104
105 CHECK(getcon(&mThisProcessContext) == 0);
Pawanab56a472022-07-26 17:06:25 +0000106#endif
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700107}
108
109Access::~Access() {
110 freecon(mThisProcessContext);
111}
112
Steven Morelanda9fe4742019-07-18 14:45:20 -0700113Access::CallingContext Access::getCallingContext() {
Pawanab56a472022-07-26 17:06:25 +0000114#ifdef __ANDROID__
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700115 IPCThreadState* ipc = IPCThreadState::self();
116
117 const char* callingSid = ipc->getCallingSid();
118 pid_t callingPid = ipc->getCallingPid();
119
120 return CallingContext {
121 .debugPid = callingPid,
122 .uid = ipc->getCallingUid(),
123 .sid = callingSid ? std::string(callingSid) : getPidcon(callingPid),
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700124 };
Pawanab56a472022-07-26 17:06:25 +0000125#else
126 return CallingContext();
127#endif
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700128}
129
Steven Morelanda9fe4742019-07-18 14:45:20 -0700130bool Access::canFind(const CallingContext& ctx,const std::string& name) {
131 return actionAllowedFromLookup(ctx, name, "find");
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700132}
133
Steven Morelanda9fe4742019-07-18 14:45:20 -0700134bool Access::canAdd(const CallingContext& ctx, const std::string& name) {
135 return actionAllowedFromLookup(ctx, name, "add");
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700136}
137
138bool Access::canList(const CallingContext& ctx) {
Steven Moreland68039a12019-07-31 19:44:16 -0700139 return actionAllowed(ctx, mThisProcessContext, "list", "service_manager");
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700140}
141
Steven Moreland68039a12019-07-31 19:44:16 -0700142bool Access::actionAllowed(const CallingContext& sctx, const char* tctx, const char* perm,
143 const std::string& tname) {
Pawanab56a472022-07-26 17:06:25 +0000144#ifdef __ANDROID__
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700145 const char* tclass = "service_manager";
146
Steven Moreland68039a12019-07-31 19:44:16 -0700147 AuditCallbackData data = {
148 .context = &sctx,
149 .tname = &tname,
150 };
151
152 return 0 == selinux_check_access(sctx.sid.c_str(), tctx, tclass, perm,
153 reinterpret_cast<void*>(&data));
Pawanab56a472022-07-26 17:06:25 +0000154#else
155 (void)sctx;
156 (void)tctx;
157 (void)perm;
158 (void)tname;
159
160 return true;
161#endif
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700162}
163
Steven Morelanda9fe4742019-07-18 14:45:20 -0700164bool Access::actionAllowedFromLookup(const CallingContext& sctx, const std::string& name, const char *perm) {
Pawanab56a472022-07-26 17:06:25 +0000165#ifdef __ANDROID__
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700166 char *tctx = nullptr;
Tri Vo6ea26982019-10-04 12:34:53 -0700167 if (selabel_lookup(getSehandle(), &tctx, name.c_str(), SELABEL_CTX_ANDROID_SERVICE) != 0) {
Steven Morelanda9fe4742019-07-18 14:45:20 -0700168 LOG(ERROR) << "SELinux: No match for " << name << " in service_contexts.\n";
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700169 return false;
170 }
171
Steven Moreland68039a12019-07-31 19:44:16 -0700172 bool allowed = actionAllowed(sctx, tctx, perm, name);
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700173 freecon(tctx);
174 return allowed;
Pawanab56a472022-07-26 17:06:25 +0000175#else
176 (void)sctx;
177 (void)name;
178 (void)perm;
179 (void)kIsVendor;
180
181 return true;
182#endif
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700183}
184
185} // android