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 §ion)
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 §ion)
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