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