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 "los_process_pri.h" 33#include "los_task_pri.h" 34#include "los_sched_pri.h" 35#include "los_hw_pri.h" 36#include "los_sys_pri.h" 37#include "los_futex_pri.h" 38#include "los_mp.h" 39#include "sys/wait.h" 40#include "user_copy.h" 41#include "time.h" 42#ifdef LOSCFG_SECURITY_CAPABILITY 43#include "capability_api.h" 44#endif 45 46static int OsPermissionToCheck(unsigned int pid, unsigned int who) 47{ 48 uintptr_t pgroupID = 0; 49 unsigned int ret = OsGetProcessGroupCB(pid, &pgroupID); 50 if (ret != 0) { 51 return -ret; 52 } else if (pgroupID == OS_KERNEL_PROCESS_GROUP) { 53 return -EPERM; 54 } else if ((pgroupID == OS_USER_PRIVILEGE_PROCESS_GROUP) && (pid != who)) { 55 return -EPERM; 56 } else if ((UINTPTR)OS_PCB_FROM_PID(pid) == OS_USER_PRIVILEGE_PROCESS_GROUP) { 57 return -EPERM; 58 } 59 60 return 0; 61} 62 63static int UserTaskSchedulerCheck(unsigned int tid, int policy, const LosSchedParam *schedParam, bool policyFlag) 64{ 65 int ret; 66 int processPolicy; 67 68 if (OS_TID_CHECK_INVALID(tid)) { 69 return EINVAL; 70 } 71 72 ret = OsSchedulerParamCheck(policy, TRUE, schedParam); 73 if (ret != 0) { 74 return ret; 75 } 76 77 if (policyFlag) { 78 ret = LOS_GetProcessScheduler(LOS_GetCurrProcessID(), &processPolicy, NULL); 79 if (ret < 0) { 80 return -ret; 81 } 82 if ((processPolicy != LOS_SCHED_DEADLINE) && (policy == LOS_SCHED_DEADLINE)) { 83 return EPERM; 84 } else if ((processPolicy == LOS_SCHED_DEADLINE) && (policy != LOS_SCHED_DEADLINE)) { 85 return EPERM; 86 } 87 } 88 return 0; 89} 90 91static int OsUserTaskSchedulerSet(unsigned int tid, int policy, const LosSchedParam *schedParam, bool policyFlag) 92{ 93 int ret; 94 unsigned int intSave; 95 bool needSched = false; 96 SchedParam param = { 0 }; 97 98 ret = UserTaskSchedulerCheck(tid, policy, schedParam, policyFlag); 99 if (ret != 0) { 100 return ret; 101 } 102 103 LosTaskCB *taskCB = OS_TCB_FROM_TID(tid); 104 SCHEDULER_LOCK(intSave); 105 ret = OsUserTaskOperatePermissionsCheck(taskCB); 106 if (ret != LOS_OK) { 107 SCHEDULER_UNLOCK(intSave); 108 return ret; 109 } 110 111 taskCB->ops->schedParamGet(taskCB, ¶m); 112 param.policy = (policyFlag == true) ? (UINT16)policy : param.policy; 113 if ((param.policy == LOS_SCHED_RR) || (param.policy == LOS_SCHED_FIFO)) { 114 param.priority = schedParam->priority; 115 } else if (param.policy == LOS_SCHED_DEADLINE) { 116#ifdef LOSCFG_SECURITY_CAPABILITY 117 /* user mode process with privilege of CAP_SCHED_SETPRIORITY can change the priority */ 118 if (!IsCapPermit(CAP_SCHED_SETPRIORITY)) { 119 SCHEDULER_UNLOCK(intSave); 120 return EPERM; 121 } 122#endif 123 param.runTimeUs = schedParam->runTimeUs; 124 param.deadlineUs = schedParam->deadlineUs; 125 param.periodUs = schedParam->periodUs; 126 } 127 128 needSched = taskCB->ops->schedParamModify(taskCB, ¶m); 129 SCHEDULER_UNLOCK(intSave); 130 131 LOS_MpSchedule(OS_MP_CPU_ALL); 132 if (needSched && OS_SCHEDULER_ACTIVE) { 133 LOS_Schedule(); 134 } 135 136 return LOS_OK; 137} 138 139void SysSchedYield(int type) 140{ 141 (void)type; 142 143 (void)LOS_TaskYield(); 144 return; 145} 146 147int SysSchedGetScheduler(int id, int flag) 148{ 149 unsigned int intSave; 150 SchedParam param = { 0 }; 151 int policy; 152 int ret; 153 154 if (flag < 0) { 155 if (OS_TID_CHECK_INVALID(id)) { 156 return -EINVAL; 157 } 158 159 LosTaskCB *taskCB = OS_TCB_FROM_TID(id); 160 SCHEDULER_LOCK(intSave); 161 ret = OsUserTaskOperatePermissionsCheck(taskCB); 162 if (ret != LOS_OK) { 163 SCHEDULER_UNLOCK(intSave); 164 return -ret; 165 } 166 167 taskCB->ops->schedParamGet(taskCB, ¶m); 168 SCHEDULER_UNLOCK(intSave); 169 return (int)param.policy; 170 } 171 172 if (id == 0) { 173 id = (int)LOS_GetCurrProcessID(); 174 } 175 176 ret = LOS_GetProcessScheduler(id, &policy, NULL); 177 if (ret < 0) { 178 return ret; 179 } 180 181 return policy; 182} 183 184int SysSchedSetScheduler(int id, int policy, const LosSchedParam *userParam, int flag) 185{ 186 int ret; 187 LosSchedParam param; 188 189 if (LOS_ArchCopyFromUser(¶m, userParam, sizeof(LosSchedParam)) != 0) { 190 return -EFAULT; 191 } 192 193 if (flag < 0) { 194 return -OsUserTaskSchedulerSet(id, policy, ¶m, true); 195 } 196 197 if (policy == LOS_SCHED_RR) { 198#ifdef LOSCFG_KERNEL_PLIMITS 199 if (param.priority < OsPidLimitGetPriorityLimit()) { 200 return -EINVAL; 201 } 202#else 203 if (param.priority < OS_USER_PROCESS_PRIORITY_HIGHEST) { 204 return -EINVAL; 205 } 206#endif 207 } 208 209 if (id == 0) { 210 id = (int)LOS_GetCurrProcessID(); 211 } 212 213 ret = OsPermissionToCheck(id, LOS_GetCurrProcessID()); 214 if (ret < 0) { 215 return ret; 216 } 217 218 return OsSetProcessScheduler(LOS_PRIO_PROCESS, id, policy, ¶m); 219} 220 221int SysSchedGetParam(int id, LosSchedParam *userParam, int flag) 222{ 223 LosSchedParam schedParam = {0}; 224 SchedParam param = { 0 }; 225 unsigned int intSave; 226 int ret; 227 228 if (flag < 0) { 229 if (OS_TID_CHECK_INVALID(id)) { 230 return -EINVAL; 231 } 232 233 LosTaskCB *taskCB = OS_TCB_FROM_TID(id); 234 SCHEDULER_LOCK(intSave); 235 ret = OsUserTaskOperatePermissionsCheck(taskCB); 236 if (ret != LOS_OK) { 237 SCHEDULER_UNLOCK(intSave); 238 return -ret; 239 } 240 241 taskCB->ops->schedParamGet(taskCB, ¶m); 242 SCHEDULER_UNLOCK(intSave); 243 if (param.policy == LOS_SCHED_DEADLINE) { 244 schedParam.runTimeUs = param.runTimeUs; 245 schedParam.deadlineUs = param.deadlineUs; 246 schedParam.periodUs = param.periodUs; 247 } else { 248 schedParam.priority = param.priority; 249 } 250 } else { 251 if (id == 0) { 252 id = (int)LOS_GetCurrProcessID(); 253 } 254 255 if (OS_PID_CHECK_INVALID(id)) { 256 return -EINVAL; 257 } 258 259 ret = LOS_GetProcessScheduler(id, NULL, &schedParam); 260 if (ret < 0) { 261 return ret; 262 } 263 } 264 265 if (LOS_ArchCopyToUser(userParam, &schedParam, sizeof(LosSchedParam))) { 266 return -EFAULT; 267 } 268 return 0; 269} 270 271int SysSetProcessPriority(int which, int who, int prio) 272{ 273 int ret; 274 275 if (which != LOS_PRIO_PROCESS) { 276 return -EINVAL; 277 } 278 279 if (who == 0) { 280 who = (int)LOS_GetCurrProcessID(); 281 } 282 283#ifdef LOSCFG_KERNEL_PLIMITS 284 if (prio < OsPidLimitGetPriorityLimit()) { 285 return -EINVAL; 286 } 287#else 288 if (prio < OS_USER_PROCESS_PRIORITY_HIGHEST) { 289 return -EINVAL; 290 } 291#endif 292 293 ret = OsPermissionToCheck(who, LOS_GetCurrProcessID()); 294 if (ret < 0) { 295 return ret; 296 } 297 298 return LOS_SetProcessPriority(who, prio); 299} 300 301int SysSchedSetParam(int id, const LosSchedParam *userParam, int flag) 302{ 303 int ret, policy; 304 LosSchedParam param; 305 306 if (flag < 0) { 307 if (LOS_ArchCopyFromUser(¶m, userParam, sizeof(LosSchedParam)) != 0) { 308 return -EFAULT; 309 } 310 return -OsUserTaskSchedulerSet(id, LOS_SCHED_RR, ¶m, false); 311 } 312 313 if (id == 0) { 314 id = (int)LOS_GetCurrProcessID(); 315 } 316 317 ret = LOS_GetProcessScheduler(id, &policy, NULL); 318 if (ret < 0) { 319 return ret; 320 } 321 322 return SysSchedSetScheduler(id, policy, userParam, flag); 323} 324 325int SysGetProcessPriority(int which, int who) 326{ 327 if (who == 0) { 328 who = (int)LOS_GetCurrProcessID(); 329 } 330 331 return OsGetProcessPriority(which, who); 332} 333 334int SysSchedGetPriorityMin(int policy) 335{ 336 if (policy != LOS_SCHED_RR) { 337 return -EINVAL; 338 } 339 340 return OS_USER_PROCESS_PRIORITY_HIGHEST; 341} 342 343int SysSchedGetPriorityMax(int policy) 344{ 345 if (policy != LOS_SCHED_RR) { 346 return -EINVAL; 347 } 348 349 return OS_USER_PROCESS_PRIORITY_LOWEST; 350} 351 352int SysSchedRRGetInterval(int pid, struct timespec *tp) 353{ 354 unsigned int intSave; 355 int ret; 356 SchedParam param = { 0 }; 357 time_t timeSlice = 0; 358 struct timespec tv = { 0 }; 359 LosTaskCB *taskCB = NULL; 360 LosProcessCB *processCB = NULL; 361 362 if (tp == NULL) { 363 return -EINVAL; 364 } 365 366 if (OS_PID_CHECK_INVALID(pid)) { 367 return -EINVAL; 368 } 369 370 if (pid == 0) { 371 processCB = OsCurrProcessGet(); 372 } else { 373 processCB = OS_PCB_FROM_PID(pid); 374 } 375 376 SCHEDULER_LOCK(intSave); 377 /* if can not find process by pid return ESRCH */ 378 if (OsProcessIsInactive(processCB)) { 379 SCHEDULER_UNLOCK(intSave); 380 return -ESRCH; 381 } 382 383 LOS_DL_LIST_FOR_EACH_ENTRY(taskCB, &processCB->threadSiblingList, LosTaskCB, threadList) { 384 if (!OsTaskIsInactive(taskCB)) { 385 taskCB->ops->schedParamGet(taskCB, ¶m); 386 if (param.policy == LOS_SCHED_RR) { 387 timeSlice += param.timeSlice; 388 } 389 } 390 } 391 392 SCHEDULER_UNLOCK(intSave); 393 394 timeSlice = timeSlice * OS_NS_PER_CYCLE; 395 tv.tv_sec = timeSlice / OS_SYS_NS_PER_SECOND; 396 tv.tv_nsec = timeSlice % OS_SYS_NS_PER_SECOND; 397 ret = LOS_ArchCopyToUser(tp, &tv, sizeof(struct timespec)); 398 if (ret != 0) { 399 return -EFAULT; 400 } 401 402 return 0; 403} 404 405int SysWait(int pid, USER int *status, int options, void *rusage) 406{ 407 (void)rusage; 408 409 return LOS_Wait(pid, status, (unsigned int)options, NULL); 410} 411 412int SysWaitid(idtype_t type, int pid, USER siginfo_t *info, int options, void *rusage) 413{ 414 (void)rusage; 415 int ret; 416 int truepid = 0; 417 418 switch (type) { 419 case P_ALL: 420 /* Wait for any child; id is ignored. */ 421 truepid = -1; 422 break; 423 case P_PID: 424 /* Wait for the child whose process ID matches id */ 425 if (pid <= 0) { 426 return -EINVAL; 427 } 428 truepid = pid; 429 break; 430 case P_PGID: 431 /* Wait for any child whose process group ID matches id */ 432 if (pid <= 1) { 433 return -EINVAL; 434 } 435 truepid = -pid; 436 break; 437 default: 438 return -EINVAL; 439 } 440 441 ret = LOS_Waitid(truepid, info, (unsigned int)options, NULL); 442 if (ret > 0) { 443 ret = 0; 444 } 445 return ret; 446} 447 448int SysFork(void) 449{ 450 return OsClone(0, 0, 0); 451} 452 453int SysVfork(void) 454{ 455 return OsClone(CLONE_VFORK, 0, 0); 456} 457 458int SysClone(int flags, void *stack, int *parentTid, unsigned long tls, int *childTid) 459{ 460 (void)parentTid; 461 (void)tls; 462 (void)childTid; 463 464 return OsClone((UINT32)flags, (UINTPTR)stack, 0); 465} 466 467int SysUnshare(int flags) 468{ 469#ifdef LOSCFG_KERNEL_CONTAINER 470 return OsUnshare(flags); 471#else 472 return -ENOSYS; 473#endif 474} 475 476int SysSetns(int fd, int type) 477{ 478#ifdef LOSCFG_KERNEL_CONTAINER 479 return OsSetNs(fd, type); 480#else 481 return -ENOSYS; 482#endif 483} 484 485unsigned int SysGetPPID(void) 486{ 487#ifdef LOSCFG_PID_CONTAINER 488 if (OsCurrProcessGet()->processID == OS_USER_ROOT_PROCESS_ID) { 489 return 0; 490 } 491#endif 492 return OsCurrProcessGet()->parentProcess->processID; 493} 494 495unsigned int SysGetPID(void) 496{ 497 return LOS_GetCurrProcessID(); 498} 499 500int SysSetProcessGroupID(unsigned int pid, unsigned int gid) 501{ 502 int ret; 503 504 if (pid == 0) { 505 pid = LOS_GetCurrProcessID(); 506 } 507 508 if (gid == 0) { 509 gid = pid; 510 } 511 512 ret = OsPermissionToCheck(pid, gid); 513 if (ret < 0) { 514 return ret; 515 } 516 517 return OsSetProcessGroupID(pid, gid); 518} 519 520int SysGetProcessGroupID(unsigned int pid) 521{ 522 if (pid == 0) { 523 pid = LOS_GetCurrProcessID(); 524 } 525 526 return LOS_GetProcessGroupID(pid); 527} 528 529int SysGetCurrProcessGroupID(void) 530{ 531 return LOS_GetCurrProcessGroupID(); 532} 533 534int SysGetUserID(void) 535{ 536 return LOS_GetUserID(); 537} 538 539int SysGetEffUserID(void) 540{ 541#ifdef LOSCFG_SECURITY_CAPABILITY 542 UINT32 intSave; 543 int euid; 544 545 SCHEDULER_LOCK(intSave); 546#ifdef LOSCFG_USER_CONTAINER 547 euid = OsFromKuidMunged(OsCurrentUserContainer(), CurrentCredentials()->euid); 548#else 549 euid = (int)OsCurrUserGet()->effUserID; 550#endif 551 SCHEDULER_UNLOCK(intSave); 552 return euid; 553#else 554 return 0; 555#endif 556} 557 558int SysGetEffGID(void) 559{ 560#ifdef LOSCFG_SECURITY_CAPABILITY 561 UINT32 intSave; 562 int egid; 563 564 SCHEDULER_LOCK(intSave); 565#ifdef LOSCFG_USER_CONTAINER 566 egid = OsFromKuidMunged(OsCurrentUserContainer(), CurrentCredentials()->egid); 567#else 568 egid = (int)OsCurrUserGet()->effGid; 569#endif 570 SCHEDULER_UNLOCK(intSave); 571 return egid; 572#else 573 return 0; 574#endif 575} 576 577int SysGetRealEffSaveUserID(int *ruid, int *euid, int *suid) 578{ 579 int ret; 580 int realUserID, effUserID, saveUserID; 581#ifdef LOSCFG_SECURITY_CAPABILITY 582 unsigned int intSave; 583 584 SCHEDULER_LOCK(intSave); 585#ifdef LOSCFG_USER_CONTAINER 586 realUserID = OsFromKuidMunged(OsCurrentUserContainer(), CurrentCredentials()->uid); 587 effUserID = OsFromKuidMunged(OsCurrentUserContainer(), CurrentCredentials()->euid); 588 saveUserID = OsFromKuidMunged(OsCurrentUserContainer(), CurrentCredentials()->euid); 589#else 590 realUserID = OsCurrUserGet()->userID; 591 effUserID = OsCurrUserGet()->effUserID; 592 saveUserID = OsCurrUserGet()->effUserID; 593#endif 594 SCHEDULER_UNLOCK(intSave); 595#else 596 realUserID = 0; 597 effUserID = 0; 598 saveUserID = 0; 599#endif 600 601 ret = LOS_ArchCopyToUser(ruid, &realUserID, sizeof(int)); 602 if (ret != 0) { 603 return -EFAULT; 604 } 605 606 ret = LOS_ArchCopyToUser(euid, &effUserID, sizeof(int)); 607 if (ret != 0) { 608 return -EFAULT; 609 } 610 611 ret = LOS_ArchCopyToUser(suid, &saveUserID, sizeof(int)); 612 if (ret != 0) { 613 return -EFAULT; 614 } 615 616 return 0; 617} 618 619#ifdef LOSCFG_USER_CONTAINER 620long SysSetUserID(int uid) 621{ 622#ifdef LOSCFG_SECURITY_CAPABILITY 623 UserContainer *userContainer = CurrentCredentials()->userContainer; 624 int retval = -EPERM; 625 unsigned int intSave; 626 627 if (uid < 0) { 628 return -EINVAL; 629 } 630 631 UINT32 kuid = OsMakeKuid(userContainer, uid); 632 if (kuid == (UINT32)-1) { 633 return -EINVAL; 634 } 635 636 Credentials *newCredentials = PrepareCredential(OsCurrProcessGet()); 637 if (newCredentials == NULL) { 638 return -ENOMEM; 639 } 640 641 Credentials *oldCredentials = CurrentCredentials(); 642 643 SCHEDULER_LOCK(intSave); 644 User *user = OsCurrUserGet(); 645 if (IsCapPermit(CAP_SETUID)) { 646 newCredentials->uid = kuid; 647 if (kuid != oldCredentials->uid) { 648 user->userID = kuid; 649 user->effUserID = kuid; 650 } 651 retval = LOS_OK; 652 } else if (kuid != oldCredentials->uid) { 653 goto ERROR; 654 } 655 newCredentials->euid = kuid; 656 657 retval = CommitCredentials(newCredentials); 658 SCHEDULER_UNLOCK(intSave); 659 return retval; 660 661ERROR: 662 FreeCredential(newCredentials); 663 SCHEDULER_UNLOCK(intSave); 664 return retval; 665#else 666 if (uid != 0) { 667 return -EPERM; 668 } 669 return 0; 670#endif 671} 672 673#else 674 675int SysSetUserID(int uid) 676{ 677#ifdef LOSCFG_SECURITY_CAPABILITY 678 int ret = -EPERM; 679 unsigned int intSave; 680 681 if (uid < 0) { 682 return -EINVAL; 683 } 684 685 SCHEDULER_LOCK(intSave); 686 User *user = OsCurrUserGet(); 687 if (IsCapPermit(CAP_SETUID)) { 688 user->userID = uid; 689 user->effUserID = uid; 690 /* add process to a user */ 691 } else if (user->userID != uid) { 692 goto EXIT; 693 } 694 695 ret = LOS_OK; 696 /* add process to a user */ 697EXIT: 698 SCHEDULER_UNLOCK(intSave); 699 return ret; 700#else 701 if (uid != 0) { 702 return -EPERM; 703 } 704 705 return 0; 706#endif 707} 708#endif 709 710#ifdef LOSCFG_SECURITY_CAPABILITY 711static int SetRealEffSaveUserIDCheck(int ruid, int euid, int suid) 712{ 713 if ((ruid < 0) && (ruid != -1)) { 714 return -EINVAL; 715 } 716 717 if ((euid < 0) && (euid != -1)) { 718 return -EINVAL; 719 } 720 721 if ((suid < 0) && (suid != -1)) { 722 return -EINVAL; 723 } 724 725 return 0; 726} 727#endif 728 729int SysSetRealEffSaveUserID(int ruid, int euid, int suid) 730{ 731#ifdef LOSCFG_SECURITY_CAPABILITY 732 int ret; 733 734 if ((ruid == -1) && (euid == -1) && (suid == -1)) { 735 return 0; 736 } 737 738 ret = SetRealEffSaveUserIDCheck(ruid, euid, suid); 739 if (ret != 0) { 740 return ret; 741 } 742 743 if (ruid >= 0) { 744 if (((euid != -1) && (euid != ruid)) || ((suid != -1) && (suid != ruid))) { 745 return -EPERM; 746 } 747 return SysSetUserID(ruid); 748 } else if (euid >= 0) { 749 if ((suid != -1) && (suid != euid)) { 750 return -EPERM; 751 } 752 return SysSetUserID(euid); 753 } else { 754 return SysSetUserID(suid); 755 } 756#else 757 if ((ruid != 0) || (euid != 0) || (suid != 0)) { 758 return -EPERM; 759 } 760 return 0; 761#endif 762} 763 764int SysSetRealEffUserID(int ruid, int euid) 765{ 766#ifdef LOSCFG_SECURITY_CAPABILITY 767 return SysSetRealEffSaveUserID(ruid, euid, -1); 768#else 769 if ((ruid != 0) || (euid != 0)) { 770 return -EPERM; 771 } 772 return 0; 773#endif 774} 775 776#ifdef LOSCFG_USER_CONTAINER 777int SysSetGroupID(int gid) 778{ 779#ifdef LOSCFG_SECURITY_CAPABILITY 780 UserContainer *userContainer = CurrentCredentials()->userContainer; 781 int retval = -EPERM; 782 unsigned int oldGid; 783 unsigned int intSave; 784 int count; 785 786 if (gid < 0) { 787 return -EINVAL; 788 } 789 790 unsigned int kgid = OsMakeKgid(userContainer, gid); 791 if (kgid == (UINT32)-1) { 792 return -EINVAL; 793 } 794 795 Credentials *newCredentials = PrepareCredential(OsCurrProcessGet()); 796 if (newCredentials == NULL) { 797 return -ENOMEM; 798 } 799 800 SCHEDULER_LOCK(intSave); 801 User *user = OsCurrUserGet(); 802 if (IsCapPermit(CAP_SETGID)) { 803 newCredentials->gid = kgid; 804 newCredentials->egid = kgid; 805 oldGid = user->gid; 806 user->gid = kgid; 807 user->effGid = kgid; 808 for (count = 0; count < user->groupNumber; count++) { 809 if (user->groups[count] == oldGid) { 810 user->groups[count] = kgid; 811 retval = LOS_OK; 812 break; 813 } 814 } 815 } else if (user->gid != kgid) { 816 goto ERROR; 817 } 818 819 retval = CommitCredentials(newCredentials); 820 SCHEDULER_UNLOCK(intSave); 821 return retval; 822 823ERROR: 824 FreeCredential(newCredentials); 825 SCHEDULER_UNLOCK(intSave); 826 return retval; 827 828#else 829 if (gid != 0) { 830 return -EPERM; 831 } 832 return 0; 833#endif 834} 835#else 836int SysSetGroupID(int gid) 837{ 838#ifdef LOSCFG_SECURITY_CAPABILITY 839 int ret = -EPERM; 840 unsigned int intSave; 841 unsigned int count; 842 unsigned int oldGid; 843 User *user = NULL; 844 845 if (gid < 0) { 846 return -EINVAL; 847 } 848 849 SCHEDULER_LOCK(intSave); 850 user = OsCurrUserGet(); 851 if (IsCapPermit(CAP_SETGID)) { 852 oldGid = user->gid; 853 user->gid = gid; 854 user->effGid = gid; 855 for (count = 0; count < user->groupNumber; count++) { 856 if (user->groups[count] == oldGid) { 857 user->groups[count] = gid; 858 ret = LOS_OK; 859 goto EXIT; 860 } 861 } 862 } else if (user->gid != gid) { 863 goto EXIT; 864 } 865 866 ret = LOS_OK; 867 /* add process to a user */ 868EXIT: 869 SCHEDULER_UNLOCK(intSave); 870 return ret; 871 872#else 873 if (gid != 0) { 874 return -EPERM; 875 } 876 877 return 0; 878#endif 879} 880#endif 881 882int SysGetRealEffSaveGroupID(int *rgid, int *egid, int *sgid) 883{ 884 int ret; 885 int realGroupID, effGroupID, saveGroupID; 886#ifdef LOSCFG_SECURITY_CAPABILITY 887 unsigned int intSave; 888 889 SCHEDULER_LOCK(intSave); 890#ifdef LOSCFG_USER_CONTAINER 891 realGroupID = OsFromKuidMunged(OsCurrentUserContainer(), CurrentCredentials()->gid); 892 effGroupID = OsFromKuidMunged(OsCurrentUserContainer(), CurrentCredentials()->egid); 893 saveGroupID = OsFromKuidMunged(OsCurrentUserContainer(), CurrentCredentials()->egid); 894#else 895 realGroupID = OsCurrUserGet()->gid; 896 effGroupID = OsCurrUserGet()->effGid; 897 saveGroupID = OsCurrUserGet()->effGid; 898#endif 899 SCHEDULER_UNLOCK(intSave); 900#else 901 realGroupID = 0; 902 effGroupID = 0; 903 saveGroupID = 0; 904#endif 905 906 ret = LOS_ArchCopyToUser(rgid, &realGroupID, sizeof(int)); 907 if (ret != 0) { 908 return -EFAULT; 909 } 910 911 ret = LOS_ArchCopyToUser(egid, &effGroupID, sizeof(int)); 912 if (ret != 0) { 913 return -EFAULT; 914 } 915 916 ret = LOS_ArchCopyToUser(sgid, &saveGroupID, sizeof(int)); 917 if (ret != 0) { 918 return -EFAULT; 919 } 920 921 return 0; 922} 923 924#ifdef LOSCFG_SECURITY_CAPABILITY 925static int SetRealEffSaveGroupIDCheck(int rgid, int egid, int sgid) 926{ 927 if ((rgid < 0) && (rgid != -1)) { 928 return -EINVAL; 929 } 930 931 if ((egid < 0) && (egid != -1)) { 932 return -EINVAL; 933 } 934 935 if ((sgid < 0) && (sgid != -1)) { 936 return -EINVAL; 937 } 938 939 return 0; 940} 941#endif 942 943int SysSetRealEffSaveGroupID(int rgid, int egid, int sgid) 944{ 945#ifdef LOSCFG_SECURITY_CAPABILITY 946 int ret; 947 948 if ((rgid == -1) && (egid == -1) && (sgid == -1)) { 949 return 0; 950 } 951 952 ret = SetRealEffSaveGroupIDCheck(rgid, egid, sgid); 953 if (ret != 0) { 954 return ret; 955 } 956 957 if (rgid >= 0) { 958 if (((egid != -1) && (egid != rgid)) || ((sgid != -1) && (sgid != rgid))) { 959 return -EPERM; 960 } 961 return SysSetGroupID(rgid); 962 } else if (egid >= 0) { 963 if ((sgid != -1) && (sgid != egid)) { 964 return -EPERM; 965 } 966 return SysSetGroupID(egid); 967 } else { 968 return SysSetGroupID(sgid); 969 } 970 971#else 972 if ((rgid != 0) || (egid != 0) || (sgid != 0)) { 973 return -EPERM; 974 } 975 return 0; 976#endif 977} 978 979int SysSetRealEffGroupID(int rgid, int egid) 980{ 981#ifdef LOSCFG_SECURITY_CAPABILITY 982 return SysSetRealEffSaveGroupID(rgid, egid, -1); 983#else 984 if ((rgid != 0) || (egid != 0)) { 985 return -EPERM; 986 } 987 return 0; 988#endif 989} 990 991int SysGetGroupID(void) 992{ 993 return LOS_GetGroupID(); 994} 995 996#ifdef LOSCFG_SECURITY_CAPABILITY 997static int SetGroups(int listSize, const int *safeList, int size) 998{ 999 User *oldUser = NULL; 1000 unsigned int intSave; 1001 1002 User *newUser = LOS_MemAlloc(m_aucSysMem1, sizeof(User) + listSize * sizeof(int)); 1003 if (newUser == NULL) { 1004 return -ENOMEM; 1005 } 1006 1007 SCHEDULER_LOCK(intSave); 1008 oldUser = OsCurrUserGet(); 1009 (VOID)memcpy_s(newUser, sizeof(User), oldUser, sizeof(User)); 1010 if (safeList != NULL) { 1011 (VOID)memcpy_s(newUser->groups, size * sizeof(int), safeList, size * sizeof(int)); 1012 } 1013 if (listSize == size) { 1014 newUser->groups[listSize] = oldUser->gid; 1015 } 1016 1017 newUser->groupNumber = listSize + 1; 1018 OsCurrProcessGet()->user = newUser; 1019 SCHEDULER_UNLOCK(intSave); 1020 1021 (void)LOS_MemFree(m_aucSysMem1, oldUser); 1022 return 0; 1023} 1024 1025static int GetGroups(int size, int list[]) 1026{ 1027 unsigned int intSave; 1028 int groupCount; 1029 int ret; 1030 int *safeList = NULL; 1031 unsigned int listSize; 1032 1033 SCHEDULER_LOCK(intSave); 1034 groupCount = OsCurrUserGet()->groupNumber; 1035 SCHEDULER_UNLOCK(intSave); 1036 1037 listSize = groupCount * sizeof(int); 1038 if (size == 0) { 1039 return groupCount; 1040 } else if (list == NULL) { 1041 return -EFAULT; 1042 } else if (size < groupCount) { 1043 return -EINVAL; 1044 } 1045 1046 safeList = LOS_MemAlloc(m_aucSysMem1, listSize); 1047 if (safeList == NULL) { 1048 return -ENOMEM; 1049 } 1050 1051 SCHEDULER_LOCK(intSave); 1052 (void)memcpy_s(safeList, listSize, &OsCurrProcessGet()->user->groups[0], listSize); 1053 SCHEDULER_UNLOCK(intSave); 1054 1055 ret = LOS_ArchCopyToUser(list, safeList, listSize); 1056 if (ret != 0) { 1057 groupCount = -EFAULT; 1058 } 1059 1060 (void)LOS_MemFree(m_aucSysMem1, safeList); 1061 return groupCount; 1062} 1063#endif 1064 1065int SysGetGroups(int size, int list[]) 1066{ 1067#ifdef LOSCFG_SECURITY_CAPABILITY 1068 return GetGroups(size, list); 1069#else 1070 int group = 0; 1071 int groupCount = 1; 1072 int ret; 1073 1074 if (size == 0) { 1075 return groupCount; 1076 } else if (list == NULL) { 1077 return -EFAULT; 1078 } else if (size < groupCount) { 1079 return -EINVAL; 1080 } 1081 1082 ret = LOS_ArchCopyToUser(list, &group, sizeof(int)); 1083 if (ret != 0) { 1084 return -EFAULT; 1085 } 1086 1087 return groupCount; 1088#endif 1089} 1090 1091int SysSetGroups(int size, const int list[]) 1092{ 1093#ifdef LOSCFG_SECURITY_CAPABILITY 1094 int ret; 1095 int gid; 1096 int listSize = size; 1097 unsigned int count; 1098 int *safeList = NULL; 1099#endif 1100 1101 if ((size != 0) && (list == NULL)) { 1102 return -EFAULT; 1103 } 1104 1105 if ((size < 0) || (size > OS_GROUPS_NUMBER_MAX)) { 1106 return -EINVAL; 1107 } 1108 1109#ifdef LOSCFG_SECURITY_CAPABILITY 1110 if (!IsCapPermit(CAP_SETGID)) { 1111 return -EPERM; 1112 } 1113 1114 if (size != 0) { 1115 safeList = LOS_MemAlloc(m_aucSysMem1, size * sizeof(int)); 1116 if (safeList == NULL) { 1117 return -ENOMEM; 1118 } 1119 1120 ret = LOS_ArchCopyFromUser(safeList, list, size * sizeof(int)); 1121 if (ret != 0) { 1122 ret = -EFAULT; 1123 goto EXIT; 1124 } 1125 gid = OsCurrUserGet()->gid; 1126 for (count = 0; count < size; count++) { 1127 if (safeList[count] == gid) { 1128 listSize = size - 1; 1129 } else if (safeList[count] < 0) { 1130 ret = -EINVAL; 1131 goto EXIT; 1132 } 1133 } 1134 } 1135 1136 ret = SetGroups(listSize, safeList, size); 1137EXIT: 1138 if (safeList != NULL) { 1139 (void)LOS_MemFree(m_aucSysMem1, safeList); 1140 } 1141 1142 return ret; 1143#else 1144 return 0; 1145#endif 1146} 1147 1148unsigned int SysCreateUserThread(const TSK_ENTRY_FUNC func, const UserTaskParam *userParam, bool joinable) 1149{ 1150 TSK_INIT_PARAM_S param = { 0 }; 1151 int ret; 1152 1153 ret = LOS_ArchCopyFromUser(&(param.userParam), userParam, sizeof(UserTaskParam)); 1154 if (ret != 0) { 1155 return OS_INVALID_VALUE; 1156 } 1157 1158 param.pfnTaskEntry = func; 1159 if (joinable == TRUE) { 1160 param.uwResved = LOS_TASK_ATTR_JOINABLE; 1161 } else { 1162 param.uwResved = LOS_TASK_STATUS_DETACHED; 1163 } 1164 1165 return OsCreateUserTask(OS_INVALID_VALUE, ¶m); 1166} 1167 1168int SysSetThreadArea(const char *area) 1169{ 1170 unsigned int intSave; 1171 int ret = LOS_OK; 1172 1173 if (!LOS_IsUserAddress((unsigned long)(uintptr_t)area)) { 1174 return EINVAL; 1175 } 1176 1177 LosTaskCB *taskCB = OsCurrTaskGet(); 1178 SCHEDULER_LOCK(intSave); 1179 LosProcessCB *processCB = OS_PCB_FROM_TCB(taskCB); 1180 if (processCB->processMode != OS_USER_MODE) { 1181 ret = EPERM; 1182 goto OUT; 1183 } 1184 1185 taskCB->userArea = (unsigned long)(uintptr_t)area; 1186OUT: 1187 SCHEDULER_UNLOCK(intSave); 1188 return ret; 1189} 1190 1191char *SysGetThreadArea(void) 1192{ 1193 return (char *)(OsCurrTaskGet()->userArea); 1194} 1195 1196int SysUserThreadSetDetach(unsigned int taskID) 1197{ 1198 unsigned int intSave; 1199 int ret; 1200 1201 if (OS_TID_CHECK_INVALID(taskID)) { 1202 return EINVAL; 1203 } 1204 1205 LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID); 1206 SCHEDULER_LOCK(intSave); 1207 ret = OsUserTaskOperatePermissionsCheck(taskCB); 1208 if (ret != LOS_OK) { 1209 goto EXIT; 1210 } 1211 1212 ret = (int)OsTaskSetDetachUnsafe(taskCB); 1213 1214EXIT: 1215 SCHEDULER_UNLOCK(intSave); 1216 return ret; 1217} 1218 1219int SysUserThreadDetach(unsigned int taskID) 1220{ 1221 unsigned int intSave; 1222 int ret; 1223 1224 if (OS_TID_CHECK_INVALID(taskID)) { 1225 return EINVAL; 1226 } 1227 1228 SCHEDULER_LOCK(intSave); 1229 ret = OsUserTaskOperatePermissionsCheck(OS_TCB_FROM_TID(taskID)); 1230 SCHEDULER_UNLOCK(intSave); 1231 if (ret != LOS_OK) { 1232 return ret; 1233 } 1234 1235 if (LOS_TaskDelete(taskID) != LOS_OK) { 1236 return ESRCH; 1237 } 1238 1239 return LOS_OK; 1240} 1241 1242int SysThreadJoin(unsigned int taskID) 1243{ 1244 unsigned int intSave; 1245 int ret; 1246 1247 if (OS_TID_CHECK_INVALID(taskID)) { 1248 return EINVAL; 1249 } 1250 1251 LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID); 1252 SCHEDULER_LOCK(intSave); 1253 ret = OsUserTaskOperatePermissionsCheck(taskCB); 1254 if (ret != LOS_OK) { 1255 goto EXIT; 1256 } 1257 1258 ret = (int)OsTaskJoinPendUnsafe(OS_TCB_FROM_TID(taskID)); 1259 1260EXIT: 1261 SCHEDULER_UNLOCK(intSave); 1262 return ret; 1263} 1264 1265void SysUserExitGroup(int status) 1266{ 1267 (void)status; 1268 OsProcessThreadGroupDestroy(); 1269} 1270 1271void SysThreadExit(int status) 1272{ 1273 OsRunningTaskToExit(OsCurrTaskGet(), (unsigned int)status); 1274} 1275 1276int SysFutex(const unsigned int *uAddr, unsigned int flags, int val, 1277 unsigned int absTime, const unsigned int *newUserAddr) 1278{ 1279 if ((flags & FUTEX_MASK) == FUTEX_REQUEUE) { 1280 return -OsFutexRequeue(uAddr, flags, val, absTime, newUserAddr); 1281 } 1282 1283 if ((flags & FUTEX_MASK) == FUTEX_WAKE) { 1284 return -OsFutexWake(uAddr, flags, val); 1285 } 1286 1287 return -OsFutexWait(uAddr, flags, val, absTime); 1288} 1289 1290unsigned int SysGetTid(void) 1291{ 1292 return OsCurrTaskGet()->taskID; 1293} 1294 1295/* If flag >= 0, the process mode is used. If flag < 0, the thread mode is used. */ 1296static int SchedAffinityParameterPreprocess(int id, int flag, unsigned int *taskID, unsigned int *processID) 1297{ 1298 if (flag >= 0) { 1299 if (OS_PID_CHECK_INVALID(id)) { 1300 return -ESRCH; 1301 } 1302 LosProcessCB *ProcessCB = OS_PCB_FROM_PID((UINT32)id); 1303 if (ProcessCB->threadGroup == NULL) { 1304 return -ESRCH; 1305 } 1306 *taskID = (id == 0) ? (OsCurrTaskGet()->taskID) : (ProcessCB->threadGroup->taskID); 1307 *processID = (id == 0) ? (OS_PCB_FROM_TID(*taskID)->processID) : id; 1308 } else { 1309 if (OS_TID_CHECK_INVALID(id)) { 1310 return -ESRCH; 1311 } 1312 *taskID = id; 1313 *processID = OS_INVALID_VALUE; 1314 } 1315 return LOS_OK; 1316} 1317 1318/* If flag >= 0, the process mode is used. If flag < 0, the thread mode is used. */ 1319int SysSchedGetAffinity(int id, unsigned int *cpuset, int flag) 1320{ 1321 int ret; 1322 unsigned int processID; 1323 unsigned int taskID; 1324 unsigned int intSave; 1325 unsigned int cpuAffiMask; 1326 1327 ret = SchedAffinityParameterPreprocess(id, flag, &taskID, &processID); 1328 if (ret != LOS_OK) { 1329 return ret; 1330 } 1331 1332 SCHEDULER_LOCK(intSave); 1333 if (flag >= 0) { 1334 if (OsProcessIsInactive(OS_PCB_FROM_PID(processID))) { 1335 SCHEDULER_UNLOCK(intSave); 1336 return -ESRCH; 1337 } 1338 } else { 1339 ret = OsUserTaskOperatePermissionsCheck(OS_TCB_FROM_TID(taskID)); 1340 if (ret != LOS_OK) { 1341 SCHEDULER_UNLOCK(intSave); 1342 if (ret == EINVAL) { 1343 return -ESRCH; 1344 } 1345 return -ret; 1346 } 1347 } 1348 1349#ifdef LOSCFG_KERNEL_SMP 1350 cpuAffiMask = (unsigned int)OS_TCB_FROM_TID(taskID)->cpuAffiMask; 1351#else 1352 cpuAffiMask = 1; 1353#endif /* LOSCFG_KERNEL_SMP */ 1354 1355 SCHEDULER_UNLOCK(intSave); 1356 ret = LOS_ArchCopyToUser(cpuset, &cpuAffiMask, sizeof(unsigned int)); 1357 if (ret != LOS_OK) { 1358 return -EFAULT; 1359 } 1360 1361 return LOS_OK; 1362} 1363 1364/* If flag >= 0, the process mode is used. If flag < 0, the thread mode is used. */ 1365int SysSchedSetAffinity(int id, const unsigned short cpuset, int flag) 1366{ 1367 int ret; 1368 unsigned int processID; 1369 unsigned int taskID; 1370 unsigned int intSave; 1371 unsigned short currCpuMask; 1372 bool needSched = FALSE; 1373 1374 if (cpuset > LOSCFG_KERNEL_CPU_MASK) { 1375 return -EINVAL; 1376 } 1377 1378 ret = SchedAffinityParameterPreprocess(id, flag, &taskID, &processID); 1379 if (ret != LOS_OK) { 1380 return ret; 1381 } 1382 1383 if (flag >= 0) { 1384 ret = OsPermissionToCheck(processID, LOS_GetCurrProcessID()); 1385 if (ret != LOS_OK) { 1386 return ret; 1387 } 1388 SCHEDULER_LOCK(intSave); 1389 if (OsProcessIsInactive(OS_PCB_FROM_PID(processID))) { 1390 SCHEDULER_UNLOCK(intSave); 1391 return -ESRCH; 1392 } 1393 } else { 1394 SCHEDULER_LOCK(intSave); 1395 ret = OsUserTaskOperatePermissionsCheck(OS_TCB_FROM_TID(taskID)); 1396 if (ret != LOS_OK) { 1397 SCHEDULER_UNLOCK(intSave); 1398 if (ret == EINVAL) { 1399 return -ESRCH; 1400 } 1401 return -ret; 1402 } 1403 } 1404 1405 needSched = OsTaskCpuAffiSetUnsafe(taskID, cpuset, &currCpuMask); 1406 SCHEDULER_UNLOCK(intSave); 1407 if (needSched && OS_SCHEDULER_ACTIVE) { 1408 LOS_MpSchedule(currCpuMask); 1409 LOS_Schedule(); 1410 } 1411 1412 return LOS_OK; 1413} 1414 1415