xref: /kernel/liteos_a/syscall/process_syscall.c (revision 0d163575)
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, &param);
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, &param);
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, &param);
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(&param, userParam, sizeof(LosSchedParam)) != 0) {
190        return -EFAULT;
191    }
192
193    if (flag < 0) {
194        return -OsUserTaskSchedulerSet(id, policy, &param, 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, &param);
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, &param);
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(&param, userParam, sizeof(LosSchedParam)) != 0) {
308            return -EFAULT;
309        }
310        return -OsUserTaskSchedulerSet(id, LOS_SCHED_RR, &param, 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, &param);
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, &param);
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