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