1 /*
2 * Copyright (c) 2021-2023 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_wrapper.h"
21 #include "nlohmann/json.hpp"
22
23 namespace OHOS {
24 namespace AppExecFwk {
25 namespace {
26 const std::string HSPLIST_BUNDLES = "bundles";
27 const std::string HSPLIST_MODULES = "modules";
28 const std::string HSPLIST_VERSIONS = "versions";
29 const std::string HSPLIST_SOCKET_TYPE = "|HspList|";
30 const std::string OVERLAY_SOCKET_TYPE = "|Overlay|";
31 const std::string DATA_GROUP_SOCKET_TYPE = "|DataGroup|";
32 const std::string DATAGROUPINFOLIST_DATAGROUPID = "dataGroupId";
33 const std::string DATAGROUPINFOLIST_GID = "gid";
34 const std::string DATAGROUPINFOLIST_DIR = "dir";
35 const std::string JSON_DATA_APP = "/data/app/el2/";
36 const std::string JSON_GROUP = "/group/";
37 const std::string VERSION_PREFIX = "v";
38 }
39
~AppSpawnMsgWrapper()40 AppSpawnMsgWrapper::~AppSpawnMsgWrapper()
41 {
42 FreeMsg();
43 }
44
DumpToJson(const HspList & hspList)45 static std::string DumpToJson(const HspList &hspList)
46 {
47 nlohmann::json hspListJson;
48 for (auto& hsp : hspList) {
49 hspListJson[HSPLIST_BUNDLES].emplace_back(hsp.bundleName);
50 hspListJson[HSPLIST_MODULES].emplace_back(hsp.moduleName);
51 hspListJson[HSPLIST_VERSIONS].emplace_back(VERSION_PREFIX + std::to_string(hsp.versionCode));
52 }
53 return hspListJson.dump();
54 }
55
DumpToJson(const DataGroupInfoList & dataGroupInfoList)56 static std::string DumpToJson(const DataGroupInfoList &dataGroupInfoList)
57 {
58 nlohmann::json dataGroupInfoListJson;
59 for (auto& dataGroupInfo : dataGroupInfoList) {
60 dataGroupInfoListJson[DATAGROUPINFOLIST_DATAGROUPID].emplace_back(dataGroupInfo.dataGroupId);
61 dataGroupInfoListJson[DATAGROUPINFOLIST_GID].emplace_back(std::to_string(dataGroupInfo.gid));
62 std::string dir = JSON_DATA_APP + std::to_string(dataGroupInfo.userId)
63 + JSON_GROUP + dataGroupInfo.uuid;
64 dataGroupInfoListJson[DATAGROUPINFOLIST_DIR].emplace_back(dir);
65 }
66 return dataGroupInfoListJson.dump();
67 }
68
AssembleMsg(const AppSpawnStartMsg & startMsg)69 bool AppSpawnMsgWrapper::AssembleMsg(const AppSpawnStartMsg &startMsg)
70 {
71 if (!VerifyMsg(startMsg)) {
72 return false;
73 }
74 FreeMsg();
75 size_t msgSize = sizeof(AppSpawnMsg) + 1;
76 msg_ = static_cast<AppSpawnMsg *>(malloc(msgSize));
77 if (msg_ == nullptr) {
78 HILOG_ERROR("failed to malloc!");
79 return false;
80 }
81 if (memset_s(msg_, msgSize, 0, msgSize) != EOK) {
82 HILOG_ERROR("failed to memset!");
83 return false;
84 }
85 msg_->code = static_cast<AppSpawn::ClientSocket::AppOperateCode>(startMsg.code);
86 if (msg_->code == AppSpawn::ClientSocket::AppOperateCode::DEFAULT ||
87 msg_->code == AppSpawn::ClientSocket::AppOperateCode::SPAWN_NATIVE_PROCESS) {
88 msg_->uid = startMsg.uid;
89 msg_->gid = startMsg.gid;
90 msg_->gidCount = startMsg.gids.size() + startMsg.dataGroupInfoList.size();
91 msg_->bundleIndex = startMsg.bundleIndex;
92 msg_->setAllowInternet = startMsg.setAllowInternet;
93 msg_->allowInternet = startMsg.allowInternet;
94 msg_->mountPermissionFlags = startMsg.mountPermissionFlags;
95 if (strcpy_s(msg_->ownerId, sizeof(msg_->ownerId), startMsg.ownerId.c_str()) != EOK) {
96 HILOG_ERROR("failed to transform ownerId!");
97 return false;
98 }
99 for (uint32_t i = 0; i < startMsg.gids.size(); ++i) {
100 msg_->gidTable[i] = startMsg.gids[i];
101 }
102 for (uint32_t i = startMsg.gids.size(); i < msg_->gidCount; ++i) {
103 msg_->gidTable[i] = startMsg.dataGroupInfoList[i - startMsg.gids.size()].gid;
104 }
105 if (strcpy_s(msg_->processName, sizeof(msg_->processName), startMsg.procName.c_str()) != EOK) {
106 HILOG_ERROR("failed to transform procName!");
107 return false;
108 }
109 if (strcpy_s(msg_->soPath, sizeof(msg_->soPath), startMsg.soPath.c_str()) != EOK) {
110 HILOG_ERROR("failed to transform soPath!");
111 return false;
112 }
113 msg_->accessTokenId = startMsg.accessTokenId;
114 if (strcpy_s(msg_->apl, sizeof(msg_->apl), startMsg.apl.c_str()) != EOK) {
115 HILOG_ERROR("failed to transform apl!");
116 return false;
117 }
118 if (strcpy_s(msg_->bundleName, sizeof(msg_->bundleName), startMsg.bundleName.c_str()) != EOK) {
119 HILOG_ERROR("failed to transform bundleName!");
120 return false;
121 }
122
123 if (strcpy_s(msg_->renderCmd, sizeof(msg_->renderCmd), startMsg.renderParam.c_str()) != EOK) {
124 HILOG_ERROR("failed to transform renderCmd!");
125 return false;
126 }
127 msg_->flags = startMsg.flags;
128 msg_->accessTokenIdEx = startMsg.accessTokenIdEx;
129 msg_->hapFlags = startMsg.hapFlags;
130
131 if (!startMsg.hspList.empty()) {
132 this->extraInfoStr += HSPLIST_SOCKET_TYPE + DumpToJson(startMsg.hspList) +
133 HSPLIST_SOCKET_TYPE;
134 }
135
136 if (!startMsg.dataGroupInfoList.empty()) {
137 this->extraInfoStr += DATA_GROUP_SOCKET_TYPE + DumpToJson(startMsg.dataGroupInfoList) +
138 DATA_GROUP_SOCKET_TYPE;
139 }
140
141 if (!startMsg.overlayInfo.empty()) {
142 this->extraInfoStr += OVERLAY_SOCKET_TYPE + startMsg.overlayInfo +
143 OVERLAY_SOCKET_TYPE;
144 }
145 if (!this->extraInfoStr.empty()) {
146 msg_->extraInfo.totalLength = this->extraInfoStr.size() + 1;
147 }
148 } else if (msg_->code == AppSpawn::ClientSocket::AppOperateCode::GET_RENDER_TERMINATION_STATUS) {
149 msg_->pid = startMsg.pid;
150 } else {
151 HILOG_ERROR("invalid code");
152 return false;
153 }
154
155 isValid_ = true;
156 DumpMsg();
157 return isValid_;
158 }
159
VerifyMsg(const AppSpawnStartMsg & startMsg) const160 bool AppSpawnMsgWrapper::VerifyMsg(const AppSpawnStartMsg &startMsg) const
161 {
162 if (startMsg.code == AppSpawn::ClientSocket::AppOperateCode::DEFAULT ||
163 startMsg.code == AppSpawn::ClientSocket::AppOperateCode::SPAWN_NATIVE_PROCESS) {
164 if (startMsg.uid < 0) {
165 HILOG_ERROR("invalid uid! [%{public}d]", startMsg.uid);
166 return false;
167 }
168
169 if (startMsg.gid < 0) {
170 HILOG_ERROR("invalid gid! [%{public}d]", startMsg.gid);
171 return false;
172 }
173
174 if (startMsg.gids.size() > AppSpawn::ClientSocket::MAX_GIDS) {
175 HILOG_ERROR("too many app gids!");
176 return false;
177 }
178
179 for (uint32_t i = 0; i < startMsg.gids.size(); ++i) {
180 if (startMsg.gids[i] < 0) {
181 HILOG_ERROR("invalid gids array! [%{public}d]", startMsg.gids[i]);
182 return false;
183 }
184 }
185
186 if (startMsg.procName.empty() || startMsg.procName.size() >= AppSpawn::ClientSocket::LEN_PROC_NAME) {
187 HILOG_ERROR("invalid procName!");
188 return false;
189 }
190 } else if (startMsg.code == AppSpawn::ClientSocket::AppOperateCode::GET_RENDER_TERMINATION_STATUS) {
191 if (startMsg.pid < 0) {
192 HILOG_ERROR("invalid pid!");
193 return false;
194 }
195 } else {
196 HILOG_ERROR("invalid code!");
197 return false;
198 }
199
200 return true;
201 }
202
DumpMsg() const203 void AppSpawnMsgWrapper::DumpMsg() const
204 {
205 if (!isValid_) {
206 return;
207 }
208 std::string accessTokenIdExString = std::to_string(msg_->accessTokenIdEx);
209 HILOG_DEBUG("uid: %{public}d, gid: %{public}d, procName: %{public}s, accessTokenIdEx :%{public}s",
210 msg_->uid, msg_->gid, msg_->processName, accessTokenIdExString.c_str());
211 }
212
FreeMsg()213 void AppSpawnMsgWrapper::FreeMsg()
214 {
215 if (msg_ != nullptr) {
216 free(msg_);
217 msg_ = nullptr;
218 isValid_ = false;
219 }
220 }
221 } // namespace AppExecFwk
222 } // namespace OHOS
223