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 <stdio.h>
33 #include <unistd.h>
34 #include "stdlib.h"
35 #include "los_printf.h"
36 #include "los_base.h"
37 #include "los_seq_buf.h"
38 #include "internal.h"
39 #include "proc_fs.h"
40 #include "los_task_pri.h"
41 #include "los_process_pri.h"
42 #include "los_process.h"
43 #include "show.h"
44 #include "vnode.h"
45 #include "proc_file.h"
46 #include "user_copy.h"
47
48 #ifdef LOSCFG_KERNEL_PLIMITS
49 #include "los_plimits.h"
50
51 #define PLIMITS_ENTRY_NAME_MAX 64
52 #define PLIMITERSET_DELETE_ALLOC 4
53 #define UNITPTR_NULL ((uintptr_t)(0xFFFFFFFF))
54 #define PLIMIT_FILE_MODE_READ_WRITE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
55 #define PLIMIT_FILE_MODE_READ_ONLY (S_IRUSR | S_IRGRP | S_IROTH)
56 #define PLIMIT_FILE_MODE_WRITE_ONLY (S_IWUSR)
57 #define PLIMIT_FILE_MODE_MASK_WRITE (~((mode_t)(S_IWUSR)))
58 #define PLIMIT_FILE_MODE_MASK_NONE (~((mode_t)(0)))
59 #define LOS_MAX_CACHE (UINT64)(0xFFFFFFFFFFFFFFFF)
60 #define PLIMIT_CAT_BUF_SIZE 512
61 #define MAX_PROTECTED_PROCESS_ID 14
62 #define UNITPTR_NULL ((uintptr_t)(0xFFFFFFFF))
63
64 static int ShowPids(struct SeqBuf *seqBuf, VOID *data);
65 static ssize_t PidMigrateFromProcLimiterSet(struct ProcFile *pf, const CHAR *buf, size_t count, loff_t *ppos);
66 static ssize_t PidLimitReadPidLimit(struct SeqBuf *seqBuf, VOID *data);
67 static ssize_t PidLimitReadPriorityLimit(struct SeqBuf *seqBuf, VOID *data);
68 static ssize_t PriorityLimitVariableWrite(struct ProcFile *pf, const CHAR *buf, size_t count, loff_t *ppos);
69 static ssize_t PidsMaxVariableWrite(struct ProcFile *pf, const CHAR *buf, size_t count, loff_t *ppos);
70 static ssize_t ProcLimitsShowLimiters(struct SeqBuf *seqBuf, VOID *data);
71 static int ProcfsPlimitsMkdir(struct ProcDirEntry *parent, const char *dirName, mode_t mode, struct ProcDirEntry **pde);
72 static int ProcfsPlimitsRmdir(struct ProcDirEntry *parent, struct ProcDirEntry *pde, const char *name);
73 #ifdef LOSCFG_KERNEL_MEM_PLIMIT
74 static ssize_t MemLimitReadLimit(struct SeqBuf *seqBuf, VOID *data);
75 static ssize_t MemLimitWriteLimit(struct ProcFile *pf, const CHAR *buf, size_t count, loff_t *ppos);
76 static ssize_t MemLimitStatShow(struct SeqBuf *seqBuf, VOID *data);
77 #endif
78 #ifdef LOSCFG_KERNEL_IPC_PLIMIT
79 static ssize_t IPCLimitReadMqLimit(struct SeqBuf *seqBuf, VOID *data);
80 static ssize_t IPCLimitWriteMqLimit(struct ProcFile *pf, const CHAR *buf, size_t count, loff_t *ppos);
81 static ssize_t IPCLimitReadShmLimit(struct SeqBuf *seqBuf, VOID *data);
82 static ssize_t IPCLimitWriteShmLimit(struct ProcFile *pf, const CHAR *buf, size_t count, loff_t *ppos);
83 static ssize_t IPCLimitShowStat(struct SeqBuf *seqBuf, VOID *data);
84 #endif
85 #ifdef LOSCFG_KERNEL_DEV_PLIMIT
86 static ssize_t DevLimitWriteAllow(struct ProcFile *pf, const CHAR *buf, size_t count, loff_t *ppos);
87 static ssize_t DevLimitWriteDeny(struct ProcFile *pf, const CHAR *buf, size_t count, loff_t *ppos);
88 static ssize_t DevLimitShow(struct SeqBuf *seqBuf, VOID *data);
89 #endif
90 #ifdef LOSCFG_KERNEL_SCHED_PLIMIT
91 static ssize_t SchedLimitReadPeriod(struct SeqBuf *seqBuf, VOID *data);
92 static ssize_t SchedLimitWritePeriod(struct ProcFile *pf, const CHAR *buf, size_t count, loff_t *ppos);
93 static ssize_t SchedLimitReadQuota(struct SeqBuf *seqBuf, VOID *data);
94 static ssize_t SchedLimitWriteQuota(struct ProcFile *pf, const CHAR *buf, size_t count, loff_t *ppos);
95 static ssize_t SchedLimitShow(struct SeqBuf *seqBuf, VOID *data);
96 #endif
97
98 struct PLimitsEntryOpt {
99 int id;
100 char name[PLIMITS_ENTRY_NAME_MAX];
101 mode_t mode;
102 uintptr_t offset;
103 struct ProcFileOperations ops;
104 };
105
106 static struct ProcDirOperations g_procDirOperations = {
107 .mkdir = ProcfsPlimitsMkdir,
108 .rmdir = ProcfsPlimitsRmdir,
109 };
110
111 static struct PLimitsEntryOpt g_plimitsEntryOpts[] = {
112 {
113 .id = PROCESS_LIMITER_COUNT,
114 .name = "plimits.limiters",
115 .mode = PLIMIT_FILE_MODE_READ_ONLY,
116 .offset = UNITPTR_NULL,
117 .ops = {
118 .read = ProcLimitsShowLimiters,
119 }
120 },
121 {
122 .id = PROCESS_LIMITER_COUNT,
123 .name = "plimits.procs",
124 .mode = PLIMIT_FILE_MODE_READ_WRITE,
125 .offset = UNITPTR_NULL,
126 .ops = {
127 .read = ShowPids,
128 .write = PidMigrateFromProcLimiterSet,
129 },
130 },
131 {
132 .id = PROCESS_LIMITER_ID_PIDS,
133 .name = "pids.max",
134 .mode = PLIMIT_FILE_MODE_READ_WRITE,
135 .offset = 0,
136 .ops = {
137 .read = PidLimitReadPidLimit,
138 .write = PidsMaxVariableWrite,
139 },
140 },
141 {
142 .id = PROCESS_LIMITER_ID_PIDS,
143 .name = "pids.priority",
144 .mode = PLIMIT_FILE_MODE_READ_WRITE,
145 .offset = 0,
146 .ops = {
147 .read = PidLimitReadPriorityLimit,
148 .write = PriorityLimitVariableWrite,
149 },
150 },
151 #ifdef LOSCFG_KERNEL_MEM_PLIMIT
152 {
153 .id = PROCESS_LIMITER_ID_MEM,
154 .name = "memory.limit",
155 .mode = PLIMIT_FILE_MODE_READ_WRITE,
156 .offset = 0,
157 .ops = {
158 .read = MemLimitReadLimit,
159 .write = MemLimitWriteLimit,
160 },
161 },
162 {
163 .id = PROCESS_LIMITER_ID_MEM,
164 .name = "memory.stat",
165 .mode = PLIMIT_FILE_MODE_READ_ONLY,
166 .offset = UNITPTR_NULL,
167 .ops = {
168 .read = MemLimitStatShow,
169 }
170 },
171 #endif
172 #ifdef LOSCFG_KERNEL_IPC_PLIMIT
173 {
174 .id = PROCESS_LIMITER_ID_IPC,
175 .name = "ipc.mq_limit",
176 .mode = PLIMIT_FILE_MODE_READ_WRITE,
177 .offset = 0,
178 .ops = {
179 .read = IPCLimitReadMqLimit,
180 .write = IPCLimitWriteMqLimit,
181 }
182 },
183 {
184 .id = PROCESS_LIMITER_ID_IPC,
185 .name = "ipc.shm_limit",
186 .mode = PLIMIT_FILE_MODE_READ_WRITE,
187 .offset = 0,
188 .ops = {
189 .read = IPCLimitReadShmLimit,
190 .write = IPCLimitWriteShmLimit,
191 }
192 },
193 {
194 .id = PROCESS_LIMITER_ID_IPC,
195 .name = "ipc.stat",
196 .mode = PLIMIT_FILE_MODE_READ_ONLY,
197 .offset = UNITPTR_NULL,
198 .ops = {
199 .read = IPCLimitShowStat,
200 }
201 },
202 #endif
203 #ifdef LOSCFG_KERNEL_DEV_PLIMIT
204 {
205 .id = PROCESS_LIMITER_ID_DEV,
206 .name = "devices.allow",
207 .mode = PLIMIT_FILE_MODE_WRITE_ONLY,
208 .offset = UNITPTR_NULL,
209 .ops = {
210 .write = DevLimitWriteAllow,
211 }
212 },
213 {
214 .id = PROCESS_LIMITER_ID_DEV,
215 .name = "devices.deny",
216 .mode = PLIMIT_FILE_MODE_WRITE_ONLY,
217 .offset = UNITPTR_NULL,
218 .ops = {
219 .write = DevLimitWriteDeny,
220 }
221 },
222 {
223 .id = PROCESS_LIMITER_ID_DEV,
224 .name = "devices.list",
225 .mode = PLIMIT_FILE_MODE_READ_ONLY,
226 .offset = 0,
227 .ops = {
228 .read = DevLimitShow,
229 }
230 },
231 #endif
232 #ifdef LOSCFG_KERNEL_SCHED_PLIMIT
233 {
234 .id = PROCESS_LIMITER_ID_SCHED,
235 .name = "sched.period",
236 .mode = PLIMIT_FILE_MODE_READ_WRITE,
237 .offset = 0,
238 .ops = {
239 .read = SchedLimitReadPeriod,
240 .write = SchedLimitWritePeriod,
241 },
242 },
243 {
244 .id = PROCESS_LIMITER_ID_SCHED,
245 .name = "sched.quota",
246 .mode = PLIMIT_FILE_MODE_READ_WRITE,
247 .offset = 0,
248 .ops = {
249 .read = SchedLimitReadQuota,
250 .write = SchedLimitWriteQuota,
251 },
252 },
253 {
254 .id = PROCESS_LIMITER_ID_SCHED,
255 .name = "sched.stat",
256 .mode = PLIMIT_FILE_MODE_READ_ONLY,
257 .offset = UNITPTR_NULL,
258 .ops = {
259 .read = SchedLimitShow,
260 }
261 },
262 #endif
263 };
264
MemUserCopy(const char * src,size_t len,char ** kbuf)265 static unsigned int MemUserCopy(const char *src, size_t len, char **kbuf)
266 {
267 if (LOS_IsUserAddressRange((VADDR_T)(UINTPTR)src, len)) {
268 char *kernelBuf = LOS_MemAlloc(m_aucSysMem1, len + 1);
269 if (kernelBuf == NULL) {
270 return ENOMEM;
271 }
272
273 if (LOS_ArchCopyFromUser(kernelBuf, src, len) != 0) {
274 (VOID)LOS_MemFree(m_aucSysMem1, kernelBuf);
275 return EFAULT;
276 }
277 kernelBuf[len] = '\0';
278 *kbuf = kernelBuf;
279 return 0;
280 }
281 return 0;
282 }
283
GetCurrDirectory(struct ProcDirEntry * dirEntry)284 static inline struct ProcDirEntry *GetCurrDirectory(struct ProcDirEntry *dirEntry)
285 {
286 return ((dirEntry == NULL) || S_ISDIR(dirEntry->mode)) ? dirEntry : dirEntry->parent;
287 }
288
GetProcLimiterSetFromDirEntry(struct ProcDirEntry * dirEntry)289 static inline ProcLimiterSet *GetProcLimiterSetFromDirEntry(struct ProcDirEntry *dirEntry)
290 {
291 struct ProcDirEntry *currDirectory = GetCurrDirectory(dirEntry);
292 return (currDirectory == NULL) || (currDirectory->data == NULL) ? NULL : (ProcLimiterSet *)currDirectory->data;
293 }
294
ProcCreateLimiterFiles(struct ProcDirEntry * parentEntry,struct PLimitsEntryOpt * entryOpt,mode_t mode,void * data)295 static struct ProcDirEntry *ProcCreateLimiterFiles(struct ProcDirEntry *parentEntry,
296 struct PLimitsEntryOpt *entryOpt,
297 mode_t mode, void *data)
298 {
299 struct ProcDataParm dataParm = {
300 .data = data,
301 .dataType = PROC_DATA_STATIC,
302 };
303 struct ProcDirEntry *plimitFile = ProcCreateData(entryOpt->name, entryOpt->mode & mode, parentEntry,
304 &entryOpt->ops, &dataParm);
305 if (plimitFile == NULL) {
306 return NULL;
307 }
308 return plimitFile;
309 }
310
ProcLimiterDirEntryInit(struct ProcDirEntry * dirEntry,unsigned mask,mode_t mode)311 static void ProcLimiterDirEntryInit(struct ProcDirEntry *dirEntry, unsigned mask, mode_t mode)
312 {
313 struct ProcDirEntry *currDir = GetCurrDirectory(dirEntry);
314 if (currDir == NULL) {
315 return;
316 }
317
318 ProcLimiterSet *plimiterData = (ProcLimiterSet *)currDir->data;
319 if (plimiterData == NULL) {
320 return;
321 }
322
323 for (int index = 0; index < (sizeof(g_plimitsEntryOpts) / sizeof(struct PLimitsEntryOpt)); index++) {
324 struct PLimitsEntryOpt *entryOpt = &g_plimitsEntryOpts[index];
325 enum ProcLimiterID plimiterType = entryOpt->id;
326 if (!(BIT(plimiterType) & mask)) {
327 continue;
328 }
329
330 void *head = (entryOpt->offset == UNITPTR_NULL) ?
331 plimiterData : (void *)plimiterData->limitsList[plimiterType];
332 struct ProcDirEntry *entry = ProcCreateLimiterFiles(currDir, entryOpt, mode, head);
333 if (entry == NULL) {
334 RemoveProcEntry(currDir->name, NULL);
335 return;
336 }
337 }
338 return;
339 }
340
PLimitsCopyLimits(struct ProcDirEntry * dirEntry)341 static ssize_t PLimitsCopyLimits(struct ProcDirEntry *dirEntry)
342 {
343 struct ProcDirEntry *parentPde = dirEntry->parent;
344 ProcLimiterSet *parentPLimits = (ProcLimiterSet *)parentPde->data;
345 if (parentPLimits == NULL) {
346 return -EINVAL;
347 }
348
349 ProcLimiterSet *newPLimits = OsPLimitsCreate(parentPLimits);
350 if (newPLimits == NULL) {
351 return -ENOMEM;
352 }
353 dirEntry->data = (VOID *)newPLimits;
354 dirEntry->dataType = PROC_DATA_STATIC;
355 dirEntry->procDirOps = parentPde->procDirOps;
356 ProcLimiterDirEntryInit(dirEntry, newPLimits->mask, PLIMIT_FILE_MODE_MASK_NONE);
357 return 0;
358 }
359
ProcfsPlimitsMkdir(struct ProcDirEntry * parent,const char * dirName,mode_t mode,struct ProcDirEntry ** pde)360 static int ProcfsPlimitsMkdir(struct ProcDirEntry *parent, const char *dirName, mode_t mode, struct ProcDirEntry **pde)
361 {
362 int ret;
363 if (strcmp(parent->name, "plimits") != 0) {
364 return -EPERM;
365 }
366
367 struct ProcDirEntry *plimitDir = ProcCreateData(dirName, S_IFDIR | mode, parent, NULL, NULL);
368 if (plimitDir == NULL) {
369 return -EINVAL;
370 }
371
372 ret = PLimitsCopyLimits(plimitDir);
373 if (ret != LOS_OK) {
374 ProcFreeEntry(plimitDir);
375 return -ENOSYS;
376 }
377 *pde = plimitDir;
378 return ret;
379 }
380
ProcfsPlimitsRmdir(struct ProcDirEntry * parent,struct ProcDirEntry * pde,const char * name)381 static int ProcfsPlimitsRmdir(struct ProcDirEntry *parent, struct ProcDirEntry *pde, const char *name)
382 {
383 if (pde == NULL) {
384 return -EINVAL;
385 }
386
387 ProcLimiterSet *plimits = GetProcLimiterSetFromDirEntry(pde);
388 pde->data = NULL;
389
390 unsigned ret = OsPLimitsFree(plimits);
391 if (ret != 0) {
392 pde->data = plimits;
393 return -ret;
394 }
395
396 spin_lock(&procfsLock);
397 ProcDetachNode(pde);
398 spin_unlock(&procfsLock);
399
400 RemoveProcEntryTravalsal(pde->subdir);
401
402 ProcFreeEntry(pde);
403 return 0;
404 }
405
ProcLimitsShowLimiters(struct SeqBuf * seqBuf,VOID * data)406 static ssize_t ProcLimitsShowLimiters(struct SeqBuf *seqBuf, VOID *data)
407 {
408 ProcLimiterSet *plimits = (ProcLimiterSet *)data;
409 UINT32 mask;
410 if (plimits == NULL) {
411 return -LOS_NOK;
412 }
413 mask = plimits->mask;
414
415 if (mask & BIT(PROCESS_LIMITER_ID_PIDS)) {
416 LosBufPrintf(seqBuf, "%s ", "pids");
417 }
418 #ifdef LOSCFG_KERNEL_MEM_PLIMIT
419 if (mask & BIT(PROCESS_LIMITER_ID_MEM)) {
420 LosBufPrintf(seqBuf, "%s ", "memory");
421 }
422 #endif
423 #ifdef LOSCFG_KERNEL_IPC_PLIMIT
424 if (mask & BIT(PROCESS_LIMITER_ID_IPC)) {
425 LosBufPrintf(seqBuf, "%s ", "ipc");
426 }
427 #endif
428 #ifdef LOSCFG_KERNEL_DEV_PLIMIT
429 if (mask & BIT(PROCESS_LIMITER_ID_DEV)) {
430 LosBufPrintf(seqBuf, "%s ", "devices");
431 }
432 #endif
433 #ifdef LOSCFG_KERNEL_SCHED_PLIMIT
434 if (mask & BIT(PROCESS_LIMITER_ID_SCHED)) {
435 LosBufPrintf(seqBuf, "%s ", "sched");
436 }
437 #endif
438 return LOS_OK;
439 }
440
441 #define PLIMITS_PID_STR_LENGTH 4
ShowPids(struct SeqBuf * seqBuf,VOID * data)442 static int ShowPids(struct SeqBuf *seqBuf, VOID *data)
443 {
444 unsigned int size, pidMax;
445 if (data == NULL) {
446 return -EINVAL;
447 }
448
449 const ProcLimiterSet *plimits = (const ProcLimiterSet *)data;
450 pidMax = LOS_GetSystemProcessMaximum();
451 size = pidMax * sizeof(unsigned int);
452 unsigned int *pids = (unsigned int *)LOS_MemAlloc(m_aucSysMem1, size);
453 if (pids == NULL) {
454 return -ENOMEM;
455 }
456 (void)memset_s(pids, size, 0, size);
457
458 unsigned int ret = OsPLimitsPidsGet(plimits, pids, size);
459 if (ret != LOS_OK) {
460 (VOID)LOS_MemFree(m_aucSysMem1, pids);
461 return -ret;
462 }
463
464 (void)LosBufPrintf(seqBuf, "\n");
465 for (unsigned int index = 0; index < pidMax; index++) {
466 if (pids[index] == 0) {
467 continue;
468 }
469 (void)LosBufPrintf(seqBuf, "%u ", index);
470 }
471 (void)LOS_MemFree(m_aucSysMem1, pids);
472 return 0;
473 }
474
GetPidLimitValue(struct ProcFile * pf,const CHAR * buf,size_t count)475 static long long int GetPidLimitValue(struct ProcFile *pf, const CHAR *buf, size_t count)
476 {
477 long long int value;
478 char *kbuf = NULL;
479
480 if ((pf == NULL) || (pf->pPDE == NULL) || (buf == NULL) || (count <= 0)) {
481 return -EINVAL;
482 }
483
484 unsigned ret = MemUserCopy(buf, count, &kbuf);
485 if (ret != 0) {
486 return -ret;
487 } else if ((ret == 0) && (kbuf != NULL)) {
488 buf = (const char *)kbuf;
489 }
490
491 if (strspn(buf, "0123456789") != count) {
492 (void)LOS_MemFree(m_aucSysMem1, kbuf);
493 return -EINVAL;
494 }
495 value = strtoll(buf, NULL, 10); /* 10: decimal */
496 (void)LOS_MemFree(m_aucSysMem1, kbuf);
497 return value;
498 }
499
PidMigrateFromProcLimiterSet(struct ProcFile * pf,const CHAR * buf,size_t count,loff_t * ppos)500 static ssize_t PidMigrateFromProcLimiterSet(struct ProcFile *pf, const CHAR *buf, size_t count, loff_t *ppos)
501 {
502 (VOID)ppos;
503 unsigned ret;
504
505 long long int pid = GetPidLimitValue(pf, buf, count);
506 if (pid < 0) {
507 return pid;
508 }
509
510 ProcLimiterSet *plimits = GetCurrDirectory(pf->pPDE)->data;
511 ret = OsPLimitsAddPid(plimits, (unsigned int)pid);
512 if (ret != LOS_OK) {
513 return -ret;
514 }
515 return count;
516 }
517
PidLimitReadPidLimit(struct SeqBuf * seqBuf,VOID * data)518 static ssize_t PidLimitReadPidLimit(struct SeqBuf *seqBuf, VOID *data)
519 {
520 PidLimit *pidLimit = (PidLimit *)data;
521 if ((seqBuf == NULL) || (pidLimit == NULL)) {
522 return -EINVAL;
523 }
524
525 (void)LosBufPrintf(seqBuf, "%u\n", pidLimit->pidLimit);
526 return 0;
527 }
528
PidLimitReadPriorityLimit(struct SeqBuf * seqBuf,VOID * data)529 static ssize_t PidLimitReadPriorityLimit(struct SeqBuf *seqBuf, VOID *data)
530 {
531 PidLimit *pidLimit = (PidLimit *)data;
532 if ((seqBuf == NULL) || (pidLimit == NULL)) {
533 return -EINVAL;
534 }
535
536 (void)LosBufPrintf(seqBuf, "%u\n", pidLimit->priorityLimit);
537 return 0;
538 }
539
PriorityLimitVariableWrite(struct ProcFile * pf,const CHAR * buf,size_t count,loff_t * ppos)540 static ssize_t PriorityLimitVariableWrite(struct ProcFile *pf, const CHAR *buf, size_t count, loff_t *ppos)
541 {
542 (void)ppos;
543 long long int value = GetPidLimitValue(pf, buf, count);
544 if (value < 0) {
545 return value;
546 }
547
548 PidLimit *pidLimit = (PidLimit *)pf->pPDE->data;
549 unsigned ret = PidLimitSetPriorityLimit(pidLimit, (unsigned)value);
550 if (ret != LOS_OK) {
551 return -ret;
552 }
553 return count;
554 }
555
PidsMaxVariableWrite(struct ProcFile * pf,const CHAR * buf,size_t count,loff_t * ppos)556 static ssize_t PidsMaxVariableWrite(struct ProcFile *pf, const CHAR *buf, size_t count, loff_t *ppos)
557 {
558 (void)ppos;
559 long long int value = GetPidLimitValue(pf, buf, count);
560 if (value < 0) {
561 return value;
562 }
563
564 PidLimit *pidLimit = (PidLimit *)pf->pPDE->data;
565 unsigned ret = PidLimitSetPidLimit(pidLimit, (unsigned)value);
566 if (ret != LOS_OK) {
567 return -ret;
568 }
569 return count;
570 }
571
572 #ifdef LOSCFG_KERNEL_MEM_PLIMIT
MemLimitReadLimit(struct SeqBuf * seqBuf,VOID * data)573 static ssize_t MemLimitReadLimit(struct SeqBuf *seqBuf, VOID *data)
574 {
575 ProcMemLimiter *memLimit = (ProcMemLimiter *)data;
576 if ((seqBuf == NULL) || (memLimit == NULL)) {
577 return -EINVAL;
578 }
579
580 (void)LosBufPrintf(seqBuf, "%llu\n", memLimit->limit);
581 return 0;
582 }
583
MemLimitWriteLimit(struct ProcFile * pf,const CHAR * buf,size_t count,loff_t * ppos)584 static ssize_t MemLimitWriteLimit(struct ProcFile *pf, const CHAR *buf, size_t count, loff_t *ppos)
585 {
586 (void)ppos;
587 long long int value = GetPidLimitValue(pf, buf, count);
588 if ((value < 0) || (value > (long long int)OS_NULL_INT)) {
589 return value;
590 }
591
592 ProcMemLimiter *memLimit = (ProcMemLimiter *)pf->pPDE->data;
593 unsigned ret = OsMemLimitSetMemLimit(memLimit, (unsigned long long)value);
594 if (ret != LOS_OK) {
595 return -ret;
596 }
597 return count;
598 }
599
MemLimitStatShow(struct SeqBuf * seqBuf,VOID * data)600 static ssize_t MemLimitStatShow(struct SeqBuf *seqBuf, VOID *data)
601 {
602 ProcLimiterSet *plimits = (ProcLimiterSet *)data;
603 if ((seqBuf == NULL) || (plimits == NULL)) {
604 return -EINVAL;
605 }
606
607 UINT32 pidMax = LOS_GetSystemProcessMaximum();
608 UINT32 size = sizeof(ProcMemLimiter) + pidMax * sizeof(unsigned long long);
609 unsigned long long *usage = (unsigned long long *)LOS_MemAlloc(m_aucSysMem1, size);
610 if (usage == NULL) {
611 return -ENOMEM;
612 }
613 (void)memset_s(usage, size, 0, size);
614
615 unsigned int ret = OsPLimitsMemUsageGet(plimits, usage, size);
616 if (ret != LOS_OK) {
617 (VOID)LOS_MemFree(m_aucSysMem1, usage);
618 return -ret;
619 }
620
621 ProcMemLimiter *memLimit = (ProcMemLimiter *)usage;
622 unsigned long long *memUsage = (unsigned long long *)((uintptr_t)usage + sizeof(ProcMemLimiter));
623 (void)LosBufPrintf(seqBuf, "\nMem used: %llu\n", memLimit->usage);
624 (void)LosBufPrintf(seqBuf, "Mem peak: %llu\n", memLimit->peak);
625 (void)LosBufPrintf(seqBuf, "Mem failed count: %u\n", memLimit->failcnt);
626
627 for (unsigned int index = 0; index < pidMax; index++) {
628 if (memUsage[index] == 0) {
629 continue;
630 }
631 (void)LosBufPrintf(seqBuf, "PID: %u mem used: %llu \n", index, memUsage[index]);
632 }
633 (void)LOS_MemFree(m_aucSysMem1, usage);
634 return 0;
635 }
636 #endif
637
638 #ifdef LOSCFG_KERNEL_IPC_PLIMIT
IPCLimitReadMqLimit(struct SeqBuf * seqBuf,VOID * data)639 static ssize_t IPCLimitReadMqLimit(struct SeqBuf *seqBuf, VOID *data)
640 {
641 ProcIPCLimit *ipcLimit = (ProcIPCLimit *)data;
642 if ((seqBuf == NULL) || (ipcLimit == NULL)) {
643 return -EINVAL;
644 }
645
646 (void)LosBufPrintf(seqBuf, "%u\n", ipcLimit->mqCountLimit);
647 return 0;
648 }
649
IPCLimitWriteMqLimit(struct ProcFile * pf,const CHAR * buf,size_t count,loff_t * ppos)650 static ssize_t IPCLimitWriteMqLimit(struct ProcFile *pf, const CHAR *buf, size_t count, loff_t *ppos)
651 {
652 (void)ppos;
653 long long int value = GetPidLimitValue(pf, buf, count);
654 if (value < 0) {
655 return value;
656 }
657
658 ProcIPCLimit *ipcLimit = (ProcIPCLimit *)pf->pPDE->data;
659 unsigned ret = OsIPCLimitSetMqLimit(ipcLimit, (unsigned long long)value);
660 if (ret != LOS_OK) {
661 return -ret;
662 }
663 return count;
664 }
665
IPCLimitReadShmLimit(struct SeqBuf * seqBuf,VOID * data)666 static ssize_t IPCLimitReadShmLimit(struct SeqBuf *seqBuf, VOID *data)
667 {
668 ProcIPCLimit *ipcLimit = (ProcIPCLimit *)data;
669 if ((seqBuf == NULL) || (ipcLimit == NULL)) {
670 return -EINVAL;
671 }
672
673 (void)LosBufPrintf(seqBuf, "%u\n", ipcLimit->shmSizeLimit);
674 return 0;
675 }
676
IPCLimitWriteShmLimit(struct ProcFile * pf,const CHAR * buf,size_t count,loff_t * ppos)677 static ssize_t IPCLimitWriteShmLimit(struct ProcFile *pf, const CHAR *buf, size_t count, loff_t *ppos)
678 {
679 (void)ppos;
680 long long int value = GetPidLimitValue(pf, buf, count);
681 if ((value < 0) || (value > (long long int)OS_NULL_INT)) {
682 return value;
683 }
684
685 ProcIPCLimit *ipcLimit = (ProcIPCLimit *)pf->pPDE->data;
686 unsigned ret = OsIPCLimitSetShmLimit(ipcLimit, (unsigned long long)value);
687 if (ret != LOS_OK) {
688 return -ret;
689 }
690 return count;
691 }
692
IPCLimitShowStat(struct SeqBuf * seqBuf,VOID * data)693 static ssize_t IPCLimitShowStat(struct SeqBuf *seqBuf, VOID *data)
694 {
695 ProcLimiterSet *plimits = (ProcLimiterSet *)data;
696 if ((seqBuf == NULL) || (plimits == NULL)) {
697 return -EINVAL;
698 }
699
700 unsigned int size = sizeof(ProcIPCLimit);
701 ProcIPCLimit *newIPCLimit = (ProcIPCLimit *)LOS_MemAlloc(m_aucSysMem1, size);
702 if (newIPCLimit == NULL) {
703 return -ENOMEM;
704 }
705 (void)memset_s(newIPCLimit, size, 0, size);
706
707 unsigned int ret = OsPLimitsIPCStatGet(plimits, newIPCLimit, size);
708 if (ret != LOS_OK) {
709 (VOID)LOS_MemFree(m_aucSysMem1, newIPCLimit);
710 return -ret;
711 }
712
713 (void)LosBufPrintf(seqBuf, "mq count: %u\n", newIPCLimit->mqCount);
714 (void)LosBufPrintf(seqBuf, "mq failed count: %u\n", newIPCLimit->mqFailedCount);
715 (void)LosBufPrintf(seqBuf, "shm size: %u\n", newIPCLimit->shmSize);
716 (void)LosBufPrintf(seqBuf, "shm failed count: %u\n", newIPCLimit->shmFailedCount);
717 (void)LOS_MemFree(m_aucSysMem1, newIPCLimit);
718 return 0;
719 }
720 #endif
721
722 #ifdef LOSCFG_KERNEL_DEV_PLIMIT
DevLimitWriteAllow(struct ProcFile * pf,const CHAR * buf,size_t count,loff_t * ppos)723 static ssize_t DevLimitWriteAllow(struct ProcFile *pf, const CHAR *buf, size_t count, loff_t *ppos)
724 {
725 (void)ppos;
726 char *kbuf = NULL;
727
728 if ((pf == NULL) || (pf->pPDE == NULL) || (buf == NULL) || (count <= 0)) {
729 return -EINVAL;
730 }
731
732 unsigned ret = MemUserCopy(buf, count, &kbuf);
733 if (ret != 0) {
734 return -ret;
735 } else if ((ret == 0) && (kbuf != NULL)) {
736 buf = (const char *)kbuf;
737 }
738
739 ProcLimiterSet *plimit = (ProcLimiterSet *)pf->pPDE->data;
740 ret = OsDevLimitWriteAllow(plimit, buf, count);
741 (VOID)LOS_MemFree(m_aucSysMem1, kbuf);
742 if (ret != LOS_OK) {
743 return -ret;
744 }
745 return count;
746 }
747
DevLimitWriteDeny(struct ProcFile * pf,const CHAR * buf,size_t count,loff_t * ppos)748 static ssize_t DevLimitWriteDeny(struct ProcFile *pf, const CHAR *buf, size_t count, loff_t *ppos)
749 {
750 (void)ppos;
751 char *kbuf = NULL;
752
753 if ((pf == NULL) || (pf->pPDE == NULL) || (buf == NULL) || (count <= 0)) {
754 return -EINVAL;
755 }
756
757 unsigned ret = MemUserCopy(buf, count, &kbuf);
758 if (ret != 0) {
759 return -ret;
760 } else if ((ret == 0) && (kbuf != NULL)) {
761 buf = (const char *)kbuf;
762 }
763
764 ProcLimiterSet *plimit = (ProcLimiterSet *)pf->pPDE->data;
765 ret = OsDevLimitWriteDeny(plimit, buf, count);
766 (VOID)LOS_MemFree(m_aucSysMem1, kbuf);
767 if (ret != LOS_OK) {
768 return -ret;
769 }
770 return count;
771 }
772
DevLimitShow(struct SeqBuf * seqBuf,VOID * data)773 static ssize_t DevLimitShow(struct SeqBuf *seqBuf, VOID *data)
774 {
775 ProcDevLimit *devLimit = (ProcDevLimit *)data;
776 if ((seqBuf == NULL) || (devLimit == NULL)) {
777 return -EINVAL;
778 }
779
780 unsigned ret = OsDevLimitShow(devLimit, seqBuf);
781 if (ret != LOS_OK) {
782 return -ret;
783 }
784 return 0;
785 }
786 #endif
787
788 #ifdef LOSCFG_KERNEL_SCHED_PLIMIT
SchedLimitReadPeriod(struct SeqBuf * seqBuf,VOID * data)789 static ssize_t SchedLimitReadPeriod(struct SeqBuf *seqBuf, VOID *data)
790 {
791 ProcSchedLimiter *schedLimit = (ProcSchedLimiter *)data;
792 if ((seqBuf == NULL) || (schedLimit == NULL)) {
793 return -EINVAL;
794 }
795
796 (void)LosBufPrintf(seqBuf, "%lld\n", schedLimit->period);
797 return 0;
798 }
799
SchedLimitWritePeriod(struct ProcFile * pf,const CHAR * buf,size_t count,loff_t * ppos)800 static ssize_t SchedLimitWritePeriod(struct ProcFile *pf, const CHAR *buf, size_t count, loff_t *ppos)
801 {
802 (void)ppos;
803 long long int value = GetPidLimitValue(pf, buf, count);
804 if (value < 0) {
805 return value;
806 }
807
808 ProcSchedLimiter *schedLimit = (ProcSchedLimiter *)pf->pPDE->data;
809 unsigned ret = OsSchedLimitSetPeriod(schedLimit, (unsigned long long)value);
810 if (ret != LOS_OK) {
811 return -ret;
812 }
813 return count;
814 }
815
SchedLimitReadQuota(struct SeqBuf * seqBuf,VOID * data)816 static ssize_t SchedLimitReadQuota(struct SeqBuf *seqBuf, VOID *data)
817 {
818 ProcSchedLimiter *schedLimit = (ProcSchedLimiter *)data;
819 if ((seqBuf == NULL) || (schedLimit == NULL)) {
820 return -EINVAL;
821 }
822
823 (void)LosBufPrintf(seqBuf, "%lld\n", schedLimit->quota);
824 return 0;
825 }
826
SchedLimitWriteQuota(struct ProcFile * pf,const CHAR * buf,size_t count,loff_t * ppos)827 static ssize_t SchedLimitWriteQuota(struct ProcFile *pf, const CHAR *buf, size_t count, loff_t *ppos)
828 {
829 (void)ppos;
830 long long int value = GetPidLimitValue(pf, buf, count);
831 if (value < 0) {
832 return value;
833 }
834
835 ProcSchedLimiter *schedLimit = (ProcSchedLimiter *)pf->pPDE->data;
836 unsigned ret = OsSchedLimitSetQuota(schedLimit, (unsigned long long)value);
837 if (ret != LOS_OK) {
838 return -ret;
839 }
840 return count;
841 }
842
843 #define TIME_CYCLE_TO_US(time) ((((UINT64)time) * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US)
844 #define SCHED_DEFAULT_VALUE (0x101010101010101)
845
SchedLimitShow(struct SeqBuf * seqBuf,VOID * data)846 static ssize_t SchedLimitShow(struct SeqBuf *seqBuf, VOID *data)
847 {
848 ProcLimiterSet *plimits = (ProcLimiterSet *)data;
849 if ((seqBuf == NULL) || (plimits == NULL)) {
850 return -EINVAL;
851 }
852
853 UINT32 pidMax = LOS_GetSystemProcessMaximum();
854 UINT32 size = pidMax * sizeof(unsigned long long);
855 unsigned long long *usage = (unsigned long long *)LOS_MemAlloc(m_aucSysMem1, size);
856 if (usage == NULL) {
857 return -ENOMEM;
858 }
859 (void)memset_s(usage, size, 1, size);
860
861 unsigned int ret = OsPLimitsSchedUsageGet(plimits, usage, size);
862 if (ret != LOS_OK) {
863 (VOID)LOS_MemFree(m_aucSysMem1, usage);
864 return -ret;
865 }
866
867 for (unsigned int index = 0; index < pidMax; index++) {
868 if (usage[index] == SCHED_DEFAULT_VALUE) {
869 continue;
870 }
871 (void)LosBufPrintf(seqBuf, "PID: %u runTime: %llu us\n", index, TIME_CYCLE_TO_US(usage[index]));
872 }
873 (void)LOS_MemFree(m_aucSysMem1, usage);
874 return 0;
875 }
876 #endif
877
878 #define PROC_PLIMITS_MODE (S_IFDIR | S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
ProcLimitsInit(void)879 void ProcLimitsInit(void)
880 {
881 struct ProcDirEntry *parentPDE = CreateProcEntry("plimits", PROC_PLIMITS_MODE, NULL);
882 if (parentPDE == NULL) {
883 return;
884 }
885 ProcLimiterSet *plimits = OsRootPLimitsGet();
886 parentPDE->procDirOps = &g_procDirOperations;
887 parentPDE->data = (VOID *)plimits;
888 parentPDE->dataType = PROC_DATA_STATIC;
889 plimits->mask = BIT(PROCESS_LIMITER_ID_PIDS) | BIT(PROCESS_LIMITER_COUNT);
890 #ifdef LOSCFG_KERNEL_MEM_PLIMIT
891 plimits->mask |= BIT(PROCESS_LIMITER_ID_MEM);
892 #endif
893 #ifdef LOSCFG_KERNEL_IPC_PLIMIT
894 plimits->mask |= BIT(PROCESS_LIMITER_ID_IPC);
895 #endif
896 #ifdef LOSCFG_KERNEL_DEV_PLIMIT
897 plimits->mask |= BIT(PROCESS_LIMITER_ID_DEV);
898 #endif
899 #ifdef LOSCFG_KERNEL_SCHED_PLIMIT
900 plimits->mask |= BIT(PROCESS_LIMITER_ID_SCHED);
901 #endif
902 ProcLimiterDirEntryInit(parentPDE, plimits->mask, PLIMIT_FILE_MODE_MASK_WRITE);
903 return;
904 }
905 #endif
906