1/*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2023 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 *    conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 *    of conditions and the following disclaimer in the documentation and/or other materials
13 *    provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 *    to endorse or promote products derived from this software without specific prior written
17 *    permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <sys/statfs.h>
33#include <sys/mount.h>
34#include "proc_fs.h"
35#include "internal.h"
36#include "los_process_pri.h"
37#include "user_copy.h"
38#include "los_memory.h"
39
40#ifdef LOSCFG_PROC_PROCESS_DIR
41#include "los_vm_dump.h"
42
43typedef enum {
44    PROC_PID,
45    PROC_PID_MEM,
46#ifdef LOSCFG_KERNEL_CPUP
47    PROC_PID_CPUP,
48#endif
49#ifdef LOSCFG_USER_CONTAINER
50    PROC_UID_MAP,
51    PROC_GID_MAP,
52#endif
53    PROC_P_TYPE_MAX,
54} ProcessDataType;
55
56struct ProcProcess {
57    char         *name;
58    mode_t       mode;
59    int          type;
60    const struct ProcFileOperations *fileOps;
61};
62
63struct ProcessData {
64    uintptr_t process;
65    unsigned int type;
66};
67
68static LosProcessCB *ProcGetProcessCB(struct ProcessData *data)
69{
70    if (data->process != 0) {
71        return (LosProcessCB *)data->process;
72    }
73    return OsCurrProcessGet();
74}
75
76#define PROC_PID_PRIVILEGE 7
77#define PROC_PID_DIR_LEN 100
78#ifdef LOSCFG_KERNEL_CONTAINER
79static ssize_t ProcessContainerLink(unsigned int containerID, ContainerType type, char *buffer, size_t bufLen)
80{
81    ssize_t count = -1;
82    if ((type == PID_CONTAINER) || (type == PID_CHILD_CONTAINER)) {
83        count = snprintf_s(buffer, bufLen, bufLen - 1, "'pid:[%u]'", containerID);
84    } else if (type == UTS_CONTAINER) {
85        count = snprintf_s(buffer, bufLen, bufLen - 1, "'uts:[%u]'", containerID);
86    } else if (type == MNT_CONTAINER) {
87        count = snprintf_s(buffer, bufLen, bufLen - 1, "'mnt:[%u]'", containerID);
88    } else if (type == IPC_CONTAINER) {
89        count = snprintf_s(buffer, bufLen, bufLen - 1, "'ipc:[%u]'", containerID);
90    } else if ((type == TIME_CONTAINER) || (type == TIME_CHILD_CONTAINER)) {
91        count = snprintf_s(buffer, bufLen, bufLen - 1, "'time:[%u]'", containerID);
92    } else if (type == USER_CONTAINER) {
93        count = snprintf_s(buffer, bufLen, bufLen - 1, "'user:[%u]'", containerID);
94    }  else if (type == NET_CONTAINER) {
95        count = snprintf_s(buffer, bufLen, bufLen - 1, "'net:[%u]'", containerID);
96    }
97
98    if (count < 0) {
99        return -EBADF;
100    }
101    return count;
102}
103
104static ssize_t ProcessContainerReadLink(struct ProcDirEntry *entry, char *buffer, size_t bufLen)
105{
106    char *freeBuf = NULL;
107    char *buf = buffer;
108    ssize_t count;
109    unsigned int intSave;
110    if (entry == NULL) {
111        return -EINVAL;
112    }
113    struct ProcessData *data = (struct ProcessData *)entry->data;
114    if (data == NULL) {
115        return -EINVAL;
116    }
117
118    if (LOS_IsUserAddressRange((VADDR_T)(UINTPTR)buffer, bufLen)) {
119        buf = LOS_MemAlloc(m_aucSysMem1, bufLen);
120        if (buf == NULL) {
121            return -ENOMEM;
122        }
123        (void)memset_s(buf, bufLen, 0, bufLen);
124        freeBuf = buf;
125    }
126
127    LosProcessCB *processCB = ProcGetProcessCB(data);
128    SCHEDULER_LOCK(intSave);
129    UINT32 containerID = OsGetContainerID(processCB, (ContainerType)data->type);
130    SCHEDULER_UNLOCK(intSave);
131    if (containerID != OS_INVALID_VALUE) {
132        count = ProcessContainerLink(containerID, (ContainerType)data->type, buf, bufLen);
133    } else {
134        count = strlen("(unknown)");
135        if (memcpy_s(buf, bufLen, "(unknown)", count + 1) != EOK) {
136            (void)LOS_MemFree(m_aucSysMem1, freeBuf);
137            return -EBADF;
138        }
139    }
140    if (count < 0) {
141        (void)LOS_MemFree(m_aucSysMem1, freeBuf);
142        return count;
143    }
144
145    if (LOS_IsUserAddressRange((VADDR_T)(UINTPTR)buffer, bufLen)) {
146        if (LOS_ArchCopyToUser(buffer, buf, bufLen) != 0) {
147            (void)LOS_MemFree(m_aucSysMem1, freeBuf);
148            return -EFAULT;
149        }
150    }
151    (void)LOS_MemFree(m_aucSysMem1, freeBuf);
152    return count;
153}
154
155static const struct ProcFileOperations PID_CONTAINER_FOPS = {
156    .readLink = ProcessContainerReadLink,
157};
158
159void *ProcfsContainerGet(int fd, unsigned int *containerType)
160{
161    if ((fd <= 0) || (containerType == NULL)) {
162        return NULL;
163    }
164
165    VnodeHold();
166    struct Vnode *vnode = VnodeFind(fd);
167    if (vnode == NULL) {
168        VnodeDrop();
169        return NULL;
170    }
171
172    struct ProcDirEntry *entry = VnodeToEntry(vnode);
173    if (entry == NULL) {
174        VnodeDrop();
175        return NULL;
176    }
177
178    struct ProcessData *data = (struct ProcessData *)entry->data;
179    if (data == NULL) {
180        VnodeDrop();
181        return NULL;
182    }
183
184    void *processCB = (void *)ProcGetProcessCB(data);
185    *containerType = data->type;
186    VnodeDrop();
187    return processCB;
188}
189
190#endif /* LOSCFG_KERNEL_CONTAINER */
191
192static int ProcessMemInfoRead(struct SeqBuf *seqBuf, LosProcessCB *pcb)
193{
194    unsigned int intSave;
195    unsigned int size = sizeof(LosVmSpace) + sizeof(LosVmMapRegion);
196    LosVmSpace *vmSpace = (LosVmSpace *)LOS_MemAlloc(m_aucSysMem1, size);
197    if (vmSpace == NULL) {
198        return -ENOMEM;
199    }
200    (void)memset_s(vmSpace, size, 0, size);
201    LosVmMapRegion *heap = (LosVmMapRegion *)((char *)vmSpace + sizeof(LosVmSpace));
202
203    SCHEDULER_LOCK(intSave);
204    if (OsProcessIsInactive(pcb)) {
205        SCHEDULER_UNLOCK(intSave);
206        (void)LOS_MemFree(m_aucSysMem1, vmSpace);
207        return -EINVAL;
208    }
209    (void)memcpy_s(vmSpace, sizeof(LosVmSpace), pcb->vmSpace, sizeof(LosVmSpace));
210    (void)memcpy_s(heap, sizeof(LosVmMapRegion), pcb->vmSpace->heap, sizeof(LosVmMapRegion));
211    SCHEDULER_UNLOCK(intSave);
212
213    (void)LosBufPrintf(seqBuf, "\nVMSpaceSize:      %u byte\n", vmSpace->size);
214    (void)LosBufPrintf(seqBuf, "VMSpaceMapSize:   %u byte\n", vmSpace->mapSize);
215    (void)LosBufPrintf(seqBuf, "VM TLB Asid:      %u\n", vmSpace->archMmu.asid);
216    (void)LosBufPrintf(seqBuf, "VMHeapSize:       %u byte\n", heap->range.size);
217    (void)LosBufPrintf(seqBuf, "VMHeapRegionName: %s\n", OsGetRegionNameOrFilePath(heap));
218    (void)LosBufPrintf(seqBuf, "VMHeapRegionType: 0x%x\n", heap->regionType);
219    (void)LOS_MemFree(m_aucSysMem1, vmSpace);
220    return 0;
221}
222
223#ifdef LOSCFG_KERNEL_CPUP
224#define TIME_CYCLE_TO_US(time) ((((UINT64)time) * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US)
225static int ProcessCpupRead(struct SeqBuf *seqBuf, LosProcessCB *pcb)
226{
227    unsigned int intSave;
228    OsCpupBase *processCpup = (OsCpupBase *)LOS_MemAlloc(m_aucSysMem1, sizeof(OsCpupBase));
229    if (processCpup == NULL) {
230        return -ENOMEM;
231    }
232    (void)memset_s(processCpup, sizeof(OsCpupBase), 0, sizeof(OsCpupBase));
233
234    SCHEDULER_LOCK(intSave);
235    if (OsProcessIsInactive(pcb)) {
236        SCHEDULER_UNLOCK(intSave);
237        (VOID)LOS_MemFree(m_aucSysMem1, processCpup);
238        return -EINVAL;
239    }
240    (void)memcpy_s(processCpup, sizeof(OsCpupBase), pcb->processCpup, sizeof(OsCpupBase));
241    SCHEDULER_UNLOCK(intSave);
242
243    (void)LosBufPrintf(seqBuf, "\nTotalRunningTime: %lu us\n", TIME_CYCLE_TO_US(processCpup->allTime));
244    (void)LosBufPrintf(seqBuf, "HistoricalRunningTime:(us) ");
245    for (UINT32 i = 0; i < OS_CPUP_HISTORY_RECORD_NUM + 1; i++) {
246        (void)LosBufPrintf(seqBuf, "%lu  ", TIME_CYCLE_TO_US(processCpup->historyTime[i]));
247    }
248    (void)LosBufPrintf(seqBuf, "\n");
249    (void)LOS_MemFree(m_aucSysMem1, processCpup);
250    return 0;
251}
252#endif
253
254#ifdef LOSCFG_TIME_CONTAINER
255static const CHAR *g_monotonic = "monotonic";
256#define DECIMAL_BASE 10
257
258static int ProcTimeContainerRead(struct SeqBuf *m, void *v)
259{
260    int ret;
261    unsigned int intSave;
262    struct timespec64 offsets = {0};
263
264    if ((m == NULL) || (v == NULL)) {
265        return -EINVAL;
266    }
267
268    struct ProcessData *data = (struct ProcessData *)v;
269    SCHEDULER_LOCK(intSave);
270    LosProcessCB *processCB = ProcGetProcessCB(data);
271    ret = OsGetTimeContainerMonotonic(processCB, &offsets);
272    SCHEDULER_UNLOCK(intSave);
273    if (ret != LOS_OK) {
274        return -ret;
275    }
276
277    LosBufPrintf(m, "monotonic %lld %ld\n", offsets.tv_sec, offsets.tv_nsec);
278    return 0;
279}
280
281static int ProcSetTimensOffset(const char *buf, LosProcessCB *processCB)
282{
283    unsigned int intSave;
284    struct timespec64 offsets;
285    char *endptr = NULL;
286
287    offsets.tv_sec = strtoll(buf, &endptr, DECIMAL_BASE);
288    offsets.tv_nsec = strtoll(endptr, NULL, DECIMAL_BASE);
289    if (offsets.tv_nsec >= OS_SYS_NS_PER_SECOND) {
290        return -EACCES;
291    }
292
293    SCHEDULER_LOCK(intSave);
294    unsigned int ret = OsSetTimeContainerMonotonic(processCB, &offsets);
295    SCHEDULER_UNLOCK(intSave);
296    if (ret != LOS_OK) {
297        return -ret;
298    }
299    return 0;
300}
301
302static int ProcTimeContainerWrite(struct ProcFile *pf, const char *buf, size_t count, loff_t *ppos)
303{
304    (void)ppos;
305    char *kbuf = NULL;
306    int ret;
307
308    if ((pf == NULL) || (count <= 0)) {
309        return -EINVAL;
310    }
311
312    struct ProcDirEntry *entry = pf->pPDE;
313    if (entry == NULL) {
314        return -EINVAL;
315    }
316
317    struct ProcessData *data = (struct ProcessData *)entry->data;
318    if (data == NULL) {
319        return -EINVAL;
320    }
321
322    if (LOS_IsUserAddressRange((VADDR_T)(UINTPTR)buf, count)) {
323        kbuf = LOS_MemAlloc(m_aucSysMem1, count + 1);
324        if (kbuf == NULL) {
325            return -ENOMEM;
326        }
327
328        if (LOS_ArchCopyFromUser(kbuf, buf, count) != 0) {
329            (VOID)LOS_MemFree(m_aucSysMem1, kbuf);
330            return -EFAULT;
331        }
332        kbuf[count] = '\0';
333        buf = kbuf;
334    }
335
336    ret = strncmp(buf, g_monotonic, strlen(g_monotonic));
337    if (ret != 0) {
338        (VOID)LOS_MemFree(m_aucSysMem1, kbuf);
339        return -EINVAL;
340    }
341
342    buf += strlen(g_monotonic);
343    ret = ProcSetTimensOffset(buf, ProcGetProcessCB(data));
344    if (ret < 0) {
345        (VOID)LOS_MemFree(m_aucSysMem1, kbuf);
346        return ret;
347    }
348    (VOID)LOS_MemFree(m_aucSysMem1, kbuf);
349    return count;
350}
351
352static const struct ProcFileOperations TIME_CONTAINER_FOPS = {
353    .read = ProcTimeContainerRead,
354    .write = ProcTimeContainerWrite,
355};
356#endif
357
358#ifdef LOSCFG_USER_CONTAINER
359
360static void *MemdupUserNul(const void *src, size_t len)
361{
362    char *des = NULL;
363    if (len <= 0) {
364        return NULL;
365    }
366    des = LOS_MemAlloc(OS_SYS_MEM_ADDR, len + 1);
367    if (des == NULL) {
368        return NULL;
369    }
370
371    if (LOS_ArchCopyFromUser(des, src, len) != 0) {
372        (VOID)LOS_MemFree(OS_SYS_MEM_ADDR, des);
373        return NULL;
374    }
375
376    des[len] = '\0';
377    return des;
378}
379
380static LosProcessCB *ProcUidGidMapWriteCheck(struct ProcFile *pf, const char *buf, size_t size,
381                                             char **kbuf, ProcessDataType *type)
382{
383    if ((pf == NULL) || (size <= 0) || (size >= PAGE_SIZE)) {
384        return NULL;
385    }
386
387    struct ProcDirEntry *entry = pf->pPDE;
388    if (entry == NULL) {
389        return NULL;
390    }
391
392    struct ProcessData *data = (struct ProcessData *)entry->data;
393    if (data == NULL) {
394        return NULL;
395    }
396
397    *kbuf = MemdupUserNul(buf, size);
398    if (*kbuf == NULL) {
399        return NULL;
400    }
401    *type = (ProcessDataType)data->type;
402    return ProcGetProcessCB(data);
403}
404
405static ssize_t ProcIDMapWrite(struct ProcFile *file, const char *buf, size_t size, loff_t *ppos)
406{
407    (void)ppos;
408    char *kbuf = NULL;
409    int ret;
410    unsigned int intSave;
411    ProcessDataType type = PROC_P_TYPE_MAX;
412    LosProcessCB *processCB = ProcUidGidMapWriteCheck(file, buf, size, &kbuf, &type);
413    if (processCB == NULL) {
414        return -EINVAL;
415    }
416
417    SCHEDULER_LOCK(intSave);
418    if ((processCB->credentials == NULL) || (processCB->credentials->userContainer == NULL)) {
419        SCHEDULER_UNLOCK(intSave);
420        (void)LOS_MemFree(m_aucSysMem1, kbuf);
421        return -EINVAL;
422    }
423    UserContainer *userContainer = processCB->credentials->userContainer;
424    if (userContainer->parent == NULL) {
425        SCHEDULER_UNLOCK(intSave);
426        (void)LOS_MemFree(m_aucSysMem1, kbuf);
427        return -EPERM;
428    }
429    if (type == PROC_UID_MAP) {
430        ret = OsUserContainerMapWrite(file, kbuf, size, CAP_SETUID,
431                                      &userContainer->uidMap, &userContainer->parent->uidMap);
432    } else {
433        ret = OsUserContainerMapWrite(file, kbuf, size, CAP_SETGID,
434                                      &userContainer->gidMap, &userContainer->parent->gidMap);
435    }
436    SCHEDULER_UNLOCK(intSave);
437    (void)LOS_MemFree(m_aucSysMem1, kbuf);
438    return ret;
439}
440
441static int ProcIDMapRead(struct SeqBuf *seqBuf, void *v)
442{
443    unsigned int intSave;
444    if ((seqBuf == NULL) || (v == NULL)) {
445        return -EINVAL;
446    }
447    struct ProcessData *data = (struct ProcessData *)v;
448    LosProcessCB *processCB = ProcGetProcessCB(data);
449
450    SCHEDULER_LOCK(intSave);
451    if ((processCB->credentials == NULL) || (processCB->credentials->userContainer == NULL)) {
452        SCHEDULER_UNLOCK(intSave);
453        return -EINVAL;
454    }
455    UserContainer *userContainer = processCB->credentials->userContainer;
456    if ((userContainer != NULL) && (userContainer->parent == NULL)) {
457        UidGidExtent uidGidExtent = userContainer->uidMap.extent[0];
458        SCHEDULER_UNLOCK(intSave);
459        (void)LosBufPrintf(seqBuf, "%d %d %u\n", uidGidExtent.first, uidGidExtent.lowerFirst,
460                           uidGidExtent.count);
461        return 0;
462    }
463    SCHEDULER_LOCK(intSave);
464    return 0;
465}
466
467static const struct ProcFileOperations UID_GID_MAP_FOPS = {
468    .read = ProcIDMapRead,
469    .write = ProcIDMapWrite,
470};
471#endif
472
473static int ProcProcessRead(struct SeqBuf *m, void *v)
474{
475    if ((m == NULL) || (v == NULL)) {
476        return -EINVAL;
477    }
478    struct ProcessData *data = (struct ProcessData *)v;
479    switch (data->type) {
480        case PROC_PID_MEM:
481            return ProcessMemInfoRead(m, ProcGetProcessCB(data));
482#ifdef LOSCFG_KERNEL_CPUP
483        case PROC_PID_CPUP:
484            return ProcessCpupRead(m, ProcGetProcessCB(data));
485#endif
486        default:
487            break;
488    }
489    return -EINVAL;
490}
491
492static const struct ProcFileOperations PID_FOPS = {
493    .read = ProcProcessRead,
494};
495
496static struct ProcProcess g_procProcess[] = {
497    {
498        .name = NULL,
499        .mode = S_IFDIR | S_IRWXU | S_IRWXG | S_IROTH,
500        .type = PROC_PID,
501        .fileOps = &PID_FOPS
502
503    },
504    {
505        .name = "meminfo",
506        .mode = 0,
507        .type = PROC_PID_MEM,
508        .fileOps = &PID_FOPS
509    },
510#ifdef LOSCFG_KERNEL_CPUP
511    {
512        .name = "cpup",
513        .mode = 0,
514        .type = PROC_PID_CPUP,
515        .fileOps = &PID_FOPS
516
517    },
518#endif
519#ifdef LOSCFG_KERNEL_CONTAINER
520    {
521        .name = "container",
522        .mode = S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH,
523        .type = CONTAINER,
524        .fileOps = &PID_CONTAINER_FOPS
525
526    },
527#ifdef LOSCFG_PID_CONTAINER
528    {
529        .name = "container/pid",
530        .mode = S_IFLNK,
531        .type = PID_CONTAINER,
532        .fileOps = &PID_CONTAINER_FOPS
533    },
534    {
535        .name = "container/pid_for_children",
536        .mode = S_IFLNK,
537        .type = PID_CHILD_CONTAINER,
538        .fileOps = &PID_CONTAINER_FOPS
539    },
540#endif
541#ifdef LOSCFG_UTS_CONTAINER
542    {
543        .name = "container/uts",
544        .mode = S_IFLNK,
545        .type = UTS_CONTAINER,
546        .fileOps = &PID_CONTAINER_FOPS
547    },
548#endif
549#ifdef LOSCFG_MNT_CONTAINER
550    {
551        .name = "container/mnt",
552        .mode = S_IFLNK,
553        .type = MNT_CONTAINER,
554        .fileOps = &PID_CONTAINER_FOPS
555    },
556#endif
557#ifdef LOSCFG_IPC_CONTAINER
558    {
559        .name = "container/ipc",
560        .mode = S_IFLNK,
561        .type = IPC_CONTAINER,
562        .fileOps = &PID_CONTAINER_FOPS
563    },
564#endif
565#ifdef LOSCFG_TIME_CONTAINER
566    {
567        .name = "container/time",
568        .mode = S_IFLNK,
569        .type = TIME_CONTAINER,
570        .fileOps = &PID_CONTAINER_FOPS
571    },
572    {
573        .name = "container/time_for_children",
574        .mode = S_IFLNK,
575        .type = TIME_CHILD_CONTAINER,
576        .fileOps = &PID_CONTAINER_FOPS
577    },
578    {
579        .name = "time_offsets",
580        .mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
581        .type = TIME_CONTAINER,
582        .fileOps = &TIME_CONTAINER_FOPS
583    },
584#endif
585#ifdef LOSCFG_IPC_CONTAINER
586    {
587        .name = "container/user",
588        .mode = S_IFLNK,
589        .type = USER_CONTAINER,
590        .fileOps = &PID_CONTAINER_FOPS
591    },
592    {
593        .name = "uid_map",
594        .mode = 0,
595        .type = PROC_UID_MAP,
596        .fileOps = &UID_GID_MAP_FOPS
597    },
598    {
599        .name = "gid_map",
600        .mode = 0,
601        .type = PROC_GID_MAP,
602        .fileOps = &UID_GID_MAP_FOPS
603    },
604#endif
605#ifdef LOSCFG_IPC_CONTAINER
606    {
607        .name = "container/net",
608        .mode = S_IFLNK,
609        .type = NET_CONTAINER,
610        .fileOps = &PID_CONTAINER_FOPS
611    },
612#endif
613#endif
614};
615
616void ProcFreeProcessDir(struct ProcDirEntry *processDir)
617{
618    if (processDir == NULL) {
619        return;
620    }
621    RemoveProcEntry(processDir->name, NULL);
622}
623
624static struct ProcDirEntry *ProcCreatePorcess(UINT32 pid, struct ProcProcess *porcess, uintptr_t processCB)
625{
626    int ret;
627    struct ProcDataParm dataParm;
628    char pidName[PROC_PID_DIR_LEN] = {0};
629    struct ProcessData *data = (struct ProcessData *)malloc(sizeof(struct ProcessData));
630    if (data == NULL) {
631        return NULL;
632    }
633    if (pid != OS_INVALID_VALUE) {
634        if (porcess->name != NULL) {
635            ret = snprintf_s(pidName, PROC_PID_DIR_LEN, PROC_PID_DIR_LEN - 1, "%u/%s", pid, porcess->name);
636        } else {
637            ret = snprintf_s(pidName, PROC_PID_DIR_LEN, PROC_PID_DIR_LEN - 1, "%u", pid);
638        }
639    } else {
640        if (porcess->name != NULL) {
641            ret = snprintf_s(pidName, PROC_PID_DIR_LEN, PROC_PID_DIR_LEN - 1, "%s/%s", "self", porcess->name);
642        } else {
643            ret = snprintf_s(pidName, PROC_PID_DIR_LEN, PROC_PID_DIR_LEN - 1, "%s", "self");
644        }
645    }
646    if (ret < 0) {
647        free(data);
648        return NULL;
649    }
650
651    data->process = processCB;
652    data->type = porcess->type;
653    dataParm.data = data;
654    dataParm.dataType = PROC_DATA_FREE;
655    struct ProcDirEntry *container = ProcCreateData(pidName, porcess->mode, NULL, porcess->fileOps, &dataParm);
656    if (container == NULL) {
657        free(data);
658        PRINT_ERR("create /proc/%s error!\n", pidName);
659        return NULL;
660    }
661    return container;
662}
663
664int ProcCreateProcessDir(UINT32 pid, uintptr_t process)
665{
666    unsigned int intSave;
667    struct ProcDirEntry *pidDir = NULL;
668    for (int index = 0; index < (sizeof(g_procProcess) / sizeof(struct ProcProcess)); index++) {
669        struct ProcProcess *procProcess = &g_procProcess[index];
670        struct ProcDirEntry *dir = ProcCreatePorcess(pid, procProcess, process);
671        if (dir == NULL) {
672            PRINT_ERR("create /proc/%s error!\n", procProcess->name);
673            goto CREATE_ERROR;
674        }
675        if (index == 0) {
676            pidDir = dir;
677        }
678    }
679
680    if (process != 0) {
681        SCHEDULER_LOCK(intSave);
682        ((LosProcessCB *)process)->procDir = pidDir;
683        SCHEDULER_UNLOCK(intSave);
684    }
685
686    return 0;
687
688CREATE_ERROR:
689    if (pidDir != NULL) {
690        RemoveProcEntry(pidDir->name, NULL);
691    }
692    return -1;
693}
694#endif /* LOSCFG_PROC_PROCESS_DIR */
695
696static int ProcessProcFill(struct SeqBuf *m, void *v)
697{
698    (void)v;
699    (void)OsShellCmdTskInfoGet(OS_ALL_TASK_MASK, m, OS_PROCESS_INFO_ALL);
700    return 0;
701}
702
703static const struct ProcFileOperations PROCESS_PROC_FOPS = {
704    .read       = ProcessProcFill,
705};
706
707void ProcProcessInit(void)
708{
709    struct ProcDirEntry *pde = CreateProcEntry("process", 0, NULL);
710    if (pde == NULL) {
711        PRINT_ERR("create /proc/process error!\n");
712        return;
713    }
714    pde->procFileOps = &PROCESS_PROC_FOPS;
715
716#ifdef LOSCFG_PROC_PROCESS_DIR
717    int ret = ProcCreateProcessDir(OS_INVALID_VALUE, 0);
718    if (ret < 0) {
719        PRINT_ERR("Create proc process self dir failed!\n");
720    }
721
722    ret = ProcCreateProcessDir(OS_USER_ROOT_PROCESS_ID, (uintptr_t)OsGetUserInitProcess());
723    if (ret < 0) {
724        PRINT_ERR("Create proc process %d dir failed!\n", OS_USER_ROOT_PROCESS_ID);
725    }
726#endif
727    return;
728}
729