From a8de85de0b18e17ea4d9aa24d790b0949df4e7c7 Mon Sep 17 00:00:00 2001 From: chao an Date: Tue, 26 Mar 2024 09:15:32 +0800 Subject: [PATCH] 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 --- sched/signal/sig_dispatch.c | 12 ++++++++++-- sched/signal/sig_timedwait.c | 32 ++++++++++++++++++++------------ 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/sched/signal/sig_dispatch.c b/sched/signal/sig_dispatch.c index a657a92a923..45744cb9f57 100644 --- a/sched/signal/sig_dispatch.c +++ b/sched/signal/sig_dispatch.c @@ -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)) diff --git a/sched/signal/sig_timedwait.c b/sched/signal/sig_timedwait.c index 9bbef85438b..1b7985deebd 100644 --- a/sched/signal/sig_timedwait.c +++ b/sched/signal/sig_timedwait.c @@ -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; }