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 <errno.h>
17 #include <fcntl.h>
18 #include <sched.h>
19 #include <stdbool.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 
24 #include <sys/mount.h>
25 #include <sys/stat.h>
26 #include <sys/syscall.h>
27 #include <sys/types.h>
28 
29 #include "appspawn_sandbox.h"
30 #include "appspawn_utils.h"
31 #include "securec.h"
32 
33 /*
34 名称            fs-type      flags                          options                 说明
35 default                      MS_BIND MS_REC                                         默认可读写
36 rdonly                       MS_NODEV MS_RDONLY                                     只读挂载
37 epfs            epfs         MS_NODEV                                                待讨论
38 dac_override                 MS_NODEV MS_RDONLY             "support_overwrite=1"
39 开启const.filemanager.full_mount.enable
40 fuse            fuse         MS_NOSUID MS_NODEV MS_NOEXEC MS_NOATIME MS_LAZYTIME
41 dlp_fuse        fuse         MS_NOSUID MS_NODEV MS_NOEXEC MS_NOATIME MS_LAZYTIME     为dlpmanager管理应用专用的挂载参数
42 shared                       MS_BIND MS_REC                                           root
43 namespace上是MS_SHARED方式挂载
44 
45 */
46 /**
47     "dac-override-sensitive": "true",  默认值:false。使能后直接使用默认值
48     "sandbox-flags-customized": [ "MS_NODEV", "MS_RDONLY" ],
49     "fs-type": "sharefs",
50     "options": "support_overwrite=1"
51 */
52 #define FUSE_MOUNT_FLAGS (MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME | MS_LAZYTIME)
53 #define FUSE_MOUNT_OPTIONS  \
54     "fd=%d, rootmode=40000,user_id=%d,group_id=%d,allow_other," \
55     "context=\"u:object_r:dlp_fuse_file:s0\", fscontext=u:object_r:dlp_fuse_file:s0"
56 
57 static const MountArgTemplate DEF_MOUNT_ARG_TMP[MOUNT_TMP_MAX] = {
58     {"default", MOUNT_TMP_DEFAULT, NULL, MS_BIND | MS_REC, NULL, MS_SLAVE},
59     {"rdonly", MOUNT_TMP_RDONLY, NULL, MS_NODEV | MS_RDONLY, NULL, MS_SLAVE},
60     {"epfs", MOUNT_TMP_EPFS, "epfs", MS_NODEV, NULL, MS_SLAVE},
61     {"dac_override_delete", MOUNT_TMP_DAC_OVERRIDE_DELETE, "sharefs", MS_NODEV, "override_support_delete", MS_SLAVE},
62     {"dac_override", MOUNT_TMP_DAC_OVERRIDE, "sharefs", MS_NODEV, "support_overwrite=1", MS_SLAVE},
63     {"fuse", MOUNT_TMP_FUSE, "fuse", FUSE_MOUNT_FLAGS, FUSE_MOUNT_OPTIONS, MS_SHARED},
64     {"dlp_fuse", MOUNT_TMP_DLP_FUSE, "fuse", FUSE_MOUNT_FLAGS, FUSE_MOUNT_OPTIONS, MS_SHARED},
65     {"shared", MOUNT_TMP_SHRED, NULL, MS_BIND | MS_REC, NULL, MS_SHARED},
66 };
67 
68 static const SandboxFlagInfo MOUNT_FLAGS_MAP[] = {
69     {"rec", MS_REC}, {"MS_REC", MS_REC},
70     {"bind", MS_BIND}, {"MS_BIND", MS_BIND}, {"move", MS_MOVE}, {"MS_MOVE", MS_MOVE},
71     {"slave", MS_SLAVE}, {"MS_SLAVE", MS_SLAVE}, {"rdonly", MS_RDONLY}, {"MS_RDONLY", MS_RDONLY},
72     {"shared", MS_SHARED}, {"MS_SHARED", MS_SHARED}, {"unbindable", MS_UNBINDABLE},
73     {"MS_UNBINDABLE", MS_UNBINDABLE}, {"remount", MS_REMOUNT}, {"MS_REMOUNT", MS_REMOUNT},
74     {"nosuid", MS_NOSUID}, {"MS_NOSUID", MS_NOSUID}, {"nodev", MS_NODEV}, {"MS_NODEV", MS_NODEV},
75     {"noexec", MS_NOEXEC}, {"MS_NOEXEC", MS_NOEXEC}, {"noatime", MS_NOATIME}, {"MS_NOATIME", MS_NOATIME},
76     {"lazytime", MS_LAZYTIME}, {"MS_LAZYTIME", MS_LAZYTIME}
77 };
78 
79 static const SandboxFlagInfo PATH_MODE_MAP[] = {
80     {"S_IRUSR", S_IRUSR}, {"S_IWUSR", S_IWUSR}, {"S_IXUSR", S_IXUSR},
81     {"S_IRGRP", S_IRGRP}, {"S_IWGRP", S_IWGRP}, {"S_IXGRP", S_IXGRP},
82     {"S_IROTH", S_IROTH}, {"S_IWOTH", S_IWOTH}, {"S_IXOTH", S_IXOTH},
83     {"S_IRWXU", S_IRWXU}, {"S_IRWXG", S_IRWXG}, {"S_IRWXO", S_IRWXO}
84 };
85 
GetMountCategory(const char *name)86 uint32_t GetMountCategory(const char *name)
87 {
88     APPSPAWN_CHECK_ONLY_EXPER(name != NULL, return MOUNT_TMP_DEFAULT);
89     uint32_t count = ARRAY_LENGTH(DEF_MOUNT_ARG_TMP);
90     for (uint32_t i = 0; i < count; i++) {
91         if (strcmp(DEF_MOUNT_ARG_TMP[i].name, name) == 0) {
92             return DEF_MOUNT_ARG_TMP[i].category;
93         }
94     }
95     return MOUNT_TMP_DEFAULT;
96 }
97 
GetMountArgTemplate(uint32_t category)98 const MountArgTemplate *GetMountArgTemplate(uint32_t category)
99 {
100     uint32_t count = ARRAY_LENGTH(DEF_MOUNT_ARG_TMP);
101     if (category > count) {
102         return NULL;
103     }
104     for (uint32_t i = 0; i < count; i++) {
105         if (DEF_MOUNT_ARG_TMP[i].category == category) {
106             return &DEF_MOUNT_ARG_TMP[i];
107         }
108     }
109     return NULL;
110 }
111 
GetSandboxFlagInfo(const char *key, const SandboxFlagInfo *flagsInfos, uint32_t count)112 const SandboxFlagInfo *GetSandboxFlagInfo(const char *key, const SandboxFlagInfo *flagsInfos, uint32_t count)
113 {
114     APPSPAWN_CHECK_ONLY_EXPER(key != NULL, return NULL);
115     APPSPAWN_CHECK_ONLY_EXPER(flagsInfos != NULL, return NULL);
116     for (uint32_t i = 0; i < count; i++) {
117         if (strcmp(flagsInfos[i].name, key) == 0) {
118             return &flagsInfos[i];
119         }
120     }
121     return NULL;
122 }
123 
GetPathMode(const char *name)124 int GetPathMode(const char *name)
125 {
126     APPSPAWN_CHECK_ONLY_EXPER(name != NULL, return 0);
127     const SandboxFlagInfo *info = GetSandboxFlagInfo(name, PATH_MODE_MAP, ARRAY_LENGTH(PATH_MODE_MAP));
128     if (info != NULL) {
129         return info->flags;
130     }
131     return 0;
132 }
133 
DumpSandboxFlags(char *buffer, uint32_t bufferSize, unsigned long flags, const SandboxFlagInfo *flagsInfos, uint32_t count)134 static void DumpSandboxFlags(char *buffer, uint32_t bufferSize, unsigned long flags,
135     const SandboxFlagInfo *flagsInfos, uint32_t count)
136 {
137     bool first = true;
138     size_t currLen = 0;
139     int len = 0;
140     unsigned long tmp = flags;
141     for (uint32_t i = 0; i < count; i++) {
142         if ((flagsInfos[i].flags & tmp) == 0) {
143             continue;
144         }
145         tmp &= ~(flagsInfos[i].flags);
146         if (!first) {
147             len = sprintf_s(buffer + currLen, bufferSize - currLen - 1, " %s ", "|");
148             APPSPAWN_CHECK_ONLY_EXPER(len > 0, return);
149             currLen += len;
150         }
151         first = false;
152         len = sprintf_s(buffer + currLen, bufferSize - currLen, "%s", flagsInfos[i].name);
153         APPSPAWN_CHECK_ONLY_EXPER(len > 0, return);
154         currLen += len;
155     }
156 }
157 
DumpMode(const char *info, mode_t mode)158 static void DumpMode(const char *info, mode_t mode)
159 {
160     APPSPAWN_CHECK_ONLY_EXPER(info != NULL, return);
161     char buffer[64] = {0};  // 64 to show flags
162     DumpSandboxFlags(buffer, sizeof(buffer), mode, PATH_MODE_MAP, ARRAY_LENGTH(PATH_MODE_MAP));
163     APPSPAPWN_DUMP("%{public}s[0x%{public}x] %{public}s", info, (uint32_t)(mode), buffer);
164 }
165 
DumpMountFlags(const char *info, unsigned long mountFlags)166 static void DumpMountFlags(const char *info, unsigned long mountFlags)
167 {
168     APPSPAWN_CHECK_ONLY_EXPER(info != NULL, return);
169     char buffer[128] = {0};  // 64 to show flags
170     DumpSandboxFlags(buffer, sizeof(buffer), mountFlags, MOUNT_FLAGS_MAP, ARRAY_LENGTH(MOUNT_FLAGS_MAP));
171     APPSPAPWN_DUMP("%{public}s[0x%{public}x] %{public}s", info, (uint32_t)(mountFlags), buffer);
172 }
173 
DumpMountPathMountNode(const PathMountNode *pathNode)174 void DumpMountPathMountNode(const PathMountNode *pathNode)
175 {
176     const MountArgTemplate *tmp = GetMountArgTemplate(pathNode->category);
177     if (tmp == NULL) {
178         return;
179     }
180     APPSPAPWN_DUMP("        sandbox node category: %{public}u(%{public}s)", tmp->category, tmp->name);
181     DumpMountFlags("        sandbox node mountFlags: ", tmp->mountFlags);
182     APPSPAPWN_DUMP("        sandbox node mountSharedFlag: %{public}s",
183         tmp->mountSharedFlag == MS_SLAVE ? "MS_SLAVE" : "MS_SHARED");
184     APPSPAPWN_DUMP("        sandbox node options: %{public}s", tmp->options ? tmp->options : "null");
185     APPSPAPWN_DUMP("        sandbox node fsType: %{public}s", tmp->fsType ? tmp->fsType : "null");
186     DumpMode("        sandbox node destMode: ", pathNode->destMode);
187     APPSPAPWN_DUMP("        sandbox node config mountSharedFlag: %{public}s",
188         pathNode->mountSharedFlag ? "MS_SHARED" : "MS_SLAVE");
189 }