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