fix: init进程收到子进程退出信号后,调用fork重新拉起进程,会导致系统卡死

问题原因:init进程执行信号时,线程栈底预留了部分空间给信号上下文使用,
从而导致处理信号时线程栈底比线程控制块里面记录的大,这样在fork的过程中内核
从init线程栈底copy线程上下文给新进程时,copy的不是实际运行的栈底,以致于
新进程的线程上下文不对,在实际运行时跑飞,引发系统卡死。
解决方案:在fork过程copy线程上下文时,判断是否预留了信号上下文空间,如果预留
了,则copy的栈底要基于预留后的栈底去copy线程上下文。

close: #I41HOY

Signed-off-by: zff <zhangfanfan2@huawei.com>
Change-Id: I61cb05183c78919730e3a68c1c85b72fa1decd16
This commit is contained in:
YOUR_NAME 2021-07-20 18:21:36 +08:00
parent c40e1464b9
commit 35a2f3af33
2 changed files with 10 additions and 1 deletions

View File

@ -105,7 +105,15 @@ LITE_OS_SEC_TEXT_INIT VOID *OsTaskStackInit(UINT32 taskID, UINT32 stackSize, VOI
LITE_OS_SEC_TEXT VOID OsUserCloneParentStack(VOID *childStack, UINTPTR parentTopOfStack, UINT32 parentStackSize) LITE_OS_SEC_TEXT VOID OsUserCloneParentStack(VOID *childStack, UINTPTR parentTopOfStack, UINT32 parentStackSize)
{ {
VOID *cloneStack = (VOID *)(((UINTPTR)parentTopOfStack + parentStackSize) - sizeof(TaskContext)); LosTaskCB *task = OsCurrTaskGet();
sig_cb *sigcb = &task->sig;
VOID *cloneStack = NULL;
if (sigcb->sigContext != NULL) {
cloneStack = (VOID *)((UINTPTR)sigcb->sigContext - sizeof(TaskContext));
} else {
cloneStack = (VOID *)(((UINTPTR)parentTopOfStack + parentStackSize) - sizeof(TaskContext));
}
(VOID)memcpy_s(childStack, sizeof(TaskContext), cloneStack, sizeof(TaskContext)); (VOID)memcpy_s(childStack, sizeof(TaskContext), cloneStack, sizeof(TaskContext));
((TaskContext *)childStack)->R0 = 0; ((TaskContext *)childStack)->R0 = 0;

View File

@ -678,6 +678,7 @@ VOID *OsRestorSignalContext(VOID *sp)
LosProcessCB *process = OsCurrProcessGet(); LosProcessCB *process = OsCurrProcessGet();
VOID *saveContext = sigcb->sigContext; VOID *saveContext = sigcb->sigContext;
sigcb->sigContext = NULL;
sigcb->count--; sigcb->count--;
process->sigShare = 0; process->sigShare = 0;
OsProcessExitCodeSignalClear(process); OsProcessExitCodeSignalClear(process);