1 /*
2 * Copyright (c) 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 "nlohmann/json.hpp"
17 #include "system_ability_manager.h"
18 #include "system_ability_manager_util.h"
19 #include "parameter.h"
20 #include "parameters.h"
21 #include "accesstoken_kit.h"
22 #include "ipc_skeleton.h"
23 #include "string_ex.h"
24 #include "tools.h"
25 #include "sam_log.h"
26
27 namespace OHOS {
28 namespace fs = std::filesystem;
29 using namespace std;
30 #ifdef SUPPORT_PENGLAI_MODE
31 using PenglaiFunc = bool (*)(const int32_t, const int32_t);
32 constexpr const char* PENGLAI_SO_PATH = "libpenglai_client.z.so";
33 constexpr const char* PENGLAI_SYM = "IsLaunchAllowedByUid";
34 void* SamgrUtil::penglaiFunc_ = InitPenglaiFunc();
35 #endif
36 constexpr int32_t MAX_NAME_SIZE = 200;
37 constexpr int32_t SPLIT_NAME_VECTOR_SIZE = 2;
38 constexpr int32_t UID_ROOT = 0;
39 constexpr int32_t UID_SYSTEM = 1000;
40 constexpr int32_t SHFIT_BIT = 32;
41
42 constexpr const char* EVENT_TYPE = "eventId";
43 constexpr const char* EVENT_NAME = "name";
44 constexpr const char* EVENT_VALUE = "value";
45 constexpr const char* EVENT_EXTRA_DATA_ID = "extraDataId";
46 constexpr const char* MODULE_UPDATE_PARAM = "persist.samgr.moduleupdate";
47 constexpr const char* PENG_LAI_PARAM = "ohos.boot.minisys.mode";
48 constexpr const char* PENG_LAI = "penglai";
49 constexpr const char* PENGLAI_PATH = "profile/penglai";
50 std::shared_ptr<FFRTHandler> SamgrUtil::setParmHandler_ = make_shared<FFRTHandler>("setParmHandler");
51
IsNameInValid(const std::u16string & name)52 bool SamgrUtil::IsNameInValid(const std::u16string& name)
53 {
54 HILOGD("%{public}s called:name = %{public}s", __func__, Str16ToStr8(name).c_str());
55 bool ret = false;
56 if (name.empty() || name.size() > MAX_NAME_SIZE || DeleteBlank(name).empty()) {
57 ret = true;
58 }
59
60 return ret;
61 }
62
ParseRemoteSaName(const std::u16string & name,std::string & deviceId,std::u16string & saName)63 void SamgrUtil::ParseRemoteSaName(const std::u16string& name, std::string& deviceId,
64 std::u16string& saName)
65 {
66 vector<string> strVector;
67 SplitStr(Str16ToStr8(name), "_", strVector);
68 if (strVector.size() == SPLIT_NAME_VECTOR_SIZE) {
69 deviceId = strVector[0];
70 saName = Str8ToStr16(strVector[1]);
71 }
72 }
73
CheckDistributedPermission()74 bool SamgrUtil::CheckDistributedPermission()
75 {
76 auto callingUid = IPCSkeleton::GetCallingUid();
77 if (callingUid != UID_ROOT && callingUid != UID_SYSTEM) {
78 return false;
79 }
80 return true;
81 }
82
IsSameEvent(const OnDemandEvent & event,std::list<OnDemandEvent> & enableOnceList)83 bool SamgrUtil::IsSameEvent(const OnDemandEvent& event, std::list<OnDemandEvent>& enableOnceList)
84 {
85 for (auto iter = enableOnceList.begin(); iter != enableOnceList.end(); iter++) {
86 if (event.eventId == iter->eventId && event.name == iter->name && event.value == iter->value) {
87 HILOGI("event already exits in enable-once list");
88 return true;
89 }
90 }
91 return false;
92 }
93
EventToStr(const OnDemandEvent & event)94 std::string SamgrUtil::EventToStr(const OnDemandEvent& event)
95 {
96 nlohmann::json eventJson;
97 eventJson[EVENT_TYPE] = event.eventId;
98 eventJson[EVENT_NAME] = event.name;
99 eventJson[EVENT_VALUE] = event.value;
100 eventJson[EVENT_EXTRA_DATA_ID] = event.extraDataId;
101 std::string eventStr = eventJson.dump();
102 return eventStr;
103 }
104
TransformDeviceId(const std::string & deviceId,int32_t type,bool isPrivate)105 std::string SamgrUtil::TransformDeviceId(const std::string& deviceId, int32_t type, bool isPrivate)
106 {
107 return isPrivate ? std::string() : deviceId;
108 }
109
CheckCallerProcess(const CommonSaProfile & saProfile)110 bool SamgrUtil::CheckCallerProcess(const CommonSaProfile& saProfile)
111 {
112 if (!CheckCallerProcess(Str16ToStr8(saProfile.process))) {
113 HILOGE("can't operate SA: %{public}d by proc:%{public}s",
114 saProfile.saId, Str16ToStr8(saProfile.process).c_str());
115 return false;
116 }
117 return true;
118 }
119
CheckCallerProcess(const std::string & callProcess)120 bool SamgrUtil::CheckCallerProcess(const std::string& callProcess)
121 {
122 uint32_t accessToken = IPCSkeleton::GetCallingTokenID();
123 Security::AccessToken::NativeTokenInfo nativeTokenInfo;
124 int32_t tokenInfoResult = Security::AccessToken::AccessTokenKit::GetNativeTokenInfo(accessToken, nativeTokenInfo);
125 if (tokenInfoResult != ERR_OK) {
126 HILOGE("get token info failed");
127 return false;
128 }
129
130 if (nativeTokenInfo.processName != callProcess) {
131 HILOGE("can't operate by proc:%{public}s", nativeTokenInfo.processName.c_str());
132 return false;
133 }
134 return true;
135 }
136
CheckAllowUpdate(OnDemandPolicyType type,const CommonSaProfile & saProfile)137 bool SamgrUtil::CheckAllowUpdate(OnDemandPolicyType type, const CommonSaProfile& saProfile)
138 {
139 if (type == OnDemandPolicyType::START_POLICY && saProfile.startAllowUpdate) {
140 return true;
141 } else if (type == OnDemandPolicyType::STOP_POLICY && saProfile.stopAllowUpdate) {
142 return true;
143 }
144 return false;
145 }
146
ConvertToOnDemandEvent(const SystemAbilityOnDemandEvent & from,OnDemandEvent & to)147 void SamgrUtil::ConvertToOnDemandEvent(const SystemAbilityOnDemandEvent& from, OnDemandEvent& to)
148 {
149 to.eventId = static_cast<int32_t>(from.eventId);
150 to.name = from.name;
151 to.value = from.value;
152 to.persistence = from.persistence;
153 for (auto& item : from.conditions) {
154 OnDemandCondition condition;
155 condition.eventId = static_cast<int32_t>(item.eventId);
156 condition.name = item.name;
157 condition.value = item.value;
158 to.conditions.push_back(condition);
159 }
160 to.enableOnce = from.enableOnce;
161 }
162
ConvertToSystemAbilityOnDemandEvent(const OnDemandEvent & from,SystemAbilityOnDemandEvent & to)163 void SamgrUtil::ConvertToSystemAbilityOnDemandEvent(const OnDemandEvent& from,
164 SystemAbilityOnDemandEvent& to)
165 {
166 to.eventId = static_cast<OnDemandEventId>(from.eventId);
167 to.name = from.name;
168 to.value = from.value;
169 to.persistence = from.persistence;
170 for (auto& item : from.conditions) {
171 SystemAbilityOnDemandCondition condition;
172 condition.eventId = static_cast<OnDemandEventId>(item.eventId);
173 condition.name = item.name;
174 condition.value = item.value;
175 to.conditions.push_back(condition);
176 }
177 to.enableOnce = from.enableOnce;
178 }
179
GenerateFreKey(int32_t uid,int32_t saId)180 uint64_t SamgrUtil::GenerateFreKey(int32_t uid, int32_t saId)
181 {
182 uint32_t uSaid = static_cast<uint32_t>(saId);
183 uint64_t key = static_cast<uint64_t>(uid);
184 return (key << SHFIT_BIT) | uSaid;
185 }
186
GetCacheCommonEventSa(const OnDemandEvent & event,const std::list<SaControlInfo> & saControlList)187 std::list<int32_t> SamgrUtil::GetCacheCommonEventSa(const OnDemandEvent& event,
188 const std::list<SaControlInfo>& saControlList)
189 {
190 std::list<int32_t> saList;
191 if (event.eventId != COMMON_EVENT || event.extraDataId == -1) {
192 return saList;
193 }
194 for (auto& item : saControlList) {
195 if (item.cacheCommonEvent) {
196 saList.emplace_back(item.saId);
197 }
198 }
199 return saList;
200 }
201
SetModuleUpdateParam(const std::string & key,const std::string & value)202 void SamgrUtil::SetModuleUpdateParam(const std::string& key, const std::string& value)
203 {
204 auto SetParamTask = [=] () {
205 int ret = SetParameter(key.c_str(), value.c_str());
206 if (ret != 0) {
207 HILOGE("SetModuleUpdateParam SetParameter error:%{public}d!", ret);
208 return;
209 }
210 };
211 setParmHandler_->PostTask(SetParamTask);
212 }
213
SendUpdateSaState(int32_t systemAbilityId,const std::string & updateSaState)214 void SamgrUtil::SendUpdateSaState(int32_t systemAbilityId, const std::string& updateSaState)
215 {
216 if (SystemAbilityManager::GetInstance()->IsModuleUpdate(systemAbilityId)) {
217 std::string startKey = std::string(MODULE_UPDATE_PARAM) + ".start";
218 std::string saKey = std::string(MODULE_UPDATE_PARAM) + "." + std::to_string(systemAbilityId);
219 SamgrUtil::SetModuleUpdateParam(startKey, "true");
220 SamgrUtil::SetModuleUpdateParam(saKey, updateSaState);
221 }
222 }
223
InvalidateSACache()224 void SamgrUtil::InvalidateSACache()
225 {
226 auto invalidateCacheTask = [] () {
227 SystemAbilityManager::GetInstance()->InvalidateCache();
228 };
229 setParmHandler_->PostTask(invalidateCacheTask);
230 }
231
FilterCommonSaProfile(const SaProfile & oldProfile,CommonSaProfile & newProfile)232 void SamgrUtil::FilterCommonSaProfile(const SaProfile& oldProfile, CommonSaProfile& newProfile)
233 {
234 newProfile.process = oldProfile.process;
235 newProfile.saId = oldProfile.saId;
236 newProfile.moduleUpdate = oldProfile.moduleUpdate;
237 newProfile.distributed = oldProfile.distributed;
238 newProfile.cacheCommonEvent = oldProfile.cacheCommonEvent;
239 newProfile.startAllowUpdate = oldProfile.startOnDemand.allowUpdate;
240 newProfile.stopAllowUpdate = oldProfile.stopOnDemand.allowUpdate;
241 newProfile.recycleStrategy = oldProfile.recycleStrategy;
242 newProfile.extension.assign(oldProfile.extension.begin(), oldProfile.extension.end());
243 }
244
CheckPengLai()245 bool SamgrUtil::CheckPengLai()
246 {
247 std::string defaultValue = "";
248 std::string paramValue = system::GetParameter(PENG_LAI_PARAM, defaultValue);
249 return paramValue == PENG_LAI;
250 }
251
252 #ifdef SUPPORT_PENGLAI_MODE
InitPenglaiFunc()253 void* SamgrUtil::InitPenglaiFunc()
254 {
255 if (!CheckPengLai()) {
256 HILOGI("InitPenglaiFunc not penglai");
257 return nullptr;
258 }
259 DlHandle handle = dlopen(PENGLAI_SO_PATH, RTLD_NOW);
260 if (handle == nullptr) {
261 HILOGE("InitPenglaiFunc dlopen %{public}s so failed.", PENGLAI_SO_PATH);
262 return nullptr;
263 }
264 void* func = dlsym(handle, PENGLAI_SYM);
265 if (func == nullptr) {
266 HILOGE("InitPenglaiFunc dlsym %{public}s symbol failed.", PENGLAI_SYM);
267 dlclose(handle);
268 return nullptr;
269 }
270 HILOGI("InitPenglaiFunc success.");
271 return func;
272 }
273
CheckPengLaiPermission(int32_t systemAbilityId)274 bool SamgrUtil::CheckPengLaiPermission(int32_t systemAbilityId)
275 {
276 auto callingUid = IPCSkeleton::GetCallingUid();
277
278 if (penglaiFunc_ == nullptr) {
279 return true;
280 }
281 PenglaiFunc IsLaunchAllowedByUid = (PenglaiFunc)penglaiFunc_;
282 bool isAllow = IsLaunchAllowedByUid(callingUid, systemAbilityId);
283 if (!isAllow) {
284 HILOGE("IsLaunchAllowedByUid failed. callingUid:%{public}d, SA:%{public}d", callingUid, systemAbilityId);
285 return false;
286 }
287 HILOGD("CheckPengLaiPerm suc. cUid:%{public}d,SA:%{public}d", callingUid, systemAbilityId);
288 return isAllow;
289 }
290 #endif
291
GetFilesFromPath(const std::string & path,std::map<std::string,std::string> & fileNamesMap)292 void SamgrUtil::GetFilesFromPath(const std::string& path, std::map<std::string, std::string>& fileNamesMap)
293 {
294 CfgFiles* filePaths = GetCfgFiles(path.c_str());
295 for (int i = 0; filePaths && i < MAX_CFG_POLICY_DIRS_CNT; i++) {
296 if (filePaths->paths[i] == nullptr) {
297 continue;
298 }
299 HILOGI("GetFilesByPriority filePaths : %{public}s!", filePaths->paths[i]);
300 std::vector<std::string> files;
301 GetDirFiles(filePaths->paths[i], files);
302 for (const auto& file : files) {
303 HILOGD("GetFilesByPriority file : %{public}s!", file.c_str());
304 fileNamesMap[fs::path(file).filename().string()] = file;
305 }
306 }
307 FreeCfgFiles(filePaths);
308 }
309
GetFilesByPriority(const std::string & path,std::vector<std::string> & fileNames)310 void SamgrUtil::GetFilesByPriority(const std::string& path, std::vector<std::string>& fileNames)
311 {
312 std::map<std::string, std::string> fileNamesMap;
313
314 GetFilesFromPath(path, fileNamesMap);
315
316 if (SamgrUtil::CheckPengLai()) {
317 HILOGI("GetFilesByPriority penglai!");
318 GetFilesFromPath(PENGLAI_PATH, fileNamesMap);
319 }
320
321 for (const auto& pair : fileNamesMap) {
322 HILOGD("GetFilesByPriority files : %{public}s!", pair.second.c_str());
323 fileNames.push_back(pair.second);
324 }
325 }
326 }
327