• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "sandbox_utils.h"
17 
18 #include <algorithm>
19 #include <fcntl.h>
20 #include <set>
21 #include <unistd.h>
22 #include <vector>
23 
24 #include <sys/mount.h>
25 #include <sys/stat.h>
26 #include <sys/syscall.h>
27 #include <sys/types.h>
28 #include <cerrno>
29 #include <set>
30 
31 #include "json_utils.h"
32 #include "securec.h"
33 #include "appspawn_server.h"
34 #include "appspawn_service.h"
35 #include "appspawn_mount_permission.h"
36 #include "parameter.h"
37 #include "os_account_manager.h"
38 
39 #ifdef WITH_SELINUX
40 #include "hap_restorecon.h"
41 #endif
42 
43 using namespace std;
44 using namespace OHOS;
45 
46 namespace OHOS {
47 namespace AppSpawn {
48 namespace {
49     constexpr int32_t UID_BASE = 200000;
50     constexpr int32_t FUSE_OPTIONS_MAX_LEN = 256;
51     constexpr int32_t DLP_FUSE_FD = 1000;
52     constexpr static mode_t FILE_MODE = 0711;
53     constexpr static mode_t BASIC_MOUNT_FLAGS = MS_REC | MS_BIND;
54     constexpr std::string_view APL_SYSTEM_CORE("system_core");
55     constexpr std::string_view APL_SYSTEM_BASIC("system_basic");
56     const std::string g_physicalAppInstallPath = "/data/app/el1/bundle/public/";
57     const std::string g_sandboxGroupPath = "/data/storage/el2/group/";
58     const std::string g_sandboxHspInstallPath = "/data/storage/el1/bundle/";
59     const std::string g_sandBoxAppInstallPath = "/data/accounts/account_0/applications/";
60     const std::string g_bundleResourceSrcPath = "/data/service/el1/public/bms/bundle_resources/";
61     const std::string g_bundleResourceDestPath = "/data/storage/bundle_resources/";
62     const std::string g_dataBundles = "/data/bundles/";
63     const std::string g_userId = "<currentUserId>";
64     const std::string g_packageName = "<PackageName>";
65     const std::string g_packageNameIndex = "<PackageName_index>";
66     const std::string g_sandBoxDir = "/mnt/sandbox/";
67     const std::string g_statusCheck = "true";
68     const std::string g_sbxSwitchCheck = "ON";
69     const std::string g_dlpBundleName = "com.ohos.dlpmanager";
70     const std::string g_dlpUiExtType = "sys/commonUI";
71     const std::string g_internal = "__internal__";
72     const std::string g_hspList_key_bundles = "bundles";
73     const std::string g_hspList_key_modules = "modules";
74     const std::string g_hspList_key_versions = "versions";
75     const std::string g_overlayPath = "/data/storage/overlay/";
76     const std::string g_groupList_key_dataGroupId = "dataGroupId";
77     const std::string g_groupList_key_gid = "gid";
78     const std::string g_groupList_key_dir = "dir";
79     const std::string HSPLIST_SOCKET_TYPE = "|HspList|";
80     const std::string OVERLAY_SOCKET_TYPE = "|Overlay|";
81     const std::string DATA_GROUP_SOCKET_TYPE = "|DataGroup|";
82     const char *g_actionStatuc = "check-action-status";
83     const char *g_appBase = "app-base";
84     const char *g_appResources = "app-resources";
85     const char *g_appAplName = "app-apl-name";
86     const char *g_commonPrefix = "common";
87     const char *g_destMode = "dest-mode";
88     const char *g_fsType = "fs-type";
89     const char *g_linkName = "link-name";
90     const char *g_mountPrefix = "mount-paths";
91     const char *g_gidPrefix = "gids";
92     const char *g_privatePrefix = "individual";
93     const char *g_permissionPrefix = "permission";
94     const char *g_srcPath = "src-path";
95     const char *g_sandBoxPath = "sandbox-path";
96     const char *g_sandBoxFlags = "sandbox-flags";
97     const char *g_sandBoxFlagsCustomized = "sandbox-flags-customized";
98     const char *g_sandBoxOptions = "options";
99     const char *g_dacOverrideSensitive = "dac-override-sensitive";
100     const char *g_sandBoxShared = "sandbox-shared";
101     const char *g_sandBoxSwitchPrefix = "sandbox-switch";
102     const char *g_symlinkPrefix = "symbol-links";
103     const char *g_sandboxRootPrefix = "sandbox-root";
104     const char *g_topSandBoxSwitchPrefix = "top-sandbox-switch";
105     const char *g_targetName = "target-name";
106     const char *g_flagePoint = "flags-point";
107     const char *g_mountSharedFlag = "mount-shared-flag";
108     const char *g_flags = "flags";
109     const char *g_sandBoxNsFlags = "sandbox-ns-flags";
110     const char* g_fileSeparator = "/";
111     const char* g_overlayDecollator = "|";
112     const std::string g_sandBoxRootDir = "/mnt/sandbox/";
113     const std::string g_ohosRender = "__internal__.com.ohos.render";
114     const std::string g_sandBoxRootDirNweb = "/mnt/sandbox/com.ohos.render/";
115     constexpr int MAX_VALUE_LENGTH = PARAM_CONST_VALUE_LEN_MAX;
116     const std::string FILE_CROSS_APP_MODE = "ohos.permission.FILE_CROSS_APP";
117 }
118 
119 std::vector<nlohmann::json> SandboxUtils::appSandboxConfig_ = {};
120 bool SandboxUtils::deviceTypeEnable_ = false;
121 
StoreJsonConfig(nlohmann::json & appSandboxConfig)122 void SandboxUtils::StoreJsonConfig(nlohmann::json &appSandboxConfig)
123 {
124     SandboxUtils::appSandboxConfig_.push_back(appSandboxConfig);
125 }
126 
GetJsonConfig()127 std::vector<nlohmann::json> &SandboxUtils::GetJsonConfig()
128 {
129     return SandboxUtils::appSandboxConfig_;
130 }
131 
MakeDirRecursive(const std::string & path,mode_t mode)132 static void MakeDirRecursive(const std::string &path, mode_t mode)
133 {
134     size_t size = path.size();
135     if (size == 0) {
136         return;
137     }
138 
139     size_t index = 0;
140     do {
141         size_t pathIndex = path.find_first_of('/', index);
142         index = pathIndex == std::string::npos ? size : pathIndex + 1;
143         std::string dir = path.substr(0, index);
144 #ifndef APPSPAWN_TEST
145         APPSPAWN_CHECK(!(access(dir.c_str(), F_OK) < 0 && mkdir(dir.c_str(), mode) < 0),
146             return, "errno is %{public}d, mkdir %{public}s failed", errno, dir.c_str());
147 #endif
148     } while (index < size);
149 }
150 
DoAppSandboxMountOnce(const char * originPath,const char * destinationPath,const char * fsType,unsigned long mountFlags,const char * options,mode_t mountSharedFlag)151 int32_t SandboxUtils::DoAppSandboxMountOnce(const char *originPath, const char *destinationPath,
152                                             const char *fsType, unsigned long mountFlags,
153                                             const char *options, mode_t mountSharedFlag)
154 {
155     // To make sure destinationPath exist
156     MakeDirRecursive(destinationPath, FILE_MODE);
157 #ifndef APPSPAWN_TEST
158     int ret = 0;
159     // to mount fs and bind mount files or directory
160     ret = mount(originPath, destinationPath, fsType, mountFlags, options);
161     if (ret != 0) {
162         APPSPAWN_LOGI("errno is: %{public}d, bind mount %{public}s to %{public}s", errno, originPath,
163                       destinationPath);
164         return ret;
165     }
166     ret = mount(NULL, destinationPath, NULL, mountSharedFlag, NULL);
167     APPSPAWN_CHECK(ret == 0, return ret,
168         "errno is: %{public}d, private mount to %{public}s failed", errno, destinationPath);
169 #endif
170     return 0;
171 }
172 
replace_all(std::string & str,const std::string & old_value,const std::string & new_value)173 static std::string& replace_all(std::string& str, const std::string& old_value, const std::string& new_value)
174 {
175     while (true) {
176         std::string::size_type pos(0);
177         if ((pos = str.find(old_value)) != std::string::npos) {
178             str.replace(pos, old_value.length(), new_value);
179         } else {
180             break;
181         }
182     }
183     return str;
184 }
185 
split(std::string & str,const std::string & pattern)186 static std::vector<std::string> split(std::string &str, const std::string &pattern)
187 {
188     std::string::size_type pos;
189     std::vector<std::string> result;
190     str += pattern;
191     size_t size = str.size();
192 
193     for (unsigned int i = 0; i < size; i++) {
194         pos = str.find(pattern, i);
195         if (pos < size) {
196             std::string s = str.substr(i, pos - i);
197             result.push_back(s);
198             i = pos + pattern.size() - 1;
199         }
200     }
201 
202     return result;
203 }
204 
DoSandboxChmod(nlohmann::json jsonConfig,std::string & sandboxRoot)205 void SandboxUtils::DoSandboxChmod(nlohmann::json jsonConfig, std::string &sandboxRoot)
206 {
207     const std::map<std::string, mode_t> modeMap = {{"S_IRUSR", S_IRUSR}, {"S_IWUSR", S_IWUSR}, {"S_IXUSR", S_IXUSR},
208                                                    {"S_IRGRP", S_IRGRP}, {"S_IWGRP", S_IWGRP}, {"S_IXGRP", S_IXGRP},
209                                                    {"S_IROTH", S_IROTH}, {"S_IWOTH", S_IWOTH}, {"S_IXOTH", S_IXOTH},
210                                                    {"S_IRWXU", S_IRWXU}, {"S_IRWXG", S_IRWXG}, {"S_IRWXO", S_IRWXO}};
211     std::string fileModeStr;
212     mode_t mode = 0;
213 
214     bool rc = JsonUtils::GetStringFromJson(jsonConfig, g_destMode, fileModeStr);
215     if (rc == false) {
216         return;
217     }
218 
219     std::vector<std::string> modeVec = split(fileModeStr, "|");
220     for (unsigned int i = 0; i < modeVec.size(); i++) {
221         if (modeMap.count(modeVec[i])) {
222             mode |= modeMap.at(modeVec[i]);
223         }
224     }
225 
226     chmod(sandboxRoot.c_str(), mode);
227 }
228 
GetMountFlagsFromConfig(const std::vector<std::string> & vec)229 unsigned long SandboxUtils::GetMountFlagsFromConfig(const std::vector<std::string> &vec)
230 {
231     const std::map<std::string, mode_t> MountFlagsMap = { {"rec", MS_REC}, {"MS_REC", MS_REC},
232                                                           {"bind", MS_BIND}, {"MS_BIND", MS_BIND},
233                                                           {"move", MS_MOVE}, {"MS_MOVE", MS_MOVE},
234                                                           {"slave", MS_SLAVE}, {"MS_SLAVE", MS_SLAVE},
235                                                           {"rdonly", MS_RDONLY}, {"MS_RDONLY", MS_RDONLY},
236                                                           {"shared", MS_SHARED}, {"MS_SHARED", MS_SHARED},
237                                                           {"unbindable", MS_UNBINDABLE},
238                                                           {"MS_UNBINDABLE", MS_UNBINDABLE},
239                                                           {"remount", MS_REMOUNT}, {"MS_REMOUNT", MS_REMOUNT},
240                                                           {"nosuid", MS_NOSUID}, {"MS_NOSUID", MS_NOSUID},
241                                                           {"nodev", MS_NODEV}, {"MS_NODEV", MS_NODEV},
242                                                           {"noexec", MS_NOEXEC}, {"MS_NOEXEC", MS_NOEXEC},
243                                                           {"noatime", MS_NOATIME}, {"MS_NOATIME", MS_NOATIME},
244                                                           {"lazytime", MS_LAZYTIME}, {"MS_LAZYTIME", MS_LAZYTIME}};
245     unsigned long mountFlags = 0;
246 
247     for (unsigned int i = 0; i < vec.size(); i++) {
248         if (MountFlagsMap.count(vec[i])) {
249             mountFlags |= MountFlagsMap.at(vec[i]);
250         }
251     }
252 
253     return mountFlags;
254 }
255 
ConvertToRealPath(const ClientSocket::AppProperty * appProperty,std::string path)256 string SandboxUtils::ConvertToRealPath(const ClientSocket::AppProperty *appProperty, std::string path)
257 {
258     if (path.find(g_packageNameIndex) != std::string::npos) {
259         std::string bundleNameWithIndex = appProperty->bundleName;
260         if (appProperty->bundleIndex != 0) {
261             bundleNameWithIndex = std::to_string(appProperty->bundleIndex) + "_" + bundleNameWithIndex;
262         }
263         path = replace_all(path, g_packageNameIndex, bundleNameWithIndex);
264     }
265 
266     if (path.find(g_packageName) != std::string::npos) {
267         path = replace_all(path, g_packageName, appProperty->bundleName);
268     }
269 
270     if (path.find(g_userId) != std::string::npos) {
271         path = replace_all(path, g_userId, std::to_string(appProperty->uid / UID_BASE));
272     }
273 
274     return path;
275 }
276 
ConvertToRealPathWithPermission(const ClientSocket::AppProperty * appProperty,std::string path)277 std::string SandboxUtils::ConvertToRealPathWithPermission(const ClientSocket::AppProperty *appProperty,
278                                                           std::string path)
279 {
280     if (path.find(g_packageNameIndex) != std::string::npos) {
281         std::string bundleNameWithIndex = appProperty->bundleName;
282         if (appProperty->bundleIndex != 0) {
283             bundleNameWithIndex = std::to_string(appProperty->bundleIndex) + "_" + bundleNameWithIndex;
284         }
285         path = replace_all(path, g_packageNameIndex, bundleNameWithIndex);
286     }
287 
288     if (path.find(g_packageName) != std::string::npos) {
289         path = replace_all(path, g_packageName, appProperty->bundleName);
290     }
291 
292     if (path.find(g_userId) != std::string::npos) {
293         if (deviceTypeEnable_) {
294             path = replace_all(path, g_userId, "currentUser");
295         } else {
296             path = replace_all(path, g_userId, "currentUser");
297         }
298     }
299     return path;
300 }
301 
GetSandboxDacOverrideEnable(nlohmann::json & config)302 bool SandboxUtils::GetSandboxDacOverrideEnable(nlohmann::json &config)
303 {
304     std::string dacOverrideSensitive = "";
305     if (config.find(g_dacOverrideSensitive) == config.end()) {
306         return false;
307     }
308     dacOverrideSensitive = config[g_dacOverrideSensitive].get<std::string>();
309     if (dacOverrideSensitive.compare("true") == 0) {
310         return true;
311     }
312     return false;
313 }
314 
GetSbxPathByConfig(const ClientSocket::AppProperty * appProperty,nlohmann::json & config)315 std::string SandboxUtils::GetSbxPathByConfig(const ClientSocket::AppProperty *appProperty, nlohmann::json &config)
316 {
317     std::string sandboxRoot = "";
318     const std::string originSandboxPath = "/mnt/sandbox/<PackageName>";
319     const std::string defaultSandboxRoot = g_sandBoxDir + to_string(appProperty->uid / UID_BASE) +
320         "/" + appProperty->bundleName;
321     if (config.find(g_sandboxRootPrefix) != config.end()) {
322         sandboxRoot = config[g_sandboxRootPrefix].get<std::string>();
323         if (sandboxRoot == originSandboxPath) {
324             sandboxRoot = defaultSandboxRoot;
325         } else {
326             sandboxRoot = ConvertToRealPath(appProperty, sandboxRoot);
327         }
328     } else {
329         sandboxRoot = defaultSandboxRoot;
330         APPSPAWN_LOGI("set sandbox-root to default rootapp name is %{public}s", appProperty->bundleName);
331     }
332 
333     return sandboxRoot;
334 }
335 
GetSbxSwitchStatusByConfig(nlohmann::json & config)336 bool SandboxUtils::GetSbxSwitchStatusByConfig(nlohmann::json &config)
337 {
338     if (config.find(g_sandBoxSwitchPrefix) != config.end()) {
339         std::string switchStatus = config[g_sandBoxSwitchPrefix].get<std::string>();
340         if (switchStatus == g_sbxSwitchCheck) {
341             return true;
342         } else {
343             return false;
344         }
345     }
346 
347     // if not find sandbox-switch node, default switch status is true
348     return true;
349 }
350 
CheckMountConfig(nlohmann::json & mntPoint,const ClientSocket::AppProperty * appProperty,bool checkFlag)351 static bool CheckMountConfig(nlohmann::json &mntPoint, const ClientSocket::AppProperty *appProperty,
352                              bool checkFlag)
353 {
354     bool istrue = mntPoint.find(g_srcPath) == mntPoint.end() || mntPoint.find(g_sandBoxPath) == mntPoint.end() ||
355                   ((mntPoint.find(g_sandBoxFlags) == mntPoint.end()) &&
356                     (mntPoint.find(g_sandBoxFlagsCustomized) == mntPoint.end()));
357     APPSPAWN_CHECK(!istrue, return false, "read mount config failed, app name is %{public}s", appProperty->bundleName);
358 
359     if (mntPoint[g_appAplName] != nullptr) {
360         std::string app_apl_name = mntPoint[g_appAplName].get<std::string>();
361         const char *p_app_apl = nullptr;
362         p_app_apl = app_apl_name.c_str();
363         if (!strcmp(p_app_apl, appProperty->apl)) {
364             return false;
365         }
366     }
367 
368     const std::string configSrcPath = mntPoint[g_srcPath].get<std::string>();
369     // special handle wps and don't use /data/app/xxx/<Package> config
370     if (checkFlag && (configSrcPath.find("/data/app") != std::string::npos &&
371         (configSrcPath.find("/base") != std::string::npos ||
372          configSrcPath.find("/database") != std::string::npos
373         ) && configSrcPath.find(g_packageName) != std::string::npos)) {
374         return false;
375     }
376 
377     return true;
378 }
379 
DoDlpAppMountStrategy(const ClientSocket::AppProperty * appProperty,const std::string & srcPath,const std::string & sandboxPath,const std::string & fsType,unsigned long mountFlags)380 static int32_t DoDlpAppMountStrategy(const ClientSocket::AppProperty *appProperty,
381                                      const std::string &srcPath, const std::string &sandboxPath,
382                                      const std::string &fsType, unsigned long mountFlags)
383 {
384     // umount fuse path, make sure that sandbox path is not a mount point
385     umount2(sandboxPath.c_str(), MNT_DETACH);
386 
387     int fd = open("/dev/fuse", O_RDWR);
388     APPSPAWN_CHECK(fd != -1, return -EINVAL, "open /dev/fuse failed, errno is %{public}d", errno);
389 
390     char options[FUSE_OPTIONS_MAX_LEN];
391     (void)sprintf_s(options, sizeof(options), "fd=%d,"
392         "rootmode=40000,user_id=%d,group_id=%d,allow_other,"
393         "context=\"u:object_r:dlp_fuse_file:s0\","
394         "fscontext=u:object_r:dlp_fuse_file:s0",
395         fd, appProperty->uid, appProperty->gid);
396 
397     // To make sure destinationPath exist
398     MakeDirRecursive(sandboxPath, FILE_MODE);
399 
400     int ret = 0;
401 #ifndef APPSPAWN_TEST
402     ret = mount(srcPath.c_str(), sandboxPath.c_str(), fsType.c_str(), mountFlags, options);
403     APPSPAWN_CHECK(ret == 0, return ret, "DoDlpAppMountStrategy failed, bind mount %{public}s to %{public}s"
404         "failed %{public}d", srcPath.c_str(), sandboxPath.c_str(), errno);
405 
406     ret = mount(NULL, sandboxPath.c_str(), NULL, MS_SHARED, NULL);
407     APPSPAWN_CHECK(ret == 0, return ret,
408         "errno is: %{public}d, private mount to %{public}s failed", errno, sandboxPath.c_str());
409 #endif
410     /* close DLP_FUSE_FD and dup FD to it */
411     close(DLP_FUSE_FD);
412     ret = dup2(fd, DLP_FUSE_FD);
413     APPSPAWN_CHECK_ONLY_LOG(ret != -1, "dup fuse fd %{public}d failed, errno is %{public}d", fd, errno);
414     return ret;
415 }
416 
HandleSpecialAppMount(const ClientSocket::AppProperty * appProperty,const std::string & srcPath,const std::string & sandboxPath,const std::string & fsType,unsigned long mountFlags)417 static int32_t HandleSpecialAppMount(const ClientSocket::AppProperty *appProperty,
418                                      const std::string &srcPath, const std::string &sandboxPath,
419                                      const std::string &fsType, unsigned long mountFlags)
420 {
421     std::string bundleName = appProperty->bundleName;
422     std::string processName = appProperty->processName;
423 
424     /* dlp application mount strategy */
425     /* dlp is an example, we should change to real bundle name later */
426     if (bundleName.find(g_dlpBundleName) != std::string::npos &&
427         processName.find(g_dlpUiExtType) == std::string::npos) {
428         if (fsType.empty()) {
429             return -1;
430         } else {
431             return DoDlpAppMountStrategy(appProperty, srcPath, sandboxPath, fsType, mountFlags);
432         }
433     }
434 
435     return -1;
436 }
437 
ConvertFlagStr(const std::string & flagStr)438 static uint32_t ConvertFlagStr(const std::string &flagStr)
439 {
440     const std::map<std::string, int> flagsMap = {{"0", 0}, {"START_FLAGS_BACKUP", 1},
441                                                  {"DLP_MANAGER", 2}};
442 
443     if (flagsMap.count(flagStr)) {
444         return 1 << flagsMap.at(flagStr);
445     }
446 
447     return 0;
448 }
449 
GetSandboxMountFlags(nlohmann::json & config)450 unsigned long SandboxUtils::GetSandboxMountFlags(nlohmann::json &config)
451 {
452     unsigned long mountFlags;
453     if (GetSandboxDacOverrideEnable(config) && (deviceTypeEnable_ == true) &&
454         (config.find(g_sandBoxFlagsCustomized) != config.end())) {
455         mountFlags = GetMountFlagsFromConfig(config[g_sandBoxFlagsCustomized].get<std::vector<std::string>>());
456     } else {
457         mountFlags = GetMountFlagsFromConfig(config[g_sandBoxFlags].get<std::vector<std::string>>());
458     }
459     return mountFlags;
460 }
461 
GetSandboxFsType(nlohmann::json & config)462 const char *SandboxUtils::GetSandboxFsType(nlohmann::json &config)
463 {
464     std::string fsType;
465     if (GetSandboxDacOverrideEnable(config) && (deviceTypeEnable_ == true)
466         && (config.find(g_fsType) != config.end())) {
467         fsType = config[g_fsType].get<std::string>();
468     } else {
469         fsType = "";
470     }
471     const char *fsTypePoint = fsType.empty() ? nullptr : fsType.c_str();
472     return fsTypePoint;
473 }
474 
GetSandboxOptions(nlohmann::json & config)475 const char *SandboxUtils::GetSandboxOptions(nlohmann::json &config)
476 {
477     std::string options;
478     if (GetSandboxDacOverrideEnable(config) && (deviceTypeEnable_ == true) &&
479         (config.find(g_sandBoxOptions) != config.end())) {
480         options = config[g_sandBoxOptions].get<std::string>();
481     } else {
482         options = "";
483     }
484     const char *optionsPoint = options.empty() ? nullptr : options.c_str();
485     return optionsPoint;
486 }
487 
GetSandboxMountConfig(const std::string & section,nlohmann::json & mntPoint,SandboxMountConfig & mountConfig)488 void SandboxUtils::GetSandboxMountConfig(const std::string &section, nlohmann::json &mntPoint,
489                                          SandboxMountConfig &mountConfig)
490 {
491     if (section.compare(g_permissionPrefix) == 0) {
492         mountConfig.optionsPoint = GetSandboxOptions(mntPoint);
493         mountConfig.fsTypePoint = GetSandboxFsType(mntPoint);
494         mountConfig.fsType = (mountConfig.fsTypePoint != nullptr) ? mountConfig.fsTypePoint : "";
495     } else {
496         mountConfig.fsType = (mntPoint.find(g_fsType) != mntPoint.end()) ? mntPoint[g_fsType].get<std::string>() : "";
497         mountConfig.fsTypePoint = mountConfig.fsType.empty() ? nullptr : mountConfig.fsType.c_str();
498         mountConfig.optionsPoint = nullptr;
499     }
500     return;
501 }
502 
GetSandboxPath(const ClientSocket::AppProperty * appProperty,nlohmann::json & mntPoint,const std::string & section,std::string sandboxRoot)503 std::string SandboxUtils::GetSandboxPath(const ClientSocket::AppProperty *appProperty, nlohmann::json &mntPoint,
504                                      const std::string &section, std::string sandboxRoot)
505 {
506     std::string sandboxPath = "";
507     if (section.compare(g_permissionPrefix) == 0) {
508         sandboxPath = sandboxRoot + ConvertToRealPathWithPermission(appProperty,
509                                                                     mntPoint[g_sandBoxPath].get<std::string>());
510     } else {
511         sandboxPath = sandboxRoot + ConvertToRealPath(appProperty, mntPoint[g_sandBoxPath].get<std::string>());
512     }
513     return sandboxPath;
514 }
515 
DoAllMntPointsMount(const ClientSocket::AppProperty * appProperty,nlohmann::json & appConfig,const std::string & section)516 int SandboxUtils::DoAllMntPointsMount(const ClientSocket::AppProperty *appProperty,
517                                       nlohmann::json &appConfig, const std::string &section)
518 {
519     std::string bundleName = appProperty->bundleName;
520     if (appConfig.find(g_mountPrefix) == appConfig.end()) {
521         APPSPAWN_LOGV("mount config is not found in %{public}s, app name is %{public}s",
522             section.c_str(), bundleName.c_str());
523         return 0;
524     }
525 
526     bool checkFlag = false;
527     if (appConfig.find(g_flags) != appConfig.end()) {
528         if (((ConvertFlagStr(appConfig[g_flags].get<std::string>()) & appProperty->flags) != 0) &&
529             bundleName.find("wps") != std::string::npos) {
530             checkFlag = true;
531         }
532     }
533 
534     nlohmann::json mountPoints = appConfig[g_mountPrefix];
535     std::string sandboxRoot = GetSbxPathByConfig(appProperty, appConfig);
536     unsigned int mountPointSize = mountPoints.size();
537 
538     for (unsigned int i = 0; i < mountPointSize; i++) {
539         nlohmann::json mntPoint = mountPoints[i];
540 
541         if (CheckMountConfig(mntPoint, appProperty, checkFlag) == false) {
542             continue;
543         }
544 
545         std::string srcPath = ConvertToRealPath(appProperty, mntPoint[g_srcPath].get<std::string>());
546         std::string sandboxPath = GetSandboxPath(appProperty, mntPoint, section, sandboxRoot);
547         SandboxMountConfig mountConfig = {0};
548         GetSandboxMountConfig(section, mntPoint, mountConfig);
549         unsigned long mountFlags = GetSandboxMountFlags(mntPoint);
550         mode_t mountSharedFlag = (mntPoint.find(g_mountSharedFlag) != mntPoint.end()) ? MS_SHARED : MS_SLAVE;
551 
552         /* if app mount failed for special strategy, we need deal with common mount config */
553         int ret = HandleSpecialAppMount(appProperty, srcPath, sandboxPath, mountConfig.fsType, mountFlags);
554         if (ret < 0) {
555             ret = DoAppSandboxMountOnce(srcPath.c_str(), sandboxPath.c_str(), mountConfig.fsTypePoint,
556                                         mountFlags, mountConfig.optionsPoint, mountSharedFlag);
557         }
558         if (ret) {
559             std::string actionStatus = g_statusCheck;
560             (void)JsonUtils::GetStringFromJson(mntPoint, g_actionStatuc, actionStatus);
561             if (actionStatus == g_statusCheck) {
562                 APPSPAWN_LOGE("DoAppSandboxMountOnce section %{public}s failed, %{public}s",
563                     section.c_str(), sandboxPath.c_str());
564                 return ret;
565             }
566         }
567 
568         DoSandboxChmod(mntPoint, sandboxRoot);
569     }
570 
571     return 0;
572 }
573 
DoAddGid(ClientSocket::AppProperty * appProperty,nlohmann::json & appConfig,const char * permissionName,const std::string & section)574 int32_t SandboxUtils::DoAddGid(ClientSocket::AppProperty *appProperty, nlohmann::json &appConfig,
575                                const char* permissionName, const std::string &section)
576 {
577     std::string bundleName = appProperty->bundleName;
578     if (appConfig.find(g_gidPrefix) == appConfig.end()) {
579         APPSPAWN_LOGV("gids config is not found in %{public}s, app name is %{public}s permission is %{public}s",
580             section.c_str(), bundleName.c_str(), permissionName);
581         return 0;
582     }
583     nlohmann::json gids = appConfig[g_gidPrefix];
584     unsigned int gidSize = gids.size();
585     for (unsigned int i = 0; i < gidSize; i++) {
586         if (appProperty->gidCount < APP_MAX_GIDS) {
587             APPSPAWN_LOGI("add gid to gitTable in %{public}s, permission is %{public}s, gid:%{public}u",
588                 bundleName.c_str(), permissionName, gids[i].get<uint32_t>());
589             appProperty->gidTable[appProperty->gidCount++] = gids[i].get<uint32_t>();
590         }
591     }
592     return 0;
593 }
594 
DoAllSymlinkPointslink(const ClientSocket::AppProperty * appProperty,nlohmann::json & appConfig)595 int SandboxUtils::DoAllSymlinkPointslink(const ClientSocket::AppProperty *appProperty, nlohmann::json &appConfig)
596 {
597     APPSPAWN_CHECK(appConfig.find(g_symlinkPrefix) != appConfig.end(), return 0, "symlink config is not found,"
598         "maybe result sandbox launch failed app name is %{public}s", appProperty->bundleName);
599 
600     nlohmann::json symlinkPoints = appConfig[g_symlinkPrefix];
601     std::string sandboxRoot = GetSbxPathByConfig(appProperty, appConfig);
602     unsigned int symlinkPointSize = symlinkPoints.size();
603 
604     for (unsigned int i = 0; i < symlinkPointSize; i++) {
605         nlohmann::json symPoint = symlinkPoints[i];
606 
607         // Check the validity of the symlink configuration
608         if (symPoint.find(g_targetName) == symPoint.end() || symPoint.find(g_linkName) == symPoint.end()) {
609             APPSPAWN_LOGE("read symlink config failed, app name is %{public}s", appProperty->bundleName);
610             continue;
611         }
612 
613         std::string targetName = ConvertToRealPath(appProperty, symPoint[g_targetName].get<std::string>());
614         std::string linkName = sandboxRoot + ConvertToRealPath(appProperty, symPoint[g_linkName].get<std::string>());
615         APPSPAWN_LOGV("symlink, from %{public}s to %{public}s", targetName.c_str(), linkName.c_str());
616 
617         int ret = symlink(targetName.c_str(), linkName.c_str());
618         if (ret && errno != EEXIST) {
619             APPSPAWN_LOGE("errno is %{public}d, symlink failed, %{public}s", errno, linkName.c_str());
620 
621             std::string actionStatus = g_statusCheck;
622             (void)JsonUtils::GetStringFromJson(symPoint, g_actionStatuc, actionStatus);
623             if (actionStatus == g_statusCheck) {
624                 return ret;
625             }
626         }
627 
628         DoSandboxChmod(symPoint, sandboxRoot);
629     }
630 
631     return 0;
632 }
633 
DoSandboxFilePrivateBind(const ClientSocket::AppProperty * appProperty,nlohmann::json & wholeConfig)634 int32_t SandboxUtils::DoSandboxFilePrivateBind(const ClientSocket::AppProperty *appProperty,
635                                                nlohmann::json &wholeConfig)
636 {
637     nlohmann::json privateAppConfig = wholeConfig[g_privatePrefix][0];
638     if (privateAppConfig.find(appProperty->bundleName) != privateAppConfig.end()) {
639         APPSPAWN_LOGV("DoSandboxFilePrivateBind %{public}s", appProperty->bundleName);
640         return DoAllMntPointsMount(appProperty, privateAppConfig[appProperty->bundleName][0], g_privatePrefix);
641     }
642 
643     return 0;
644 }
645 
DoSandboxFilePermissionBind(ClientSocket::AppProperty * appProperty,nlohmann::json & wholeConfig)646 int32_t SandboxUtils::DoSandboxFilePermissionBind(ClientSocket::AppProperty *appProperty,
647                                                   nlohmann::json &wholeConfig)
648 {
649     if (wholeConfig.find(g_permissionPrefix) == wholeConfig.end()) {
650         APPSPAWN_LOGV("DoSandboxFilePermissionBind not found permission information in config file");
651         return 0;
652     }
653     nlohmann::json permissionAppConfig = wholeConfig[g_permissionPrefix][0];
654     for (nlohmann::json::iterator it = permissionAppConfig.begin(); it != permissionAppConfig.end(); ++it) {
655         const std::string permissionstr = it.key();
656         APPSPAWN_LOGV("DoSandboxFilePermissionBind mountPermissionFlags %{public}u",
657                       appProperty -> mountPermissionFlags);
658         if (AppspawnMountPermission::IsMountPermission(appProperty -> mountPermissionFlags, permissionstr)) {
659             DoAddGid(appProperty, permissionAppConfig[permissionstr][0], permissionstr.c_str(), g_permissionPrefix);
660             DoAllMntPointsMount(appProperty, permissionAppConfig[permissionstr][0], g_permissionPrefix);
661         } else {
662             APPSPAWN_LOGV("DoSandboxFilePermissionBind false %{public}s permission %{public}s",
663                 appProperty->bundleName, permissionstr.c_str());
664         }
665     }
666     return 0;
667 }
668 
GetMountPermissionNames()669 std::set<std::string> SandboxUtils::GetMountPermissionNames()
670 {
671     std::set<std::string> permissionSet;
672     for (auto config : SandboxUtils::GetJsonConfig()) {
673         if (config.find(g_permissionPrefix) == config.end()) {
674             continue;
675         }
676         nlohmann::json permissionAppConfig = config[g_permissionPrefix][0];
677         for (auto it = permissionAppConfig.begin(); it != permissionAppConfig.end(); it++) {
678             permissionSet.insert(it.key());
679         }
680     }
681     APPSPAWN_LOGI("GetMountPermissionNames size: %{public}lu", static_cast<unsigned long>(permissionSet.size()));
682     return permissionSet;
683 }
684 
DoSandboxFilePrivateSymlink(const ClientSocket::AppProperty * appProperty,nlohmann::json & wholeConfig)685 int32_t SandboxUtils::DoSandboxFilePrivateSymlink(const ClientSocket::AppProperty *appProperty,
686                                                   nlohmann::json &wholeConfig)
687 {
688     nlohmann::json privateAppConfig = wholeConfig[g_privatePrefix][0];
689     if (privateAppConfig.find(appProperty->bundleName) != privateAppConfig.end()) {
690         return DoAllSymlinkPointslink(appProperty, privateAppConfig[appProperty->bundleName][0]);
691     }
692 
693     return 0;
694 }
695 
HandleFlagsPoint(const ClientSocket::AppProperty * appProperty,nlohmann::json & appConfig)696 int32_t SandboxUtils::HandleFlagsPoint(const ClientSocket::AppProperty *appProperty,
697                                        nlohmann::json &appConfig)
698 {
699     if (appConfig.find(g_flagePoint) == appConfig.end()) {
700         return 0;
701     }
702 
703     nlohmann::json flagsPoints = appConfig[g_flagePoint];
704     unsigned int flagsPointSize = flagsPoints.size();
705 
706     for (unsigned int i = 0; i < flagsPointSize; i++) {
707         nlohmann::json flagPoint = flagsPoints[i];
708 
709         if (flagPoint.find(g_flags) != flagPoint.end()) {
710             std::string flagsStr = flagPoint[g_flags].get<std::string>();
711             uint32_t flag = ConvertFlagStr(flagsStr);
712             if ((appProperty->flags & flag) != 0) {
713                 return DoAllMntPointsMount(appProperty, flagPoint, g_flagePoint);
714             }
715         } else {
716             APPSPAWN_LOGE("read flags config failed, app name is %{public}s", appProperty->bundleName);
717         }
718     }
719 
720     return 0;
721 }
722 
DoSandboxFilePrivateFlagsPointHandle(const ClientSocket::AppProperty * appProperty,nlohmann::json & wholeConfig)723 int32_t SandboxUtils::DoSandboxFilePrivateFlagsPointHandle(const ClientSocket::AppProperty *appProperty,
724                                                            nlohmann::json &wholeConfig)
725 {
726     nlohmann::json privateAppConfig = wholeConfig[g_privatePrefix][0];
727     if (privateAppConfig.find(appProperty->bundleName) != privateAppConfig.end()) {
728         return HandleFlagsPoint(appProperty, privateAppConfig[appProperty->bundleName][0]);
729     }
730 
731     return 0;
732 }
733 
DoSandboxFileCommonFlagsPointHandle(const ClientSocket::AppProperty * appProperty,nlohmann::json & wholeConfig)734 int32_t SandboxUtils::DoSandboxFileCommonFlagsPointHandle(const ClientSocket::AppProperty *appProperty,
735                                                           nlohmann::json &wholeConfig)
736 {
737     nlohmann::json commonConfig = wholeConfig[g_commonPrefix][0];
738     if (commonConfig.find(g_appResources) != commonConfig.end()) {
739         return HandleFlagsPoint(appProperty, commonConfig[g_appResources][0]);
740     }
741 
742     return 0;
743 }
744 
DoSandboxFileCommonBind(const ClientSocket::AppProperty * appProperty,nlohmann::json & wholeConfig)745 int32_t SandboxUtils::DoSandboxFileCommonBind(const ClientSocket::AppProperty *appProperty, nlohmann::json &wholeConfig)
746 {
747     nlohmann::json commonConfig = wholeConfig[g_commonPrefix][0];
748     int ret = 0;
749 
750     if (commonConfig.find(g_appBase) != commonConfig.end()) {
751         ret = DoAllMntPointsMount(appProperty, commonConfig[g_appBase][0], g_appBase);
752         if (ret) {
753             return ret;
754         }
755     }
756 
757     if (commonConfig.find(g_appResources) != commonConfig.end()) {
758         ret = DoAllMntPointsMount(appProperty, commonConfig[g_appResources][0], g_appResources);
759     }
760 
761     return ret;
762 }
763 
DoSandboxFileCommonSymlink(const ClientSocket::AppProperty * appProperty,nlohmann::json & wholeConfig)764 int32_t SandboxUtils::DoSandboxFileCommonSymlink(const ClientSocket::AppProperty *appProperty,
765                                                  nlohmann::json &wholeConfig)
766 {
767     nlohmann::json commonConfig = wholeConfig[g_commonPrefix][0];
768     int ret = 0;
769 
770     if (commonConfig.find(g_appBase) != commonConfig.end()) {
771         ret = DoAllSymlinkPointslink(appProperty, commonConfig[g_appBase][0]);
772         if (ret) {
773             return ret;
774         }
775     }
776 
777     if (commonConfig.find(g_appResources) != commonConfig.end()) {
778         ret = DoAllSymlinkPointslink(appProperty, commonConfig[g_appResources][0]);
779     }
780 
781     return ret;
782 }
783 
SetPrivateAppSandboxProperty_(const ClientSocket::AppProperty * appProperty,nlohmann::json & config)784 int32_t SandboxUtils::SetPrivateAppSandboxProperty_(const ClientSocket::AppProperty *appProperty,
785                                                     nlohmann::json &config)
786 {
787     int ret = DoSandboxFilePrivateBind(appProperty, config);
788     APPSPAWN_CHECK(ret == 0, return ret, "DoSandboxFilePrivateBind failed");
789 
790     ret = DoSandboxFilePrivateSymlink(appProperty, config);
791     APPSPAWN_CHECK_ONLY_LOG(ret == 0, "DoSandboxFilePrivateSymlink failed");
792 
793     ret = DoSandboxFilePrivateFlagsPointHandle(appProperty, config);
794     APPSPAWN_CHECK_ONLY_LOG(ret == 0, "DoSandboxFilePrivateFlagsPointHandle failed");
795 
796     return ret;
797 }
798 
SetPermissionAppSandboxProperty_(ClientSocket::AppProperty * appProperty,nlohmann::json & config)799 int32_t SandboxUtils::SetPermissionAppSandboxProperty_(ClientSocket::AppProperty *appProperty,
800                                                        nlohmann::json &config)
801 {
802     int ret = DoSandboxFilePermissionBind(appProperty, config);
803     APPSPAWN_CHECK(ret == 0, return ret, "DoSandboxFilePermissionBind failed");
804     return ret;
805 }
806 
807 
SetRenderSandboxProperty(const ClientSocket::AppProperty * appProperty,std::string & sandboxPackagePath)808 int32_t SandboxUtils::SetRenderSandboxProperty(const ClientSocket::AppProperty *appProperty,
809                                                std::string &sandboxPackagePath)
810 {
811     return 0;
812 }
813 
SetRenderSandboxPropertyNweb(const ClientSocket::AppProperty * appProperty,std::string & sandboxPackagePath)814 int32_t SandboxUtils::SetRenderSandboxPropertyNweb(const ClientSocket::AppProperty *appProperty,
815                                                    std::string &sandboxPackagePath)
816 {
817     for (auto config : SandboxUtils::GetJsonConfig()) {
818         nlohmann::json privateAppConfig = config[g_privatePrefix][0];
819 
820         if (privateAppConfig.find(g_ohosRender) != privateAppConfig.end()) {
821             int ret = DoAllMntPointsMount(appProperty, privateAppConfig[g_ohosRender][0], g_ohosRender);
822             APPSPAWN_CHECK(ret == 0, return ret, "DoAllMntPointsMount failed, %{public}s",
823                 appProperty->bundleName);
824             ret = DoAllSymlinkPointslink(appProperty, privateAppConfig[g_ohosRender][0]);
825             APPSPAWN_CHECK(ret == 0, return ret, "DoAllSymlinkPointslink failed, %{public}s",
826                 appProperty->bundleName);
827             ret = HandleFlagsPoint(appProperty, privateAppConfig[g_ohosRender][0]);
828             APPSPAWN_CHECK_ONLY_LOG(ret == 0, "HandleFlagsPoint for render-sandbox failed, %{public}s",
829                 appProperty->bundleName);
830         }
831     }
832     return 0;
833 }
834 
SetPrivateAppSandboxProperty(const ClientSocket::AppProperty * appProperty)835 int32_t SandboxUtils::SetPrivateAppSandboxProperty(const ClientSocket::AppProperty *appProperty)
836 {
837     int ret = 0;
838     for (auto config : SandboxUtils::GetJsonConfig()) {
839         ret = SetPrivateAppSandboxProperty_(appProperty, config);
840         APPSPAWN_CHECK(ret == 0, return ret, "parse adddata-sandbox config failed");
841     }
842     return ret;
843 }
844 
GetSandboxPrivateSharedStatus(const string & bundleName)845 static bool GetSandboxPrivateSharedStatus(const string &bundleName)
846 {
847     bool result = false;
848     for (auto config : SandboxUtils::GetJsonConfig()) {
849         nlohmann::json privateAppConfig = config[g_privatePrefix][0];
850         if (privateAppConfig.find(bundleName) != privateAppConfig.end() &&
851             privateAppConfig[bundleName][0].find(g_sandBoxShared) !=
852             privateAppConfig[bundleName][0].end()) {
853             string sandboxSharedStatus =
854                 privateAppConfig[bundleName][0][g_sandBoxShared].get<std::string>();
855             if (sandboxSharedStatus == g_statusCheck) {
856                 result = true;
857             }
858         }
859     }
860     return result;
861 }
862 
SetPermissionAppSandboxProperty(ClientSocket::AppProperty * appProperty)863 int32_t SandboxUtils::SetPermissionAppSandboxProperty(ClientSocket::AppProperty *appProperty)
864 {
865     int ret = 0;
866     for (auto config : SandboxUtils::GetJsonConfig()) {
867         ret = SetPermissionAppSandboxProperty_(appProperty, config);
868         APPSPAWN_CHECK(ret == 0, return ret, "parse adddata-sandbox config failed");
869     }
870     return ret;
871 }
872 
873 
SetCommonAppSandboxProperty_(const ClientSocket::AppProperty * appProperty,nlohmann::json & config)874 int32_t SandboxUtils::SetCommonAppSandboxProperty_(const ClientSocket::AppProperty *appProperty,
875                                                    nlohmann::json &config)
876 {
877     int rc = 0;
878 
879     rc = DoSandboxFileCommonBind(appProperty, config);
880     APPSPAWN_CHECK(rc == 0, return rc, "DoSandboxFileCommonBind failed, %{public}s", appProperty->bundleName);
881 
882     // if sandbox switch is off, don't do symlink work again
883     if (CheckAppSandboxSwitchStatus(appProperty) == true && (CheckTotalSandboxSwitchStatus(appProperty) == true)) {
884         rc = DoSandboxFileCommonSymlink(appProperty, config);
885         APPSPAWN_CHECK(rc == 0, return rc, "DoSandboxFileCommonSymlink failed, %{public}s", appProperty->bundleName);
886     }
887 
888     rc = DoSandboxFileCommonFlagsPointHandle(appProperty, config);
889     APPSPAWN_CHECK_ONLY_LOG(rc == 0, "DoSandboxFilePrivateFlagsPointHandle failed");
890 
891     return rc;
892 }
893 
SetCommonAppSandboxProperty(const ClientSocket::AppProperty * appProperty,std::string & sandboxPackagePath)894 int32_t SandboxUtils::SetCommonAppSandboxProperty(const ClientSocket::AppProperty *appProperty,
895                                                   std::string &sandboxPackagePath)
896 {
897     int ret = 0;
898     for (auto jsonConfig : SandboxUtils::GetJsonConfig()) {
899         ret = SetCommonAppSandboxProperty_(appProperty, jsonConfig);
900         APPSPAWN_CHECK(ret == 0, return ret,
901             "parse appdata config for common failed, %{public}s", sandboxPackagePath.c_str());
902     }
903 
904     ret = MountAllHsp(appProperty, sandboxPackagePath);
905     APPSPAWN_CHECK(ret == 0, return ret, "mount extraInfo failed, %{public}s", sandboxPackagePath.c_str());
906 
907     ret = MountAllGroup(appProperty, sandboxPackagePath);
908     APPSPAWN_CHECK(ret == 0, return ret, "mount groupList failed, %{public}s", sandboxPackagePath.c_str());
909 
910     if (strcmp(appProperty->apl, APL_SYSTEM_BASIC.data()) == 0 ||
911         strcmp(appProperty->apl, APL_SYSTEM_CORE.data()) == 0 ||
912         (appProperty->flags & APP_ACCESS_BUNDLE_DIR) != 0) {
913         // need permission check for system app here
914         std::string destbundlesPath = sandboxPackagePath + g_dataBundles;
915         DoAppSandboxMountOnce(g_physicalAppInstallPath.c_str(), destbundlesPath.c_str(), "", BASIC_MOUNT_FLAGS,
916                               nullptr);
917     }
918 
919     return 0;
920 }
921 
CheckPath(const std::string & name)922 static inline bool CheckPath(const std::string& name)
923 {
924     return !name.empty() && name != "." && name != ".." && name.find("/") == std::string::npos;
925 }
926 
GetExtraInfoByType(const ClientSocket::AppProperty * appProperty,const std::string & type)927 static std::string GetExtraInfoByType(const ClientSocket::AppProperty *appProperty, const std::string &type)
928 {
929     if (appProperty->extraInfo.totalLength == 0 || appProperty->extraInfo.data == NULL) {
930         return "";
931     }
932 
933     std::string extraInfoStr = std::string(appProperty->extraInfo.data);
934     std::size_t firstPos = extraInfoStr.find(type);
935     if (firstPos == std::string::npos && firstPos != (extraInfoStr.size() - 1)) {
936         return "";
937     }
938 
939     extraInfoStr = extraInfoStr.substr(firstPos + type.size());
940     std::size_t secondPos = extraInfoStr.find(type);
941     if (secondPos == std::string::npos) {
942         return "";
943     }
944     return extraInfoStr.substr(0, secondPos);
945 }
946 
MountAllHsp(const ClientSocket::AppProperty * appProperty,std::string & sandboxPackagePath)947 int32_t SandboxUtils::MountAllHsp(const ClientSocket::AppProperty *appProperty, std::string &sandboxPackagePath)
948 {
949     int ret = 0;
950     string hspListInfo = GetExtraInfoByType(appProperty, HSPLIST_SOCKET_TYPE);
951     if (hspListInfo.length() == 0) {
952         return ret;
953     }
954 
955     nlohmann::json hsps = nlohmann::json::parse(hspListInfo.c_str(), nullptr, false);
956     APPSPAWN_CHECK(!hsps.is_discarded() && hsps.contains(g_hspList_key_bundles) && hsps.contains(g_hspList_key_modules)
957         && hsps.contains(g_hspList_key_versions), return -1, "MountAllHsp: json parse failed");
958 
959     nlohmann::json& bundles = hsps[g_hspList_key_bundles];
960     nlohmann::json& modules = hsps[g_hspList_key_modules];
961     nlohmann::json& versions = hsps[g_hspList_key_versions];
962     APPSPAWN_CHECK(bundles.is_array() && modules.is_array() && versions.is_array() && bundles.size() == modules.size()
963         && bundles.size() == versions.size(), return -1, "MountAllHsp: value is not arrary or sizes are not same");
964 
965     APPSPAWN_LOGI("MountAllHsp: app = %{public}s, cnt = %{public}lu",
966         appProperty->bundleName, static_cast<unsigned long>(bundles.size()));
967     for (uint32_t i = 0; i < bundles.size(); i++) {
968         // elements in json arrary can be different type
969         APPSPAWN_CHECK(bundles[i].is_string() && modules[i].is_string() && versions[i].is_string(),
970             return -1, "MountAllHsp: element type error");
971 
972         std::string libBundleName = bundles[i];
973         std::string libModuleName = modules[i];
974         std::string libVersion = versions[i];
975         APPSPAWN_CHECK(CheckPath(libBundleName) && CheckPath(libModuleName) && CheckPath(libVersion),
976             return -1, "MountAllHsp: path error");
977 
978         std::string libPhysicalPath = g_physicalAppInstallPath + libBundleName + "/" + libVersion + "/" + libModuleName;
979         std::string mntPath =  sandboxPackagePath + g_sandboxHspInstallPath + libBundleName + "/" + libModuleName;
980         ret = DoAppSandboxMountOnce(libPhysicalPath.c_str(), mntPath.c_str(), "", BASIC_MOUNT_FLAGS, nullptr);
981         APPSPAWN_CHECK(ret == 0, return ret, "mount library failed %{public}d", ret);
982     }
983     return ret;
984 }
985 
DoSandboxRootFolderCreateAdapt(std::string & sandboxPackagePath)986 int32_t SandboxUtils::DoSandboxRootFolderCreateAdapt(std::string &sandboxPackagePath)
987 {
988 #ifndef APPSPAWN_TEST
989     int rc = mount(NULL, "/", NULL, MS_REC | MS_SLAVE, NULL);
990     APPSPAWN_CHECK(rc == 0, return rc, "set propagation slave failed");
991 #endif
992     MakeDirRecursive(sandboxPackagePath, FILE_MODE);
993 
994     // bind mount "/" to /mnt/sandbox/<currentUserId>/<packageName> path
995     // rootfs: to do more resources bind mount here to get more strict resources constraints
996 #ifndef APPSPAWN_TEST
997     rc = mount("/", sandboxPackagePath.c_str(), NULL, BASIC_MOUNT_FLAGS, NULL);
998     APPSPAWN_CHECK(rc == 0, return rc, "mount bind / failed, %{public}d", errno);
999 #endif
1000     return 0;
1001 }
1002 
MountAllGroup(const ClientSocket::AppProperty * appProperty,std::string & sandboxPackagePath)1003 int32_t SandboxUtils::MountAllGroup(const ClientSocket::AppProperty *appProperty, std::string &sandboxPackagePath)
1004 {
1005     int ret = 0;
1006     string dataGroupInfo = GetExtraInfoByType(appProperty, DATA_GROUP_SOCKET_TYPE);
1007     if (dataGroupInfo.length() == 0) {
1008         return ret;
1009     }
1010 
1011     nlohmann::json groups = nlohmann::json::parse(dataGroupInfo.c_str(), nullptr, false);
1012     APPSPAWN_CHECK(!groups.is_discarded() && groups.contains(g_groupList_key_dataGroupId)
1013         && groups.contains(g_groupList_key_gid) && groups.contains(g_groupList_key_dir), return -1,
1014             "MountAllGroup: json parse failed");
1015 
1016     nlohmann::json& dataGroupIds = groups[g_groupList_key_dataGroupId];
1017     nlohmann::json& gids = groups[g_groupList_key_gid];
1018     nlohmann::json& dirs = groups[g_groupList_key_dir];
1019     APPSPAWN_CHECK(dataGroupIds.is_array() && gids.is_array() && dirs.is_array() && dataGroupIds.size() == gids.size()
1020         && dataGroupIds.size() == dirs.size(), return -1, "MountAllGroup: value is not arrary or sizes are not same");
1021     APPSPAWN_LOGI("MountAllGroup: app = %{public}s, cnt = %{public}lu",
1022         appProperty->bundleName, static_cast<unsigned long>(dataGroupIds.size()));
1023     for (uint32_t i = 0; i < dataGroupIds.size(); i++) {
1024         // elements in json arrary can be different type
1025         APPSPAWN_CHECK(dataGroupIds[i].is_string() && gids[i].is_string() && dirs[i].is_string(),
1026             return -1, "MountAllGroup: element type error");
1027 
1028         std::string libPhysicalPath = dirs[i];
1029         APPSPAWN_CHECK(!CheckPath(libPhysicalPath), return -1, "MountAllGroup: path error");
1030 
1031         size_t lastPathSplitPos = libPhysicalPath.find_last_of(g_fileSeparator);
1032         APPSPAWN_CHECK(lastPathSplitPos != std::string::npos, return -1, "MountAllGroup: path error");
1033 
1034         std::string dataGroupUuid = libPhysicalPath.substr(lastPathSplitPos + 1);
1035         std::string mntPath = sandboxPackagePath + g_sandboxGroupPath + dataGroupUuid;
1036         ret = DoAppSandboxMountOnce(libPhysicalPath.c_str(), mntPath.c_str(), "", BASIC_MOUNT_FLAGS, nullptr);
1037         APPSPAWN_CHECK(ret == 0, return ret, "mount library failed %d", ret);
1038     }
1039     return ret;
1040 }
1041 
DoSandboxRootFolderCreate(const ClientSocket::AppProperty * appProperty,std::string & sandboxPackagePath)1042 int32_t SandboxUtils::DoSandboxRootFolderCreate(const ClientSocket::AppProperty *appProperty,
1043                                                 std::string &sandboxPackagePath)
1044 {
1045 #ifndef APPSPAWN_TEST
1046     int rc = mount(NULL, "/", NULL, MS_REC | MS_SLAVE, NULL);
1047     if (rc) {
1048         return rc;
1049     }
1050 #endif
1051     DoAppSandboxMountOnce(sandboxPackagePath.c_str(), sandboxPackagePath.c_str(), "",
1052                           BASIC_MOUNT_FLAGS, nullptr);
1053 
1054     return 0;
1055 }
1056 
GetSandboxNsFlags(bool isNweb)1057 uint32_t SandboxUtils::GetSandboxNsFlags(bool isNweb)
1058 {
1059     uint32_t nsFlags = 0;
1060     nlohmann::json appConfig;
1061     const std::map<std::string, uint32_t> NamespaceFlagsMap = { {"pid", CLONE_NEWPID},
1062                                                                 {"net", CLONE_NEWNET} };
1063 
1064     if (!CheckTotalSandboxSwitchStatus(NULL)) {
1065         return nsFlags;
1066     }
1067 
1068     for (auto config : SandboxUtils::GetJsonConfig()) {
1069         if (isNweb) {
1070             nlohmann::json privateAppConfig = config[g_privatePrefix][0];
1071             if (privateAppConfig.find(g_ohosRender) == privateAppConfig.end()) {
1072                 continue;
1073             }
1074             appConfig = privateAppConfig[g_ohosRender][0];
1075         } else {
1076             nlohmann::json baseConfig = config[g_commonPrefix][0];
1077             if (baseConfig.find(g_appBase) == baseConfig.end()) {
1078                 continue;
1079             }
1080             appConfig = baseConfig[g_appBase][0];
1081         }
1082         if (appConfig.find(g_sandBoxNsFlags) == appConfig.end()) {
1083             continue;
1084         }
1085         const auto vec = appConfig[g_sandBoxNsFlags].get<std::vector<std::string>>();
1086         for (unsigned int j = 0; j < vec.size(); j++) {
1087             if (NamespaceFlagsMap.count(vec[j])) {
1088                 nsFlags |= NamespaceFlagsMap.at(vec[j]);
1089             }
1090         }
1091     }
1092 
1093     if (!nsFlags) {
1094         APPSPAWN_LOGE("config is not found %{public}s ns config", isNweb ? "Nweb" : "App");
1095     }
1096     return nsFlags;
1097 }
1098 
CheckBundleNameForPrivate(const std::string & bundleName)1099 bool SandboxUtils::CheckBundleNameForPrivate(const std::string &bundleName)
1100 {
1101     if (bundleName.find(g_internal) != std::string::npos) {
1102         return false;
1103     }
1104     return true;
1105 }
1106 
CheckTotalSandboxSwitchStatus(const ClientSocket::AppProperty * appProperty)1107 bool SandboxUtils::CheckTotalSandboxSwitchStatus(const ClientSocket::AppProperty *appProperty)
1108 {
1109     for (auto wholeConfig : SandboxUtils::GetJsonConfig()) {
1110         nlohmann::json commonAppConfig = wholeConfig[g_commonPrefix][0];
1111         if (commonAppConfig.find(g_topSandBoxSwitchPrefix) != commonAppConfig.end()) {
1112             std::string switchStatus = commonAppConfig[g_topSandBoxSwitchPrefix].get<std::string>();
1113             if (switchStatus == g_sbxSwitchCheck) {
1114                 return true;
1115             } else {
1116                 return false;
1117             }
1118         }
1119     }
1120     // default sandbox switch is on
1121     return true;
1122 }
1123 
CheckAppSandboxSwitchStatus(const ClientSocket::AppProperty * appProperty)1124 bool SandboxUtils::CheckAppSandboxSwitchStatus(const ClientSocket::AppProperty *appProperty)
1125 {
1126     bool rc = true;
1127     for (auto wholeConfig : SandboxUtils::GetJsonConfig()) {
1128         APPSPAWN_LOGV("CheckAppSandboxSwitchStatus middle ");
1129         nlohmann::json privateAppConfig = wholeConfig[g_privatePrefix][0];
1130         if (privateAppConfig.find(appProperty->bundleName) != privateAppConfig.end()) {
1131             nlohmann::json appConfig = privateAppConfig[appProperty->bundleName][0];
1132             rc = GetSbxSwitchStatusByConfig(appConfig);
1133             APPSPAWN_LOGE("CheckAppSandboxSwitchStatus middle, %{public}d", rc);
1134             if (rc) {
1135                 break;
1136             }
1137         }
1138     }
1139     // default sandbox switch is on
1140     return rc;
1141 }
1142 
CheckBundleName(const std::string & bundleName)1143 static int CheckBundleName(const std::string &bundleName)
1144 {
1145     if (bundleName.empty() || bundleName.size() > APP_LEN_BUNDLE_NAME) {
1146         return -1;
1147     }
1148     if (bundleName.find('\\') != std::string::npos || bundleName.find('/') != std::string::npos) {
1149         return -1;
1150     }
1151     return 0;
1152 }
1153 
SetOverlayAppSandboxProperty(const ClientSocket::AppProperty * appProperty,string & sandboxPackagePath)1154 int32_t SandboxUtils::SetOverlayAppSandboxProperty(const ClientSocket::AppProperty *appProperty,
1155                                                    string &sandboxPackagePath)
1156 {
1157     int ret = 0;
1158     if ((appProperty->flags & APP_OVERLAY_FLAG) != APP_OVERLAY_FLAG) {
1159         return ret;
1160     }
1161 
1162     string overlayInfo = GetExtraInfoByType(appProperty, OVERLAY_SOCKET_TYPE);
1163     set<string> mountedSrcSet;
1164     vector<string> splits = split(overlayInfo, g_overlayDecollator);
1165     string sandboxOverlayPath = sandboxPackagePath + g_overlayPath;
1166     for (auto hapPath : splits) {
1167         size_t pathIndex = hapPath.find_last_of(g_fileSeparator);
1168         if (pathIndex == string::npos) {
1169             continue;
1170         }
1171         std::string srcPath = hapPath.substr(0, pathIndex);
1172         if (mountedSrcSet.find(srcPath) != mountedSrcSet.end()) {
1173             APPSPAWN_LOGV("%{public}s have mounted before, no need to mount twice.", srcPath.c_str());
1174             continue;
1175         }
1176 
1177         auto bundleNameIndex = srcPath.find_last_of(g_fileSeparator);
1178         string destPath = sandboxOverlayPath + srcPath.substr(bundleNameIndex + 1, srcPath.length());
1179         int32_t retMount = DoAppSandboxMountOnce(srcPath.c_str(), destPath.c_str(),
1180                                                  nullptr, BASIC_MOUNT_FLAGS, nullptr);
1181         if (retMount != 0) {
1182             APPSPAWN_LOGE("fail to mount overlay path, src is %s.", hapPath.c_str());
1183             ret = retMount;
1184         }
1185 
1186         mountedSrcSet.emplace(srcPath);
1187     }
1188     return ret;
1189 }
1190 
SetBundleResourceAppSandboxProperty(const ClientSocket::AppProperty * appProperty,string & sandboxPackagePath)1191 int32_t SandboxUtils::SetBundleResourceAppSandboxProperty(const ClientSocket::AppProperty *appProperty,
1192                                                           string &sandboxPackagePath)
1193 {
1194     int ret = 0;
1195     if ((appProperty->flags & GET_BUNDLE_RESOURCES_FLAG) != GET_BUNDLE_RESOURCES_FLAG) {
1196         return ret;
1197     }
1198 
1199     string srcPath = g_bundleResourceSrcPath;
1200     string destPath = sandboxPackagePath + g_bundleResourceDestPath;
1201     ret = DoAppSandboxMountOnce(
1202         srcPath.c_str(), destPath.c_str(), nullptr, BASIC_MOUNT_FLAGS, nullptr);
1203     return ret;
1204 }
1205 
GetProductDeviceType()1206 bool SandboxUtils::GetProductDeviceType()
1207 {
1208     char value[MAX_VALUE_LENGTH];
1209     int32_t ret = GetParameter("const.product.devicetype", "0", value, MAX_VALUE_LENGTH);
1210     APPSPAWN_CHECK(ret > 0 && (strcmp(value, "2in1") == 0), return false, "Not device type %{public}s", value);
1211     deviceTypeEnable_ = true;
1212     return true;
1213 }
1214 
GetMountPermissionFlags(const std::string permissionName)1215 int32_t SandboxUtils::GetMountPermissionFlags(const std::string permissionName)
1216 {
1217     std::set<std::string> mountPermissionList = AppspawnMountPermission::GetMountPermissionList();
1218     std::set<std::string> permissions;
1219     for (std::string permission : mountPermissionList) {
1220         if (permission.compare(permissionName) == 0) {
1221             permissions.insert(permission);
1222         }
1223     }
1224     int32_t mountPermissionFlags = AppspawnMountPermission::GenPermissionCode(permissions);
1225     return mountPermissionFlags;
1226 }
1227 
SetSandboxProperty(ClientSocket::AppProperty * appProperty,std::string & sandboxPackagePath)1228 int32_t SandboxUtils::SetSandboxProperty(ClientSocket::AppProperty *appProperty,
1229                                                 std::string &sandboxPackagePath)
1230 {
1231     int32_t ret = 0;
1232     const std::string bundleName = appProperty->bundleName;
1233     ret = SetCommonAppSandboxProperty(appProperty, sandboxPackagePath);
1234     APPSPAWN_CHECK(ret == 0, return ret, "SetCommonAppSandboxProperty failed, packagename is %{public}s",
1235                    bundleName.c_str());
1236     if (CheckBundleNameForPrivate(bundleName)) {
1237         ret = SetPrivateAppSandboxProperty(appProperty);
1238         APPSPAWN_CHECK(ret == 0, return ret, "SetPrivateAppSandboxProperty failed, packagename is %{public}s",
1239                        bundleName.c_str());
1240     }
1241     ret = SetPermissionAppSandboxProperty(appProperty);
1242     APPSPAWN_CHECK(ret == 0, return ret, "SetPermissionAppSandboxProperty failed, packagename is %{public}s",
1243                    bundleName.c_str());
1244 
1245     ret = SetOverlayAppSandboxProperty(appProperty, sandboxPackagePath);
1246     APPSPAWN_CHECK(ret == 0, return ret, "SetOverlayAppSandboxProperty failed, packagename is %s",
1247                    bundleName.c_str());
1248 
1249     ret = SetBundleResourceAppSandboxProperty(appProperty, sandboxPackagePath);
1250     APPSPAWN_CHECK(ret == 0, return ret, "SetBundleResourceAppSandboxProperty failed, packagename is %s",
1251                    bundleName.c_str());
1252     return ret;
1253 }
1254 
ChangeCurrentDir(std::string & sandboxPackagePath,const std::string & bundleName,bool sandboxSharedStatus)1255 int32_t SandboxUtils::ChangeCurrentDir(std::string &sandboxPackagePath, const std::string &bundleName,
1256                                        bool sandboxSharedStatus)
1257 {
1258     int32_t ret = 0;
1259     ret = chdir(sandboxPackagePath.c_str());
1260     APPSPAWN_CHECK(ret == 0, return ret, "chdir failed, packagename is %{public}s, path is %{public}s",
1261         bundleName.c_str(), sandboxPackagePath.c_str());
1262 
1263     if (sandboxSharedStatus) {
1264         ret = chroot(sandboxPackagePath.c_str());
1265         APPSPAWN_CHECK(ret == 0, return ret, "chroot failed, path is %{public}s errno is %{public}d",
1266             sandboxPackagePath.c_str(), errno);
1267         return ret;
1268     }
1269 
1270     ret = syscall(SYS_pivot_root, sandboxPackagePath.c_str(), sandboxPackagePath.c_str());
1271     APPSPAWN_CHECK(ret == 0, return ret, "errno is %{public}d, pivot root failed, packagename is %{public}s",
1272         errno, bundleName.c_str());
1273 
1274     ret = umount2(".", MNT_DETACH);
1275     APPSPAWN_CHECK(ret == 0, return ret, "MNT_DETACH failed, packagename is %{public}s", bundleName.c_str());
1276     return ret;
1277 }
1278 
SetAppSandboxProperty(AppSpawnClient * client)1279 int32_t SandboxUtils::SetAppSandboxProperty(AppSpawnClient *client)
1280 {
1281     APPSPAWN_CHECK(client != NULL, return -1, "Invalid appspwn client");
1282     AppSpawnClientExt *clientExt = reinterpret_cast<AppSpawnClientExt *>(client);
1283     ClientSocket::AppProperty *appProperty = &clientExt->property;
1284     if (CheckBundleName(appProperty->bundleName) != 0) {
1285         return -1;
1286     }
1287     std::string sandboxPackagePath = g_sandBoxRootDir + to_string(appProperty->uid / UID_BASE) + "/";
1288     const std::string bundleName = appProperty->bundleName;
1289     bool sandboxSharedStatus = GetSandboxPrivateSharedStatus(bundleName);
1290     sandboxPackagePath += bundleName;
1291     MakeDirRecursive(sandboxPackagePath.c_str(), FILE_MODE);
1292 
1293     // add pid to a new mnt namespace
1294     int rc = unshare(CLONE_NEWNS);
1295     APPSPAWN_CHECK(rc == 0, return rc, "unshare failed, packagename is %{public}s", bundleName.c_str());
1296 
1297     if (GetProductDeviceType()) {
1298         appProperty->mountPermissionFlags |= GetMountPermissionFlags(FILE_CROSS_APP_MODE);
1299     }
1300 
1301     // check app sandbox switch
1302     if ((CheckTotalSandboxSwitchStatus(appProperty) == false) ||
1303         (CheckAppSandboxSwitchStatus(appProperty) == false)) {
1304         rc = DoSandboxRootFolderCreateAdapt(sandboxPackagePath);
1305     } else if (!sandboxSharedStatus) {
1306         rc = DoSandboxRootFolderCreate(appProperty, sandboxPackagePath);
1307     }
1308     APPSPAWN_CHECK(rc == 0, return rc, "DoSandboxRootFolderCreate failed, %{public}s", bundleName.c_str());
1309     rc = SetSandboxProperty(appProperty, sandboxPackagePath);
1310     APPSPAWN_CHECK(rc == 0, return rc, "SetSandboxProperty failed, %{public}s", bundleName.c_str());
1311 
1312 #ifndef APPSPAWN_TEST
1313     rc = ChangeCurrentDir(sandboxPackagePath, bundleName, sandboxSharedStatus);
1314     APPSPAWN_CHECK(rc == 0, return rc, "change current dir failed");
1315 #endif
1316     return 0;
1317 }
1318 
SetAppSandboxPropertyNweb(AppSpawnClient * client)1319 int32_t SandboxUtils::SetAppSandboxPropertyNweb(AppSpawnClient *client)
1320 {
1321     APPSPAWN_CHECK(client != NULL, return -1, "Invalid appspwn client");
1322     AppSpawnClientExt *clientExt = reinterpret_cast<AppSpawnClientExt *>(client);
1323     ClientSocket::AppProperty *appProperty = &clientExt->property;
1324     if (CheckBundleName(appProperty->bundleName) != 0) {
1325         return -1;
1326     }
1327     std::string sandboxPackagePath = g_sandBoxRootDirNweb;
1328     const std::string bundleName = appProperty->bundleName;
1329     bool sandboxSharedStatus = GetSandboxPrivateSharedStatus(bundleName);
1330     sandboxPackagePath += bundleName;
1331     MakeDirRecursive(sandboxPackagePath.c_str(), FILE_MODE);
1332 
1333     // add pid to a new mnt namespace
1334     int rc = unshare(CLONE_NEWNS);
1335     APPSPAWN_CHECK(rc == 0, return rc, "unshare failed, packagename is %{public}s", bundleName.c_str());
1336 
1337     // check app sandbox switch
1338     if ((CheckTotalSandboxSwitchStatus(appProperty) == false) ||
1339         (CheckAppSandboxSwitchStatus(appProperty) == false)) {
1340         rc = DoSandboxRootFolderCreateAdapt(sandboxPackagePath);
1341     } else if (!sandboxSharedStatus) {
1342         rc = DoSandboxRootFolderCreate(appProperty, sandboxPackagePath);
1343     }
1344     APPSPAWN_CHECK(rc == 0, return rc, "DoSandboxRootFolderCreate failed, %{public}s", bundleName.c_str());
1345     // rendering process can be created by different apps,
1346     // and the bundle names of these apps are different,
1347     // so we can't use the method SetPrivateAppSandboxProperty
1348     // which mount dirs by using bundle name.
1349     rc = SetRenderSandboxPropertyNweb(appProperty, sandboxPackagePath);
1350     APPSPAWN_CHECK(rc == 0, return rc, "SetRenderSandboxPropertyNweb failed, packagename is %{public}s",
1351         sandboxPackagePath.c_str());
1352 
1353     rc = SetOverlayAppSandboxProperty(appProperty, sandboxPackagePath);
1354     APPSPAWN_CHECK(rc == 0, return rc, "SetOverlayAppSandboxProperty failed, packagename is %s",
1355         bundleName.c_str());
1356 
1357     rc = SetBundleResourceAppSandboxProperty(appProperty, sandboxPackagePath);
1358     APPSPAWN_CHECK(rc == 0, return rc, "SetBundleResourceAppSandboxProperty failed, packagename is %s",
1359         bundleName.c_str());
1360 
1361 #ifndef APPSPAWN_TEST
1362     rc = chdir(sandboxPackagePath.c_str());
1363     APPSPAWN_CHECK(rc == 0, return rc, "chdir failed, packagename is %{public}s, path is %{public}s",
1364         bundleName.c_str(), sandboxPackagePath.c_str());
1365 
1366     if (sandboxSharedStatus) {
1367         rc = chroot(sandboxPackagePath.c_str());
1368         APPSPAWN_CHECK(rc == 0, return rc, "chroot failed, path is %{public}s errno is %{public}d",
1369             sandboxPackagePath.c_str(), errno);
1370         return 0;
1371     }
1372 
1373     rc = syscall(SYS_pivot_root, sandboxPackagePath.c_str(), sandboxPackagePath.c_str());
1374     APPSPAWN_CHECK(rc == 0, return rc, "errno is %{public}d, pivot root failed, packagename is %{public}s",
1375         errno, bundleName.c_str());
1376 
1377     rc = umount2(".", MNT_DETACH);
1378     APPSPAWN_CHECK(rc == 0, return rc, "MNT_DETACH failed, packagename is %{public}s", bundleName.c_str());
1379 #endif
1380     return 0;
1381 }
1382 } // namespace AppSpawn
1383 } // namespace OHOS
1384