blob: 119e4c387cb1cd06597dcbf4448511c0f158be81 [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 "ServiceManager.h"
18
19#include <android-base/logging.h>
20#include <cutils/android_filesystem_config.h>
21#include <cutils/multiuser.h>
22
23using ::android::binder::Status;
24
25namespace android {
26
27ServiceManager::ServiceManager(std::unique_ptr<Access>&& access) : mAccess(std::move(access)) {}
Steven Moreland130242d2019-08-26 17:41:32 -070028ServiceManager::~ServiceManager() {
29 // this should only happen in tests
30
31 for (const auto& [name, service] : mNameToService) {
32 CHECK(service.binder != nullptr) << name;
33 }
34}
Steven Moreland80e1e6d2019-06-21 12:35:59 -070035
36Status ServiceManager::getService(const std::string& name, sp<IBinder>* outBinder) {
37 // Servicemanager is single-threaded and cannot block. This method exists for legacy reasons.
38 return checkService(name, outBinder);
39}
40
41Status ServiceManager::checkService(const std::string& name, sp<IBinder>* outBinder) {
Steven Morelanda9fe4742019-07-18 14:45:20 -070042 auto ctx = mAccess->getCallingContext();
Steven Moreland80e1e6d2019-06-21 12:35:59 -070043
44 auto it = mNameToService.find(name);
45 if (it == mNameToService.end()) {
46 *outBinder = nullptr;
47 return Status::ok();
48 }
49
50 const Service& service = it->second;
51
52 if (!service.allowIsolated) {
53 uid_t appid = multiuser_get_app_id(ctx.uid);
54 bool isIsolated = appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END;
55
56 if (isIsolated) {
57 *outBinder = nullptr;
58 return Status::ok();
59 }
60 }
61
Steven Morelanda9fe4742019-07-18 14:45:20 -070062 if (!mAccess->canFind(ctx, name)) {
Steven Moreland80e1e6d2019-06-21 12:35:59 -070063 // returns ok and null for legacy reasons
64 *outBinder = nullptr;
65 return Status::ok();
66 }
67
68 *outBinder = service.binder;
69 return Status::ok();
70}
71
Steven Moreland905e2e82019-07-17 11:05:45 -070072bool isValidServiceName(const std::string& name) {
73 if (name.size() == 0) return false;
74 if (name.size() > 127) return false;
75
76 for (char c : name) {
Steven Morelandbb7951d2019-08-20 16:58:25 -070077 if (c == '_' || c == '-' || c == '.' || c == '/') continue;
Steven Moreland905e2e82019-07-17 11:05:45 -070078 if (c >= 'a' && c <= 'z') continue;
79 if (c >= 'A' && c <= 'Z') continue;
80 if (c >= '0' && c <= '9') continue;
81 return false;
82 }
83
84 return true;
85}
86
Steven Moreland80e1e6d2019-06-21 12:35:59 -070087Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) {
Steven Morelanda9fe4742019-07-18 14:45:20 -070088 auto ctx = mAccess->getCallingContext();
Steven Moreland80e1e6d2019-06-21 12:35:59 -070089
90 // apps cannot add services
91 if (multiuser_get_app_id(ctx.uid) >= AID_APP) {
92 return Status::fromExceptionCode(Status::EX_SECURITY);
93 }
94
Steven Morelanda9fe4742019-07-18 14:45:20 -070095 if (!mAccess->canAdd(ctx, name)) {
Steven Moreland80e1e6d2019-06-21 12:35:59 -070096 return Status::fromExceptionCode(Status::EX_SECURITY);
97 }
98
99 if (binder == nullptr) {
100 return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
101 }
102
Steven Moreland905e2e82019-07-17 11:05:45 -0700103 if (!isValidServiceName(name)) {
104 LOG(ERROR) << "Invalid service name: " << name;
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700105 return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
106 }
107
Steven Moreland88860b02019-08-12 14:24:14 -0700108 // implicitly unlinked when the binder is removed
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700109 if (OK != binder->linkToDeath(this)) {
110 LOG(ERROR) << "Could not linkToDeath when adding " << name;
111 return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
112 }
113
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700114 mNameToService[name] = Service {
115 .binder = binder,
116 .allowIsolated = allowIsolated,
117 .dumpPriority = dumpPriority,
118 };
119
120 return Status::ok();
121}
122
123Status ServiceManager::listServices(int32_t dumpPriority, std::vector<std::string>* outList) {
Steven Morelanda9fe4742019-07-18 14:45:20 -0700124 if (!mAccess->canList(mAccess->getCallingContext())) {
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700125 return Status::fromExceptionCode(Status::EX_SECURITY);
126 }
127
128 size_t toReserve = 0;
129 for (auto const& [name, service] : mNameToService) {
130 (void) name;
131
132 if (service.dumpPriority & dumpPriority) ++toReserve;
133 }
134
135 CHECK(outList->empty());
136
137 outList->reserve(toReserve);
138 for (auto const& [name, service] : mNameToService) {
139 (void) service;
140
141 if (service.dumpPriority & dumpPriority) {
142 outList->push_back(name);
143 }
144 }
145
146 return Status::ok();
147}
148
149void ServiceManager::binderDied(const wp<IBinder>& who) {
150 for (auto it = mNameToService.begin(); it != mNameToService.end();) {
151 if (who == it->second.binder) {
152 it = mNameToService.erase(it);
153 } else {
154 ++it;
155 }
156 }
157}
158
159} // namespace android