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     IPlugin::PolicyPermissionConfig setConfig = plugin->GetAllPermission(FuncOperateType::SET);
119     IPlugin::PolicyPermissionConfig getConfig = plugin->GetAllPermission(FuncOperateType::GET);
120     IPlugin::PermissionType setType = plugin->GetPermissionType(FuncOperateType::SET);
121     IPlugin::PermissionType getType = plugin->GetPermissionType(FuncOperateType::GET);
122     ErrCode result = PermissionManager::GetInstance()->AddPermission(setConfig.permission, setType);
123     if (result == ERR_OK && getConfig.permission != setConfig.permission) {
124         result = PermissionManager::GetInstance()->AddPermission(getConfig.permission, getType);
125     }
126     if (result == ERR_OK) {
127         for (auto &item : setConfig.tagPermissions) {
128             if (PermissionManager::GetInstance()->AddPermission(item.second, setType) != ERR_OK) {
129                 return false;
130             }
131         }
132         for (auto &item : getConfig.tagPermissions) {
133             if (PermissionManager::GetInstance()->AddPermission(item.second, getType) != ERR_OK) {
134                 return false;
135             }
136         }
137         pluginsCode_.insert(std::make_pair(plugin->GetCode(), plugin));
138         pluginsName_.insert(std::make_pair(plugin->GetPolicyName(), plugin));
139         if (extensionPluginMap_.count(plugin->GetCode()) > 0) {
140             EDMLOGD("PluginManager::AddPlugin %{public}d add extension plugin %{public}d", plugin->GetCode(),
141                 extensionPluginMap_[plugin->GetCode()]);
142             plugin->SetExtensionPlugin(GetPluginByCode(extensionPluginMap_[plugin->GetCode()]));
143         }
144         if (executeStrategyMap_.count(plugin->GetCode()) > 0) {
145             plugin->SetExecuteStrategy(CreateExecuteStrategy(executeStrategyMap_[plugin->GetCode()]));
146         } else {
147             plugin->SetExecuteStrategy(CreateExecuteStrategy(ExecuteStrategy::SINGLE));
148         }
149         return true;
150     }
151     return false;
152 }
153 
AddExtensionPlugin(std::shared_ptr<IPlugin> extensionPlugin,uint32_t basicPluginCode,ExecuteStrategy strategy)154 bool PluginManager::AddExtensionPlugin(std::shared_ptr<IPlugin> extensionPlugin, uint32_t basicPluginCode,
155     ExecuteStrategy strategy)
156 {
157     if (AddPlugin(extensionPlugin)) {
158         auto basicPlugin = GetPluginByCode(basicPluginCode);
159         if (basicPlugin != nullptr) {
160             EDMLOGD("PluginManager::AddExtensionPlugin %{public}d add extension plugin %{public}d", basicPluginCode,
161                 extensionPlugin->GetCode());
162             basicPlugin->SetExtensionPlugin(extensionPlugin);
163             basicPlugin->SetExecuteStrategy(CreateExecuteStrategy(strategy));
164         }
165         extensionPlugin->SetPluginType(IPlugin::PluginType::EXTENSION);
166         extensionPluginMap_.insert(std::make_pair(basicPluginCode, extensionPlugin->GetCode()));
167         executeStrategyMap_.insert(std::make_pair(basicPluginCode, strategy));
168         return true;
169     }
170     return false;
171 }
172 
LoadPlugin()173 void PluginManager::LoadPlugin()
174 {
175     std::lock_guard<std::mutex> autoLock(mutexLock_);
176 #if defined(_ARM64_) || defined(_X86_64_)
177     std::string pluginDir = "/system/lib64/edm_plugin/";
178 #else
179     std::string pluginDir = "/system/lib/edm_plugin/";
180 #endif
181     DIR *dir = opendir(pluginDir.c_str());
182     if (dir == nullptr) {
183         EDMLOGE("PluginManager::LoadPlugin open edm_plugin dir fail.");
184         return;
185     }
186     struct dirent *entry;
187     while ((entry = readdir(dir)) != nullptr) {
188         if (entry->d_type == DT_REG && strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
189             LoadPlugin(pluginDir + entry->d_name);
190         }
191     }
192     closedir(dir);
193 }
194 
LoadPlugin(const std::string & pluginPath)195 void PluginManager::LoadPlugin(const std::string &pluginPath)
196 {
197     void *handle = dlopen(pluginPath.c_str(), RTLD_LAZY);
198     if (!handle) {
199         EDMLOGE("PluginManager::open plugin so fail. %{public}s.", dlerror());
200         return;
201     }
202     pluginHandles_.push_back(handle);
203 }
204 
UnloadPlugin()205 void PluginManager::UnloadPlugin()
206 {
207     std::lock_guard<std::mutex> autoLock(mutexLock_);
208     for (auto codeIter = pluginsCode_.begin(); codeIter != pluginsCode_.end();) {
209         if (codeIter->second != nullptr) {
210             codeIter->second->ResetExtensionPlugin();
211         }
212         if (codeIter->second == nullptr || codeIter->first > static_cast<uint32_t>(EdmInterfaceCode::POLICY_CODE_END)) {
213             codeIter = pluginsCode_.erase(codeIter);
214         } else {
215             ++codeIter;
216         }
217     }
218     for (auto nameIter = pluginsName_.begin(); nameIter != pluginsName_.end();) {
219         if (nameIter->second == nullptr ||
220             nameIter->second->GetCode() > static_cast<uint32_t>(EdmInterfaceCode::POLICY_CODE_END)) {
221             nameIter = pluginsName_.erase(nameIter);
222         } else {
223             ++nameIter;
224         }
225     }
226     for (auto handleIter = pluginHandles_.begin(); handleIter != pluginHandles_.end();) {
227         auto handle = *handleIter;
228         if (handle == nullptr || dlclose(handle) == 0) {
229             handleIter = pluginHandles_.erase(handleIter);
230         } else {
231             EDMLOGE("PluginManager::UnloadPlugin close handle failed.");
232             ++handleIter;
233         }
234     }
235 }
236 
DumpPlugin()237 void PluginManager::DumpPlugin()
238 {
239     for (auto it = pluginsCode_.begin(); it != pluginsCode_.end(); it++) {
240         std::string setTagPermissions;
241         std::string getTagPermissions;
242         IPlugin::PolicyPermissionConfig setConfig = it->second->GetAllPermission(FuncOperateType::SET);
243         IPlugin::PolicyPermissionConfig getConfig = it->second->GetAllPermission(FuncOperateType::GET);
244         for (auto &item : setConfig.tagPermissions) {
245             setTagPermissions.append(item.second);
246         }
247         for (auto &item : getConfig.tagPermissions) {
248             getTagPermissions.append(item.second);
249         }
250         EDMLOGD("PluginManager::Dump plugins_code.code:%{public}u,name:%{public}s,get permission:%{public}s, "
251             "set permission:%{public}s,get tagPermissions:%{public}s,set tagPermissions:%{public}s",
252             it->first, it->second->GetPolicyName().c_str(),
253             it->second->GetPermission(FuncOperateType::GET).c_str(),
254             it->second->GetPermission(FuncOperateType::SET).c_str(),
255             getTagPermissions.c_str(), setTagPermissions.c_str());
256     }
257     for (auto it = pluginsName_.begin(); it != pluginsName_.end(); it++) {
258         std::string setTagPermissions;
259         std::string getTagPermissions;
260         IPlugin::PolicyPermissionConfig setConfig = it->second->GetAllPermission(FuncOperateType::SET);
261         IPlugin::PolicyPermissionConfig getConfig = it->second->GetAllPermission(FuncOperateType::GET);
262         for (auto &item : setConfig.tagPermissions) {
263             setTagPermissions.append(item.second);
264         }
265         for (auto &item : getConfig.tagPermissions) {
266             getTagPermissions.append(item.second);
267         }
268         EDMLOGD("PluginManager::Dump plugins_name.name:%{public}s,code:%{public}u,get permission type:%{public}s, "
269             "set permission type:%{public}s,get tagPermissions:%{public}s,set tagPermissions:%{public}s",
270             it->first.c_str(), it->second->GetCode(),
271             it->second->GetPermission(FuncOperateType::GET).c_str(),
272             it->second->GetPermission(FuncOperateType::SET).c_str(),
273             getTagPermissions.c_str(), setTagPermissions.c_str());
274     }
275 }
276 } // namespace EDM
277 } // namespace OHOS
278