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