1 /*
2 * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "plugin_manager.h"
17
18 #include <dirent.h>
19 #include <dlfcn.h>
20 #include <string_ex.h>
21 #include <unistd.h>
22
23 #include <cstring>
24 #include <iostream>
25 #include <mutex>
26
27 #include "edm_ipc_interface_code.h"
28 #include "edm_log.h"
29 #include "func_code_utils.h"
30 #include "permission_manager.h"
31
32 namespace OHOS {
33 namespace EDM {
34 std::shared_ptr<PluginManager> PluginManager::instance_;
35 std::mutex PluginManager::mutexLock_;
36
PluginManager()37 PluginManager::PluginManager()
38 {
39 EDMLOGD("PluginManager::PluginManager.");
40 }
41
~PluginManager()42 PluginManager::~PluginManager()
43 {
44 EDMLOGD("PluginManager::~PluginManager.");
45 persistentPluginsCode_.clear();
46 persistentPluginsName_.clear();
47 UnloadPlugin();
48 }
49
GetInstance()50 std::shared_ptr<PluginManager> PluginManager::GetInstance()
51 {
52 if (instance_ == nullptr) {
53 std::lock_guard<std::mutex> autoLock(mutexLock_);
54 if (instance_ == nullptr) {
55 instance_.reset(new (std::nothrow) PluginManager());
56 }
57 }
58
59 IPluginManager::pluginManagerInstance_ = instance_.get();
60 return instance_;
61 }
62
GetPluginByFuncCode(std::uint32_t funcCode)63 std::shared_ptr<IPlugin> PluginManager::GetPluginByFuncCode(std::uint32_t funcCode)
64 {
65 FuncCodeUtils::PrintFuncCode(funcCode);
66 FuncFlag flag = FuncCodeUtils::GetSystemFlag(funcCode);
67 if (flag == FuncFlag::POLICY_FLAG) {
68 std::uint32_t code = FuncCodeUtils::GetPolicyCode(funcCode);
69 EDMLOGD("PluginManager::code %{public}u", code);
70 auto it = pluginsCode_.find(code);
71 if (it != pluginsCode_.end()) {
72 return it->second;
73 }
74 auto iter = persistentPluginsCode_.find(code);
75 if (iter != persistentPluginsCode_.end()) {
76 return iter->second;
77 }
78 }
79 EDMLOGD("GetPluginByFuncCode::return nullptr");
80 return nullptr;
81 }
82
GetPluginByPolicyName(const std::string & policyName)83 std::shared_ptr<IPlugin> PluginManager::GetPluginByPolicyName(const std::string &policyName)
84 {
85 auto it = pluginsName_.find(policyName);
86 if (it != pluginsName_.end()) {
87 return it->second;
88 }
89 auto iter = persistentPluginsName_.find(policyName);
90 if (iter != persistentPluginsName_.end()) {
91 return iter->second;
92 }
93 return nullptr;
94 }
95
GetPluginByCode(std::uint32_t code)96 std::shared_ptr<IPlugin> PluginManager::GetPluginByCode(std::uint32_t code)
97 {
98 EDMLOGD("PluginManager::code %{public}u", code);
99 auto it = pluginsCode_.find(code);
100 if (it != pluginsCode_.end()) {
101 return it->second;
102 }
103 auto iter = persistentPluginsCode_.find(code);
104 if (iter != persistentPluginsCode_.end()) {
105 return iter->second;
106 }
107 EDMLOGI("GetPluginByCode::return nullptr");
108 return nullptr;
109 }
110
CreateExecuteStrategy(ExecuteStrategy strategy)111 std::shared_ptr<IPluginExecuteStrategy> PluginManager::CreateExecuteStrategy(ExecuteStrategy strategy)
112 {
113 if (strategy == ExecuteStrategy::ENHANCE) {
114 return enhanceStrategy_;
115 }
116 if (strategy == ExecuteStrategy::REPLACE) {
117 return replaceStrategy_;
118 }
119 return singleStrategy_;
120 }
121
AddPlugin(std::shared_ptr<IPlugin> plugin)122 bool PluginManager::AddPlugin(std::shared_ptr<IPlugin> plugin)
123 {
124 if (plugin == nullptr) {
125 return false;
126 }
127 EDMLOGD("AddPlugin %{public}d", plugin->GetCode());
128 return AddPluginInner(plugin, false);
129 }
130
AddPersistentPlugin(std::shared_ptr<IPlugin> plugin)131 bool PluginManager::AddPersistentPlugin(std::shared_ptr<IPlugin> plugin)
132 {
133 if (plugin == nullptr) {
134 return false;
135 }
136 EDMLOGD("AddPersistentPlugin %{public}d", plugin->GetCode());
137 return AddPluginInner(plugin, true);
138 }
139
AddPluginInner(std::shared_ptr<IPlugin> plugin,bool isPersistent)140 bool PluginManager::AddPluginInner(std::shared_ptr<IPlugin> plugin, bool isPersistent)
141 {
142 if (plugin == nullptr) {
143 return false;
144 }
145 EDMLOGD("AddPlugin %{public}d", plugin->GetCode());
146 std::vector<IPlugin::PolicyPermissionConfig> configs = plugin->GetAllPermission();
147 if (configs.empty()) {
148 return false;
149 }
150 for (auto &config : configs) {
151 for (auto &typePermission : config.typePermissions) {
152 PermissionManager::GetInstance()->AddPermission(typePermission.second, typePermission.first);
153 }
154 for (auto &tagPermission : config.tagPermissions) {
155 for (auto &typePermission : tagPermission.second) {
156 PermissionManager::GetInstance()->AddPermission(typePermission.second, typePermission.first);
157 }
158 }
159 }
160 if (isPersistent) {
161 persistentPluginsCode_.insert(std::make_pair(plugin->GetCode(), plugin));
162 persistentPluginsName_.insert(std::make_pair(plugin->GetPolicyName(), plugin));
163 } else {
164 pluginsCode_.insert(std::make_pair(plugin->GetCode(), plugin));
165 pluginsName_.insert(std::make_pair(plugin->GetPolicyName(), plugin));
166 }
167 if (extensionPluginMap_.find(plugin->GetCode()) != extensionPluginMap_.end()) {
168 EDMLOGD("PluginManager::AddPlugin %{public}d add extension plugin %{public}d", plugin->GetCode(),
169 extensionPluginMap_[plugin->GetCode()]);
170 plugin->SetExtensionPlugin(GetPluginByCode(extensionPluginMap_[plugin->GetCode()]));
171 }
172 if (executeStrategyMap_.find(plugin->GetCode()) != executeStrategyMap_.end()) {
173 plugin->SetExecuteStrategy(CreateExecuteStrategy(executeStrategyMap_[plugin->GetCode()]));
174 } else {
175 plugin->SetExecuteStrategy(CreateExecuteStrategy(ExecuteStrategy::SINGLE));
176 }
177 return true;
178 }
179
AddExtensionPlugin(std::shared_ptr<IPlugin> extensionPlugin,uint32_t basicPluginCode,ExecuteStrategy strategy)180 bool PluginManager::AddExtensionPlugin(std::shared_ptr<IPlugin> extensionPlugin, uint32_t basicPluginCode,
181 ExecuteStrategy strategy)
182 {
183 if (AddPlugin(extensionPlugin)) {
184 auto basicPlugin = GetPluginByCode(basicPluginCode);
185 if (basicPlugin != nullptr) {
186 EDMLOGD("PluginManager::AddExtensionPlugin %{public}d add extension plugin %{public}d", basicPluginCode,
187 extensionPlugin->GetCode());
188 basicPlugin->SetExtensionPlugin(extensionPlugin);
189 basicPlugin->SetExecuteStrategy(CreateExecuteStrategy(strategy));
190 }
191 extensionPlugin->SetPluginType(IPlugin::PluginType::EXTENSION);
192 extensionPluginMap_.insert(std::make_pair(basicPluginCode, extensionPlugin->GetCode()));
193 executeStrategyMap_.insert(std::make_pair(basicPluginCode, strategy));
194 return true;
195 }
196 return false;
197 }
198
LoadPlugin()199 void PluginManager::LoadPlugin()
200 {
201 std::lock_guard<std::mutex> autoLock(mutexLock_);
202 #if defined(_ARM64_) || defined(_X86_64_)
203 std::string pluginDir = "/system/lib64/edm_plugin/";
204 #else
205 std::string pluginDir = "/system/lib/edm_plugin/";
206 #endif
207 DIR *dir = opendir(pluginDir.c_str());
208 if (dir == nullptr) {
209 EDMLOGE("PluginManager::LoadPlugin open edm_plugin dir fail.");
210 return;
211 }
212 struct dirent *entry;
213 while ((entry = readdir(dir)) != nullptr) {
214 if (entry->d_type == DT_REG && strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
215 LoadPlugin(pluginDir + entry->d_name);
216 }
217 }
218 closedir(dir);
219 }
220
LoadPlugin(const std::string & pluginPath)221 void PluginManager::LoadPlugin(const std::string &pluginPath)
222 {
223 void *handle = dlopen(pluginPath.c_str(), RTLD_LAZY);
224 if (!handle) {
225 EDMLOGE("PluginManager::open plugin so fail. %{public}s.", dlerror());
226 return;
227 }
228 pluginHandles_.push_back(handle);
229 }
230
UnloadPlugin()231 void PluginManager::UnloadPlugin()
232 {
233 std::lock_guard<std::mutex> autoLock(mutexLock_);
234 for (auto codeIter = pluginsCode_.begin(); codeIter != pluginsCode_.end();) {
235 if (codeIter->second != nullptr) {
236 codeIter->second->ResetExtensionPlugin();
237 }
238 codeIter = pluginsCode_.erase(codeIter);
239 }
240 pluginsCode_.clear();
241 pluginsName_.clear();
242 for (auto handleIter = pluginHandles_.rbegin(); handleIter != pluginHandles_.rend(); ++handleIter) {
243 auto handle = *handleIter;
244 if (handle == nullptr) {
245 continue;
246 }
247 int result = dlclose(handle);
248 if (result != 0) {
249 EDMLOGE("PluginManager::UnloadPlugin close lib failed: %{public}s.", dlerror());
250 } else {
251 EDMLOGI("PluginManager::UnloadPlugin close lib success");
252 }
253 }
254 pluginHandles_.clear();
255 EDMLOGI("PluginManager::UnloadPlugin finish.");
256 }
257
DumpPluginConfig(IPlugin::PolicyPermissionConfig config)258 void PluginManager::DumpPluginConfig(IPlugin::PolicyPermissionConfig config)
259 {
260 std::string permissionStr;
261 permissionStr.append("Type Permissions:");
262 for (const auto &typePermission : config.typePermissions) {
263 permissionStr.append("PermissionType: ");
264 if (typePermission.first == IPlugin::PermissionType::NORMAL_DEVICE_ADMIN) {
265 permissionStr.append("NORMAL_DEVICE_ADMIN:");
266 }
267 if (typePermission.first == IPlugin::PermissionType::SUPER_DEVICE_ADMIN) {
268 permissionStr.append("SUPER_DEVICE_ADMIN:");
269 }
270 if (typePermission.first == IPlugin::PermissionType::BYOD_DEVICE_ADMIN) {
271 permissionStr.append("BYOD_DEVICE_ADMIN:");
272 }
273 permissionStr.append(typePermission.second);
274 }
275 permissionStr.append("Tag Permissions:");
276 for (const auto &tagPermission : config.tagPermissions) {
277 permissionStr.append("ApiTag: ");
278 permissionStr.append(tagPermission.first);
279 for (const auto &tag : tagPermission.second) {
280 if (tag.first == IPlugin::PermissionType::NORMAL_DEVICE_ADMIN) {
281 permissionStr.append("NORMAL_DEVICE_ADMIN:");
282 }
283 if (tag.first == IPlugin::PermissionType::SUPER_DEVICE_ADMIN) {
284 permissionStr.append("SUPER_DEVICE_ADMIN:");
285 }
286 if (tag.first == IPlugin::PermissionType::BYOD_DEVICE_ADMIN) {
287 permissionStr.append("BYOD_DEVICE_ADMIN:");
288 }
289 permissionStr.append(tag.second);
290 }
291 }
292 EDMLOGD("Config permission:%{public}s", permissionStr.c_str());
293 }
294
DumpPlugin()295 void PluginManager::DumpPlugin()
296 {
297 DumpPluginInner(pluginsCode_, pluginsName_);
298 DumpPluginInner(persistentPluginsCode_, persistentPluginsName_);
299 }
300
DumpPluginInner(std::map<std::uint32_t,std::shared_ptr<IPlugin>> pluginsCode,std::map<std::string,std::shared_ptr<IPlugin>> pluginsName)301 void PluginManager::DumpPluginInner(std::map<std::uint32_t, std::shared_ptr<IPlugin>> pluginsCode,
302 std::map<std::string, std::shared_ptr<IPlugin>> pluginsName)
303 {
304 for (auto it = pluginsCode.begin(); it != pluginsCode.end(); it++) {
305 std::vector<IPlugin::PolicyPermissionConfig> configs = it->second->GetAllPermission();
306 EDMLOGD("PluginManager::Dump plugins_code.code:%{public}u,name:%{public}s", it->first,
307 it->second->GetPolicyName().c_str());
308 for (auto &config : configs) {
309 DumpPluginConfig(config);
310 }
311 }
312 for (auto it = pluginsName.begin(); it != pluginsName.end(); it++) {
313 std::vector<IPlugin::PolicyPermissionConfig> configs = it->second->GetAllPermission();
314 EDMLOGD("PluginManager::Dump plugins_name.name:%{public}s,code:%{public}u", it->first.c_str(),
315 it->second->GetCode());
316 for (auto &config : configs) {
317 DumpPluginConfig(config);
318 }
319 }
320 }
321 } // namespace EDM
322 } // namespace OHOS
323