mirror of
https://github.com/espressif/ESP8266_RTOS_SDK.git
synced 2025-12-14 01:08:49 +08:00
fix(ESPCS-924): Fixed a potential freertos crash
- Reason: A task and B interrupt indirectly access the shared resource pxDelayedTaskList without proper security protection, leading to further crash. A task uses xEventGroupSetBits() to access the pxDelayedTaskList resource: xEventGroupSetBits() -> vTaskRemoveFromUnorderedEventList() -> uxListRemove() -> pxList, where pxList is the pxDelayedTaskList. At this point, another B interrupt is triggered (xEventGroupSetBits only suspends task scheduling and does not disable interrupts) and also accesses the pxDelayedTaskList resource: MacIsrSigPostDefHdl() -> __wifi_queue_send_from_isr() -> xQueueGenericSendFromISR() -> xTaskRemoveFromEventList() -> prvResetNextTaskUnblockTime() -> pxDelayedTaskList. This leads to an unsafe access to the pxDelayedTaskList resource by two entities, causing subsequent crash exceptions. - Fix: Modify the timing of the call to prvResetNextTaskUnblockTime() within xTaskRemoveFromEventList from unconditional execution to only execute when task scheduling is enabled. This way, when the B interrupt reaches xTaskRemoveFromEventList, it will not call prvResetNextTaskUnblockTime to access the pxDelayedTaskList resource (due to task scheduling being disabled). After the B interrupt execution is complete and control returns to A task, xTaskResumeAll() will be called, and then prvResetNextTaskUnblockTime() will update the pxDelayedTaskList resource again.
This commit is contained in:
@@ -3044,6 +3044,19 @@ BaseType_t xReturn;
|
|||||||
{
|
{
|
||||||
( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );
|
( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );
|
||||||
prvAddTaskToReadyList( pxUnblockedTCB );
|
prvAddTaskToReadyList( pxUnblockedTCB );
|
||||||
|
#if( configUSE_TICKLESS_IDLE != 0 )
|
||||||
|
{
|
||||||
|
/* If a task is blocked on a kernel object then xNextTaskUnblockTime
|
||||||
|
might be set to the blocked task's time out time. If the task is
|
||||||
|
unblocked for a reason other than a timeout xNextTaskUnblockTime is
|
||||||
|
normally left unchanged, because it is automatically reset to a new
|
||||||
|
value when the tick count equals xNextTaskUnblockTime. However if
|
||||||
|
tickless idling is used it might be more important to enter sleep mode
|
||||||
|
at the earliest possible time - so reset xNextTaskUnblockTime here to
|
||||||
|
ensure it is updated at the earliest possible time. */
|
||||||
|
prvResetNextTaskUnblockTime();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -3068,20 +3081,6 @@ BaseType_t xReturn;
|
|||||||
xReturn = pdFALSE;
|
xReturn = pdFALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if( configUSE_TICKLESS_IDLE != 0 )
|
|
||||||
{
|
|
||||||
/* If a task is blocked on a kernel object then xNextTaskUnblockTime
|
|
||||||
might be set to the blocked task's time out time. If the task is
|
|
||||||
unblocked for a reason other than a timeout xNextTaskUnblockTime is
|
|
||||||
normally left unchanged, because it is automatically reset to a new
|
|
||||||
value when the tick count equals xNextTaskUnblockTime. However if
|
|
||||||
tickless idling is used it might be more important to enter sleep mode
|
|
||||||
at the earliest possible time - so reset xNextTaskUnblockTime here to
|
|
||||||
ensure it is updated at the earliest possible time. */
|
|
||||||
prvResetNextTaskUnblockTime();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return xReturn;
|
return xReturn;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|||||||
Reference in New Issue
Block a user