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_signal.h"
33 #include "pthread.h"
34 #include "los_process_pri.h"
35 #include "los_sched_pri.h"
36 #include "los_hw_pri.h"
37 #include "user_copy.h"
38 #ifdef LOSCFG_SECURITY_CAPABILITY
39 #include "capability_api.h"
40 #endif
41 #include "los_atomic.h"
42
43 #ifdef LOSCFG_KERNEL_VM
44
raise(int sig)45 int raise(int sig)
46 {
47 (VOID)sig;
48 PRINT_ERR("%s NOT SUPPORT\n", __FUNCTION__);
49 errno = ENOSYS;
50 return -1;
51 }
52
53 #define GETUNMASKSET(procmask, pendFlag) ((~(procmask)) & (sigset_t)(pendFlag))
54 #define UINT64_BIT_SIZE 64
55
OsSigIsMember(const sigset_t * set,int signo)56 int OsSigIsMember(const sigset_t *set, int signo)
57 {
58 int ret = LOS_NOK;
59 /* In musl, sig No bits 00000100 present sig No 3, but 1<< 3 = 00001000, so signo needs minus 1 */
60 signo -= 1;
61 /* Verify the signal */
62 if (GOOD_SIGNO(signo)) {
63 /* Check if the signal is in the set */
64 ret = ((*set & SIGNO2SET((unsigned int)signo)) != 0);
65 }
66
67 return ret;
68 }
69
OsMoveTmpInfoToUnbInfo(sig_cb * sigcb,INT32 signo)70 STATIC VOID OsMoveTmpInfoToUnbInfo(sig_cb *sigcb, INT32 signo)
71 {
72 SigInfoListNode *tmpInfoNode = sigcb->tmpInfoListHead;
73 SigInfoListNode **prevHook = &sigcb->tmpInfoListHead;
74 while (tmpInfoNode != NULL) {
75 if (tmpInfoNode->info.si_signo == signo) {
76 /* copy tmpinfo to unbinfo. */
77 (VOID)memcpy_s(&sigcb->sigunbinfo, sizeof(siginfo_t), &tmpInfoNode->info, sizeof(siginfo_t));
78 /* delete tmpinfo from tmpList. */
79 *prevHook = tmpInfoNode->next;
80 (VOID)LOS_MemFree(m_aucSysMem0, tmpInfoNode);
81 break;
82 }
83 prevHook = &tmpInfoNode->next;
84 tmpInfoNode = tmpInfoNode->next;
85 }
86 }
87
OsAddSigInfoToTmpList(sig_cb * sigcb,siginfo_t * info)88 STATIC INT32 OsAddSigInfoToTmpList(sig_cb *sigcb, siginfo_t *info)
89 {
90 /* try to find the old siginfo */
91 SigInfoListNode *tmp = sigcb->tmpInfoListHead;
92 while (tmp != NULL) {
93 if (tmp->info.si_signo == info->si_signo) {
94 /* found it, break. */
95 break;
96 }
97 tmp = tmp->next;
98 }
99
100 if (tmp == NULL) {
101 /* none, alloc new one */
102 tmp = (SigInfoListNode *)LOS_MemAlloc(m_aucSysMem0, sizeof(SigInfoListNode));
103 if (tmp == NULL) {
104 return LOS_NOK;
105 }
106 tmp->next = sigcb->tmpInfoListHead;
107 sigcb->tmpInfoListHead = tmp;
108 }
109
110 (VOID)memcpy_s(&tmp->info, sizeof(siginfo_t), info, sizeof(siginfo_t));
111
112 return LOS_OK;
113 }
114
OsClearSigInfoTmpList(sig_cb * sigcb)115 VOID OsClearSigInfoTmpList(sig_cb *sigcb)
116 {
117 while (sigcb->tmpInfoListHead != NULL) {
118 SigInfoListNode *tmpInfoNode = sigcb->tmpInfoListHead;
119 sigcb->tmpInfoListHead = sigcb->tmpInfoListHead->next;
120 (VOID)LOS_MemFree(m_aucSysMem0, tmpInfoNode);
121 }
122 }
123
OsSigWaitTaskWake(LosTaskCB * taskCB,INT32 signo)124 STATIC INLINE VOID OsSigWaitTaskWake(LosTaskCB *taskCB, INT32 signo)
125 {
126 sig_cb *sigcb = &taskCB->sig;
127
128 if (!LOS_ListEmpty(&sigcb->waitList) && OsSigIsMember(&sigcb->sigwaitmask, signo)) {
129 OsMoveTmpInfoToUnbInfo(sigcb, signo);
130 OsTaskWakeClearPendMask(taskCB);
131 taskCB->ops->wake(taskCB);
132 OsSigEmptySet(&sigcb->sigwaitmask);
133 }
134 }
135
OsPendingTaskWake(LosTaskCB * taskCB,INT32 signo)136 STATIC UINT32 OsPendingTaskWake(LosTaskCB *taskCB, INT32 signo)
137 {
138 if (!OsTaskIsPending(taskCB) || !OsProcessIsUserMode(OS_PCB_FROM_TCB(taskCB))) {
139 return 0;
140 }
141
142 if ((signo != SIGKILL) && (taskCB->waitFlag != OS_TASK_WAIT_SIGNAL)) {
143 return 0;
144 }
145
146 switch (taskCB->waitFlag) {
147 case OS_TASK_WAIT_PROCESS:
148 case OS_TASK_WAIT_GID:
149 case OS_TASK_WAIT_ANYPROCESS:
150 OsWaitWakeTask(taskCB, OS_INVALID_VALUE);
151 break;
152 case OS_TASK_WAIT_JOIN:
153 OsTaskWakeClearPendMask(taskCB);
154 taskCB->ops->wake(taskCB);
155 break;
156 case OS_TASK_WAIT_SIGNAL:
157 OsSigWaitTaskWake(taskCB, signo);
158 break;
159 case OS_TASK_WAIT_LITEIPC:
160 OsTaskWakeClearPendMask(taskCB);
161 taskCB->ops->wake(taskCB);
162 break;
163 case OS_TASK_WAIT_FUTEX:
164 OsFutexNodeDeleteFromFutexHash(&taskCB->futex, TRUE, NULL, NULL);
165 OsTaskWakeClearPendMask(taskCB);
166 taskCB->ops->wake(taskCB);
167 break;
168 default:
169 break;
170 }
171
172 return 0;
173 }
174
OsTcbDispatch(LosTaskCB * stcb,siginfo_t * info)175 int OsTcbDispatch(LosTaskCB *stcb, siginfo_t *info)
176 {
177 bool masked = FALSE;
178 sig_cb *sigcb = &stcb->sig;
179
180 OS_RETURN_IF_NULL(sigcb);
181 /* If signo is 0, not send signal, just check process or pthread exist */
182 if (info->si_signo == 0) {
183 return 0;
184 }
185 masked = (bool)OsSigIsMember(&sigcb->sigprocmask, info->si_signo);
186 if (masked) {
187 /* If signal is in wait list and mask list, need unblock it */
188 if (LOS_ListEmpty(&sigcb->waitList) ||
189 (!LOS_ListEmpty(&sigcb->waitList) && !OsSigIsMember(&sigcb->sigwaitmask, info->si_signo))) {
190 OsSigAddSet(&sigcb->sigPendFlag, info->si_signo);
191 }
192 } else {
193 /* unmasked signal actions */
194 OsSigAddSet(&sigcb->sigFlag, info->si_signo);
195 }
196
197 if (OsAddSigInfoToTmpList(sigcb, info) == LOS_NOK) {
198 return -ENOMEM;
199 }
200
201 return OsPendingTaskWake(stcb, info->si_signo);
202 }
203
OsSigMaskSwitch(LosTaskCB * const rtcb,sigset_t set)204 void OsSigMaskSwitch(LosTaskCB * const rtcb, sigset_t set)
205 {
206 sigset_t unmaskset;
207
208 rtcb->sig.sigprocmask = set;
209 unmaskset = GETUNMASKSET(rtcb->sig.sigprocmask, rtcb->sig.sigPendFlag);
210 if (unmaskset != NULL_SIGNAL_SET) {
211 /* pendlist do */
212 rtcb->sig.sigFlag |= unmaskset;
213 rtcb->sig.sigPendFlag ^= unmaskset;
214 }
215 }
216
OsSigprocMask(int how,const sigset_t_l * setl,sigset_t_l * oldsetl)217 int OsSigprocMask(int how, const sigset_t_l *setl, sigset_t_l *oldsetl)
218 {
219 LosTaskCB *spcb = NULL;
220 int ret = LOS_OK;
221 unsigned int intSave;
222 sigset_t set;
223
224 SCHEDULER_LOCK(intSave);
225 spcb = OsCurrTaskGet();
226 /* If requested, copy the old mask to user. */
227 if (oldsetl != NULL) {
228 *(sigset_t *)oldsetl = spcb->sig.sigprocmask;
229 }
230 /* If requested, modify the current signal mask. */
231 if (setl != NULL) {
232 set = *(sigset_t *)setl;
233 /* Okay, determine what we are supposed to do */
234 switch (how) {
235 /* Set the union of the current set and the signal
236 * set pointed to by set as the new sigprocmask.
237 */
238 case SIG_BLOCK:
239 spcb->sig.sigprocmask |= set;
240 break;
241 /* Set the intersection of the current set and the
242 * signal set pointed to by set as the new sigprocmask.
243 */
244 case SIG_UNBLOCK:
245 spcb->sig.sigprocmask &= ~(set);
246 break;
247 /* Set the signal set pointed to by set as the new sigprocmask. */
248 case SIG_SETMASK:
249 spcb->sig.sigprocmask = set;
250 break;
251 default:
252 ret = -EINVAL;
253 break;
254 }
255 /* If pending mask not in sigmask, need set sigflag. */
256 OsSigMaskSwitch(spcb, spcb->sig.sigprocmask);
257 }
258 SCHEDULER_UNLOCK(intSave);
259
260 return ret;
261 }
262
OsSigProcessForeachChild(LosProcessCB * spcb,ForEachTaskCB handler,void * arg)263 int OsSigProcessForeachChild(LosProcessCB *spcb, ForEachTaskCB handler, void *arg)
264 {
265 int ret;
266
267 /* Visit the main thread last (if present) */
268 LosTaskCB *taskCB = NULL;
269 LOS_DL_LIST_FOR_EACH_ENTRY(taskCB, &(spcb->threadSiblingList), LosTaskCB, threadList) {
270 ret = handler(taskCB, arg);
271 OS_RETURN_IF(ret != 0, ret);
272 }
273 return LOS_OK;
274 }
275
SigProcessSignalHandler(LosTaskCB * tcb,void * arg)276 static int SigProcessSignalHandler(LosTaskCB *tcb, void *arg)
277 {
278 struct ProcessSignalInfo *info = (struct ProcessSignalInfo *)arg;
279 int ret;
280 int isMember;
281
282 if (tcb == NULL) {
283 return 0;
284 }
285
286 /* If the default tcb is not set, then set this one as default. */
287 if (!info->defaultTcb) {
288 info->defaultTcb = tcb;
289 }
290
291 isMember = OsSigIsMember(&tcb->sig.sigwaitmask, info->sigInfo->si_signo);
292 if (isMember && (!info->awakenedTcb)) {
293 /* This means the task is waiting for this signal. Stop looking for it and use this tcb.
294 * The requirement is: if more than one task in this task group is waiting for the signal,
295 * then only one indeterminate task in the group will receive the signal.
296 */
297 ret = OsTcbDispatch(tcb, info->sigInfo);
298 OS_RETURN_IF(ret < 0, ret);
299
300 /* set this tcb as awakenedTcb */
301 info->awakenedTcb = tcb;
302 OS_RETURN_IF(info->receivedTcb != NULL, SIG_STOP_VISIT); /* Stop search */
303 }
304 /* Is this signal unblocked on this thread? */
305 isMember = OsSigIsMember(&tcb->sig.sigprocmask, info->sigInfo->si_signo);
306 if ((!isMember) && (!info->receivedTcb) && (tcb != info->awakenedTcb)) {
307 /* if unblockedTcb of this signal is not set, then set it. */
308 if (!info->unblockedTcb) {
309 info->unblockedTcb = tcb;
310 }
311
312 ret = OsTcbDispatch(tcb, info->sigInfo);
313 OS_RETURN_IF(ret < 0, ret);
314 /* set this tcb as receivedTcb */
315 info->receivedTcb = tcb;
316 OS_RETURN_IF(info->awakenedTcb != NULL, SIG_STOP_VISIT); /* Stop search */
317 }
318 return 0; /* Keep searching */
319 }
320
SigProcessKillSigHandler(LosTaskCB * tcb,void * arg)321 static int SigProcessKillSigHandler(LosTaskCB *tcb, void *arg)
322 {
323 struct ProcessSignalInfo *info = (struct ProcessSignalInfo *)arg;
324
325 return OsPendingTaskWake(tcb, info->sigInfo->si_signo);
326 }
327
SigProcessLoadTcb(struct ProcessSignalInfo * info,siginfo_t * sigInfo)328 static void SigProcessLoadTcb(struct ProcessSignalInfo *info, siginfo_t *sigInfo)
329 {
330 LosTaskCB *tcb = NULL;
331
332 if (info->awakenedTcb == NULL && info->receivedTcb == NULL) {
333 if (info->unblockedTcb) {
334 tcb = info->unblockedTcb;
335 } else if (info->defaultTcb) {
336 tcb = info->defaultTcb;
337 } else {
338 return;
339 }
340 /* Deliver the signal to the selected task */
341 (void)OsTcbDispatch(tcb, sigInfo);
342 }
343 }
344
OsSigProcessSend(LosProcessCB * spcb,siginfo_t * sigInfo)345 int OsSigProcessSend(LosProcessCB *spcb, siginfo_t *sigInfo)
346 {
347 int ret;
348 struct ProcessSignalInfo info = {
349 .sigInfo = sigInfo,
350 .defaultTcb = NULL,
351 .unblockedTcb = NULL,
352 .awakenedTcb = NULL,
353 .receivedTcb = NULL
354 };
355
356 if (info.sigInfo == NULL) {
357 return -EFAULT;
358 }
359
360 /* visit all taskcb and dispatch signal */
361 if (info.sigInfo->si_signo == SIGKILL) {
362 OsSigAddSet(&spcb->sigShare, info.sigInfo->si_signo);
363 (void)OsSigProcessForeachChild(spcb, SigProcessKillSigHandler, &info);
364 return 0;
365 } else {
366 ret = OsSigProcessForeachChild(spcb, SigProcessSignalHandler, &info);
367 }
368 if (ret < 0) {
369 return ret;
370 }
371 SigProcessLoadTcb(&info, sigInfo);
372 return 0;
373 }
374
OsSigEmptySet(sigset_t * set)375 int OsSigEmptySet(sigset_t *set)
376 {
377 *set = NULL_SIGNAL_SET;
378 return 0;
379 }
380
381 /* Privilege process can't send to kernel and privilege process */
OsSignalPermissionToCheck(const LosProcessCB * spcb)382 static int OsSignalPermissionToCheck(const LosProcessCB *spcb)
383 {
384 UINTPTR gid = (UINTPTR)OS_GET_PGROUP_LEADER(spcb->pgroup);
385 if (gid == OS_KERNEL_PROCESS_GROUP) {
386 return -EPERM;
387 } else if (gid == OS_USER_PRIVILEGE_PROCESS_GROUP) {
388 return -EPERM;
389 }
390
391 return 0;
392 }
393
SendSigPermissionCheck(LosProcessCB * spcb,int permission)394 STATIC int SendSigPermissionCheck(LosProcessCB *spcb, int permission)
395 {
396 if (spcb == NULL) {
397 return -ESRCH;
398 }
399
400 if (OsProcessIsUnused(spcb)) {
401 return -ESRCH;
402 }
403
404 #ifdef LOSCFG_SECURITY_CAPABILITY
405 LosProcessCB *current = OsCurrProcessGet();
406 /* Kernel process always has kill permission and user process should check permission */
407 if (OsProcessIsUserMode(current) && !(current->processStatus & OS_PROCESS_FLAG_EXIT)) {
408 if ((current != spcb) && (!IsCapPermit(CAP_KILL)) && (current->user->userID != spcb->user->userID)) {
409 return -EPERM;
410 }
411 }
412 #endif
413 if ((permission == OS_USER_KILL_PERMISSION) && (OsSignalPermissionToCheck(spcb) < 0)) {
414 return -EPERM;
415 }
416 return LOS_OK;
417 }
418
OsSendSigToProcess(LosProcessCB * spcb,int sig,int permission)419 int OsSendSigToProcess(LosProcessCB *spcb, int sig, int permission)
420 {
421 siginfo_t info;
422 int ret = SendSigPermissionCheck(spcb, permission);
423 if (ret != LOS_OK) {
424 return ret;
425 }
426
427 /* If the process you want to kill had been inactive, but still exist. should return LOS_OK */
428 if (OsProcessIsInactive(spcb)) {
429 return LOS_OK;
430 }
431
432 if (!GOOD_SIGNO(sig)) {
433 return -EINVAL;
434 }
435
436 info.si_signo = sig;
437 info.si_code = SI_USER;
438 info.si_value.sival_ptr = NULL;
439
440 return OsSigProcessSend(spcb, &info);
441 }
442
OsDispatch(pid_t pid,siginfo_t * info,int permission)443 int OsDispatch(pid_t pid, siginfo_t *info, int permission)
444 {
445 if (OsProcessIDUserCheckInvalid(pid) || pid < 0) {
446 return -ESRCH;
447 }
448
449 LosProcessCB *spcb = OS_PCB_FROM_PID(pid);
450 int ret = SendSigPermissionCheck(spcb, permission);
451 if (ret != LOS_OK) {
452 return ret;
453 }
454
455 /* If the process you want to kill had been inactive, but still exist. should return LOS_OK */
456 if (OsProcessIsInactive(spcb)) {
457 return LOS_OK;
458 }
459
460 return OsSigProcessSend(spcb, info);
461 }
462
OsKill(pid_t pid,int sig,int permission)463 int OsKill(pid_t pid, int sig, int permission)
464 {
465 siginfo_t info;
466 int ret;
467
468 /* Make sure that the para is valid */
469 if (!GOOD_SIGNO(sig)) {
470 return -EINVAL;
471 }
472
473 /* Create the siginfo structure */
474 info.si_signo = sig;
475 info.si_code = SI_USER;
476 info.si_value.sival_ptr = NULL;
477
478 if (pid > 0) {
479 /* Send the signal to the specify process */
480 ret = OsDispatch(pid, &info, permission);
481 } else if (pid == -1) {
482 /* Send SIG to all processes */
483 ret = OsSendSignalToAllProcess(&info, permission);
484 } else {
485 /* Send SIG to all processes in process group PGRP.
486 If PGRP is zero, send SIG to all processes in
487 the current process's process group. */
488 ret = OsSendSignalToProcessGroup(pid, &info, permission);
489 }
490 return ret;
491 }
492
OsKillLock(pid_t pid,int sig)493 int OsKillLock(pid_t pid, int sig)
494 {
495 int ret;
496 unsigned int intSave;
497
498 SCHEDULER_LOCK(intSave);
499 ret = OsKill(pid, sig, OS_USER_KILL_PERMISSION);
500 SCHEDULER_UNLOCK(intSave);
501 return ret;
502 }
503
OsTaskKillUnsafe(UINT32 taskID,INT32 signo)504 INT32 OsTaskKillUnsafe(UINT32 taskID, INT32 signo)
505 {
506 siginfo_t info;
507 LosTaskCB *taskCB = OsGetTaskCB(taskID);
508 INT32 ret = OsUserTaskOperatePermissionsCheck(taskCB);
509 if (ret != LOS_OK) {
510 return -ret;
511 }
512
513 /* Create the siginfo structure */
514 info.si_signo = signo;
515 info.si_code = SI_USER;
516 info.si_value.sival_ptr = NULL;
517
518 /* Dispatch the signal to thread, bypassing normal task group thread
519 * dispatch rules. */
520 return OsTcbDispatch(taskCB, &info);
521 }
522
OsPthreadKill(UINT32 tid,int signo)523 int OsPthreadKill(UINT32 tid, int signo)
524 {
525 int ret;
526 UINT32 intSave;
527
528 /* Make sure that the signal is valid */
529 OS_RETURN_IF(!GOOD_SIGNO(signo), -EINVAL);
530 if (OS_TID_CHECK_INVALID(tid)) {
531 return -ESRCH;
532 }
533
534 /* Keep things stationary through the following */
535 SCHEDULER_LOCK(intSave);
536 ret = OsTaskKillUnsafe(tid, signo);
537 SCHEDULER_UNLOCK(intSave);
538 return ret;
539 }
540
OsSigAddSet(sigset_t * set,int signo)541 int OsSigAddSet(sigset_t *set, int signo)
542 {
543 /* Verify the signal */
544 if (!GOOD_SIGNO(signo)) {
545 return -EINVAL;
546 } else {
547 /* In musl, sig No bits 00000100 present sig No 3, but 1<< 3 = 00001000, so signo needs minus 1 */
548 signo -= 1;
549 /* Add the signal to the set */
550 *set |= SIGNO2SET((unsigned int)signo);
551 return LOS_OK;
552 }
553 }
554
OsSigPending(sigset_t * set)555 int OsSigPending(sigset_t *set)
556 {
557 LosTaskCB *tcb = NULL;
558 unsigned int intSave;
559
560 if (set == NULL) {
561 return -EFAULT;
562 }
563
564 SCHEDULER_LOCK(intSave);
565 tcb = OsCurrTaskGet();
566 *set = tcb->sig.sigPendFlag;
567 SCHEDULER_UNLOCK(intSave);
568 return LOS_OK;
569 }
570
FindFirstSetedBit(UINT64 n)571 STATIC int FindFirstSetedBit(UINT64 n)
572 {
573 int count;
574
575 if (n == 0) {
576 return -1;
577 }
578 for (count = 0; (count < UINT64_BIT_SIZE) && (n ^ 1ULL); n >>= 1, count++) {}
579 return (count < UINT64_BIT_SIZE) ? count : (-1);
580 }
581
OsSigTimedWaitNoLock(sigset_t * set,siginfo_t * info,unsigned int timeout)582 int OsSigTimedWaitNoLock(sigset_t *set, siginfo_t *info, unsigned int timeout)
583 {
584 LosTaskCB *task = NULL;
585 sig_cb *sigcb = NULL;
586 int ret;
587
588 task = OsCurrTaskGet();
589 sigcb = &task->sig;
590
591 if (sigcb->waitList.pstNext == NULL) {
592 LOS_ListInit(&sigcb->waitList);
593 }
594 /* If pendingflag & set > 0, should clear pending flag */
595 sigset_t clear = sigcb->sigPendFlag & *set;
596 if (clear) {
597 sigcb->sigPendFlag ^= clear;
598 ret = FindFirstSetedBit((UINT64)clear) + 1;
599 OsMoveTmpInfoToUnbInfo(sigcb, ret);
600 } else {
601 OsSigAddSet(set, SIGKILL);
602 OsSigAddSet(set, SIGSTOP);
603
604 sigcb->sigwaitmask |= *set;
605 OsTaskWaitSetPendMask(OS_TASK_WAIT_SIGNAL, sigcb->sigwaitmask, timeout);
606 ret = task->ops->wait(task, &sigcb->waitList, timeout);
607 if (ret == LOS_ERRNO_TSK_TIMEOUT) {
608 ret = -EAGAIN;
609 }
610 sigcb->sigwaitmask = NULL_SIGNAL_SET;
611 }
612 if (info != NULL) {
613 (VOID)memcpy_s(info, sizeof(siginfo_t), &sigcb->sigunbinfo, sizeof(siginfo_t));
614 }
615 return ret;
616 }
617
OsSigTimedWait(sigset_t * set,siginfo_t * info,unsigned int timeout)618 int OsSigTimedWait(sigset_t *set, siginfo_t *info, unsigned int timeout)
619 {
620 int ret;
621 unsigned int intSave;
622
623 SCHEDULER_LOCK(intSave);
624
625 ret = OsSigTimedWaitNoLock(set, info, timeout);
626
627 SCHEDULER_UNLOCK(intSave);
628 return ret;
629 }
630
OsPause(void)631 int OsPause(void)
632 {
633 LosTaskCB *spcb = NULL;
634 sigset_t oldSigprocmask;
635
636 spcb = OsCurrTaskGet();
637 oldSigprocmask = spcb->sig.sigprocmask;
638 return OsSigSuspend(&oldSigprocmask);
639 }
640
OsSigSuspend(const sigset_t * set)641 int OsSigSuspend(const sigset_t *set)
642 {
643 unsigned int intSave;
644 LosTaskCB *rtcb = NULL;
645 sigset_t setSuspend;
646 int ret;
647
648 if (set == NULL) {
649 return -EINVAL;
650 }
651 SCHEDULER_LOCK(intSave);
652 rtcb = OsCurrTaskGet();
653
654 /* Wait signal calc */
655 setSuspend = FULL_SIGNAL_SET & (~(*set));
656
657 /* If pending mask not in sigmask, need set sigflag */
658 OsSigMaskSwitch(rtcb, *set);
659
660 if (rtcb->sig.sigFlag > 0) {
661 SCHEDULER_UNLOCK(intSave);
662
663 /*
664 * If rtcb->sig.sigFlag > 0, it means that some signal have been
665 * received, and we need to do schedule to handle the signal directly.
666 */
667 LOS_Schedule();
668 return -EINTR;
669 } else {
670 ret = OsSigTimedWaitNoLock(&setSuspend, NULL, LOS_WAIT_FOREVER);
671 if (ret < 0) {
672 PRINT_ERR("FUNC %s LINE = %d, ret = %x\n", __FUNCTION__, __LINE__, ret);
673 }
674 }
675
676 SCHEDULER_UNLOCK(intSave);
677 return -EINTR;
678 }
679
OsSigAction(int sig,const sigaction_t * act,sigaction_t * oact)680 int OsSigAction(int sig, const sigaction_t *act, sigaction_t *oact)
681 {
682 UINTPTR addr;
683 sigaction_t action;
684
685 if (!GOOD_SIGNO(sig) || sig < 1 || act == NULL) {
686 return -EINVAL;
687 }
688 if (LOS_ArchCopyFromUser(&action, act, sizeof(sigaction_t)) != LOS_OK) {
689 return -EFAULT;
690 }
691
692 if (sig == SIGSYS) {
693 addr = OsGetSigHandler();
694 if (addr == 0) {
695 OsSetSigHandler((unsigned long)(UINTPTR)action.sa_handler);
696 return LOS_OK;
697 }
698 return -EINVAL;
699 }
700
701 return LOS_OK;
702 }
703
OsSigIntLock(VOID)704 VOID OsSigIntLock(VOID)
705 {
706 LosTaskCB *task = OsCurrTaskGet();
707 sig_cb *sigcb = &task->sig;
708
709 (VOID)LOS_AtomicAdd((Atomic *)&sigcb->sigIntLock, 1);
710 }
711
OsSigIntUnlock(VOID)712 VOID OsSigIntUnlock(VOID)
713 {
714 LosTaskCB *task = OsCurrTaskGet();
715 sig_cb *sigcb = &task->sig;
716
717 (VOID)LOS_AtomicSub((Atomic *)&sigcb->sigIntLock, 1);
718 }
719
OsSaveSignalContext(VOID * sp,VOID * newSp)720 VOID *OsSaveSignalContext(VOID *sp, VOID *newSp)
721 {
722 UINTPTR sigHandler;
723 UINT32 intSave;
724
725 LosTaskCB *task = OsCurrTaskGet();
726 LosProcessCB *process = OsCurrProcessGet();
727 sig_cb *sigcb = &task->sig;
728
729 /* A thread is not allowed to interrupt the processing of its signals during a system call */
730 if (sigcb->sigIntLock > 0) {
731 return sp;
732 }
733
734 if (OsTaskIsKilled(task)) {
735 OsRunningTaskToExit(task, 0);
736 return sp;
737 }
738
739 SCHEDULER_LOCK(intSave);
740 if ((sigcb->count == 0) && ((sigcb->sigFlag != 0) || (process->sigShare != 0))) {
741 sigHandler = OsGetSigHandler();
742 if (sigHandler == 0) {
743 sigcb->sigFlag = 0;
744 process->sigShare = 0;
745 SCHEDULER_UNLOCK(intSave);
746 PRINT_ERR("The signal processing function for the current process pid =%d is NULL!\n", process->processID);
747 return sp;
748 }
749 /* One pthread do the share signal */
750 sigcb->sigFlag |= process->sigShare;
751 UINT32 signo = (UINT32)FindFirstSetedBit(sigcb->sigFlag) + 1;
752 UINT32 sigVal = (UINT32)(UINTPTR)(sigcb->sigunbinfo.si_value.sival_ptr);
753 OsMoveTmpInfoToUnbInfo(sigcb, signo);
754 OsProcessExitCodeSignalSet(process, signo);
755 sigcb->sigContext = sp;
756
757 OsInitSignalContext(sp, newSp, sigHandler, signo, sigVal);
758
759 /* sig No bits 00000100 present sig No 3, but 1<< 3 = 00001000, so signo needs minus 1 */
760 sigcb->sigFlag ^= 1ULL << (signo - 1);
761 sigcb->count++;
762 SCHEDULER_UNLOCK(intSave);
763 return newSp;
764 }
765
766 SCHEDULER_UNLOCK(intSave);
767 return sp;
768 }
769
OsRestorSignalContext(VOID * sp)770 VOID *OsRestorSignalContext(VOID *sp)
771 {
772 UINT32 intSave;
773
774 LosTaskCB *task = OsCurrTaskGet();
775 sig_cb *sigcb = &task->sig;
776
777 SCHEDULER_LOCK(intSave);
778 if (sigcb->count != 1) {
779 SCHEDULER_UNLOCK(intSave);
780 PRINT_ERR("sig error count : %d\n", sigcb->count);
781 return sp;
782 }
783
784 LosProcessCB *process = OsCurrProcessGet();
785 VOID *saveContext = sigcb->sigContext;
786 sigcb->sigContext = NULL;
787 sigcb->count--;
788 process->sigShare = 0;
789 OsProcessExitCodeSignalClear(process);
790 SCHEDULER_UNLOCK(intSave);
791 return saveContext;
792 }
793
794 #endif
795