1
0
Fork 0
forked from nuttx/nuttx-update

waitpid: CRITICAL BUGFIX. Add a reference counting mechansim to prevent wait from using stale memory that was freed by the exiting task

This commit is contained in:
Gregory Nutt 2015-12-22 11:48:17 -06:00
parent 8f540fd81a
commit b90da3f27b
13 changed files with 44 additions and 85 deletions

View file

@ -11244,4 +11244,7 @@
Entinger (2015-12-15).
* configs/launchxl-tms57004: Add basic board support for TI LaunchXL-
TMS57004. Not much to see there yet (2015-12-15).
* waitpid: CRITICAL BUGFIX. Add a reference count to prevent waitpid
from using stale memory released by the waited-for task group
(2015-12-22).

2
arch

@ -1 +1 @@
Subproject commit a8666b5bb6841d514d1fccedb0071df38d78217a
Subproject commit 1519d53e182663632e4b115baa1b3b15ce9840a3

@ -1 +1 @@
Subproject commit 196f9f3f3f067ccb3c285078a704a2a5eb37b7ea
Subproject commit b30cbace6afab3caed2dcfec09071af60a2b0d7f

View file

@ -154,6 +154,7 @@
#define GROUP_FLAG_NOCLDWAIT (1 << 0) /* Bit 0: Do not retain child exit status */
#define GROUP_FLAG_ADDRENV (1 << 1) /* Bit 1: Group has an address environment */
#define GROUP_FLAG_PRIVILEGED (1 << 2) /* Bit 2: Group is privileged */
#define GROUP_FLAG_DELETED (1 << 3) /* Bit 3: Group has been deleted but not yet freed */
/* Values for struct child_status_s ch_flags */
@ -418,6 +419,7 @@ struct task_group_s
/* waitpid support ************************************************************/
/* Simple mechanism used only when there is no support for SIGCHLD */
uint8_t tg_nwaiters; /* Number of waiters */
sem_t tg_exitsem; /* Support for waitpid */
int *tg_statloc; /* Location to return exit status */
#endif

View file

@ -44,14 +44,6 @@
#include <nuttx/mm/mm.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/

View file

@ -43,10 +43,6 @@
#include <nuttx/mm/mm.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/

View file

@ -42,6 +42,10 @@ CSRCS += task_reparent.c
ifeq ($(CONFIG_SCHED_CHILD_STATUS),y)
CSRCS += group_childstatus.c
endif
else
ifeq ($(CONFIG_SCHED_WAITPID),y)
CSRCS += group_waiter.c
endif
endif
ifeq ($(CONFIG_ARCH_ADDRENV),y)

View file

@ -1,7 +1,7 @@
/****************************************************************************
* sched/group/group.h
*
* Copyright (C) 2007-2013 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2013, 2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -102,6 +102,10 @@ int group_bind(FAR struct pthread_tcb_s *tcb);
int group_join(FAR struct pthread_tcb_s *tcb);
#endif
void group_leave(FAR struct tcb_s *tcb);
#if defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_SCHED_HAVE_PARENT)
void group_addwaiter(FAR struct task_group_s *group);
void group_delwaiter(FAR struct task_group_s *group);
#endif
#if defined(HAVE_GROUP_MEMBERS) || defined(CONFIG_ARCH_ADDRENV)
FAR struct task_group_s *group_findbygid(gid_t gid);

View file

@ -50,26 +50,6 @@
#if (defined(CONFIG_BUILD_PROTECTED) || defined(CONFIG_BUILD_KERNEL)) && \
defined(CONFIG_MM_KERNEL_HEAP)
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Type Declarations
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Variables
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
@ -100,7 +80,7 @@ void group_free(FAR struct task_group_s *group, FAR void *mem)
{
/* It is a privileged group... use the kernel mode memory allocator */
return kmm_free(mem);
kmm_free(mem);
}
else
{
@ -108,7 +88,7 @@ void group_free(FAR struct task_group_s *group, FAR void *mem)
* allocator.
*/
return kumm_free(mem);
kumm_free(mem);
}
}

View file

@ -1,7 +1,7 @@
/****************************************************************************
* sched/group/group_leave.c
*
* Copyright (C) 2013-2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2013-2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -56,18 +56,6 @@
#ifdef HAVE_TASK_GROUP
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
@ -271,9 +259,23 @@ static inline void group_release(FAR struct task_group_s *group)
# endif
#endif
/* Release the group container itself */
#if defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_SCHED_HAVE_PARENT)
/* If there are threads waiting for this group to be freed, then we cannot
* yet free the memory resources. Instead just mark the group deleted
* and wait for those threads complete their waits.
*/
sched_kfree(group);
if (group->tg_nwaiters > 0)
{
group->tg_flags |= GROUP_FLAG_DELETED;
}
else
#endif
{
/* Release the group container itself */
sched_kfree(group);
}
}
/****************************************************************************

View file

@ -51,10 +51,6 @@
#ifdef CONFIG_SCHED_WAITPID
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
@ -217,6 +213,10 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
group = ctcb->group;
DEBUGASSERT(group);
/* Lock this group so that it cannot be deleted until the wait completes */
group_addwaiter(group);
/* "If more than one thread is suspended in waitpid() awaiting termination of
* the same process, exactly one thread will return the process status at the
* time of the target process termination." Hmmm.. what do we return to the
@ -236,6 +236,8 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
/* Don't wait if status is not available */
ret = sem_trywait(&group->tg_exitsem);
group_delwaiter(group);
if (ret < 0)
{
pid = 0;
@ -246,6 +248,8 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
/* Wait if necessary for status to become available */
ret = sem_wait(&group->tg_exitsem);
group_delwaiter(group);
if (ret < 0)
{
/* Unlock pre-emption and return the ERROR (sem_wait has already set

View file

@ -68,11 +68,7 @@ typedef int (*holderhandler_t)(FAR struct semholder_s *pholder,
FAR sem_t *sem, FAR void *arg);
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Variables
* Private Data
****************************************************************************/
/* Preallocated holder structures */
@ -82,10 +78,6 @@ static struct semholder_s g_holderalloc[CONFIG_SEM_PREALLOCHOLDERS];
static FAR struct semholder_s *g_freeholders;
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: sem_allocholder
****************************************************************************/

View file

@ -48,26 +48,6 @@
#include "sched/sched.h"
#include "semaphore/semaphore.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Type Declarations
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Variables
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/