1 /*
2 * Copyright (c) 2023-2023 Huawei Device Co., Ltd. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific prior written
16 * permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #ifdef LOSCFG_MNT_CONTAINER
32 #include <unistd.h>
33 #include "los_mnt_container_pri.h"
34 #include "los_container_pri.h"
35 #include "los_process_pri.h"
36 #include "sys/mount.h"
37 #include "vnode.h"
38 #include "internal.h"
39
40 STATIC UINT32 g_currentMntContainerNum;
41
GetContainerMntList(VOID)42 LIST_HEAD *GetContainerMntList(VOID)
43 {
44 return &OsCurrProcessGet()->container->mntContainer->mountList;
45 }
46
CreateNewMntContainer(MntContainer * parent)47 STATIC MntContainer *CreateNewMntContainer(MntContainer *parent)
48 {
49 MntContainer *mntContainer = (MntContainer *)LOS_MemAlloc(m_aucSysMem1, sizeof(MntContainer));
50 if (mntContainer == NULL) {
51 return NULL;
52 }
53 mntContainer->containerID = OsAllocContainerID();
54 LOS_ListInit(&mntContainer->mountList);
55
56 if (parent != NULL) {
57 LOS_AtomicSet(&mntContainer->rc, 1);
58 } else {
59 LOS_AtomicSet(&mntContainer->rc, 3); /* 3: Three system processes */
60 }
61 return mntContainer;
62 }
63
CreateMntContainer(LosProcessCB * child,LosProcessCB * parent)64 STATIC UINT32 CreateMntContainer(LosProcessCB *child, LosProcessCB *parent)
65 {
66 UINT32 intSave;
67 MntContainer *parentContainer = parent->container->mntContainer;
68 MntContainer *newMntContainer = CreateNewMntContainer(parentContainer);
69 if (newMntContainer == NULL) {
70 return ENOMEM;
71 }
72
73 SCHEDULER_LOCK(intSave);
74 g_currentMntContainerNum++;
75 child->container->mntContainer = newMntContainer;
76 SCHEDULER_UNLOCK(intSave);
77 return LOS_OK;
78 }
79
OsInitRootMntContainer(MntContainer ** mntContainer)80 UINT32 OsInitRootMntContainer(MntContainer **mntContainer)
81 {
82 UINT32 intSave;
83 MntContainer *newMntContainer = CreateNewMntContainer(NULL);
84 if (newMntContainer == NULL) {
85 return ENOMEM;
86 }
87
88 SCHEDULER_LOCK(intSave);
89 g_currentMntContainerNum++;
90 *mntContainer = newMntContainer;
91 SCHEDULER_UNLOCK(intSave);
92 return LOS_OK;
93 }
94
CopyMountList(MntContainer * parentContainer,MntContainer * newContainer)95 STATIC UINT32 CopyMountList(MntContainer *parentContainer, MntContainer *newContainer)
96 {
97 struct Mount *mnt = NULL;
98 VnodeHold();
99 LOS_DL_LIST_FOR_EACH_ENTRY(mnt, &parentContainer->mountList, struct Mount, mountList) {
100 struct Mount *newMnt = (struct Mount *)zalloc(sizeof(struct Mount));
101 if (newMnt == NULL) {
102 VnodeDrop();
103 return ENOMEM;
104 }
105 *newMnt = *mnt;
106 LOS_ListTailInsert(&newContainer->mountList, &newMnt->mountList);
107 newMnt->vnodeCovered->mntCount++;
108 }
109 VnodeDrop();
110 return LOS_OK;
111 }
112
OsCopyMntContainer(UINTPTR flags,LosProcessCB * child,LosProcessCB * parent)113 UINT32 OsCopyMntContainer(UINTPTR flags, LosProcessCB *child, LosProcessCB *parent)
114 {
115 UINT32 ret;
116 UINT32 intSave;
117 MntContainer *currMntContainer = parent->container->mntContainer;
118
119 if (!(flags & CLONE_NEWNS)) {
120 SCHEDULER_LOCK(intSave);
121 LOS_AtomicInc(&currMntContainer->rc);
122 child->container->mntContainer = currMntContainer;
123 SCHEDULER_UNLOCK(intSave);
124 return LOS_OK;
125 }
126
127 if (OsContainerLimitCheck(MNT_CONTAINER, &g_currentMntContainerNum) != LOS_OK) {
128 return EPERM;
129 }
130
131 ret = CreateMntContainer(child, parent);
132 if (ret != LOS_OK) {
133 return ret;
134 }
135
136 return CopyMountList(currMntContainer, child->container->mntContainer);
137 }
138
OsUnshareMntContainer(UINTPTR flags,LosProcessCB * curr,Container * newContainer)139 UINT32 OsUnshareMntContainer(UINTPTR flags, LosProcessCB *curr, Container *newContainer)
140 {
141 UINT32 intSave;
142 UINT32 ret;
143 MntContainer *parentContainer = curr->container->mntContainer;
144
145 if (!(flags & CLONE_NEWNS)) {
146 SCHEDULER_LOCK(intSave);
147 newContainer->mntContainer = parentContainer;
148 LOS_AtomicInc(&parentContainer->rc);
149 SCHEDULER_UNLOCK(intSave);
150 return LOS_OK;
151 }
152
153 if (OsContainerLimitCheck(MNT_CONTAINER, &g_currentMntContainerNum) != LOS_OK) {
154 return EPERM;
155 }
156
157 MntContainer *mntContainer = CreateNewMntContainer(parentContainer);
158 if (mntContainer == NULL) {
159 return ENOMEM;
160 }
161
162 ret = CopyMountList(parentContainer, mntContainer);
163 if (ret != LOS_OK) {
164 (VOID)LOS_MemFree(m_aucSysMem1, mntContainer);
165 return ret;
166 }
167
168 SCHEDULER_LOCK(intSave);
169 newContainer->mntContainer = mntContainer;
170 g_currentMntContainerNum++;
171 SCHEDULER_UNLOCK(intSave);
172 return LOS_OK;
173 }
174
OsSetNsMntContainer(UINT32 flags,Container * container,Container * newContainer)175 UINT32 OsSetNsMntContainer(UINT32 flags, Container *container, Container *newContainer)
176 {
177 if (flags & CLONE_NEWNS) {
178 newContainer->mntContainer = container->mntContainer;
179 LOS_AtomicInc(&container->mntContainer->rc);
180 return LOS_OK;
181 }
182
183 newContainer->mntContainer = OsCurrProcessGet()->container->mntContainer;
184 LOS_AtomicInc(&newContainer->mntContainer->rc);
185 return LOS_OK;
186 }
187
FreeMountList(LIST_HEAD * mountList)188 STATIC VOID FreeMountList(LIST_HEAD *mountList)
189 {
190 struct Mount *mnt = NULL;
191 struct Mount *nextMnt = NULL;
192
193 VnodeHold();
194 if (LOS_ListEmpty(mountList)) {
195 VnodeDrop();
196 return;
197 }
198
199 LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(mnt, nextMnt, mountList, struct Mount, mountList) {
200 if (mnt->vnodeCovered->mntCount > 0) {
201 mnt->vnodeCovered->mntCount--;
202 LOS_ListDelete(&mnt->mountList);
203 free(mnt);
204 } else {
205 umount(mnt->pathName);
206 }
207 }
208 VnodeDrop();
209 return;
210 }
211
OsMntContainerDestroy(Container * container)212 VOID OsMntContainerDestroy(Container *container)
213 {
214 UINT32 intSave;
215 if (container == NULL) {
216 return;
217 }
218
219 SCHEDULER_LOCK(intSave);
220 MntContainer *mntContainer = container->mntContainer;
221 if (mntContainer == NULL) {
222 SCHEDULER_UNLOCK(intSave);
223 return;
224 }
225
226 LOS_AtomicDec(&mntContainer->rc);
227 if (LOS_AtomicRead(&mntContainer->rc) > 0) {
228 SCHEDULER_UNLOCK(intSave);
229 return;
230 }
231
232 g_currentMntContainerNum--;
233 SCHEDULER_UNLOCK(intSave);
234 FreeMountList(&mntContainer->mountList);
235 container->mntContainer = NULL;
236 (VOID)LOS_MemFree(m_aucSysMem1, mntContainer);
237 return;
238 }
239
OsGetMntContainerID(MntContainer * mntContainer)240 UINT32 OsGetMntContainerID(MntContainer *mntContainer)
241 {
242 if (mntContainer == NULL) {
243 return OS_INVALID_VALUE;
244 }
245
246 return mntContainer->containerID;
247 }
248
OsGetMntContainerCount(VOID)249 UINT32 OsGetMntContainerCount(VOID)
250 {
251 return g_currentMntContainerNum;
252 }
253 #endif
254