mirror of
https://github.com/apache/nuttx.git
synced 2026-05-09 23:12:17 +08:00
sched/group: skip group_release for kernel thread group
When CONFIG_DISABLE_PTHREAD=y, HAVE_GROUP_MEMBERS is undefined and group_leave() unconditionally calls group_release() for every exiting thread. This destroys the shared g_kthread_group resources (mutex, fdlist, task_info) while other kernel threads are still using them, causing use-after-free crashes. Fix by checking TCB_FLAG_TTYPE_KERNEL in group_leave() before calling group_release(), so the entire release path is skipped for kernel threads. This is safe because g_kthread_group is statically allocated and its lifetime is the entire system. Signed-off-by: wangyongrong <wangyongrong@xiaomi.com>
This commit is contained in:
@@ -118,7 +118,7 @@
|
||||
#define GROUP_FLAG_DELETED (1 << 2) /* Bit 2: Group has been deleted but not yet freed */
|
||||
#define GROUP_FLAG_EXITING (1 << 3) /* Bit 3: Group exit is in progress */
|
||||
#define GROUP_FLAG_FD_BACKTRACE (1 << 4) /* Bit 4: Enable FD backtrace for the group */
|
||||
/* Bits 3-7: Available */
|
||||
/* Bits 5-7: Available */
|
||||
|
||||
/* Values for struct child_status_s ch_flags */
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
* Release group resources after the last member has left the group.
|
||||
*
|
||||
* Input Parameters:
|
||||
* group - The group to be removed.
|
||||
* group - The group to be released.
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
@@ -173,17 +173,26 @@ void group_leave(FAR struct tcb_s *tcb)
|
||||
group = tcb->group;
|
||||
if (group)
|
||||
{
|
||||
/* Kernel threads share a single statically allocated g_kthread_group.
|
||||
* Never call group_release() for them: doing so would destroy shared
|
||||
* resources (mutex, fdlist, task_info) while other kernel threads are
|
||||
* still using them, causing use-after-free crashes.
|
||||
*/
|
||||
|
||||
bool release = !(tcb->flags & TCB_FLAG_TTYPE_KERNEL);
|
||||
|
||||
/* Remove the member from group. */
|
||||
|
||||
#ifdef HAVE_GROUP_MEMBERS
|
||||
flags = spin_lock_irqsave(&group->tg_lock);
|
||||
sq_rem(&tcb->member, &group->tg_members);
|
||||
release = release && sq_empty(&group->tg_members);
|
||||
spin_unlock_irqrestore(&group->tg_lock, flags);
|
||||
|
||||
/* Have all of the members left the group? */
|
||||
|
||||
if (sq_empty(&group->tg_members))
|
||||
#endif
|
||||
|
||||
if (release)
|
||||
{
|
||||
/* Yes.. Release all of the resource held by the task group */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user