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 #include <sys/statfs.h>
32 #include <sys/mount.h>
33 #include "proc_fs.h"
34 #include "internal.h"
35 #include "los_process_pri.h"
36 #include "user_copy.h"
37 #include "los_memory.h"
38
39 #ifdef LOSCFG_KERNEL_CONTAINER
40 struct ProcSysUser {
41 char *name;
42 mode_t mode;
43 int type;
44 const struct ProcFileOperations *fileOps;
45 };
46
MemUserCopy(const char * src,size_t len,char ** kbuf)47 static unsigned int MemUserCopy(const char *src, size_t len, char **kbuf)
48 {
49 if (LOS_IsUserAddressRange((VADDR_T)(UINTPTR)src, len)) {
50 char *kernelBuf = LOS_MemAlloc(m_aucSysMem1, len + 1);
51 if (kernelBuf == NULL) {
52 return ENOMEM;
53 }
54
55 if (LOS_ArchCopyFromUser(kernelBuf, src, len) != 0) {
56 (VOID)LOS_MemFree(m_aucSysMem1, kernelBuf);
57 return EFAULT;
58 }
59 kernelBuf[len] = '\0';
60 *kbuf = kernelBuf;
61 return 0;
62 }
63 return 0;
64 }
65
GetContainerLimitValue(struct ProcFile * pf,const CHAR * buf,size_t count)66 static int GetContainerLimitValue(struct ProcFile *pf, const CHAR *buf, size_t count)
67 {
68 int value;
69 char *kbuf = NULL;
70
71 if ((pf == NULL) || (pf->pPDE == NULL) || (buf == NULL) || (count <= 0)) {
72 return -EINVAL;
73 }
74
75 unsigned ret = MemUserCopy(buf, count, &kbuf);
76 if (ret != 0) {
77 return -ret;
78 } else if ((ret == 0) && (kbuf != NULL)) {
79 buf = (const char *)kbuf;
80 }
81
82 if (strspn(buf, "0123456789") != count) {
83 (void)LOS_MemFree(m_aucSysMem1, kbuf);
84 return -EINVAL;
85 }
86 value = atoi(buf);
87 (void)LOS_MemFree(m_aucSysMem1, kbuf);
88 return value;
89 }
90
ProcSysUserWrite(struct ProcFile * pf,const char * buf,size_t size,loff_t * ppos)91 static ssize_t ProcSysUserWrite(struct ProcFile *pf, const char *buf, size_t size, loff_t *ppos)
92 {
93 (void)ppos;
94 unsigned ret;
95 int value = GetContainerLimitValue(pf, buf, size);
96 if (value < 0) {
97 return -EINVAL;
98 }
99
100 ContainerType type = (ContainerType)(uintptr_t)pf->pPDE->data;
101 ret = OsSetContainerLimit(type, value);
102 if (ret != LOS_OK) {
103 return -EINVAL;
104 }
105 return size;
106 }
107
ProcSysUserRead(struct SeqBuf * seqBuf,void * v)108 static int ProcSysUserRead(struct SeqBuf *seqBuf, void *v)
109 {
110 unsigned ret;
111 if ((seqBuf == NULL) || (v == NULL)) {
112 return EINVAL;
113 }
114
115 ContainerType type = (ContainerType)(uintptr_t)v;
116 ret = OsGetContainerLimit(type);
117 if (ret == OS_INVALID_VALUE) {
118 return EINVAL;
119 }
120 (void)LosBufPrintf(seqBuf, "\nlimit: %u\n", ret);
121 (void)LosBufPrintf(seqBuf, "count: %u\n", OsGetContainerCount(type));
122 return 0;
123 }
124
125 static const struct ProcFileOperations SYS_USER_OPT = {
126 .read = ProcSysUserRead,
127 .write = ProcSysUserWrite,
128 };
129
130 static struct ProcSysUser g_sysUser[] = {
131 #ifdef LOSCFG_MNT_CONTAINER
132 {
133 .name = "max_mnt_container",
134 .mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
135 .type = MNT_CONTAINER,
136 .fileOps = &SYS_USER_OPT
137
138 },
139 #endif
140 #ifdef LOSCFG_PID_CONTAINER
141 {
142 .name = "max_pid_container",
143 .mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
144 .type = PID_CONTAINER,
145 .fileOps = &SYS_USER_OPT
146 },
147 #endif
148 #ifdef LOSCFG_USER_CONTAINER
149 {
150 .name = "max_user_container",
151 .mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
152 .type = USER_CONTAINER,
153 .fileOps = &SYS_USER_OPT
154
155 },
156 #endif
157 #ifdef LOSCFG_UTS_CONTAINER
158 {
159 .name = "max_uts_container",
160 .mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
161 .type = UTS_CONTAINER,
162 .fileOps = &SYS_USER_OPT
163
164 },
165 #endif
166 #ifdef LOSCFG_UTS_CONTAINER
167 {
168 .name = "max_time_container",
169 .mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
170 .type = UTS_CONTAINER,
171 .fileOps = &SYS_USER_OPT
172
173 },
174 #endif
175 #ifdef LOSCFG_IPC_CONTAINER
176 {
177 .name = "max_ipc_container",
178 .mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
179 .type = IPC_CONTAINER,
180 .fileOps = &SYS_USER_OPT
181 },
182 #endif
183 #ifdef LOSCFG_NET_CONTAINER
184 {
185 .name = "max_net_container",
186 .mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
187 .type = NET_CONTAINER,
188 .fileOps = &SYS_USER_OPT
189 },
190 #endif
191 };
192
ProcCreateSysUser(struct ProcDirEntry * parent)193 static int ProcCreateSysUser(struct ProcDirEntry *parent)
194 {
195 struct ProcDataParm parm;
196 for (int index = 0; index < (sizeof(g_sysUser) / sizeof(struct ProcSysUser)); index++) {
197 struct ProcSysUser *sysUser = &g_sysUser[index];
198 parm.data = (void *)(uintptr_t)sysUser->type;
199 parm.dataType = PROC_DATA_STATIC;
200 struct ProcDirEntry *userFile = ProcCreateData(sysUser->name, sysUser->mode, parent, sysUser->fileOps, &parm);
201 if (userFile == NULL) {
202 PRINT_ERR("create /proc/%s/%s error!\n", parent->name, sysUser->name);
203 return -1;
204 }
205 }
206 return 0;
207 }
208
209 #define PROC_SYS_USER_MODE (S_IFDIR | S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
ProcSysUserInit(void)210 void ProcSysUserInit(void)
211 {
212 struct ProcDirEntry *parentPDE = CreateProcEntry("sys", PROC_SYS_USER_MODE, NULL);
213 if (parentPDE == NULL) {
214 return;
215 }
216 struct ProcDirEntry *pde = CreateProcEntry("user", PROC_SYS_USER_MODE, parentPDE);
217 if (pde == NULL) {
218 PRINT_ERR("create /proc/process error!\n");
219 return;
220 }
221
222 int ret = ProcCreateSysUser(pde);
223 if (ret < 0) {
224 PRINT_ERR("Create proc sys user failed!\n");
225 }
226 return;
227 }
228 #endif
229