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 <cstring>
19 #include <dirent.h>
20 #include <dlfcn.h>
21 #include <iostream>
22 #include <mutex>
23 #include <string_ex.h>
24 #include <unistd.h>
25
26 #include "edm_ipc_interface_code.h"
27 #include "edm_log.h"
28 #include "func_code_utils.h"
29 #include "permission_manager.h"
30
31 namespace OHOS {
32 namespace EDM {
33 std::shared_ptr<PluginManager> PluginManager::instance_;
34 std::mutex PluginManager::mutexLock_;
35
PluginManager()36 PluginManager::PluginManager()
37 {
38 EDMLOGD("PluginManager::PluginManager.");
39 }
40
~PluginManager()41 PluginManager::~PluginManager()
42 {
43 EDMLOGD("PluginManager::~PluginManager.");
44 pluginsCode_.clear();
45 pluginsName_.clear();
46 for (auto handle : pluginHandles_) {
47 dlclose(handle);
48 }
49 pluginHandles_.clear();
50 }
51
GetInstance()52 std::shared_ptr<PluginManager> PluginManager::GetInstance()
53 {
54 if (instance_ == nullptr) {
55 std::lock_guard<std::mutex> autoLock(mutexLock_);
56 if (instance_ == nullptr) {
57 instance_.reset(new (std::nothrow) PluginManager());
58 }
59 }
60
61 IPluginManager::pluginManagerInstance_ = instance_.get();
62 return instance_;
63 }
64
GetPluginByFuncCode(std::uint32_t funcCode)65 std::shared_ptr<IPlugin> PluginManager::GetPluginByFuncCode(std::uint32_t funcCode)
66 {
67 FuncCodeUtils::PrintFuncCode(funcCode);
68 FuncFlag flag = FuncCodeUtils::GetSystemFlag(funcCode);
69 if (flag == FuncFlag::POLICY_FLAG) {
70 std::uint32_t code = FuncCodeUtils::GetPolicyCode(funcCode);
71 EDMLOGD("PluginManager::code %{public}u", code);
72 auto it = pluginsCode_.find(code);
73 if (it != pluginsCode_.end()) {
74 return it->second;
75 }
76 }
77 EDMLOGD("GetPluginByFuncCode::return nullptr");
78 return nullptr;
79 }
80
GetPluginByPolicyName(const std::string & policyName)81 std::shared_ptr<IPlugin> PluginManager::GetPluginByPolicyName(const std::string &policyName)
82 {
83 auto it = pluginsName_.find(policyName);
84 if (it != pluginsName_.end()) {
85 return it->second;
86 }
87 return nullptr;
88 }
89
GetPluginByCode(std::uint32_t code)90 std::shared_ptr<IPlugin> PluginManager::GetPluginByCode(std::uint32_t code)
91 {
92 EDMLOGD("PluginManager::code %{public}u", code);
93 auto it = pluginsCode_.find(code);
94 if (it != pluginsCode_.end()) {
95 return it->second;
96 }
97 EDMLOGD("GetPluginByCode::return nullptr");
98 return nullptr;
99 }
100
CreateExecuteStrategy(ExecuteStrategy strategy)101 std::shared_ptr<IPluginExecuteStrategy> PluginManager::CreateExecuteStrategy(ExecuteStrategy strategy)
102 {
103 if (strategy == ExecuteStrategy::ENHANCE) {
104 return enhanceStrategy_;
105 }
106 if (strategy == ExecuteStrategy::REPLACE) {
107 return replaceStrategy_;
108 }
109 return singleStrategy_;
110 }
111
AddPlugin(std::shared_ptr<IPlugin> plugin)112 bool PluginManager::AddPlugin(std::shared_ptr<IPlugin> plugin)
113 {
114 if (plugin == nullptr) {
115 return false;
116 }
117 EDMLOGD("AddPlugin %{public}d", plugin->GetCode());
118 std::vector<IPlugin::PolicyPermissionConfig> configs = plugin->GetAllPermission();
119 if (configs.empty()) {
120 return false;
121 }
122 for (auto &config : configs) {
123 for (auto &typePermission : config.typePermissions) {
124 PermissionManager::GetInstance()->AddPermission(typePermission.second, typePermission.first);
125 }
126 for (auto &tagPermission : config.tagPermissions) {
127 for (auto &typePermission : tagPermission.second) {
128 PermissionManager::GetInstance()->AddPermission(typePermission.second, typePermission.first);
129 }
130 }
131 }
132 pluginsCode_.insert(std::make_pair(plugin->GetCode(), plugin));
133 pluginsName_.insert(std::make_pair(plugin->GetPolicyName(), plugin));
134 if (extensionPluginMap_.find(plugin->GetCode()) != extensionPluginMap_.end()) {
135 EDMLOGD("PluginManager::AddPlugin %{public}d add extension plugin %{public}d", plugin->GetCode(),
136 extensionPluginMap_[plugin->GetCode()]);
137 plugin->SetExtensionPlugin(GetPluginByCode(extensionPluginMap_[plugin->GetCode()]));
138 }
139 if (executeStrategyMap_.find(plugin->GetCode()) != executeStrategyMap_.end()) {
140 plugin->SetExecuteStrategy(CreateExecuteStrategy(executeStrategyMap_[plugin->GetCode()]));
141 } else {
142 plugin->SetExecuteStrategy(CreateExecuteStrategy(ExecuteStrategy::SINGLE));
143 }
144 return true;
145 }
146
AddExtensionPlugin(std::shared_ptr<IPlugin> extensionPlugin,uint32_t basicPluginCode,ExecuteStrategy strategy)147 bool PluginManager::AddExtensionPlugin(std::shared_ptr<IPlugin> extensionPlugin, uint32_t basicPluginCode,
148 ExecuteStrategy strategy)
149 {
150 if (AddPlugin(extensionPlugin)) {
151 auto basicPlugin = GetPluginByCode(basicPluginCode);
152 if (basicPlugin != nullptr) {
153 EDMLOGD("PluginManager::AddExtensionPlugin %{public}d add extension plugin %{public}d", basicPluginCode,
154 extensionPlugin->GetCode());
155 basicPlugin->SetExtensionPlugin(extensionPlugin);
156 basicPlugin->SetExecuteStrategy(CreateExecuteStrategy(strategy));
157 }
158 extensionPlugin->SetPluginType(IPlugin::PluginType::EXTENSION);
159 extensionPluginMap_.insert(std::make_pair(basicPluginCode, extensionPlugin->GetCode()));
160 executeStrategyMap_.insert(std::make_pair(basicPluginCode, strategy));
161 return true;
162 }
163 return false;
164 }
165
LoadPlugin()166 void PluginManager::LoadPlugin()
167 {
168 std::lock_guard<std::mutex> autoLock(mutexLock_);
169 #if defined(_ARM64_) || defined(_X86_64_)
170 std::string pluginDir = "/system/lib64/edm_plugin/";
171 #else
172 std::string pluginDir = "/system/lib/edm_plugin/";
173 #endif
174 DIR *dir = opendir(pluginDir.c_str());
175 if (dir == nullptr) {
176 EDMLOGE("PluginManager::LoadPlugin open edm_plugin dir fail.");
177 return;
178 }
179 struct dirent *entry;
180 while ((entry = readdir(dir)) != nullptr) {
181 if (entry->d_type == DT_REG && strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
182 LoadPlugin(pluginDir + entry->d_name);
183 }
184 }
185 closedir(dir);
186 }
187
LoadPlugin(const std::string & pluginPath)188 void PluginManager::LoadPlugin(const std::string &pluginPath)
189 {
190 void *handle = dlopen(pluginPath.c_str(), RTLD_LAZY);
191 if (!handle) {
192 EDMLOGE("PluginManager::open plugin so fail. %{public}s.", dlerror());
193 return;
194 }
195 pluginHandles_.push_back(handle);
196 }
197
UnloadPlugin()198 void PluginManager::UnloadPlugin()
199 {
200 std::lock_guard<std::mutex> autoLock(mutexLock_);
201 for (auto codeIter = pluginsCode_.begin(); codeIter != pluginsCode_.end();) {
202 if (codeIter->second != nullptr) {
203 codeIter->second->ResetExtensionPlugin();
204 }
205 if (codeIter->second == nullptr || codeIter->first > static_cast<uint32_t>(EdmInterfaceCode::POLICY_CODE_END)) {
206 codeIter = pluginsCode_.erase(codeIter);
207 } else {
208 ++codeIter;
209 }
210 }
211 for (auto nameIter = pluginsName_.begin(); nameIter != pluginsName_.end();) {
212 if (nameIter->second == nullptr ||
213 nameIter->second->GetCode() > static_cast<uint32_t>(EdmInterfaceCode::POLICY_CODE_END)) {
214 nameIter = pluginsName_.erase(nameIter);
215 } else {
216 ++nameIter;
217 }
218 }
219 for (auto handleIter = pluginHandles_.begin(); handleIter != pluginHandles_.end();) {
220 auto handle = *handleIter;
221 if (handle == nullptr || dlclose(handle) == 0) {
222 handleIter = pluginHandles_.erase(handleIter);
223 } else {
224 EDMLOGE("PluginManager::UnloadPlugin close handle failed.");
225 ++handleIter;
226 }
227 }
228 }
229
DumpPluginConfig(IPlugin::PolicyPermissionConfig config)230 void PluginManager::DumpPluginConfig(IPlugin::PolicyPermissionConfig config)
231 {
232 std::string permissionStr;
233 permissionStr.append("Type Permissions:");
234 for (const auto &typePermission : config.typePermissions) {
235 permissionStr.append("PermissionType: ");
236 if (typePermission.first == IPlugin::PermissionType::NORMAL_DEVICE_ADMIN) {
237 permissionStr.append("NORMAL_DEVICE_ADMIN:");
238 }
239 if (typePermission.first == IPlugin::PermissionType::SUPER_DEVICE_ADMIN) {
240 permissionStr.append("SUPER_DEVICE_ADMIN:");
241 }
242 if (typePermission.first == IPlugin::PermissionType::BYOD_DEVICE_ADMIN) {
243 permissionStr.append("BYOD_DEVICE_ADMIN:");
244 }
245 permissionStr.append(typePermission.second);
246 }
247 permissionStr.append("Tag Permissions:");
248 for (const auto &tagPermission : config.tagPermissions) {
249 permissionStr.append("ApiTag: ");
250 permissionStr.append(tagPermission.first);
251 for (const auto &tag : tagPermission.second) {
252 if (tag.first == IPlugin::PermissionType::NORMAL_DEVICE_ADMIN) {
253 permissionStr.append("NORMAL_DEVICE_ADMIN:");
254 }
255 if (tag.first == IPlugin::PermissionType::SUPER_DEVICE_ADMIN) {
256 permissionStr.append("SUPER_DEVICE_ADMIN:");
257 }
258 if (tag.first == IPlugin::PermissionType::BYOD_DEVICE_ADMIN) {
259 permissionStr.append("BYOD_DEVICE_ADMIN:");
260 }
261 permissionStr.append(tag.second);
262 }
263 }
264 EDMLOGD("Config permission:%{public}s", permissionStr.c_str());
265 }
266
DumpPlugin()267 void PluginManager::DumpPlugin()
268 {
269 for (auto it = pluginsCode_.begin(); it != pluginsCode_.end(); it++) {
270 std::vector<IPlugin::PolicyPermissionConfig> configs = it->second->GetAllPermission();
271 EDMLOGD("PluginManager::Dump plugins_code.code:%{public}u,name:%{public}s",
272 it->first, it->second->GetPolicyName().c_str());
273 for (auto &config : configs) {
274 DumpPluginConfig(config);
275 }
276 }
277 for (auto it = pluginsName_.begin(); it != pluginsName_.end(); it++) {
278 std::vector<IPlugin::PolicyPermissionConfig> configs = it->second->GetAllPermission();
279 EDMLOGD("PluginManager::Dump plugins_name.name:%{public}s,code:%{public}u",
280 it->first.c_str(), it->second->GetCode());
281 for (auto &config : configs) {
282 DumpPluginConfig(config);
283 }
284 }
285 }
286 } // namespace EDM
287 } // namespace OHOS
288