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