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