1 /*
2 * Copyright (C) 2024-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 "sandbox_utils.h"
17
18 #include <cerrno>
19 #include <cstddef>
20 #include <fcntl.h>
21 #include <fstream>
22 #include <sstream>
23 #include <cerrno>
24 #include <vector>
25 #include <unistd.h>
26 #include <sys/mount.h>
27 #include <sys/stat.h>
28 #include <sys/syscall.h>
29 #include <sys/types.h>
30
31 #include "appspawn_hook.h"
32 #include "appspawn_mount_permission.h"
33 #include "appspawn_msg.h"
34 #include "appspawn_server.h"
35 #include "appspawn_service.h"
36 #include "appspawn_utils.h"
37 #include "config_policy_utils.h"
38 #include "sandbox_shared_mount.h"
39 #ifdef WITH_DLP
40 #include "dlp_fuse_fd.h"
41 #endif
42 #include "init_param.h"
43 #include "init_utils.h"
44 #include "parameter.h"
45 #include "parameters.h"
46 #include "securec.h"
47 #include "appspawn_trace.h"
48 #ifdef APPSPAWN_HISYSEVENT
49 #include "hisysevent_adapter.h"
50 #endif
51
52 #ifdef WITH_SELINUX
53 #include "hap_restorecon.h"
54 #endif
55
56 #define MAX_MOUNT_TIME 500 // 500us
57 #define LOCK_STATUS_SIZE 16
58
59 using namespace std;
60 using namespace OHOS;
61
62 namespace OHOS {
63 namespace AppSpawn {
64 namespace {
65 constexpr int32_t OPTIONS_MAX_LEN = 256;
66 constexpr int32_t FILE_ACCESS_COMMON_DIR_STATUS = 0;
67 constexpr int32_t FILE_CROSS_APP_STATUS = 1;
68 constexpr static mode_t FILE_MODE = 0711;
69 constexpr static mode_t BASIC_MOUNT_FLAGS = MS_REC | MS_BIND;
70 constexpr std::string_view APL_SYSTEM_CORE("system_core");
71 constexpr std::string_view APL_SYSTEM_BASIC("system_basic");
72 const std::string APP_JSON_CONFIG("/appdata-sandbox.json");
73 const std::string APP_ISOLATED_JSON_CONFIG("/appdata-sandbox-isolated.json");
74 const std::string g_physicalAppInstallPath = "/data/app/el1/bundle/public/";
75 const std::string g_sandboxGroupPath = "/data/storage/el2/group/";
76 const std::string g_sandboxHspInstallPath = "/data/storage/el1/bundle/";
77 const std::string g_sandBoxAppInstallPath = "/data/accounts/account_0/applications/";
78 const std::string g_bundleResourceSrcPath = "/data/service/el1/public/bms/bundle_resources/";
79 const std::string g_bundleResourceDestPath = "/data/storage/bundle_resources/";
80 const std::string g_dataBundles = "/data/bundles/";
81 const std::string g_userId = "<currentUserId>";
82 const std::string g_packageName = "<PackageName>";
83 const std::string g_packageNameIndex = "<PackageName_index>";
84 const std::string g_variablePackageName = "<variablePackageName>";
85 const std::string g_arkWebPackageName = "<arkWebPackageName>";
86 const std::string g_sandBoxDir = "/mnt/sandbox/";
87 const std::string g_statusCheck = "true";
88 const std::string g_sbxSwitchCheck = "ON";
89 const std::string g_dlpBundleName = "com.ohos.dlpmanager";
90 const std::string g_internal = "__internal__";
91 const std::string g_hspList_key_bundles = "bundles";
92 const std::string g_hspList_key_modules = "modules";
93 const std::string g_hspList_key_versions = "versions";
94 const std::string g_overlayPath = "/data/storage/overlay/";
95 const std::string g_groupList_key_dataGroupId = "dataGroupId";
96 const std::string g_groupList_key_gid = "gid";
97 const std::string g_groupList_key_dir = "dir";
98 const std::string g_groupList_key_uuid = "uuid";
99 const std::string HSPLIST_SOCKET_TYPE = "HspList";
100 const std::string OVERLAY_SOCKET_TYPE = "Overlay";
101 const std::string DATA_GROUP_SOCKET_TYPE = "DataGroup";
102 const char *g_actionStatuc = "check-action-status";
103 const char *g_appBase = "app-base";
104 const char *g_appResources = "app-resources";
105 const char *g_appAplName = "app-apl-name";
106 const char *g_commonPrefix = "common";
107 const char *g_destMode = "dest-mode";
108 const char *g_fsType = "fs-type";
109 const char *g_linkName = "link-name";
110 const char *g_mountPrefix = "mount-paths";
111 const char *g_gidPrefix = "gids";
112 const char *g_privatePrefix = "individual";
113 const char *g_permissionPrefix = "permission";
114 const char *g_srcPath = "src-path";
115 const char *g_sandBoxPath = "sandbox-path";
116 const char *g_sandBoxFlags = "sandbox-flags";
117 const char *g_sandBoxFlagsCustomized = "sandbox-flags-customized";
118 const char *g_sandBoxOptions = "options";
119 const char *g_dacOverrideSensitive = "dac-override-sensitive";
120 const char *g_sandBoxShared = "sandbox-shared";
121 const char *g_sandBoxSwitchPrefix = "sandbox-switch";
122 const char *g_symlinkPrefix = "symbol-links";
123 const char *g_sandboxRootPrefix = "sandbox-root";
124 const char *g_topSandBoxSwitchPrefix = "top-sandbox-switch";
125 const char *g_targetName = "target-name";
126 const char *g_flagePoint = "flags-point";
127 const char *g_mountSharedFlag = "mount-shared-flag";
128 const char *g_flags = "flags";
129 const char *g_sandBoxNsFlags = "sandbox-ns-flags";
130 const char* g_fileSeparator = "/";
131 const char* g_overlayDecollator = "|";
132 const std::string g_sandBoxRootDir = "/mnt/sandbox/";
133 const std::string g_ohosRender = "__internal__.com.ohos.render";
134 const std::string g_sandBoxRootDirNweb = "/mnt/sandbox/com.ohos.render/";
135 const std::string FILE_CROSS_APP_MODE = "ohos.permission.FILE_CROSS_APP";
136 const std::string FILE_ACCESS_COMMON_DIR_MODE = "ohos.permission.FILE_ACCESS_COMMON_DIR";
137 const std::string ACCESS_DLP_FILE_MODE = "ohos.permission.ACCESS_DLP_FILE";
138 const std::string FILE_ACCESS_MANAGER_MODE = "ohos.permission.FILE_ACCESS_MANAGER";
139 const std::string ARK_WEB_PERSIST_PACKAGE_NAME = "persist.arkwebcore.package_name";
140
getArkWebPackageName()141 const std::string& getArkWebPackageName()
142 {
143 static std::string arkWebPackageName;
144 if (arkWebPackageName.empty()) {
145 arkWebPackageName = system::GetParameter(ARK_WEB_PERSIST_PACKAGE_NAME, "");
146 }
147 return arkWebPackageName;
148 }
149 }
150
GetAppMsgFlags(const AppSpawningCtx * property)151 static uint32_t GetAppMsgFlags(const AppSpawningCtx *property)
152 {
153 APPSPAWN_CHECK(property != nullptr && property->message != nullptr,
154 return 0, "Invalid property for name %{public}u", TLV_MSG_FLAGS);
155 AppSpawnMsgFlags *msgFlags = (AppSpawnMsgFlags *)GetAppSpawnMsgInfo(property->message, TLV_MSG_FLAGS);
156 APPSPAWN_CHECK(msgFlags != nullptr,
157 return 0, "No TLV_MSG_FLAGS in msg %{public}s", property->message->msgHeader.processName);
158 return msgFlags->flags[0];
159 }
160
GetJsonObjFromJson(nlohmann::json & jsonObj,const std::string & jsonPath)161 bool JsonUtils::GetJsonObjFromJson(nlohmann::json &jsonObj, const std::string &jsonPath)
162 {
163 APPSPAWN_CHECK(jsonPath.length() <= PATH_MAX, return false, "jsonPath is too long");
164 std::ifstream jsonFileStream;
165 jsonFileStream.open(jsonPath.c_str(), std::ios::in);
166 APPSPAWN_CHECK_ONLY_EXPER(jsonFileStream.is_open(), return false);
167 std::ostringstream buf;
168 char ch;
169 while (buf && jsonFileStream.get(ch)) {
170 buf.put(ch);
171 }
172 jsonFileStream.close();
173 jsonObj = nlohmann::json::parse(buf.str(), nullptr, false);
174 APPSPAWN_CHECK(!jsonObj.is_discarded() && jsonObj.is_structured(), return false, "Parse json file failed");
175 return true;
176 }
177
GetStringFromJson(const nlohmann::json & json,const std::string & key,std::string & value)178 bool JsonUtils::GetStringFromJson(const nlohmann::json &json, const std::string &key, std::string &value)
179 {
180 APPSPAWN_CHECK(json.is_object(), return false, "json is not object.");
181 bool isRet = json.find(key) != json.end() && json.at(key).is_string();
182 if (isRet) {
183 value = json.at(key).get<std::string>();
184 APPSPAWN_LOGV("Find key[%{public}s] : %{public}s successful.", key.c_str(), value.c_str());
185 return true;
186 } else {
187 return false;
188 }
189 }
190
191 std::map<SandboxConfigType, std::vector<nlohmann::json>> SandboxUtils::appSandboxConfig_ = {};
192 int32_t SandboxUtils::deviceTypeEnable_ = -1;
193
StoreJsonConfig(nlohmann::json & appSandboxConfig,SandboxConfigType type)194 void SandboxUtils::StoreJsonConfig(nlohmann::json &appSandboxConfig, SandboxConfigType type)
195 {
196 SandboxUtils::appSandboxConfig_[type].push_back(appSandboxConfig);
197 }
198
GetJsonConfig(SandboxConfigType type)199 std::vector<nlohmann::json> &SandboxUtils::GetJsonConfig(SandboxConfigType type)
200 {
201 return SandboxUtils::appSandboxConfig_[type];
202 }
203
MakeDirRecursive(const std::string & path,mode_t mode)204 static void MakeDirRecursive(const std::string &path, mode_t mode)
205 {
206 size_t size = path.size();
207 if (size == 0) {
208 return;
209 }
210
211 size_t index = 0;
212 do {
213 size_t pathIndex = path.find_first_of('/', index);
214 index = pathIndex == std::string::npos ? size : pathIndex + 1;
215 std::string dir = path.substr(0, index);
216 #ifndef APPSPAWN_TEST
217 APPSPAWN_CHECK(!(access(dir.c_str(), F_OK) < 0 && mkdir(dir.c_str(), mode) < 0),
218 return, "errno is %{public}d, mkdir %{public}s failed", errno, dir.c_str());
219 #endif
220 } while (index < size);
221 }
222
MakeDirRecursiveWithClock(const std::string & path,mode_t mode)223 static void MakeDirRecursiveWithClock(const std::string &path, mode_t mode)
224 {
225 size_t size = path.size();
226 if (size == 0) {
227 return;
228 }
229 #ifdef APPSPAWN_HISYSEVENT
230 struct timespec startClock = {0};
231 clock_gettime(CLOCK_MONOTONIC, &startClock);
232 #endif
233 size_t index = 0;
234 do {
235 size_t pathIndex = path.find_first_of('/', index);
236 index = pathIndex == std::string::npos ? size : pathIndex + 1;
237 std::string dir = path.substr(0, index);
238 #ifndef APPSPAWN_TEST
239 APPSPAWN_CHECK(!(access(dir.c_str(), F_OK) < 0 && mkdir(dir.c_str(), mode) < 0),
240 return, "errno is %{public}d, mkdir %{public}s failed", errno, dir.c_str());
241 #endif
242 } while (index < size);
243
244 #ifdef APPSPAWN_HISYSEVENT
245 struct timespec endClock = {0};
246 clock_gettime(CLOCK_MONOTONIC, &endClock);
247 uint64_t diff = DiffTime(&startClock, &endClock);
248
249 APPSPAWN_CHECK_ONLY_EXPER(diff < FUNC_REPORT_DURATION,
250 ReportAbnormalDuration("MakeDirRecursive", diff));
251 #endif
252 }
253
CheckDirRecursive(const std::string & path)254 static bool CheckDirRecursive(const std::string &path)
255 {
256 size_t size = path.size();
257 if (size == 0) {
258 return false;
259 }
260 size_t index = 0;
261 do {
262 size_t pathIndex = path.find_first_of('/', index);
263 index = pathIndex == std::string::npos ? size : pathIndex + 1;
264 std::string dir = path.substr(0, index);
265 #ifndef APPSPAWN_TEST
266 APPSPAWN_CHECK(access(dir.c_str(), F_OK) == 0,
267 return false, "check dir %{public}s failed, strerror: %{public}s", dir.c_str(), strerror(errno));
268 #endif
269 } while (index < size);
270 return true;
271 }
272
CheckAndCreatFile(const char * file)273 static void CheckAndCreatFile(const char *file)
274 {
275 if (access(file, F_OK) == 0) {
276 APPSPAWN_LOGI("file %{public}s already exist", file);
277 return;
278 }
279 std::string path = file;
280 auto pos = path.find_last_of('/');
281 APPSPAWN_CHECK(pos != std::string::npos, return, "file %{public}s error", file);
282 std::string dir = path.substr(0, pos);
283 MakeDirRecursive(dir, FILE_MODE);
284 int fd = open(file, O_CREAT, FILE_MODE);
285 if (fd < 0) {
286 APPSPAWN_LOGW("failed create %{public}s, err=%{public}d", file, errno);
287 } else {
288 close(fd);
289 }
290 return;
291 }
292
DoAppSandboxMountOnce(const char * originPath,const char * destinationPath,const char * fsType,unsigned long mountFlags,const char * options,mode_t mountSharedFlag)293 int32_t SandboxUtils::DoAppSandboxMountOnce(const char *originPath, const char *destinationPath,
294 const char *fsType, unsigned long mountFlags,
295 const char *options, mode_t mountSharedFlag)
296 {
297 if (originPath == nullptr || destinationPath == nullptr || originPath[0] == '\0' || destinationPath[0] == '\0') {
298 return 0;
299 }
300 if (strstr(originPath, "system/etc/hosts") != nullptr) {
301 CheckAndCreatFile(destinationPath);
302 } else {
303 MakeDirRecursive(destinationPath, FILE_MODE);
304 }
305
306 int ret = 0;
307 // to mount fs and bind mount files or directory
308 struct timespec mountStart = {0};
309 clock_gettime(CLOCK_MONOTONIC, &mountStart);
310 APPSPAWN_LOGV("Bind mount %{public}s to %{public}s '%{public}s' '%{public}lu' '%{public}s' '%{public}u'",
311 originPath, destinationPath, fsType, mountFlags, options, mountSharedFlag);
312 ret = mount(originPath, destinationPath, fsType, mountFlags, options);
313 struct timespec mountEnd = {0};
314 clock_gettime(CLOCK_MONOTONIC, &mountEnd);
315 uint64_t diff = DiffTime(&mountStart, &mountEnd);
316 APPSPAWN_CHECK_ONLY_LOG(diff < MAX_MOUNT_TIME, "mount %{public}s time %{public}" PRId64 " us", originPath, diff);
317 #ifdef APPSPAWN_HISYSEVENT
318 APPSPAWN_CHECK_ONLY_EXPER(diff < FUNC_REPORT_DURATION, ReportAbnormalDuration("MOUNT", diff));
319 #endif
320 if (ret != 0) {
321 APPSPAWN_LOGI("errno is: %{public}d, bind mount %{public}s to %{public}s", errno, originPath, destinationPath);
322 std::string originPathStr = originPath == nullptr ? "" : originPath;
323 if (originPathStr.find("data/app/el1/") != std::string::npos ||
324 originPathStr.find("data/app/el2/") != std::string::npos) {
325 CheckDirRecursive(originPathStr);
326 }
327 return ret;
328 }
329
330 ret = mount(nullptr, destinationPath, nullptr, mountSharedFlag, nullptr);
331 APPSPAWN_CHECK(ret == 0, return ret, "errno is: %{public}d, private mount to %{public}s '%{public}u' failed",
332 errno, destinationPath, mountSharedFlag);
333 return 0;
334 }
335
replace_all(std::string & str,const std::string & old_value,const std::string & new_value)336 static std::string& replace_all(std::string& str, const std::string& old_value, const std::string& new_value)
337 {
338 while (true) {
339 std::string::size_type pos(0);
340 if ((pos = str.find(old_value)) != std::string::npos) {
341 str.replace(pos, old_value.length(), new_value);
342 } else {
343 break;
344 }
345 }
346 return str;
347 }
348
split(std::string & str,const std::string & pattern)349 static std::vector<std::string> split(std::string &str, const std::string &pattern)
350 {
351 std::string::size_type pos;
352 std::vector<std::string> result;
353 str += pattern;
354 size_t size = str.size();
355
356 for (unsigned int i = 0; i < size; i++) {
357 pos = str.find(pattern, i);
358 if (pos < size) {
359 std::string s = str.substr(i, pos - i);
360 result.push_back(s);
361 i = pos + pattern.size() - 1;
362 }
363 }
364
365 return result;
366 }
367
DoSandboxChmod(nlohmann::json jsonConfig,std::string & sandboxRoot)368 void SandboxUtils::DoSandboxChmod(nlohmann::json jsonConfig, std::string &sandboxRoot)
369 {
370 const std::map<std::string, mode_t> modeMap = {{"S_IRUSR", S_IRUSR}, {"S_IWUSR", S_IWUSR}, {"S_IXUSR", S_IXUSR},
371 {"S_IRGRP", S_IRGRP}, {"S_IWGRP", S_IWGRP}, {"S_IXGRP", S_IXGRP},
372 {"S_IROTH", S_IROTH}, {"S_IWOTH", S_IWOTH}, {"S_IXOTH", S_IXOTH},
373 {"S_IRWXU", S_IRWXU}, {"S_IRWXG", S_IRWXG}, {"S_IRWXO", S_IRWXO}};
374 std::string fileModeStr;
375 mode_t mode = 0;
376
377 bool rc = JsonUtils::GetStringFromJson(jsonConfig, g_destMode, fileModeStr);
378 if (rc == false) {
379 return;
380 }
381
382 std::vector<std::string> modeVec = split(fileModeStr, "|");
383 for (unsigned int i = 0; i < modeVec.size(); i++) {
384 if (modeMap.count(modeVec[i])) {
385 mode |= modeMap.at(modeVec[i]);
386 }
387 }
388
389 chmod(sandboxRoot.c_str(), mode);
390 }
391
GetMountFlagsFromConfig(const std::vector<std::string> & vec)392 unsigned long SandboxUtils::GetMountFlagsFromConfig(const std::vector<std::string> &vec)
393 {
394 const std::map<std::string, mode_t> MountFlagsMap = { {"rec", MS_REC}, {"MS_REC", MS_REC},
395 {"bind", MS_BIND}, {"MS_BIND", MS_BIND},
396 {"move", MS_MOVE}, {"MS_MOVE", MS_MOVE},
397 {"slave", MS_SLAVE}, {"MS_SLAVE", MS_SLAVE},
398 {"rdonly", MS_RDONLY}, {"MS_RDONLY", MS_RDONLY},
399 {"shared", MS_SHARED}, {"MS_SHARED", MS_SHARED},
400 {"unbindable", MS_UNBINDABLE},
401 {"MS_UNBINDABLE", MS_UNBINDABLE},
402 {"remount", MS_REMOUNT}, {"MS_REMOUNT", MS_REMOUNT},
403 {"nosuid", MS_NOSUID}, {"MS_NOSUID", MS_NOSUID},
404 {"nodev", MS_NODEV}, {"MS_NODEV", MS_NODEV},
405 {"noexec", MS_NOEXEC}, {"MS_NOEXEC", MS_NOEXEC},
406 {"noatime", MS_NOATIME}, {"MS_NOATIME", MS_NOATIME},
407 {"lazytime", MS_LAZYTIME}, {"MS_LAZYTIME", MS_LAZYTIME}};
408 unsigned long mountFlags = 0;
409
410 for (unsigned int i = 0; i < vec.size(); i++) {
411 if (MountFlagsMap.count(vec[i])) {
412 mountFlags |= MountFlagsMap.at(vec[i]);
413 }
414 }
415
416 return mountFlags;
417 }
418
MakeAtomicServiceDir(const AppSpawningCtx * appProperty,std::string path,std::string variablePackageName)419 static void MakeAtomicServiceDir(const AppSpawningCtx *appProperty, std::string path, std::string variablePackageName)
420 {
421 AppSpawnMsgDacInfo *dacInfo = reinterpret_cast<AppSpawnMsgDacInfo *>(GetAppProperty(appProperty, TLV_DAC_INFO));
422 APPSPAWN_CHECK(dacInfo != NULL, return, "No dac info in msg app property");
423 if (path.find("/mnt/share") != std::string::npos) {
424 path = "/data/service/el2/" + std::to_string(dacInfo->uid / UID_BASE) + "/share/" + variablePackageName;
425 }
426 struct stat st = {};
427 if (stat(path.c_str(), &st) == 0 && S_ISDIR(st.st_mode)) {
428 return;
429 }
430
431 int ret = mkdir(path.c_str(), S_IRWXU);
432 APPSPAWN_CHECK(ret == 0, return, "mkdir %{public}s failed, errno %{public}d", path.c_str(), errno);
433
434 if (path.find("/database") != std::string::npos || path.find("/data/service/el2") != std::string::npos) {
435 ret = chmod(path.c_str(), S_IRWXU | S_IRWXG | S_ISGID);
436 } else if (path.find("/log") != std::string::npos) {
437 ret = chmod(path.c_str(), S_IRWXU | S_IRWXG);
438 }
439 APPSPAWN_CHECK(ret == 0, return, "chmod %{public}s failed, errno %{public}d", path.c_str(), errno);
440
441 #ifdef WITH_SELINUX
442 AppSpawnMsgDomainInfo *msgDomainInfo =
443 reinterpret_cast<AppSpawnMsgDomainInfo *>(GetAppProperty(appProperty, TLV_DOMAIN_INFO));
444 APPSPAWN_CHECK(msgDomainInfo != NULL, return, "No domain info for %{public}s", GetProcessName(appProperty));
445 HapContext hapContext;
446 HapFileInfo hapFileInfo;
447 hapFileInfo.pathNameOrig.push_back(path);
448 hapFileInfo.apl = msgDomainInfo->apl;
449 hapFileInfo.packageName = GetBundleName(appProperty);
450 hapFileInfo.hapFlags = msgDomainInfo->hapFlags;
451 if (CheckAppMsgFlagsSet(appProperty, APP_FLAGS_DEBUGGABLE)) {
452 hapFileInfo.hapFlags |= SELINUX_HAP_DEBUGGABLE;
453 }
454 if ((path.find("/base") != std::string::npos) || (path.find("/database") != std::string::npos)) {
455 ret = hapContext.HapFileRestorecon(hapFileInfo);
456 APPSPAWN_CHECK(ret == 0, return, "set dir %{public}s selinuxLabel failed, apl %{public}s, ret %{public}d",
457 path.c_str(), hapFileInfo.apl.c_str(), ret);
458 }
459 #endif
460 if (path.find("/base") != std::string::npos || path.find("/data/service/el2") != std::string::npos) {
461 ret = chown(path.c_str(), dacInfo->uid, dacInfo->gid);
462 } else if (path.find("/database") != std::string::npos) {
463 ret = chown(path.c_str(), dacInfo->uid, DecodeGid("ddms"));
464 } else if (path.find("/log") != std::string::npos) {
465 ret = chown(path.c_str(), dacInfo->uid, DecodeGid("log"));
466 }
467 APPSPAWN_CHECK(ret == 0, return, "chown %{public}s failed, errno %{public}d", path.c_str(), errno);
468 return;
469 }
470
ReplaceVariablePackageName(const AppSpawningCtx * appProperty,const std::string & path)471 static std::string ReplaceVariablePackageName(const AppSpawningCtx *appProperty, const std::string &path)
472 {
473 std::string tmpSandboxPath = path;
474 AppSpawnMsgBundleInfo *bundleInfo =
475 reinterpret_cast<AppSpawnMsgBundleInfo *>(GetAppProperty(appProperty, TLV_BUNDLE_INFO));
476 APPSPAWN_CHECK(bundleInfo != NULL, return "", "No bundle info in msg %{public}s", GetBundleName(appProperty));
477
478 char *extension;
479 uint32_t flags = CheckAppSpawnMsgFlag(appProperty->message, TLV_MSG_FLAGS, APP_FLAGS_ATOMIC_SERVICE) ? 0x4 : 0;
480 if (flags == 0) {
481 flags = (CheckAppSpawnMsgFlag(appProperty->message, TLV_MSG_FLAGS, APP_FLAGS_CLONE_ENABLE) &&
482 bundleInfo->bundleIndex > 0) ? 0x1 : 0;
483 flags |= CheckAppSpawnMsgFlag(appProperty->message, TLV_MSG_FLAGS, APP_FLAGS_EXTENSION_SANDBOX) ? 0x2 : 0;
484 extension = reinterpret_cast<char *>(
485 GetAppSpawnMsgExtInfo(appProperty->message, MSG_EXT_NAME_APP_EXTENSION, NULL));
486 }
487 std::ostringstream variablePackageName;
488 switch (flags) {
489 case 0: // 0 default
490 variablePackageName << bundleInfo->bundleName;
491 break;
492 case 1: // 1 +clone-bundleIndex+packageName
493 variablePackageName << "+clone-" << bundleInfo->bundleIndex << "+" << bundleInfo->bundleName;
494 break;
495 case 2: { // 2 +extension-<extensionType>+packageName
496 APPSPAWN_CHECK(extension != NULL, return "", "Invalid extension data ");
497 variablePackageName << "+extension-" << extension << "+" << bundleInfo->bundleName;
498 break;
499 }
500 case 3: { // 3 +clone-bundleIndex+extension-<extensionType>+packageName
501 APPSPAWN_CHECK(extension != NULL, return "", "Invalid extension data ");
502 variablePackageName << "+clone-" << bundleInfo->bundleIndex << "+extension" << "-" <<
503 extension << "+" << bundleInfo->bundleName;
504 break;
505 }
506 case 4: { // 4 +auid-<accountId>+packageName
507 std::string accountId = SandboxUtils::GetExtraInfoByType(appProperty, MSG_EXT_NAME_ACCOUNT_ID);
508 variablePackageName << "+auid-" << accountId << "+" << bundleInfo->bundleName;
509 std::string atomicServicePath = path;
510 atomicServicePath = replace_all(atomicServicePath, g_variablePackageName, variablePackageName.str());
511 MakeAtomicServiceDir(appProperty, atomicServicePath, variablePackageName.str());
512 break;
513 }
514 default:
515 variablePackageName << bundleInfo->bundleName;
516 break;
517 }
518 tmpSandboxPath = replace_all(tmpSandboxPath, g_variablePackageName, variablePackageName.str());
519 APPSPAWN_LOGV("tmpSandboxPath %{public}s", tmpSandboxPath.c_str());
520 return tmpSandboxPath;
521 }
522
ConvertToRealPath(const AppSpawningCtx * appProperty,std::string path)523 string SandboxUtils::ConvertToRealPath(const AppSpawningCtx *appProperty, std::string path)
524 {
525 AppSpawnMsgBundleInfo *info =
526 reinterpret_cast<AppSpawnMsgBundleInfo *>(GetAppProperty(appProperty, TLV_BUNDLE_INFO));
527 AppSpawnMsgDacInfo *dacInfo = reinterpret_cast<AppSpawnMsgDacInfo *>(GetAppProperty(appProperty, TLV_DAC_INFO));
528 if (info == nullptr || dacInfo == nullptr) {
529 return "";
530 }
531 if (path.find(g_packageNameIndex) != std::string::npos) {
532 std::string bundleNameWithIndex = info->bundleName;
533 if (info->bundleIndex != 0) {
534 bundleNameWithIndex = std::to_string(info->bundleIndex) + "_" + bundleNameWithIndex;
535 }
536 path = replace_all(path, g_packageNameIndex, bundleNameWithIndex);
537 }
538
539 if (path.find(g_packageName) != std::string::npos) {
540 path = replace_all(path, g_packageName, info->bundleName);
541 }
542
543 if (path.find(g_userId) != std::string::npos) {
544 path = replace_all(path, g_userId, std::to_string(dacInfo->uid / UID_BASE));
545 }
546
547 if (path.find(g_variablePackageName) != std::string::npos) {
548 path = ReplaceVariablePackageName(appProperty, path);
549 }
550
551 if (path.find(g_arkWebPackageName) != std::string::npos) {
552 path = replace_all(path, g_arkWebPackageName, getArkWebPackageName());
553 APPSPAWN_LOGV(
554 "arkWeb sandbox, path %{public}s, package:%{public}s",
555 path.c_str(), getArkWebPackageName().c_str());
556 }
557
558 return path;
559 }
560
ConvertToRealPathWithPermission(const AppSpawningCtx * appProperty,std::string path)561 std::string SandboxUtils::ConvertToRealPathWithPermission(const AppSpawningCtx *appProperty,
562 std::string path)
563 {
564 AppSpawnMsgBundleInfo *info =
565 reinterpret_cast<AppSpawnMsgBundleInfo *>(GetAppProperty(appProperty, TLV_BUNDLE_INFO));
566 if (info == nullptr) {
567 return "";
568 }
569 if (path.find(g_packageNameIndex) != std::string::npos) {
570 std::string bundleNameWithIndex = info->bundleName;
571 if (info->bundleIndex != 0) {
572 bundleNameWithIndex = std::to_string(info->bundleIndex) + "_" + bundleNameWithIndex;
573 }
574 path = replace_all(path, g_packageNameIndex, bundleNameWithIndex);
575 }
576
577 if (path.find(g_packageName) != std::string::npos) {
578 path = replace_all(path, g_packageName, info->bundleName);
579 }
580
581 if (path.find(g_userId) != std::string::npos) {
582 if (deviceTypeEnable_ == FILE_CROSS_APP_STATUS) {
583 path = replace_all(path, g_userId, "currentUser");
584 } else if (deviceTypeEnable_ == FILE_ACCESS_COMMON_DIR_STATUS) {
585 path = replace_all(path, g_userId, "currentUser");
586 } else {
587 return "";
588 }
589 }
590 return path;
591 }
592
GetSandboxDacOverrideEnable(nlohmann::json & config)593 bool SandboxUtils::GetSandboxDacOverrideEnable(nlohmann::json &config)
594 {
595 std::string dacOverrideSensitive = "";
596 if (config.find(g_dacOverrideSensitive) == config.end()) {
597 return false;
598 }
599 dacOverrideSensitive = config[g_dacOverrideSensitive].get<std::string>();
600 if (dacOverrideSensitive.compare("true") == 0) {
601 return true;
602 }
603 return false;
604 }
605
GetSbxPathByConfig(const AppSpawningCtx * appProperty,nlohmann::json & config)606 std::string SandboxUtils::GetSbxPathByConfig(const AppSpawningCtx *appProperty, nlohmann::json &config)
607 {
608 AppSpawnMsgDacInfo *dacInfo = reinterpret_cast<AppSpawnMsgDacInfo *>(GetAppProperty(appProperty, TLV_DAC_INFO));
609 if (dacInfo == nullptr) {
610 return "";
611 }
612
613 std::string sandboxRoot = "";
614 const std::string originSandboxPath = "/mnt/sandbox/<PackageName>";
615 std::string isolatedFlagText = CheckAppMsgFlagsSet(appProperty, APP_FLAGS_ISOLATED_SANDBOX_TYPE) ? "isolated/" : "";
616 const std::string defaultSandboxRoot = g_sandBoxDir + to_string(dacInfo->uid / UID_BASE) +
617 "/" + isolatedFlagText.c_str() + GetBundleName(appProperty);
618 if (config.find(g_sandboxRootPrefix) != config.end()) {
619 sandboxRoot = config[g_sandboxRootPrefix].get<std::string>();
620 if (sandboxRoot == originSandboxPath) {
621 sandboxRoot = defaultSandboxRoot;
622 } else {
623 sandboxRoot = ConvertToRealPath(appProperty, sandboxRoot);
624 APPSPAWN_LOGV("set sandbox-root name is %{public}s", sandboxRoot.c_str());
625 }
626 } else {
627 sandboxRoot = defaultSandboxRoot;
628 APPSPAWN_LOGV("set sandbox-root to default rootapp name is %{public}s", GetBundleName(appProperty));
629 }
630
631 return sandboxRoot;
632 }
633
GetSbxSwitchStatusByConfig(nlohmann::json & config)634 bool SandboxUtils::GetSbxSwitchStatusByConfig(nlohmann::json &config)
635 {
636 if (config.find(g_sandBoxSwitchPrefix) != config.end()) {
637 std::string switchStatus = config[g_sandBoxSwitchPrefix].get<std::string>();
638 if (switchStatus == g_sbxSwitchCheck) {
639 return true;
640 } else {
641 return false;
642 }
643 }
644
645 // if not find sandbox-switch node, default switch status is true
646 return true;
647 }
648
CheckMountConfig(nlohmann::json & mntPoint,const AppSpawningCtx * appProperty,bool checkFlag)649 static bool CheckMountConfig(nlohmann::json &mntPoint, const AppSpawningCtx *appProperty,
650 bool checkFlag)
651 {
652 bool istrue = mntPoint.find(g_srcPath) == mntPoint.end() || (!mntPoint[g_srcPath].is_string()) ||
653 mntPoint.find(g_sandBoxPath) == mntPoint.end() || (!mntPoint[g_sandBoxPath].is_string()) ||
654 ((mntPoint.find(g_sandBoxFlags) == mntPoint.end()) &&
655 (mntPoint.find(g_sandBoxFlagsCustomized) == mntPoint.end()));
656 APPSPAWN_CHECK(!istrue, return false,
657 "read mount config failed, app name is %{public}s", GetBundleName(appProperty));
658
659 AppSpawnMsgDomainInfo *info =
660 reinterpret_cast<AppSpawnMsgDomainInfo *>(GetAppProperty(appProperty, TLV_DOMAIN_INFO));
661 APPSPAWN_CHECK(info != nullptr, return false, "Filed to get domain info %{public}s", GetBundleName(appProperty));
662
663 if (mntPoint[g_appAplName] != nullptr) {
664 std::string app_apl_name = mntPoint[g_appAplName].get<std::string>();
665 const char *p_app_apl = nullptr;
666 p_app_apl = app_apl_name.c_str();
667 if (!strcmp(p_app_apl, info->apl)) {
668 return false;
669 }
670 }
671
672 const std::string configSrcPath = mntPoint[g_srcPath].get<std::string>();
673 // special handle wps and don't use /data/app/xxx/<Package> config
674 if (checkFlag && (configSrcPath.find("/data/app") != std::string::npos &&
675 (configSrcPath.find("/base") != std::string::npos ||
676 configSrcPath.find("/database") != std::string::npos
677 ) && configSrcPath.find(g_packageName) != std::string::npos)) {
678 return false;
679 }
680
681 return true;
682 }
683
DoDlpAppMountStrategy(const AppSpawningCtx * appProperty,const std::string & srcPath,const std::string & sandboxPath,const std::string & fsType,unsigned long mountFlags)684 static int32_t DoDlpAppMountStrategy(const AppSpawningCtx *appProperty,
685 const std::string &srcPath, const std::string &sandboxPath,
686 const std::string &fsType, unsigned long mountFlags)
687 {
688 AppSpawnMsgDacInfo *dacInfo = reinterpret_cast<AppSpawnMsgDacInfo *>(GetAppProperty(appProperty, TLV_DAC_INFO));
689 if (dacInfo == nullptr) {
690 return -1;
691 }
692
693 // umount fuse path, make sure that sandbox path is not a mount point
694 umount2(sandboxPath.c_str(), MNT_DETACH);
695
696 int fd = open("/dev/fuse", O_RDWR);
697 APPSPAWN_CHECK(fd != -1, return -EINVAL, "open /dev/fuse failed, errno is %{public}d", errno);
698
699 char options[OPTIONS_MAX_LEN];
700 (void)sprintf_s(options, sizeof(options), "fd=%d,"
701 "rootmode=40000,user_id=%u,group_id=%u,allow_other,"
702 "context=\"u:object_r:dlp_fuse_file:s0\","
703 "fscontext=u:object_r:dlp_fuse_file:s0",
704 fd, dacInfo->uid, dacInfo->gid);
705
706 // To make sure destinationPath exist
707 MakeDirRecursive(sandboxPath, FILE_MODE);
708
709 int ret = 0;
710 #ifndef APPSPAWN_TEST
711 APPSPAWN_LOGV("Bind mount %{public}s to %{public}s '%{public}s' '%{public}lu' '%{public}s'",
712 srcPath.c_str(), sandboxPath.c_str(), fsType.c_str(), mountFlags, options);
713 ret = mount(srcPath.c_str(), sandboxPath.c_str(), fsType.c_str(), mountFlags, options);
714 APPSPAWN_CHECK(ret == 0, close(fd);
715 return ret, "DoDlpAppMountStrategy failed, bind mount %{public}s to %{public}s failed %{public}d",
716 srcPath.c_str(), sandboxPath.c_str(), errno);
717
718 ret = mount(nullptr, sandboxPath.c_str(), nullptr, MS_SHARED, nullptr);
719 APPSPAWN_CHECK(ret == 0, close(fd);
720 return ret, "errno is: %{public}d, private mount to %{public}s failed", errno, sandboxPath.c_str());
721 #endif
722 /* set DLP_FUSE_FD */
723 #ifdef WITH_DLP
724 SetDlpFuseFd(fd);
725 #endif
726 ret = fd;
727 return ret;
728 }
729
HandleSpecialAppMount(const AppSpawningCtx * appProperty,const std::string & srcPath,const std::string & sandboxPath,const std::string & fsType,unsigned long mountFlags)730 static int32_t HandleSpecialAppMount(const AppSpawningCtx *appProperty,
731 const std::string &srcPath, const std::string &sandboxPath, const std::string &fsType, unsigned long mountFlags)
732 {
733 std::string bundleName = GetBundleName(appProperty);
734 std::string processName = GetProcessName(appProperty);
735 /* dlp application mount strategy */
736 /* dlp is an example, we should change to real bundle name later */
737 if (bundleName.find(g_dlpBundleName) != std::string::npos &&
738 processName.compare(g_dlpBundleName) == 0) {
739 if (fsType.empty()) {
740 return -1;
741 } else {
742 return DoDlpAppMountStrategy(appProperty, srcPath, sandboxPath, fsType, mountFlags);
743 }
744 }
745 return -1;
746 }
747
ConvertFlagStr(const std::string & flagStr)748 static uint32_t ConvertFlagStr(const std::string &flagStr)
749 {
750 const std::map<std::string, int> flagsMap = {{"0", 0}, {"START_FLAGS_BACKUP", 1},
751 {"DLP_MANAGER", 2},
752 {"DEVELOPER_MODE", 17}};
753
754 if (flagsMap.count(flagStr)) {
755 return 1 << flagsMap.at(flagStr);
756 }
757
758 return 0;
759 }
760
GetSandboxMountFlags(nlohmann::json & config)761 unsigned long SandboxUtils::GetSandboxMountFlags(nlohmann::json &config)
762 {
763 unsigned long mountFlags = BASIC_MOUNT_FLAGS;
764 if (GetSandboxDacOverrideEnable(config) && (config.find(g_sandBoxFlagsCustomized) != config.end())) {
765 mountFlags = GetMountFlagsFromConfig(config[g_sandBoxFlagsCustomized].get<std::vector<std::string>>());
766 } else if (config.find(g_sandBoxFlags) != config.end()) {
767 mountFlags = GetMountFlagsFromConfig(config[g_sandBoxFlags].get<std::vector<std::string>>());
768 }
769 return mountFlags;
770 }
771
GetSandboxFsType(nlohmann::json & config)772 std::string SandboxUtils::GetSandboxFsType(nlohmann::json &config)
773 {
774 std::string fsType;
775 if (GetSandboxDacOverrideEnable(config) && (config.find(g_fsType) != config.end())) {
776 fsType = config[g_fsType].get<std::string>();
777 } else {
778 fsType = "";
779 }
780 return fsType;
781 }
782
GetSandboxOptions(const AppSpawningCtx * appProperty,nlohmann::json & config)783 std::string SandboxUtils::GetSandboxOptions(const AppSpawningCtx *appProperty, nlohmann::json &config)
784 {
785 AppSpawnMsgDacInfo *dacInfo = reinterpret_cast<AppSpawnMsgDacInfo *>(GetAppProperty(appProperty, TLV_DAC_INFO));
786 if (dacInfo == nullptr) {
787 return "";
788 }
789
790 std::string options;
791 const int userIdBase = UID_BASE;
792 if (GetSandboxDacOverrideEnable(config) && (config.find(g_sandBoxOptions) != config.end())) {
793 options = config[g_sandBoxOptions].get<std::string>() + ",user_id=";
794 options += std::to_string(dacInfo->uid / userIdBase);
795 } else {
796 options = "";
797 }
798 return options;
799 }
800
GetSandboxMountConfig(const AppSpawningCtx * appProperty,const std::string & section,nlohmann::json & mntPoint,SandboxMountConfig & mountConfig)801 void SandboxUtils::GetSandboxMountConfig(const AppSpawningCtx *appProperty, const std::string §ion,
802 nlohmann::json &mntPoint, SandboxMountConfig &mountConfig)
803 {
804 if (section.compare(g_permissionPrefix) == 0) {
805 mountConfig.optionsPoint = GetSandboxOptions(appProperty, mntPoint);
806 mountConfig.fsType = GetSandboxFsType(mntPoint);
807 } else {
808 mountConfig.fsType = (mntPoint.find(g_fsType) != mntPoint.end()) ? mntPoint[g_fsType].get<std::string>() : "";
809 mountConfig.optionsPoint = "";
810 }
811 return;
812 }
813
GetSandboxPath(const AppSpawningCtx * appProperty,nlohmann::json & mntPoint,const std::string & section,std::string sandboxRoot)814 std::string SandboxUtils::GetSandboxPath(const AppSpawningCtx *appProperty, nlohmann::json &mntPoint,
815 const std::string §ion, std::string sandboxRoot)
816 {
817 std::string sandboxPath = "";
818 std::string tmpSandboxPath = mntPoint[g_sandBoxPath].get<std::string>();
819 if (section.compare(g_permissionPrefix) == 0) {
820 sandboxPath = sandboxRoot + ConvertToRealPathWithPermission(appProperty, tmpSandboxPath);
821 } else {
822 sandboxPath = sandboxRoot + ConvertToRealPath(appProperty, tmpSandboxPath);
823 }
824 return sandboxPath;
825 }
826
CheckMountFlag(const AppSpawningCtx * appProperty,const std::string bundleName,nlohmann::json & appConfig)827 static bool CheckMountFlag(const AppSpawningCtx *appProperty, const std::string bundleName, nlohmann::json &appConfig)
828 {
829 if (appConfig.find(g_flags) != appConfig.end()) {
830 if (((ConvertFlagStr(appConfig[g_flags].get<std::string>()) & GetAppMsgFlags(appProperty)) != 0) &&
831 bundleName.find("wps") != std::string::npos) {
832 return true;
833 }
834 }
835 return false;
836 }
837
DoAllMntPointsMount(const AppSpawningCtx * appProperty,nlohmann::json & appConfig,const char * typeName,const std::string & section)838 int SandboxUtils::DoAllMntPointsMount(const AppSpawningCtx *appProperty,
839 nlohmann::json &appConfig, const char *typeName, const std::string §ion)
840 {
841 std::string bundleName = GetBundleName(appProperty);
842 if (appConfig.find(g_mountPrefix) == appConfig.end()) {
843 APPSPAWN_LOGV("mount config is not found in %{public}s, app name is %{public}s",
844 section.c_str(), bundleName.c_str());
845 return 0;
846 }
847
848 std::string sandboxRoot = GetSbxPathByConfig(appProperty, appConfig);
849 bool checkFlag = CheckMountFlag(appProperty, bundleName, appConfig);
850
851 nlohmann::json& mountPoints = appConfig[g_mountPrefix];
852 unsigned int mountPointSize = mountPoints.size();
853 for (unsigned int i = 0; i < mountPointSize; i++) {
854 nlohmann::json& mntPoint = mountPoints[i];
855 APPSPAWN_CHECK_ONLY_EXPER(CheckMountConfig(mntPoint, appProperty, checkFlag), continue);
856
857 std::string srcPath = ConvertToRealPath(appProperty, mntPoint[g_srcPath].get<std::string>());
858 std::string sandboxPath = GetSandboxPath(appProperty, mntPoint, section, sandboxRoot);
859 SandboxMountConfig mountConfig = {0};
860 GetSandboxMountConfig(appProperty, section, mntPoint, mountConfig);
861 unsigned long mountFlags = GetSandboxMountFlags(mntPoint);
862 mode_t mountSharedFlag = (mntPoint.find(g_mountSharedFlag) != mntPoint.end()) ? MS_SHARED : MS_SLAVE;
863
864 /* if app mount failed for special strategy, we need deal with common mount config */
865 int ret = HandleSpecialAppMount(appProperty, srcPath, sandboxPath, mountConfig.fsType, mountFlags);
866 if (ret < 0) {
867 ret = DoAppSandboxMountOnce(srcPath.c_str(), sandboxPath.c_str(), mountConfig.fsType.c_str(),
868 mountFlags, mountConfig.optionsPoint.c_str(), mountSharedFlag);
869 }
870 if (ret) {
871 std::string actionStatus = g_statusCheck;
872 (void)JsonUtils::GetStringFromJson(mntPoint, g_actionStatuc, actionStatus);
873 if (actionStatus == g_statusCheck) {
874 APPSPAWN_LOGE("DoAppSandboxMountOnce section %{public}s failed, %{public}s",
875 section.c_str(), sandboxPath.c_str());
876 #ifdef APPSPAWN_HISYSEVENT
877 ReportMountFail(bundleName.c_str(), srcPath.c_str(), sandboxPath.c_str(), errno);
878 ret = APPSPAWN_SANDBOX_MOUNT_FAIL;
879 #endif
880 return ret;
881 }
882 }
883
884 DoSandboxChmod(mntPoint, sandboxRoot);
885 }
886
887 return 0;
888 }
889
DoAddGid(AppSpawningCtx * appProperty,nlohmann::json & appConfig,const char * permissionName,const std::string & section)890 int32_t SandboxUtils::DoAddGid(AppSpawningCtx *appProperty, nlohmann::json &appConfig,
891 const char* permissionName, const std::string §ion)
892 {
893 std::string bundleName = GetBundleName(appProperty);
894 if (appConfig.find(g_gidPrefix) == appConfig.end()) {
895 return 0;
896 }
897 AppSpawnMsgDacInfo *dacInfo = reinterpret_cast<AppSpawnMsgDacInfo *>(GetAppProperty(appProperty, TLV_DAC_INFO));
898 if (dacInfo == nullptr) {
899 return 0;
900 }
901
902 nlohmann::json& gids = appConfig[g_gidPrefix];
903 unsigned int gidSize = gids.size();
904 for (unsigned int i = 0; i < gidSize; i++) {
905 if (dacInfo->gidCount < APP_MAX_GIDS) {
906 APPSPAWN_LOGI("add gid to gitTable in %{public}s, permission is %{public}s, gid:%{public}u",
907 bundleName.c_str(), permissionName, gids[i].get<uint32_t>());
908 dacInfo->gidTable[dacInfo->gidCount++] = gids[i].get<uint32_t>();
909 }
910 }
911 return 0;
912 }
913
DoAllSymlinkPointslink(const AppSpawningCtx * appProperty,nlohmann::json & appConfig)914 int SandboxUtils::DoAllSymlinkPointslink(const AppSpawningCtx *appProperty, nlohmann::json &appConfig)
915 {
916 APPSPAWN_CHECK(appConfig.find(g_symlinkPrefix) != appConfig.end(), return 0, "symlink config is not found,"
917 "maybe result sandbox launch failed app name is %{public}s", GetBundleName(appProperty));
918
919 nlohmann::json& symlinkPoints = appConfig[g_symlinkPrefix];
920 std::string sandboxRoot = GetSbxPathByConfig(appProperty, appConfig);
921 unsigned int symlinkPointSize = symlinkPoints.size();
922
923 for (unsigned int i = 0; i < symlinkPointSize; i++) {
924 nlohmann::json& symPoint = symlinkPoints[i];
925
926 // Check the validity of the symlink configuration
927 if (symPoint.find(g_targetName) == symPoint.end() || (!symPoint[g_targetName].is_string()) ||
928 symPoint.find(g_linkName) == symPoint.end() || (!symPoint[g_linkName].is_string())) {
929 APPSPAWN_LOGE("read symlink config failed, app name is %{public}s", GetBundleName(appProperty));
930 continue;
931 }
932
933 std::string targetName = ConvertToRealPath(appProperty, symPoint[g_targetName].get<std::string>());
934 std::string linkName = sandboxRoot + ConvertToRealPath(appProperty, symPoint[g_linkName].get<std::string>());
935 APPSPAWN_LOGV("symlink, from %{public}s to %{public}s", targetName.c_str(), linkName.c_str());
936
937 int ret = symlink(targetName.c_str(), linkName.c_str());
938 if (ret && errno != EEXIST) {
939 APPSPAWN_LOGE("errno is %{public}d, symlink failed, %{public}s", errno, linkName.c_str());
940
941 std::string actionStatus = g_statusCheck;
942 (void)JsonUtils::GetStringFromJson(symPoint, g_actionStatuc, actionStatus);
943 if (actionStatus == g_statusCheck) {
944 return ret;
945 }
946 }
947
948 DoSandboxChmod(symPoint, sandboxRoot);
949 }
950
951 return 0;
952 }
953
DoSandboxFilePrivateBind(const AppSpawningCtx * appProperty,nlohmann::json & wholeConfig)954 int32_t SandboxUtils::DoSandboxFilePrivateBind(const AppSpawningCtx *appProperty,
955 nlohmann::json &wholeConfig)
956 {
957 const char *bundleName = GetBundleName(appProperty);
958 nlohmann::json& privateAppConfig = wholeConfig[g_privatePrefix][0];
959 if (privateAppConfig.find(bundleName) != privateAppConfig.end()) {
960 APPSPAWN_LOGV("DoSandboxFilePrivateBind %{public}s", bundleName);
961 DoAddGid((AppSpawningCtx *)appProperty, privateAppConfig[bundleName][0], "", g_privatePrefix);
962 return DoAllMntPointsMount(appProperty, privateAppConfig[bundleName][0], nullptr, g_privatePrefix);
963 }
964
965 return 0;
966 }
967
DoSandboxFilePermissionBind(AppSpawningCtx * appProperty,nlohmann::json & wholeConfig)968 int32_t SandboxUtils::DoSandboxFilePermissionBind(AppSpawningCtx *appProperty,
969 nlohmann::json &wholeConfig)
970 {
971 if (wholeConfig.find(g_permissionPrefix) == wholeConfig.end()) {
972 APPSPAWN_LOGV("DoSandboxFilePermissionBind not found permission information in config file");
973 return 0;
974 }
975 nlohmann::json& permissionAppConfig = wholeConfig[g_permissionPrefix][0];
976 for (nlohmann::json::iterator it = permissionAppConfig.begin(); it != permissionAppConfig.end(); ++it) {
977 const std::string permission = it.key();
978 int index = GetPermissionIndex(nullptr, permission.c_str());
979 APPSPAWN_LOGV("DoSandboxFilePermissionBind mountPermissionFlags %{public}d", index);
980 if (CheckAppPermissionFlagSet(appProperty, static_cast<uint32_t>(index))) {
981 DoAddGid(appProperty, permissionAppConfig[permission][0], permission.c_str(), g_permissionPrefix);
982 DoAllMntPointsMount(appProperty, permissionAppConfig[permission][0], permission.c_str(),
983 g_permissionPrefix);
984 } else {
985 APPSPAWN_LOGV("DoSandboxFilePermissionBind false %{public}s permission %{public}s",
986 GetBundleName(appProperty), permission.c_str());
987 }
988 }
989 return 0;
990 }
991
GetMountPermissionNames()992 std::set<std::string> SandboxUtils::GetMountPermissionNames()
993 {
994 std::set<std::string> permissionSet;
995 for (auto& config : SandboxUtils::GetJsonConfig(SANBOX_APP_JSON_CONFIG)) {
996 if (config.find(g_permissionPrefix) == config.end()) {
997 continue;
998 }
999 nlohmann::json& permissionAppConfig = config[g_permissionPrefix][0];
1000 for (auto it = permissionAppConfig.begin(); it != permissionAppConfig.end(); it++) {
1001 permissionSet.insert(it.key());
1002 }
1003 }
1004 APPSPAWN_LOGI("GetMountPermissionNames size: %{public}lu", static_cast<unsigned long>(permissionSet.size()));
1005 return permissionSet;
1006 }
1007
DoSandboxFilePrivateSymlink(const AppSpawningCtx * appProperty,nlohmann::json & wholeConfig)1008 int32_t SandboxUtils::DoSandboxFilePrivateSymlink(const AppSpawningCtx *appProperty,
1009 nlohmann::json &wholeConfig)
1010 {
1011 const char *bundleName = GetBundleName(appProperty);
1012 nlohmann::json& privateAppConfig = wholeConfig[g_privatePrefix][0];
1013 if (privateAppConfig.find(bundleName) != privateAppConfig.end()) {
1014 return DoAllSymlinkPointslink(appProperty, privateAppConfig[bundleName][0]);
1015 }
1016
1017 return 0;
1018 }
1019
HandleFlagsPoint(const AppSpawningCtx * appProperty,nlohmann::json & appConfig)1020 int32_t SandboxUtils::HandleFlagsPoint(const AppSpawningCtx *appProperty,
1021 nlohmann::json &appConfig)
1022 {
1023 if (appConfig.find(g_flagePoint) == appConfig.end()) {
1024 return 0;
1025 }
1026
1027 nlohmann::json& flagsPoints = appConfig[g_flagePoint];
1028 unsigned int flagsPointSize = flagsPoints.size();
1029
1030 for (unsigned int i = 0; i < flagsPointSize; i++) {
1031 nlohmann::json& flagPoint = flagsPoints[i];
1032
1033 if (flagPoint.find(g_flags) != flagPoint.end() && flagPoint[g_flags].is_string()) {
1034 std::string flagsStr = flagPoint[g_flags].get<std::string>();
1035 uint32_t flag = ConvertFlagStr(flagsStr);
1036 if ((GetAppMsgFlags(appProperty) & flag) != 0) {
1037 return DoAllMntPointsMount(appProperty, flagPoint, nullptr, g_flagePoint);
1038 }
1039 } else {
1040 APPSPAWN_LOGE("read flags config failed, app name is %{public}s", GetBundleName(appProperty));
1041 }
1042 }
1043
1044 return 0;
1045 }
1046
DoSandboxFilePrivateFlagsPointHandle(const AppSpawningCtx * appProperty,nlohmann::json & wholeConfig)1047 int32_t SandboxUtils::DoSandboxFilePrivateFlagsPointHandle(const AppSpawningCtx *appProperty,
1048 nlohmann::json &wholeConfig)
1049 {
1050 const char *bundleName = GetBundleName(appProperty);
1051 nlohmann::json& privateAppConfig = wholeConfig[g_privatePrefix][0];
1052 if (privateAppConfig.find(bundleName) != privateAppConfig.end()) {
1053 return HandleFlagsPoint(appProperty, privateAppConfig[bundleName][0]);
1054 }
1055
1056 return 0;
1057 }
1058
DoSandboxFileCommonFlagsPointHandle(const AppSpawningCtx * appProperty,nlohmann::json & wholeConfig)1059 int32_t SandboxUtils::DoSandboxFileCommonFlagsPointHandle(const AppSpawningCtx *appProperty,
1060 nlohmann::json &wholeConfig)
1061 {
1062 nlohmann::json& commonConfig = wholeConfig[g_commonPrefix][0];
1063 if (commonConfig.find(g_appResources) != commonConfig.end()) {
1064 return HandleFlagsPoint(appProperty, commonConfig[g_appResources][0]);
1065 }
1066
1067 return 0;
1068 }
1069
DoSandboxFileCommonBind(const AppSpawningCtx * appProperty,nlohmann::json & wholeConfig)1070 int32_t SandboxUtils::DoSandboxFileCommonBind(const AppSpawningCtx *appProperty, nlohmann::json &wholeConfig)
1071 {
1072 nlohmann::json& commonConfig = wholeConfig[g_commonPrefix][0];
1073 int ret = 0;
1074
1075 if (commonConfig.find(g_appBase) != commonConfig.end()) {
1076 ret = DoAllMntPointsMount(appProperty, commonConfig[g_appBase][0], nullptr, g_appBase);
1077 if (ret) {
1078 return ret;
1079 }
1080 }
1081
1082 if (commonConfig.find(g_appResources) != commonConfig.end()) {
1083 ret = DoAllMntPointsMount(appProperty, commonConfig[g_appResources][0], nullptr, g_appResources);
1084 }
1085
1086 return ret;
1087 }
1088
DoSandboxFileCommonSymlink(const AppSpawningCtx * appProperty,nlohmann::json & wholeConfig)1089 int32_t SandboxUtils::DoSandboxFileCommonSymlink(const AppSpawningCtx *appProperty,
1090 nlohmann::json &wholeConfig)
1091 {
1092 nlohmann::json& commonConfig = wholeConfig[g_commonPrefix][0];
1093 int ret = 0;
1094
1095 if (commonConfig.find(g_appBase) != commonConfig.end()) {
1096 ret = DoAllSymlinkPointslink(appProperty, commonConfig[g_appBase][0]);
1097 if (ret) {
1098 return ret;
1099 }
1100 }
1101
1102 if (commonConfig.find(g_appResources) != commonConfig.end()) {
1103 ret = DoAllSymlinkPointslink(appProperty, commonConfig[g_appResources][0]);
1104 }
1105
1106 return ret;
1107 }
1108
SetPrivateAppSandboxProperty_(const AppSpawningCtx * appProperty,nlohmann::json & config)1109 int32_t SandboxUtils::SetPrivateAppSandboxProperty_(const AppSpawningCtx *appProperty,
1110 nlohmann::json &config)
1111 {
1112 int ret = DoSandboxFilePrivateBind(appProperty, config);
1113 APPSPAWN_CHECK(ret == 0, return ret, "DoSandboxFilePrivateBind failed");
1114
1115 ret = DoSandboxFilePrivateSymlink(appProperty, config);
1116 APPSPAWN_CHECK_ONLY_LOG(ret == 0, "DoSandboxFilePrivateSymlink failed");
1117
1118 ret = DoSandboxFilePrivateFlagsPointHandle(appProperty, config);
1119 APPSPAWN_CHECK_ONLY_LOG(ret == 0, "DoSandboxFilePrivateFlagsPointHandle failed");
1120
1121 return ret;
1122 }
1123
SetPermissionAppSandboxProperty_(AppSpawningCtx * appProperty,nlohmann::json & config)1124 int32_t SandboxUtils::SetPermissionAppSandboxProperty_(AppSpawningCtx *appProperty,
1125 nlohmann::json &config)
1126 {
1127 int ret = DoSandboxFilePermissionBind(appProperty, config);
1128 APPSPAWN_CHECK(ret == 0, return ret, "DoSandboxFilePermissionBind failed");
1129 return ret;
1130 }
1131
1132
SetRenderSandboxProperty(const AppSpawningCtx * appProperty,std::string & sandboxPackagePath)1133 int32_t SandboxUtils::SetRenderSandboxProperty(const AppSpawningCtx *appProperty,
1134 std::string &sandboxPackagePath)
1135 {
1136 return 0;
1137 }
1138
SetRenderSandboxPropertyNweb(const AppSpawningCtx * appProperty,std::string & sandboxPackagePath)1139 int32_t SandboxUtils::SetRenderSandboxPropertyNweb(const AppSpawningCtx *appProperty,
1140 std::string &sandboxPackagePath)
1141 {
1142 SandboxConfigType type = CheckAppMsgFlagsSet(appProperty, APP_FLAGS_ISOLATED_SANDBOX_TYPE) ?
1143 SANBOX_ISOLATED_JSON_CONFIG : SANBOX_APP_JSON_CONFIG;
1144
1145 for (auto& config : SandboxUtils::GetJsonConfig(type)) {
1146 nlohmann::json& privateAppConfig = config[g_privatePrefix][0];
1147 if (privateAppConfig.find(g_ohosRender) != privateAppConfig.end()) {
1148 int ret = DoAllMntPointsMount(appProperty, privateAppConfig[g_ohosRender][0], nullptr, g_ohosRender);
1149 APPSPAWN_CHECK(ret == 0, return ret, "DoAllMntPointsMount failed, %{public}s",
1150 GetBundleName(appProperty));
1151 ret = DoAllSymlinkPointslink(appProperty, privateAppConfig[g_ohosRender][0]);
1152 APPSPAWN_CHECK(ret == 0, return ret, "DoAllSymlinkPointslink failed, %{public}s",
1153 GetBundleName(appProperty));
1154 ret = HandleFlagsPoint(appProperty, privateAppConfig[g_ohosRender][0]);
1155 APPSPAWN_CHECK_ONLY_LOG(ret == 0, "HandleFlagsPoint for render-sandbox failed, %{public}s",
1156 GetBundleName(appProperty));
1157 }
1158 }
1159 return 0;
1160 }
1161
SetPrivateAppSandboxProperty(const AppSpawningCtx * appProperty)1162 int32_t SandboxUtils::SetPrivateAppSandboxProperty(const AppSpawningCtx *appProperty)
1163 {
1164 int ret = 0;
1165 SandboxConfigType type = CheckAppMsgFlagsSet(appProperty, APP_FLAGS_ISOLATED_SANDBOX_TYPE) ?
1166 SANBOX_ISOLATED_JSON_CONFIG : SANBOX_APP_JSON_CONFIG;
1167
1168 for (auto& config : SandboxUtils::GetJsonConfig(type)) {
1169 ret = SetPrivateAppSandboxProperty_(appProperty, config);
1170 APPSPAWN_CHECK(ret == 0, return ret, "parse adddata-sandbox config failed");
1171 }
1172 return ret;
1173 }
1174
GetSandboxPrivateSharedStatus(const string & bundleName,AppSpawningCtx * appProperty)1175 static bool GetSandboxPrivateSharedStatus(const string &bundleName, AppSpawningCtx *appProperty)
1176 {
1177 bool result = false;
1178 SandboxConfigType type = CheckAppMsgFlagsSet(appProperty, APP_FLAGS_ISOLATED_SANDBOX_TYPE) ?
1179 SANBOX_ISOLATED_JSON_CONFIG : SANBOX_APP_JSON_CONFIG;
1180
1181 for (auto& config : SandboxUtils::GetJsonConfig(type)) {
1182 nlohmann::json& privateAppConfig = config[g_privatePrefix][0];
1183 if (privateAppConfig.find(bundleName) != privateAppConfig.end() &&
1184 privateAppConfig[bundleName][0].find(g_sandBoxShared) !=
1185 privateAppConfig[bundleName][0].end()) {
1186 string sandboxSharedStatus =
1187 privateAppConfig[bundleName][0][g_sandBoxShared].get<std::string>();
1188 if (sandboxSharedStatus == g_statusCheck) {
1189 result = true;
1190 }
1191 }
1192 }
1193 return result;
1194 }
1195
SetPermissionAppSandboxProperty(AppSpawningCtx * appProperty)1196 int32_t SandboxUtils::SetPermissionAppSandboxProperty(AppSpawningCtx *appProperty)
1197 {
1198 int ret = 0;
1199 SandboxConfigType type = CheckAppMsgFlagsSet(appProperty, APP_FLAGS_ISOLATED_SANDBOX_TYPE) ?
1200 SANBOX_ISOLATED_JSON_CONFIG : SANBOX_APP_JSON_CONFIG;
1201
1202 for (auto& config : SandboxUtils::GetJsonConfig(type)) {
1203 ret = SetPermissionAppSandboxProperty_(appProperty, config);
1204 APPSPAWN_CHECK(ret == 0, return ret, "parse adddata-sandbox config failed");
1205 }
1206 return ret;
1207 }
1208
1209
SetCommonAppSandboxProperty_(const AppSpawningCtx * appProperty,nlohmann::json & config)1210 int32_t SandboxUtils::SetCommonAppSandboxProperty_(const AppSpawningCtx *appProperty,
1211 nlohmann::json &config)
1212 {
1213 int rc = 0;
1214
1215 rc = DoSandboxFileCommonBind(appProperty, config);
1216 APPSPAWN_CHECK(rc == 0, return rc, "DoSandboxFileCommonBind failed, %{public}s", GetBundleName(appProperty));
1217
1218 // if sandbox switch is off, don't do symlink work again
1219 if (CheckAppSandboxSwitchStatus(appProperty) == true && (CheckTotalSandboxSwitchStatus(appProperty) == true)) {
1220 rc = DoSandboxFileCommonSymlink(appProperty, config);
1221 APPSPAWN_CHECK(rc == 0, return rc, "DoSandboxFileCommonSymlink failed, %{public}s", GetBundleName(appProperty));
1222 }
1223
1224 rc = DoSandboxFileCommonFlagsPointHandle(appProperty, config);
1225 APPSPAWN_CHECK_ONLY_LOG(rc == 0, "DoSandboxFilePrivateFlagsPointHandle failed");
1226
1227 return rc;
1228 }
1229
SetCommonAppSandboxProperty(const AppSpawningCtx * appProperty,std::string & sandboxPackagePath)1230 int32_t SandboxUtils::SetCommonAppSandboxProperty(const AppSpawningCtx *appProperty,
1231 std::string &sandboxPackagePath)
1232 {
1233 int ret = 0;
1234 SandboxConfigType type = CheckAppMsgFlagsSet(appProperty, APP_FLAGS_ISOLATED_SANDBOX_TYPE) ?
1235 SANBOX_ISOLATED_JSON_CONFIG : SANBOX_APP_JSON_CONFIG;
1236
1237 for (auto& jsonConfig : SandboxUtils::GetJsonConfig(type)) {
1238 ret = SetCommonAppSandboxProperty_(appProperty, jsonConfig);
1239 APPSPAWN_CHECK(ret == 0, return ret,
1240 "parse appdata config for common failed, %{public}s", sandboxPackagePath.c_str());
1241 }
1242
1243 ret = MountAllHsp(appProperty, sandboxPackagePath);
1244 APPSPAWN_CHECK(ret == 0, return ret, "mount extraInfo failed, %{public}s", sandboxPackagePath.c_str());
1245
1246 ret = MountAllGroup(appProperty, sandboxPackagePath);
1247 APPSPAWN_CHECK(ret == 0, return ret, "mount groupList failed, %{public}s", sandboxPackagePath.c_str());
1248
1249 AppSpawnMsgDomainInfo *info =
1250 reinterpret_cast<AppSpawnMsgDomainInfo *>(GetAppProperty(appProperty, TLV_DOMAIN_INFO));
1251 APPSPAWN_CHECK(info != nullptr, return -1, "No domain info %{public}s", sandboxPackagePath.c_str());
1252 if (strcmp(info->apl, APL_SYSTEM_BASIC.data()) == 0 ||
1253 strcmp(info->apl, APL_SYSTEM_CORE.data()) == 0 ||
1254 CheckAppMsgFlagsSet(appProperty, APP_FLAGS_ACCESS_BUNDLE_DIR)) {
1255 // need permission check for system app here
1256 std::string destbundlesPath = sandboxPackagePath + g_dataBundles;
1257 DoAppSandboxMountOnce(g_physicalAppInstallPath.c_str(), destbundlesPath.c_str(), "", BASIC_MOUNT_FLAGS,
1258 nullptr);
1259 }
1260
1261 return 0;
1262 }
1263
CheckPath(const std::string & name)1264 static inline bool CheckPath(const std::string& name)
1265 {
1266 return !name.empty() && name != "." && name != ".." && name.find("/") == std::string::npos;
1267 }
1268
GetExtraInfoByType(const AppSpawningCtx * appProperty,const std::string & type)1269 std::string SandboxUtils::GetExtraInfoByType(const AppSpawningCtx *appProperty, const std::string &type)
1270 {
1271 uint32_t len = 0;
1272 char *info = reinterpret_cast<char *>(GetAppPropertyExt(appProperty, type.c_str(), &len));
1273 if (info == nullptr) {
1274 return "";
1275 }
1276 return std::string(info, len);
1277 }
1278
MountAllHsp(const AppSpawningCtx * appProperty,std::string & sandboxPackagePath)1279 int32_t SandboxUtils::MountAllHsp(const AppSpawningCtx *appProperty, std::string &sandboxPackagePath)
1280 {
1281 int ret = 0;
1282 string hspListInfo = GetExtraInfoByType(appProperty, HSPLIST_SOCKET_TYPE);
1283 if (hspListInfo.length() == 0) {
1284 return ret;
1285 }
1286
1287 nlohmann::json hsps = nlohmann::json::parse(hspListInfo.c_str(), nullptr, false);
1288 APPSPAWN_CHECK(!hsps.is_discarded() && hsps.contains(g_hspList_key_bundles) && hsps.contains(g_hspList_key_modules)
1289 && hsps.contains(g_hspList_key_versions), return -1, "MountAllHsp: json parse failed");
1290
1291 nlohmann::json& bundles = hsps[g_hspList_key_bundles];
1292 nlohmann::json& modules = hsps[g_hspList_key_modules];
1293 nlohmann::json& versions = hsps[g_hspList_key_versions];
1294 APPSPAWN_CHECK(bundles.is_array() && modules.is_array() && versions.is_array() && bundles.size() == modules.size()
1295 && bundles.size() == versions.size(), return -1, "MountAllHsp: value is not arrary or sizes are not same");
1296
1297 APPSPAWN_LOGI("MountAllHsp: app = %{public}s, cnt = %{public}lu",
1298 GetBundleName(appProperty), static_cast<unsigned long>(bundles.size()));
1299 for (uint32_t i = 0; i < bundles.size(); i++) {
1300 // elements in json arrary can be different type
1301 APPSPAWN_CHECK(bundles[i].is_string() && modules[i].is_string() && versions[i].is_string(),
1302 return -1, "MountAllHsp: element type error");
1303
1304 std::string libBundleName = bundles[i];
1305 std::string libModuleName = modules[i];
1306 std::string libVersion = versions[i];
1307 APPSPAWN_CHECK(CheckPath(libBundleName) && CheckPath(libModuleName) && CheckPath(libVersion),
1308 return -1, "MountAllHsp: path error");
1309
1310 std::string libPhysicalPath = g_physicalAppInstallPath + libBundleName + "/" + libVersion + "/" + libModuleName;
1311 std::string mntPath = sandboxPackagePath + g_sandboxHspInstallPath + libBundleName + "/" + libModuleName;
1312 ret = DoAppSandboxMountOnce(libPhysicalPath.c_str(), mntPath.c_str(), "", BASIC_MOUNT_FLAGS, nullptr);
1313 APPSPAWN_CHECK(ret == 0, return ret, "mount library failed %{public}d", ret);
1314 }
1315 return ret;
1316 }
1317
DoSandboxRootFolderCreateAdapt(std::string & sandboxPackagePath)1318 int32_t SandboxUtils::DoSandboxRootFolderCreateAdapt(std::string &sandboxPackagePath)
1319 {
1320 #ifndef APPSPAWN_TEST
1321 int rc = mount(nullptr, "/", nullptr, MS_REC | MS_SLAVE, nullptr);
1322 APPSPAWN_CHECK(rc == 0, return rc, "set propagation slave failed");
1323 #endif
1324 MakeDirRecursive(sandboxPackagePath, FILE_MODE);
1325
1326 // bind mount "/" to /mnt/sandbox/<currentUserId>/<packageName> path
1327 // rootfs: to do more resources bind mount here to get more strict resources constraints
1328 #ifndef APPSPAWN_TEST
1329 rc = mount("/", sandboxPackagePath.c_str(), nullptr, BASIC_MOUNT_FLAGS, nullptr);
1330 APPSPAWN_CHECK(rc == 0, return rc, "mount bind / failed, %{public}d", errno);
1331 #endif
1332 return 0;
1333 }
1334
MountAllGroup(const AppSpawningCtx * appProperty,std::string & sandboxPackagePath)1335 int32_t SandboxUtils::MountAllGroup(const AppSpawningCtx *appProperty, std::string &sandboxPackagePath)
1336 {
1337 int ret = 0;
1338 string dataGroupInfo = GetExtraInfoByType(appProperty, DATA_GROUP_SOCKET_TYPE);
1339 if (dataGroupInfo.length() == 0) {
1340 return ret;
1341 }
1342
1343 nlohmann::json groups = nlohmann::json::parse(dataGroupInfo.c_str(), nullptr, false);
1344 APPSPAWN_CHECK(!groups.is_discarded() && groups.contains(g_groupList_key_dataGroupId)
1345 && groups.contains(g_groupList_key_gid) && groups.contains(g_groupList_key_dir), return -1,
1346 "MountAllGroup: json parse failed");
1347
1348 nlohmann::json& dataGroupIds = groups[g_groupList_key_dataGroupId];
1349 nlohmann::json& gids = groups[g_groupList_key_gid];
1350 nlohmann::json& dirs = groups[g_groupList_key_dir];
1351 APPSPAWN_CHECK(dataGroupIds.is_array() && gids.is_array() && dirs.is_array() && dataGroupIds.size() == gids.size()
1352 && dataGroupIds.size() == dirs.size(), return -1, "MountAllGroup: value is not arrary or sizes are not same");
1353 APPSPAWN_LOGI("MountAllGroup: app = %{public}s, cnt = %{public}lu",
1354 GetBundleName(appProperty), static_cast<unsigned long>(dataGroupIds.size()));
1355 for (uint32_t i = 0; i < dataGroupIds.size(); i++) {
1356 // elements in json arrary can be different type
1357 APPSPAWN_CHECK(dataGroupIds[i].is_string() && gids[i].is_string() && dirs[i].is_string(),
1358 return -1, "MountAllGroup: element type error");
1359
1360 std::string srcPath = dirs[i];
1361 APPSPAWN_CHECK(!CheckPath(srcPath), return -1, "MountAllGroup: path error");
1362
1363 size_t lastPathSplitPos = srcPath.find_last_of(g_fileSeparator);
1364 APPSPAWN_CHECK(lastPathSplitPos != std::string::npos, return -1, "MountAllGroup: path error");
1365 std::string dataGroupUuid = srcPath.substr(lastPathSplitPos + 1);
1366
1367 uint32_t elxValue = GetElxInfoFromDir(srcPath.c_str());
1368 APPSPAWN_CHECK((elxValue >= EL2 && elxValue < ELX_MAX), return -1, "Get elx value failed");
1369
1370 const DataGroupSandboxPathTemplate *templateItem = GetDataGroupArgTemplate(elxValue);
1371 APPSPAWN_CHECK(templateItem != nullptr, return -1, "Get data group arg template failed");
1372
1373 // If permission isn't null, need check permission flag
1374 if (templateItem->permission != nullptr) {
1375 int index = GetPermissionIndex(nullptr, templateItem->permission);
1376 APPSPAWN_LOGV("mount dir no lock mount permission flag %{public}d", index);
1377 if (CheckAppPermissionFlagSet(appProperty, static_cast<uint32_t>(index)) == 0) {
1378 continue;
1379 }
1380 }
1381
1382 std::string mntPath = sandboxPackagePath + templateItem->sandboxPath + dataGroupUuid;
1383 mode_t mountFlags = MS_REC | MS_BIND;
1384 mode_t mountSharedFlag = MS_SLAVE;
1385 if (CheckAppMsgFlagsSet(appProperty, APP_FLAGS_ISOLATED_SANDBOX)) {
1386 mountSharedFlag |= MS_REMOUNT | MS_NODEV | MS_RDONLY | MS_BIND;
1387 }
1388 ret = DoAppSandboxMountOnce(srcPath.c_str(), mntPath.c_str(), "", mountFlags, nullptr, mountSharedFlag);
1389 if (ret != 0) {
1390 APPSPAWN_LOGE("mount el%{public}d datagroup failed", elxValue);
1391 }
1392 }
1393 return 0;
1394 }
1395
DoSandboxRootFolderCreate(const AppSpawningCtx * appProperty,std::string & sandboxPackagePath)1396 int32_t SandboxUtils::DoSandboxRootFolderCreate(const AppSpawningCtx *appProperty,
1397 std::string &sandboxPackagePath)
1398 {
1399 #ifndef APPSPAWN_TEST
1400 int rc = mount(nullptr, "/", nullptr, MS_REC | MS_SLAVE, nullptr);
1401 if (rc) {
1402 return rc;
1403 }
1404 #endif
1405 DoAppSandboxMountOnce(sandboxPackagePath.c_str(), sandboxPackagePath.c_str(), "",
1406 BASIC_MOUNT_FLAGS, nullptr);
1407
1408 return 0;
1409 }
1410
GetSandboxNsFlags(bool isNweb)1411 uint32_t SandboxUtils::GetSandboxNsFlags(bool isNweb)
1412 {
1413 uint32_t nsFlags = 0;
1414 nlohmann::json appConfig;
1415 const std::map<std::string, uint32_t> NamespaceFlagsMap = { {"pid", CLONE_NEWPID},
1416 {"net", CLONE_NEWNET} };
1417
1418 if (!CheckTotalSandboxSwitchStatus(nullptr)) {
1419 return nsFlags;
1420 }
1421
1422 for (auto& config : SandboxUtils::GetJsonConfig(SANBOX_APP_JSON_CONFIG)) {
1423 if (isNweb) {
1424 nlohmann::json& privateAppConfig = config[g_privatePrefix][0];
1425 if (privateAppConfig.find(g_ohosRender) == privateAppConfig.end()) {
1426 continue;
1427 }
1428 appConfig = privateAppConfig[g_ohosRender][0];
1429 } else {
1430 nlohmann::json& baseConfig = config[g_commonPrefix][0];
1431 if (baseConfig.find(g_appBase) == baseConfig.end()) {
1432 continue;
1433 }
1434 appConfig = baseConfig[g_appBase][0];
1435 }
1436 if (appConfig.find(g_sandBoxNsFlags) == appConfig.end()) {
1437 continue;
1438 }
1439 const auto vec = appConfig[g_sandBoxNsFlags].get<std::vector<std::string>>();
1440 for (unsigned int j = 0; j < vec.size(); j++) {
1441 if (NamespaceFlagsMap.count(vec[j])) {
1442 nsFlags |= NamespaceFlagsMap.at(vec[j]);
1443 }
1444 }
1445 }
1446
1447 if (!nsFlags) {
1448 APPSPAWN_LOGE("config is not found %{public}s ns config", isNweb ? "Nweb" : "App");
1449 }
1450 return nsFlags;
1451 }
1452
CheckBundleNameForPrivate(const std::string & bundleName)1453 bool SandboxUtils::CheckBundleNameForPrivate(const std::string &bundleName)
1454 {
1455 if (bundleName.find(g_internal) != std::string::npos) {
1456 return false;
1457 }
1458 return true;
1459 }
1460
CheckTotalSandboxSwitchStatus(const AppSpawningCtx * appProperty)1461 bool SandboxUtils::CheckTotalSandboxSwitchStatus(const AppSpawningCtx *appProperty)
1462 {
1463 SandboxConfigType type = CheckAppMsgFlagsSet(appProperty, APP_FLAGS_ISOLATED_SANDBOX_TYPE) ?
1464 SANBOX_ISOLATED_JSON_CONFIG : SANBOX_APP_JSON_CONFIG;
1465
1466 for (auto& wholeConfig : SandboxUtils::GetJsonConfig(type)) {
1467 if (wholeConfig.find(g_commonPrefix) == wholeConfig.end()) {
1468 continue;
1469 }
1470 nlohmann::json& commonAppConfig = wholeConfig[g_commonPrefix][0];
1471 if (commonAppConfig.find(g_topSandBoxSwitchPrefix) != commonAppConfig.end()) {
1472 std::string switchStatus = commonAppConfig[g_topSandBoxSwitchPrefix].get<std::string>();
1473 if (switchStatus == g_sbxSwitchCheck) {
1474 return true;
1475 } else {
1476 return false;
1477 }
1478 }
1479 }
1480 // default sandbox switch is on
1481 return true;
1482 }
1483
CheckAppSandboxSwitchStatus(const AppSpawningCtx * appProperty)1484 bool SandboxUtils::CheckAppSandboxSwitchStatus(const AppSpawningCtx *appProperty)
1485 {
1486 bool rc = true;
1487 SandboxConfigType type = CheckAppMsgFlagsSet(appProperty, APP_FLAGS_ISOLATED_SANDBOX_TYPE) ?
1488 SANBOX_ISOLATED_JSON_CONFIG : SANBOX_APP_JSON_CONFIG;
1489
1490 for (auto& wholeConfig : SandboxUtils::GetJsonConfig(type)) {
1491 if (wholeConfig.find(g_privatePrefix) == wholeConfig.end()) {
1492 continue;
1493 }
1494 nlohmann::json& privateAppConfig = wholeConfig[g_privatePrefix][0];
1495 if (privateAppConfig.find(GetBundleName(appProperty)) != privateAppConfig.end()) {
1496 nlohmann::json& appConfig = privateAppConfig[GetBundleName(appProperty)][0];
1497 rc = GetSbxSwitchStatusByConfig(appConfig);
1498 if (rc) {
1499 break;
1500 }
1501 }
1502 }
1503 // default sandbox switch is on
1504 return rc;
1505 }
1506
CheckBundleName(const std::string & bundleName)1507 static int CheckBundleName(const std::string &bundleName)
1508 {
1509 if (bundleName.empty() || bundleName.size() > APP_LEN_BUNDLE_NAME) {
1510 return -1;
1511 }
1512 if (bundleName.find('\\') != std::string::npos || bundleName.find('/') != std::string::npos) {
1513 return -1;
1514 }
1515 return 0;
1516 }
1517
SetOverlayAppSandboxProperty(const AppSpawningCtx * appProperty,string & sandboxPackagePath)1518 int32_t SandboxUtils::SetOverlayAppSandboxProperty(const AppSpawningCtx *appProperty,
1519 string &sandboxPackagePath)
1520 {
1521 int ret = 0;
1522 if (!CheckAppMsgFlagsSet(appProperty, APP_FLAGS_OVERLAY)) {
1523 return ret;
1524 }
1525
1526 string overlayInfo = GetExtraInfoByType(appProperty, OVERLAY_SOCKET_TYPE);
1527 set<string> mountedSrcSet;
1528 vector<string> splits = split(overlayInfo, g_overlayDecollator);
1529 string sandboxOverlayPath = sandboxPackagePath + g_overlayPath;
1530 for (auto hapPath : splits) {
1531 size_t pathIndex = hapPath.find_last_of(g_fileSeparator);
1532 if (pathIndex == string::npos) {
1533 continue;
1534 }
1535 std::string srcPath = hapPath.substr(0, pathIndex);
1536 if (mountedSrcSet.find(srcPath) != mountedSrcSet.end()) {
1537 APPSPAWN_LOGV("%{public}s have mounted before, no need to mount twice.", srcPath.c_str());
1538 continue;
1539 }
1540
1541 auto bundleNameIndex = srcPath.find_last_of(g_fileSeparator);
1542 string destPath = sandboxOverlayPath + srcPath.substr(bundleNameIndex + 1, srcPath.length());
1543 int32_t retMount = DoAppSandboxMountOnce(srcPath.c_str(), destPath.c_str(),
1544 nullptr, BASIC_MOUNT_FLAGS, nullptr);
1545 if (retMount != 0) {
1546 APPSPAWN_LOGE("fail to mount overlay path, src is %{public}s.", hapPath.c_str());
1547 ret = retMount;
1548 }
1549
1550 mountedSrcSet.emplace(srcPath);
1551 }
1552 return ret;
1553 }
1554
SetBundleResourceAppSandboxProperty(const AppSpawningCtx * appProperty,string & sandboxPackagePath)1555 int32_t SandboxUtils::SetBundleResourceAppSandboxProperty(const AppSpawningCtx *appProperty,
1556 string &sandboxPackagePath)
1557 {
1558 int ret = 0;
1559 if (!CheckAppMsgFlagsSet(appProperty, APP_FLAGS_BUNDLE_RESOURCES)) {
1560 return ret;
1561 }
1562
1563 string srcPath = g_bundleResourceSrcPath;
1564 string destPath = sandboxPackagePath + g_bundleResourceDestPath;
1565 ret = DoAppSandboxMountOnce(
1566 srcPath.c_str(), destPath.c_str(), nullptr, BASIC_MOUNT_FLAGS, nullptr);
1567 return ret;
1568 }
1569
CheckAppFullMountEnable()1570 int32_t SandboxUtils::CheckAppFullMountEnable()
1571 {
1572 if (deviceTypeEnable_ != -1) {
1573 return deviceTypeEnable_;
1574 }
1575
1576 char value[] = "false";
1577 int32_t ret = GetParameter("const.filemanager.full_mount.enable", "false", value, sizeof(value));
1578 if (ret > 0 && (strcmp(value, "true")) == 0) {
1579 deviceTypeEnable_ = FILE_CROSS_APP_STATUS;
1580 } else if (ret > 0 && (strcmp(value, "false")) == 0) {
1581 deviceTypeEnable_ = FILE_ACCESS_COMMON_DIR_STATUS;
1582 } else {
1583 deviceTypeEnable_ = -1;
1584 }
1585
1586 return deviceTypeEnable_;
1587 }
1588
SetSandboxProperty(AppSpawningCtx * appProperty,std::string & sandboxPackagePath)1589 int32_t SandboxUtils::SetSandboxProperty(AppSpawningCtx *appProperty, std::string &sandboxPackagePath)
1590 {
1591 int32_t ret = 0;
1592 const std::string bundleName = GetBundleName(appProperty);
1593 ret = SetCommonAppSandboxProperty(appProperty, sandboxPackagePath);
1594 APPSPAWN_CHECK(ret == 0, return ret, "SetCommonAppSandboxProperty failed, packagename is %{public}s",
1595 bundleName.c_str());
1596 if (CheckBundleNameForPrivate(bundleName)) {
1597 ret = SetPrivateAppSandboxProperty(appProperty);
1598 APPSPAWN_CHECK(ret == 0, return ret, "SetPrivateAppSandboxProperty failed, packagename is %{public}s",
1599 bundleName.c_str());
1600 }
1601 ret = SetPermissionAppSandboxProperty(appProperty);
1602 APPSPAWN_CHECK(ret == 0, return ret, "SetPermissionAppSandboxProperty failed, packagename is %{public}s",
1603 bundleName.c_str());
1604
1605 ret = SetOverlayAppSandboxProperty(appProperty, sandboxPackagePath);
1606 APPSPAWN_CHECK(ret == 0, return ret, "SetOverlayAppSandboxProperty failed, packagename is %{public}s",
1607 bundleName.c_str());
1608
1609 ret = SetBundleResourceAppSandboxProperty(appProperty, sandboxPackagePath);
1610 APPSPAWN_CHECK(ret == 0, return ret, "SetBundleResourceAppSandboxProperty failed, packagename is %{public}s",
1611 bundleName.c_str());
1612 APPSPAWN_LOGV("Set appsandbox property success");
1613 return ret;
1614 }
1615
ChangeCurrentDir(std::string & sandboxPackagePath,const std::string & bundleName,bool sandboxSharedStatus)1616 int32_t SandboxUtils::ChangeCurrentDir(std::string &sandboxPackagePath, const std::string &bundleName,
1617 bool sandboxSharedStatus)
1618 {
1619 int32_t ret = 0;
1620 ret = chdir(sandboxPackagePath.c_str());
1621 APPSPAWN_CHECK(ret == 0, return ret, "chdir failed, packagename is %{public}s, path is %{public}s",
1622 bundleName.c_str(), sandboxPackagePath.c_str());
1623
1624 if (sandboxSharedStatus) {
1625 ret = chroot(sandboxPackagePath.c_str());
1626 APPSPAWN_CHECK(ret == 0, return ret, "chroot failed, path is %{public}s errno is %{public}d",
1627 sandboxPackagePath.c_str(), errno);
1628 return ret;
1629 }
1630
1631 ret = syscall(SYS_pivot_root, sandboxPackagePath.c_str(), sandboxPackagePath.c_str());
1632 APPSPAWN_CHECK(ret == 0, return ret, "errno is %{public}d, pivot root failed, packagename is %{public}s",
1633 errno, bundleName.c_str());
1634
1635 ret = umount2(".", MNT_DETACH);
1636 APPSPAWN_CHECK(ret == 0, return ret, "MNT_DETACH failed, packagename is %{public}s", bundleName.c_str());
1637 return ret;
1638 }
1639
EnableSandboxNamespace(AppSpawningCtx * appProperty,uint32_t sandboxNsFlags)1640 static int EnableSandboxNamespace(AppSpawningCtx *appProperty, uint32_t sandboxNsFlags)
1641 {
1642 #ifdef APPSPAWN_HISYSEVENT
1643 struct timespec startClock = {0};
1644 clock_gettime(CLOCK_MONOTONIC, &startClock);
1645 #endif
1646 int rc = unshare(sandboxNsFlags);
1647 #ifdef APPSPAWN_HISYSEVENT
1648 struct timespec endClock = {0};
1649 clock_gettime(CLOCK_MONOTONIC, &endClock);
1650 uint64_t diff = DiffTime(&startClock, &endClock);
1651 APPSPAWN_CHECK_ONLY_EXPER(diff < FUNC_REPORT_DURATION, ReportAbnormalDuration("unshare", diff));
1652 #endif
1653 APPSPAWN_CHECK(rc == 0, return rc, "unshare failed, packagename is %{public}s", GetBundleName(appProperty));
1654
1655 if ((sandboxNsFlags & CLONE_NEWNET) == CLONE_NEWNET) {
1656 rc = EnableNewNetNamespace();
1657 APPSPAWN_CHECK(rc == 0, return rc, "Set new netnamespace failed %{public}s", GetBundleName(appProperty));
1658 }
1659 return 0;
1660 }
1661
SetPermissionWithParam(AppSpawningCtx * appProperty)1662 int32_t SandboxUtils::SetPermissionWithParam(AppSpawningCtx *appProperty)
1663 {
1664 int32_t index = 0;
1665 int32_t appFullMountStatus = CheckAppFullMountEnable();
1666 if (appFullMountStatus == FILE_CROSS_APP_STATUS) {
1667 index = GetPermissionIndex(nullptr, FILE_CROSS_APP_MODE.c_str());
1668 } else if (appFullMountStatus == FILE_ACCESS_COMMON_DIR_STATUS) {
1669 index = GetPermissionIndex(nullptr, FILE_ACCESS_COMMON_DIR_MODE.c_str());
1670 }
1671
1672 int32_t fileMgrIndex = GetPermissionIndex(nullptr, FILE_ACCESS_MANAGER_MODE.c_str());
1673 if (index > 0 && fileMgrIndex > 0 &&
1674 (CheckAppPermissionFlagSet(appProperty, static_cast<uint32_t>(fileMgrIndex)) == 0)) {
1675 return SetAppPermissionFlags(appProperty, index);
1676 }
1677 return -1;
1678 }
1679
SetAppSandboxProperty(AppSpawningCtx * appProperty,uint32_t sandboxNsFlags)1680 int32_t SandboxUtils::SetAppSandboxProperty(AppSpawningCtx *appProperty, uint32_t sandboxNsFlags)
1681 {
1682 APPSPAWN_CHECK(appProperty != nullptr, return -1, "Invalid appspwn client");
1683 if (CheckBundleName(GetBundleName(appProperty)) != 0) {
1684 return -1;
1685 }
1686 AppSpawnMsgDacInfo *dacInfo = reinterpret_cast<AppSpawnMsgDacInfo *>(GetAppProperty(appProperty, TLV_DAC_INFO));
1687 if (dacInfo == nullptr) {
1688 return -1;
1689 }
1690
1691 std::string sandboxPackagePath = g_sandBoxRootDir + to_string(dacInfo->uid / UID_BASE) + "/";
1692 const std::string bundleName = GetBundleName(appProperty);
1693 bool sandboxSharedStatus = GetSandboxPrivateSharedStatus(bundleName, appProperty) ||
1694 (CheckAppPermissionFlagSet(appProperty, static_cast<uint32_t>(GetPermissionIndex(nullptr,
1695 ACCESS_DLP_FILE_MODE.c_str()))) != 0);
1696 sandboxPackagePath += CheckAppMsgFlagsSet(appProperty, APP_FLAGS_ISOLATED_SANDBOX_TYPE) ? "isolated/" : "";
1697 sandboxPackagePath += bundleName;
1698 MakeDirRecursiveWithClock(sandboxPackagePath.c_str(), FILE_MODE);
1699
1700 // add pid to a new mnt namespace
1701 int rc = EnableSandboxNamespace(appProperty, sandboxNsFlags);
1702 APPSPAWN_CHECK(rc == 0, return rc, "unshare failed, packagename is %{public}s", bundleName.c_str());
1703 if (SetPermissionWithParam(appProperty) != 0) {
1704 APPSPAWN_LOGW("Set app permission flag fail.");
1705 }
1706 // check app sandbox switch
1707 if ((CheckTotalSandboxSwitchStatus(appProperty) == false) ||
1708 (CheckAppSandboxSwitchStatus(appProperty) == false)) {
1709 rc = DoSandboxRootFolderCreateAdapt(sandboxPackagePath);
1710 } else if (!sandboxSharedStatus) {
1711 rc = DoSandboxRootFolderCreate(appProperty, sandboxPackagePath);
1712 }
1713 APPSPAWN_CHECK(rc == 0, return rc, "DoSandboxRootFolderCreate failed, %{public}s", bundleName.c_str());
1714 rc = SetSandboxProperty(appProperty, sandboxPackagePath);
1715 APPSPAWN_CHECK(rc == 0, return rc, "SetSandboxProperty failed, %{public}s", bundleName.c_str());
1716
1717 #ifndef APPSPAWN_TEST
1718 rc = ChangeCurrentDir(sandboxPackagePath, bundleName, sandboxSharedStatus);
1719 APPSPAWN_CHECK(rc == 0, return rc, "change current dir failed");
1720 APPSPAWN_LOGV("Change root dir success");
1721 #endif
1722 return 0;
1723 }
1724
SetAppSandboxPropertyNweb(AppSpawningCtx * appProperty,uint32_t sandboxNsFlags)1725 int32_t SandboxUtils::SetAppSandboxPropertyNweb(AppSpawningCtx *appProperty, uint32_t sandboxNsFlags)
1726 {
1727 APPSPAWN_CHECK(appProperty != nullptr, return -1, "Invalid appspwn client");
1728 if (CheckBundleName(GetBundleName(appProperty)) != 0) {
1729 return -1;
1730 }
1731 std::string sandboxPackagePath = g_sandBoxRootDirNweb;
1732 const std::string bundleName = GetBundleName(appProperty);
1733 bool sandboxSharedStatus = GetSandboxPrivateSharedStatus(bundleName, appProperty);
1734 sandboxPackagePath += bundleName;
1735 MakeDirRecursiveWithClock(sandboxPackagePath.c_str(), FILE_MODE);
1736
1737 // add pid to a new mnt namespace
1738 int rc = EnableSandboxNamespace(appProperty, sandboxNsFlags);
1739 APPSPAWN_CHECK(rc == 0, return rc, "unshare failed, packagename is %{public}s", bundleName.c_str());
1740
1741 // check app sandbox switch
1742 if ((CheckTotalSandboxSwitchStatus(appProperty) == false) ||
1743 (CheckAppSandboxSwitchStatus(appProperty) == false)) {
1744 rc = DoSandboxRootFolderCreateAdapt(sandboxPackagePath);
1745 } else if (!sandboxSharedStatus) {
1746 rc = DoSandboxRootFolderCreate(appProperty, sandboxPackagePath);
1747 }
1748 APPSPAWN_CHECK(rc == 0, return rc, "DoSandboxRootFolderCreate failed, %{public}s", bundleName.c_str());
1749 // rendering process can be created by different apps,
1750 // and the bundle names of these apps are different,
1751 // so we can't use the method SetPrivateAppSandboxProperty
1752 // which mount dirs by using bundle name.
1753 rc = SetRenderSandboxPropertyNweb(appProperty, sandboxPackagePath);
1754 APPSPAWN_CHECK(rc == 0, return rc, "SetRenderSandboxPropertyNweb failed, packagename is %{public}s",
1755 sandboxPackagePath.c_str());
1756
1757 rc = SetOverlayAppSandboxProperty(appProperty, sandboxPackagePath);
1758 APPSPAWN_CHECK(rc == 0, return rc, "SetOverlayAppSandboxProperty failed, packagename is %{public}s",
1759 bundleName.c_str());
1760
1761 rc = SetBundleResourceAppSandboxProperty(appProperty, sandboxPackagePath);
1762 APPSPAWN_CHECK(rc == 0, return rc, "SetBundleResourceAppSandboxProperty failed, packagename is %{public}s",
1763 bundleName.c_str());
1764
1765 #ifndef APPSPAWN_TEST
1766 rc = chdir(sandboxPackagePath.c_str());
1767 APPSPAWN_CHECK(rc == 0, return rc, "chdir failed, packagename is %{public}s, path is %{public}s",
1768 bundleName.c_str(), sandboxPackagePath.c_str());
1769
1770 if (sandboxSharedStatus) {
1771 rc = chroot(sandboxPackagePath.c_str());
1772 APPSPAWN_CHECK(rc == 0, return rc, "chroot failed, path is %{public}s errno is %{public}d",
1773 sandboxPackagePath.c_str(), errno);
1774 return 0;
1775 }
1776
1777 rc = syscall(SYS_pivot_root, sandboxPackagePath.c_str(), sandboxPackagePath.c_str());
1778 APPSPAWN_CHECK(rc == 0, return rc, "errno is %{public}d, pivot root failed, packagename is %{public}s",
1779 errno, bundleName.c_str());
1780
1781 rc = umount2(".", MNT_DETACH);
1782 APPSPAWN_CHECK(rc == 0, return rc, "MNT_DETACH failed, packagename is %{public}s", bundleName.c_str());
1783 #endif
1784 return 0;
1785 }
1786 } // namespace AppSpawn
1787 } // namespace OHOS
1788
AppSandboxPidNsIsSupport(void)1789 static bool AppSandboxPidNsIsSupport(void)
1790 {
1791 char buffer[10] = {0};
1792 uint32_t buffSize = sizeof(buffer);
1793
1794 if (SystemGetParameter("const.sandbox.pidns.support", buffer, &buffSize) != 0) {
1795 return true;
1796 }
1797 if (!strcmp(buffer, "false")) {
1798 return false;
1799 }
1800 return true;
1801 }
1802
LoadAppSandboxConfig(AppSpawnMgr * content)1803 int LoadAppSandboxConfig(AppSpawnMgr *content)
1804 {
1805 bool rc = true;
1806 // load sandbox config
1807 nlohmann::json appSandboxConfig;
1808 CfgFiles *files = GetCfgFiles("etc/sandbox");
1809 for (int i = 0; (files != nullptr) && (i < MAX_CFG_POLICY_DIRS_CNT); ++i) {
1810 if (files->paths[i] == nullptr) {
1811 continue;
1812 }
1813 std::string path = files->paths[i];
1814 std::string appPath = path + OHOS::AppSpawn::APP_JSON_CONFIG;
1815 APPSPAWN_LOGI("LoadAppSandboxConfig %{public}s", appPath.c_str());
1816 rc = OHOS::AppSpawn::JsonUtils::GetJsonObjFromJson(appSandboxConfig, appPath);
1817 APPSPAWN_CHECK(rc, continue, "Failed to load app data sandbox config %{public}s", appPath.c_str());
1818 OHOS::AppSpawn::SandboxUtils::StoreJsonConfig(appSandboxConfig, SANBOX_APP_JSON_CONFIG);
1819
1820 std::string isolatedPath = path + OHOS::AppSpawn::APP_ISOLATED_JSON_CONFIG;
1821 APPSPAWN_LOGI("LoadAppSandboxConfig %{public}s", isolatedPath.c_str());
1822 rc = OHOS::AppSpawn::JsonUtils::GetJsonObjFromJson(appSandboxConfig, isolatedPath);
1823 APPSPAWN_CHECK(rc, continue, "Failed to load app data sandbox config %{public}s", isolatedPath.c_str());
1824 OHOS::AppSpawn::SandboxUtils::StoreJsonConfig(appSandboxConfig, SANBOX_ISOLATED_JSON_CONFIG);
1825 }
1826 FreeCfgFiles(files);
1827 bool isNweb = IsNWebSpawnMode(content);
1828 if (!isNweb && !AppSandboxPidNsIsSupport()) {
1829 return 0;
1830 }
1831 content->content.sandboxNsFlags = OHOS::AppSpawn::SandboxUtils::GetSandboxNsFlags(isNweb);
1832 return 0;
1833 }
1834
SetAppSandboxProperty(AppSpawnMgr * content,AppSpawningCtx * property)1835 int32_t SetAppSandboxProperty(AppSpawnMgr *content, AppSpawningCtx *property)
1836 {
1837 APPSPAWN_CHECK(property != nullptr, return -1, "Invalid appspwn client");
1838 APPSPAWN_CHECK(content != nullptr, return -1, "Invalid appspwn content");
1839 // clear g_mountInfo in the child process
1840 std::map<std::string, int>* mapPtr = static_cast<std::map<std::string, int>*>(GetEl1BundleMountCount());
1841 if (mapPtr == nullptr) {
1842 APPSPAWN_LOGE("Get el1 bundle mount count failed");
1843 return APPSPAWN_ARG_INVALID;
1844 }
1845 mapPtr->clear();
1846 int ret = 0;
1847 // no sandbox
1848 if (CheckAppMsgFlagsSet(property, APP_FLAGS_NO_SANDBOX)) {
1849 return 0;
1850 }
1851 if ((content->content.sandboxNsFlags & CLONE_NEWPID) == CLONE_NEWPID) {
1852 ret = getprocpid();
1853 if (ret < 0) {
1854 return ret;
1855 }
1856 }
1857 uint32_t sandboxNsFlags = CLONE_NEWNS;
1858 if ((CheckAppMsgFlagsSet(property, APP_FLAGS_ISOLATED_SANDBOX) && !IsDeveloperModeOpen()) ||
1859 CheckAppMsgFlagsSet(property, APP_FLAGS_ISOLATED_NETWORK)) {
1860 sandboxNsFlags |= content->content.sandboxNsFlags & CLONE_NEWNET ? CLONE_NEWNET : 0;
1861 }
1862 APPSPAWN_LOGV("SetAppSandboxProperty sandboxNsFlags 0x%{public}x", sandboxNsFlags);
1863 StartAppspawnTrace("SetAppSandboxProperty");
1864 if (IsNWebSpawnMode(content)) {
1865 ret = OHOS::AppSpawn::SandboxUtils::SetAppSandboxPropertyNweb(property, sandboxNsFlags);
1866 } else {
1867 ret = OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(property, sandboxNsFlags);
1868 }
1869 FinishAppspawnTrace();
1870 // for module test do not create sandbox, use APP_FLAGS_IGNORE_SANDBOX to ignore sandbox result
1871 if (CheckAppMsgFlagsSet(property, APP_FLAGS_IGNORE_SANDBOX)) {
1872 APPSPAWN_LOGW("Do not care sandbox result %{public}d", ret);
1873 return 0;
1874 }
1875 return ret;
1876 }
1877
1878 #define USER_ID_SIZE 16
1879 #define DIR_MODE 0711
1880
SpawnMountDirToShared(AppSpawnMgr * content,AppSpawningCtx * property)1881 static int SpawnMountDirToShared(AppSpawnMgr *content, AppSpawningCtx *property)
1882 {
1883 #ifndef APPSPAWN_SANDBOX_NEW
1884 if (!IsNWebSpawnMode(content)) {
1885 // mount dynamic directory
1886 MountToShared(content, property);
1887 }
1888 #endif
1889 return 0;
1890 }
1891
UmountDir(const char * rootPath,const char * targetPath,const AppSpawnedProcessInfo * appInfo)1892 static void UmountDir(const char *rootPath, const char *targetPath, const AppSpawnedProcessInfo *appInfo)
1893 {
1894 size_t allPathSize = strlen(rootPath) + USER_ID_SIZE + strlen(appInfo->name) + strlen(targetPath) + 2;
1895 char *path = reinterpret_cast<char *>(malloc(sizeof(char) * (allPathSize)));
1896 APPSPAWN_CHECK(path != NULL, return, "Failed to malloc path");
1897
1898 int ret = sprintf_s(path, allPathSize, "%s%u/%s%s", rootPath, appInfo->uid / UID_BASE,
1899 appInfo->name, targetPath);
1900 APPSPAWN_CHECK(ret > 0 && ((size_t)ret < allPathSize), free(path);
1901 return, "Failed to get sandbox path errno %{public}d", errno);
1902
1903 ret = umount2(path, MNT_DETACH);
1904 if (ret == 0) {
1905 APPSPAWN_LOGI("Umount2 sandbox path %{public}s success", path);
1906 } else {
1907 APPSPAWN_LOGW("Failed to umount2 sandbox path %{public}s errno %{public}d", path, errno);
1908 }
1909 free(path);
1910 }
1911
UmountSandboxPath(const AppSpawnMgr * content,const AppSpawnedProcessInfo * appInfo)1912 static int UmountSandboxPath(const AppSpawnMgr *content, const AppSpawnedProcessInfo *appInfo)
1913 {
1914 APPSPAWN_CHECK(content != NULL && appInfo != NULL && appInfo->name != NULL,
1915 return -1, "Invalid content or appInfo");
1916 if (IsNWebSpawnMode(content)) {
1917 return 0;
1918 }
1919 APPSPAWN_LOGV("UmountSandboxPath name %{public}s pid %{public}d", appInfo->name, appInfo->pid);
1920 const char rootPath[] = "/mnt/sandbox/";
1921 const char el1Path[] = "/data/storage/el1/bundle";
1922
1923 uint32_t userId = appInfo->uid / UID_BASE;
1924 std::string key = std::to_string(userId) + "-" + std::string(appInfo->name);
1925 map<string, int> *el1BundleCountMap = static_cast<std::map<std::string, int>*>(GetEl1BundleMountCount());
1926 if (el1BundleCountMap == nullptr || el1BundleCountMap->find(key) == el1BundleCountMap->end()) {
1927 return 0;
1928 }
1929 (*el1BundleCountMap)[key]--;
1930 if ((*el1BundleCountMap)[key] == 0) {
1931 APPSPAWN_LOGV("no app %{public}s use it in userId %{public}u, need umount", appInfo->name, userId);
1932 UmountDir(rootPath, el1Path, appInfo);
1933 el1BundleCountMap->erase(key);
1934 } else {
1935 APPSPAWN_LOGV("app %{public}s use it mount times %{public}d in userId %{public}u, not need umount",
1936 appInfo->name, (*el1BundleCountMap)[key], userId);
1937 }
1938 return 0;
1939 }
1940
1941 #ifndef APPSPAWN_SANDBOX_NEW
MODULE_CONSTRUCTOR(void)1942 MODULE_CONSTRUCTOR(void)
1943 {
1944 APPSPAWN_LOGV("Load sandbox module ...");
1945 (void)AddServerStageHook(STAGE_SERVER_PRELOAD, HOOK_PRIO_SANDBOX, LoadAppSandboxConfig);
1946 (void)AddAppSpawnHook(STAGE_PARENT_PRE_FORK, HOOK_PRIO_COMMON, SpawnMountDirToShared);
1947 (void)AddAppSpawnHook(STAGE_CHILD_EXECUTE, HOOK_PRIO_SANDBOX, SetAppSandboxProperty);
1948 (void)AddProcessMgrHook(STAGE_SERVER_APP_UMOUNT, HOOK_PRIO_SANDBOX, UmountSandboxPath);
1949 }
1950 #endif
1951