1 /*
2 * Copyright (c) 2021-2025 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 "app_spawn_msg_wrapper.h"
17
18 #include "securec.h"
19
20 #include "hilog_tag_wrapper.h"
21 #include "nlohmann/json.hpp"
22
23 namespace OHOS {
24 namespace AppExecFwk {
25 namespace {
26 constexpr const char* HSPLIST_BUNDLES = "bundles";
27 constexpr const char* HSPLIST_MODULES = "modules";
28 constexpr const char* HSPLIST_VERSIONS = "versions";
29 constexpr const char* HSPLIST_SOCKET_TYPE = "|HspList|";
30 constexpr const char* OVERLAY_SOCKET_TYPE = "|Overlay|";
31 constexpr const char* DATA_GROUP_SOCKET_TYPE = "|DataGroup|";
32 constexpr const char* APP_ENV_TYPE = "|AppEnv|";
33 constexpr const char* DATAGROUPINFOLIST_DATAGROUPID = "dataGroupId";
34 constexpr const char* DATAGROUPINFOLIST_GID = "gid";
35 constexpr const char* DATAGROUPINFOLIST_UUID = "uuid";
36 constexpr const char* DATAGROUPINFOLIST_DIR = "dir";
37 constexpr const char* JSON_DATA_APP_DIR_EL2 = "/data/app/el2/";
38 constexpr const char* JSON_DATA_APP_DIR_EL3 = "/data/app/el3/";
39 constexpr const char* JSON_DATA_APP_DIR_EL4 = "/data/app/el4/";
40 constexpr const char* JSON_DATA_APP_DIR_EL5 = "/data/app/el5/";
41 constexpr const char* JSON_GROUP = "/group/";
42 constexpr const char* VERSION_PREFIX = "v";
43 }
44
~AppSpawnMsgWrapper()45 AppSpawnMsgWrapper::~AppSpawnMsgWrapper()
46 {
47 FreeMsg();
48 }
49
DumpToJson(const HspList & hspList)50 static std::string DumpToJson(const HspList &hspList)
51 {
52 nlohmann::json hspListJson;
53 for (auto& hsp : hspList) {
54 hspListJson[HSPLIST_BUNDLES].emplace_back(hsp.bundleName);
55 hspListJson[HSPLIST_MODULES].emplace_back(hsp.moduleName);
56 hspListJson[HSPLIST_VERSIONS].emplace_back(VERSION_PREFIX + std::to_string(hsp.versionCode));
57 }
58 return hspListJson.dump();
59 }
60
DumpToJson(const DataGroupInfoList & dataGroupInfoList,bool isScreenLockDataProtect)61 static std::string DumpToJson(const DataGroupInfoList &dataGroupInfoList, bool isScreenLockDataProtect)
62 {
63 nlohmann::json dataGroupInfoListJson;
64 for (auto& dataGroupInfo : dataGroupInfoList) {
65 nlohmann::json dataGroupInfoJson;
66 dataGroupInfoJson[DATAGROUPINFOLIST_DATAGROUPID] = dataGroupInfo.dataGroupId;
67 dataGroupInfoJson[DATAGROUPINFOLIST_GID] = std::to_string(dataGroupInfo.gid);
68 dataGroupInfoJson[DATAGROUPINFOLIST_UUID] = dataGroupInfo.uuid;
69 std::string dir = std::to_string(dataGroupInfo.userId) + JSON_GROUP + dataGroupInfo.uuid;
70 dataGroupInfoJson[DATAGROUPINFOLIST_DIR] = JSON_DATA_APP_DIR_EL2 + dir;
71 dataGroupInfoListJson.emplace_back(dataGroupInfoJson);
72
73 dataGroupInfoJson[DATAGROUPINFOLIST_DIR] = JSON_DATA_APP_DIR_EL3 + dir;
74 dataGroupInfoListJson.emplace_back(dataGroupInfoJson);
75
76 dataGroupInfoJson[DATAGROUPINFOLIST_DIR] = JSON_DATA_APP_DIR_EL4 + dir;
77 dataGroupInfoListJson.emplace_back(dataGroupInfoJson);
78 if (isScreenLockDataProtect) {
79 dataGroupInfoJson[DATAGROUPINFOLIST_DIR] = JSON_DATA_APP_DIR_EL5 + dir;
80 dataGroupInfoListJson.emplace_back(dataGroupInfoJson);
81 }
82 }
83 TAG_LOGD(AAFwkTag::APPMGR, "dataGroupInfoListJson %{public}s", dataGroupInfoListJson.dump().c_str());
84 return dataGroupInfoListJson.dump();
85 }
86
DumpAppEnvToJson(const std::map<std::string,std::string> & appEnv)87 static std::string DumpAppEnvToJson(const std::map<std::string, std::string> &appEnv)
88 {
89 nlohmann::json appEnvJson;
90 for (const auto &[envName, envValue] : appEnv) {
91 appEnvJson[envName] = envValue;
92 }
93 return appEnvJson.dump();
94 }
95
AssembleMsg(const AppSpawnStartMsg & startMsg)96 bool AppSpawnMsgWrapper::AssembleMsg(const AppSpawnStartMsg &startMsg)
97 {
98 if (!VerifyMsg(startMsg)) {
99 return false;
100 }
101 FreeMsg();
102 size_t msgSize = sizeof(AppSpawnMsg) + 1;
103 msg_ = static_cast<AppSpawnMsg *>(malloc(msgSize));
104 if (msg_ == nullptr) {
105 TAG_LOGE(AAFwkTag::APPMGR, "malloc fail");
106 return false;
107 }
108 if (memset_s(msg_, msgSize, 0, msgSize) != EOK) {
109 TAG_LOGE(AAFwkTag::APPMGR, "memset fail");
110 return false;
111 }
112 msg_->code = static_cast<AppSpawn::ClientSocket::AppOperateCode>(startMsg.code);
113 if (msg_->code == AppSpawn::ClientSocket::AppOperateCode::DEFAULT ||
114 msg_->code == AppSpawn::ClientSocket::AppOperateCode::SPAWN_NATIVE_PROCESS) {
115 msg_->uid = startMsg.uid;
116 msg_->gid = startMsg.gid;
117 msg_->gidCount = startMsg.gids.size() + startMsg.dataGroupInfoList.size();
118 msg_->bundleIndex = startMsg.bundleIndex;
119 msg_->setAllowInternet = startMsg.setAllowInternet;
120 msg_->allowInternet = startMsg.allowInternet;
121 msg_->mountPermissionFlags = startMsg.mountPermissionFlags;
122 if (strcpy_s(msg_->ownerId, sizeof(msg_->ownerId), startMsg.ownerId.c_str()) != EOK) {
123 TAG_LOGE(AAFwkTag::APPMGR, "transform ownerId fail");
124 return false;
125 }
126 for (uint32_t i = 0; i < startMsg.gids.size(); ++i) {
127 msg_->gidTable[i] = startMsg.gids[i];
128 }
129 for (uint32_t i = startMsg.gids.size(); i < msg_->gidCount; ++i) {
130 msg_->gidTable[i] = startMsg.dataGroupInfoList[i - startMsg.gids.size()].gid;
131 }
132 if (strcpy_s(msg_->processName, sizeof(msg_->processName), startMsg.procName.c_str()) != EOK) {
133 TAG_LOGE(AAFwkTag::APPMGR, "transform procName fail");
134 return false;
135 }
136 if (strcpy_s(msg_->soPath, sizeof(msg_->soPath), startMsg.soPath.c_str()) != EOK) {
137 TAG_LOGE(AAFwkTag::APPMGR, "transform soPath fail");
138 return false;
139 }
140 msg_->accessTokenId = startMsg.accessTokenId;
141 if (strcpy_s(msg_->apl, sizeof(msg_->apl), startMsg.apl.c_str()) != EOK) {
142 TAG_LOGE(AAFwkTag::APPMGR, "transform apl fail");
143 return false;
144 }
145 if (strcpy_s(msg_->bundleName, sizeof(msg_->bundleName), startMsg.bundleName.c_str()) != EOK) {
146 TAG_LOGE(AAFwkTag::APPMGR, "transform bundleName fail");
147 return false;
148 }
149
150 if (strcpy_s(msg_->renderCmd, sizeof(msg_->renderCmd), startMsg.renderParam.c_str()) != EOK) {
151 TAG_LOGE(AAFwkTag::APPMGR, "transform renderCmd fail");
152 return false;
153 }
154 msg_->flags = startMsg.flags;
155 msg_->accessTokenIdEx = startMsg.accessTokenIdEx;
156 msg_->hapFlags = startMsg.hapFlags;
157
158 BuildExtraInfo(startMsg);
159 } else if (msg_->code == AppSpawn::ClientSocket::AppOperateCode::GET_RENDER_TERMINATION_STATUS) {
160 msg_->pid = startMsg.pid;
161 } else {
162 TAG_LOGE(AAFwkTag::APPMGR, "invalid code");
163 return false;
164 }
165
166 isValid_ = true;
167 DumpMsg();
168 return isValid_;
169 }
170
BuildExtraInfo(const AppSpawnStartMsg & startMsg)171 void AppSpawnMsgWrapper::BuildExtraInfo(const AppSpawnStartMsg &startMsg)
172 {
173 if (!startMsg.hspList.empty()) {
174 extraInfoStr_ += HSPLIST_SOCKET_TYPE + DumpToJson(startMsg.hspList) +
175 HSPLIST_SOCKET_TYPE;
176 }
177
178 if (!startMsg.dataGroupInfoList.empty()) {
179 extraInfoStr_ += DATA_GROUP_SOCKET_TYPE +
180 DumpToJson(startMsg.dataGroupInfoList, startMsg.isScreenLockDataProtect) + DATA_GROUP_SOCKET_TYPE;
181 }
182
183 if (!startMsg.overlayInfo.empty()) {
184 extraInfoStr_ += OVERLAY_SOCKET_TYPE + startMsg.overlayInfo +
185 OVERLAY_SOCKET_TYPE;
186 }
187
188 if (!startMsg.appEnv.empty()) {
189 auto appEnvStr = DumpAppEnvToJson(startMsg.appEnv);
190 TAG_LOGD(AAFwkTag::APPMGR, "AppEnv: %{public}s", appEnvStr.c_str());
191 extraInfoStr_ += APP_ENV_TYPE + appEnvStr + APP_ENV_TYPE;
192 }
193
194 if (!extraInfoStr_.empty()) {
195 msg_->extraInfo.totalLength = extraInfoStr_.size() + 1;
196 }
197 }
198
VerifyMsg(const AppSpawnStartMsg & startMsg) const199 bool AppSpawnMsgWrapper::VerifyMsg(const AppSpawnStartMsg &startMsg) const
200 {
201 if (startMsg.code == AppSpawn::ClientSocket::AppOperateCode::DEFAULT ||
202 startMsg.code == AppSpawn::ClientSocket::AppOperateCode::SPAWN_NATIVE_PROCESS) {
203 if (startMsg.uid < 0) {
204 TAG_LOGE(AAFwkTag::APPMGR, "invalid uid! [%{public}d]", startMsg.uid);
205 return false;
206 }
207
208 if (startMsg.gid < 0) {
209 TAG_LOGE(AAFwkTag::APPMGR, "invalid gid! [%{public}d]", startMsg.gid);
210 return false;
211 }
212
213 if (startMsg.gids.size() > AppSpawn::ClientSocket::MAX_GIDS) {
214 TAG_LOGE(AAFwkTag::APPMGR, "many app gids");
215 return false;
216 }
217
218 for (uint32_t i = 0; i < startMsg.gids.size(); ++i) {
219 if (startMsg.gids[i] < 0) {
220 TAG_LOGE(AAFwkTag::APPMGR, "invalid gids array! [%{public}d]", startMsg.gids[i]);
221 return false;
222 }
223 }
224
225 if (startMsg.procName.empty() || startMsg.procName.size() >= AppSpawn::ClientSocket::LEN_PROC_NAME) {
226 TAG_LOGE(AAFwkTag::APPMGR, "invalid procName");
227 return false;
228 }
229 } else if (startMsg.code == AppSpawn::ClientSocket::AppOperateCode::GET_RENDER_TERMINATION_STATUS) {
230 if (startMsg.pid < 0) {
231 TAG_LOGE(AAFwkTag::APPMGR, "invalid pid");
232 return false;
233 }
234 } else {
235 TAG_LOGE(AAFwkTag::APPMGR, "invalid code");
236 return false;
237 }
238
239 return true;
240 }
241
DumpMsg() const242 void AppSpawnMsgWrapper::DumpMsg() const
243 {
244 if (!isValid_) {
245 return;
246 }
247 std::string accessTokenIdExString = std::to_string(msg_->accessTokenIdEx);
248 TAG_LOGD(AAFwkTag::APPMGR, "uid: %{public}d, gid: %{public}d, procName: %{public}s, accessTokenIdEx :%{public}s",
249 msg_->uid, msg_->gid, msg_->processName, accessTokenIdExString.c_str());
250 }
251
FreeMsg()252 void AppSpawnMsgWrapper::FreeMsg()
253 {
254 if (msg_ != nullptr) {
255 free(msg_);
256 msg_ = nullptr;
257 isValid_ = false;
258 }
259 }
260 } // namespace AppExecFwk
261 } // namespace OHOS
262