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