1 /*
2 * Copyright (c) 2024 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_adapter.h"
17 #include "init_utils.h"
18
19 #ifdef WITH_SELINUX
20 #include "hap_restorecon.h"
21 #endif
22
23 using namespace std;
24
MakeAtomicServiceDir(const SandboxContext * context,const char * originPath,const char * varPackageName)25 void MakeAtomicServiceDir(const SandboxContext *context, const char *originPath, const char *varPackageName)
26 {
27 APPSPAWN_CHECK_ONLY_EXPER(context != NULL && originPath != NULL && varPackageName != NULL, return);
28 AppSpawnMsgDacInfo *dacInfo = (AppSpawnMsgDacInfo *)GetSpawningMsgInfo(context, TLV_DAC_INFO);
29 APPSPAWN_CHECK(dacInfo != NULL, return, "No dac info for %{public}s", context->bundleName);
30 string path(originPath);
31 if (path.find("/mnt/share") != string::npos) {
32 path = "/data/service/el2/" + to_string(dacInfo->uid / UID_BASE) + "/share/" + string(varPackageName);
33 }
34 if (access(path.c_str(), F_OK) == 0) {
35 APPSPAWN_LOGV("path %{public}s already exist, no need to recreate", path.c_str());
36 return;
37 }
38 int ret = mkdir(path.c_str(), S_IRWXU);
39 APPSPAWN_CHECK(ret == 0, return, "mkdir %{public}s failed, errno %{public}d", path.c_str(), errno);
40
41 if (path.find("/database") != string::npos || path.find("/data/service/el2") != string::npos) {
42 ret = chmod(path.c_str(), S_IRWXU | S_IRWXG | S_ISGID);
43 } else if (path.find("/log") != string::npos) {
44 ret = chmod(path.c_str(), S_IRWXU | S_IRWXG);
45 }
46 APPSPAWN_CHECK(ret == 0, return, "chmod %{public}s failed, errno %{public}d", path.c_str(), errno);
47
48 #ifdef WITH_SELINUX
49 AppSpawnMsgDomainInfo *msgDomainInfo = (AppSpawnMsgDomainInfo *)GetSpawningMsgInfo(context, TLV_DOMAIN_INFO);
50 APPSPAWN_CHECK(msgDomainInfo != NULL, return, "No domain info for %{public}s", context->bundleName);
51 HapContext hapContext;
52 HapFileInfo hapFileInfo;
53 hapFileInfo.pathNameOrig.push_back(path);
54 hapFileInfo.apl = msgDomainInfo->apl;
55 hapFileInfo.packageName = context->bundleName;
56 hapFileInfo.hapFlags = msgDomainInfo->hapFlags;
57 if (CheckAppSpawnMsgFlag(context->message, TLV_MSG_FLAGS, APP_FLAGS_DEBUGGABLE)) {
58 hapFileInfo.hapFlags |= SELINUX_HAP_DEBUGGABLE;
59 }
60 if ((path.find("/base") != string::npos) || (path.find("/database") != string::npos)) {
61 ret = hapContext.HapFileRestorecon(hapFileInfo);
62 APPSPAWN_CHECK(ret == 0, return, "set dir %{public}s selinuxLabel failed, apl %{public}s, ret %{public}d",
63 path.c_str(), hapFileInfo.apl.c_str(), ret);
64 }
65 #endif
66 if (path.find("/base") != string::npos || path.find("/data/service/el2") != string::npos) {
67 ret = chown(path.c_str(), dacInfo->uid, dacInfo->gid);
68 } else if (path.find("/database") != string::npos) {
69 ret = chown(path.c_str(), dacInfo->uid, DecodeGid("ddms"));
70 } else if (path.find("/log") != string::npos) {
71 ret = chown(path.c_str(), dacInfo->uid, DecodeGid("log"));
72 }
73 APPSPAWN_CHECK(ret == 0, return, "chown %{public}s failed, errno %{public}d", path.c_str(), errno);
74 return;
75 }
76