• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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