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