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