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