sched/signal: add sanity check for siginfo

add sanity check for siginfo to ensure whether there is really a
consumer waiting for the signal, since the task state will not be
changed appropriately if in cancel/killed case

Test Case:
https://github.com/linux-test-project/ltp/blob/master/testcases/open_posix_testsuite/conformance/interfaces/sigpause/1-1.c#L63

Signed-off-by: chao an <anchao@lixiang.com>
This commit is contained in:
chao an
2024-03-26 09:15:32 +08:00
committed by Xiang Xiao
parent 33485cfe7c
commit a8de85de0b
2 changed files with 30 additions and 14 deletions
+10 -2
View File
@@ -398,7 +398,11 @@ int nxsig_tcbdispatch(FAR struct tcb_s *stcb, siginfo_t *info)
(masked == 0 ||
nxsig_ismember(&stcb->sigwaitmask, info->si_signo)))
{
memcpy(stcb->sigunbinfo, info, sizeof(siginfo_t));
if (stcb->sigunbinfo != NULL)
{
memcpy(stcb->sigunbinfo, info, sizeof(siginfo_t));
}
sigemptyset(&stcb->sigwaitmask);
if (WDOG_ISACTIVE(&stcb->waitdog))
@@ -461,7 +465,11 @@ int nxsig_tcbdispatch(FAR struct tcb_s *stcb, siginfo_t *info)
if (stcb->task_state == TSTATE_WAIT_SIG)
{
memcpy(stcb->sigunbinfo, info, sizeof(siginfo_t));
if (stcb->sigunbinfo != NULL)
{
memcpy(stcb->sigunbinfo, info, sizeof(siginfo_t));
}
sigemptyset(&stcb->sigwaitmask);
if (WDOG_ISACTIVE(&stcb->waitdog))
+20 -12
View File
@@ -99,14 +99,17 @@ static void nxsig_timeout(wdparm_t arg)
{
FAR struct tcb_s *rtcb = this_task();
wtcb->sigunbinfo->si_signo = SIG_WAIT_TIMEOUT;
wtcb->sigunbinfo->si_code = SI_TIMER;
wtcb->sigunbinfo->si_errno = ETIMEDOUT;
wtcb->sigunbinfo->si_value.sival_int = 0;
if (wtcb->sigunbinfo != NULL)
{
wtcb->sigunbinfo->si_signo = SIG_WAIT_TIMEOUT;
wtcb->sigunbinfo->si_code = SI_TIMER;
wtcb->sigunbinfo->si_errno = ETIMEDOUT;
wtcb->sigunbinfo->si_value.sival_int = 0;
#ifdef CONFIG_SCHED_HAVE_PARENT
wtcb->sigunbinfo->si_pid = 0; /* Not applicable */
wtcb->sigunbinfo->si_status = OK;
wtcb->sigunbinfo->si_pid = 0; /* Not applicable */
wtcb->sigunbinfo->si_status = OK;
#endif
}
/* Remove the task from waitting list */
@@ -166,14 +169,17 @@ void nxsig_wait_irq(FAR struct tcb_s *wtcb, int errcode)
{
FAR struct tcb_s *rtcb = this_task();
wtcb->sigunbinfo->si_signo = SIG_CANCEL_TIMEOUT;
wtcb->sigunbinfo->si_code = SI_USER;
wtcb->sigunbinfo->si_errno = errcode;
wtcb->sigunbinfo->si_value.sival_int = 0;
if (wtcb->sigunbinfo != NULL)
{
wtcb->sigunbinfo->si_signo = SIG_CANCEL_TIMEOUT;
wtcb->sigunbinfo->si_code = SI_USER;
wtcb->sigunbinfo->si_errno = errcode;
wtcb->sigunbinfo->si_value.sival_int = 0;
#ifdef CONFIG_SCHED_HAVE_PARENT
wtcb->sigunbinfo->si_pid = 0; /* Not applicable */
wtcb->sigunbinfo->si_status = OK;
wtcb->sigunbinfo->si_pid = 0; /* Not applicable */
wtcb->sigunbinfo->si_status = OK;
#endif
}
/* Remove the task from waitting list */
@@ -376,6 +382,8 @@ int nxsig_timedwait(FAR const sigset_t *set, FAR struct siginfo *info,
}
else
{
rtcb->sigunbinfo = NULL;
leave_critical_section(flags);
return -EAGAIN;
}