blob: 6cfcf409701bd055c4ca03fe36df4391b1dbb1e4 [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)) {}
28
29Status ServiceManager::getService(const std::string& name, sp<IBinder>* outBinder) {
30 // Servicemanager is single-threaded and cannot block. This method exists for legacy reasons.
31 return checkService(name, outBinder);
32}
33
34Status ServiceManager::checkService(const std::string& name, sp<IBinder>* outBinder) {
35 auto ctx = mAccess->getCallingContext(name);
36
37 auto it = mNameToService.find(name);
38 if (it == mNameToService.end()) {
39 *outBinder = nullptr;
40 return Status::ok();
41 }
42
43 const Service& service = it->second;
44
45 if (!service.allowIsolated) {
46 uid_t appid = multiuser_get_app_id(ctx.uid);
47 bool isIsolated = appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END;
48
49 if (isIsolated) {
50 *outBinder = nullptr;
51 return Status::ok();
52 }
53 }
54
55 // TODO(b/136023468): move this check to be first
56 if (!mAccess->canFind(ctx)) {
57 // returns ok and null for legacy reasons
58 *outBinder = nullptr;
59 return Status::ok();
60 }
61
62 *outBinder = service.binder;
63 return Status::ok();
64}
65
Steven Moreland905e2e82019-07-17 11:05:45 -070066bool isValidServiceName(const std::string& name) {
67 if (name.size() == 0) return false;
68 if (name.size() > 127) return false;
69
70 for (char c : name) {
71 if (c == '_' || c == '-' || c == '.') continue;
72 if (c >= 'a' && c <= 'z') continue;
73 if (c >= 'A' && c <= 'Z') continue;
74 if (c >= '0' && c <= '9') continue;
75 return false;
76 }
77
78 return true;
79}
80
Steven Moreland80e1e6d2019-06-21 12:35:59 -070081Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) {
82 auto ctx = mAccess->getCallingContext(name);
83
84 // apps cannot add services
85 if (multiuser_get_app_id(ctx.uid) >= AID_APP) {
86 return Status::fromExceptionCode(Status::EX_SECURITY);
87 }
88
89 if (!mAccess->canAdd(ctx)) {
90 return Status::fromExceptionCode(Status::EX_SECURITY);
91 }
92
93 if (binder == nullptr) {
94 return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
95 }
96
Steven Moreland905e2e82019-07-17 11:05:45 -070097 if (!isValidServiceName(name)) {
98 LOG(ERROR) << "Invalid service name: " << name;
Steven Moreland80e1e6d2019-06-21 12:35:59 -070099 return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
100 }
101
102 if (OK != binder->linkToDeath(this)) {
103 LOG(ERROR) << "Could not linkToDeath when adding " << name;
104 return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
105 }
106
107 auto it = mNameToService.find(name);
108 if (it != mNameToService.end()) {
109 if (OK != it->second.binder->unlinkToDeath(this)) {
110 LOG(WARNING) << "Could not unlinkToDeath when adding " << name;
111 }
112 }
113
114 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) {
124 if (!mAccess->canList(mAccess->getCallingContext(""))) {
125 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