• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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