Fix flaw in thread creation APIs

The arguments passed to the thread function must be allocated on
the heap, rather than the stack, since it is possible for the
spawning thread to continue before the new thread runs at all.
In such a case, it is possible that the area of stack where the
thread args were stored is overwritten.

* src/util/threads-pthread.c, src/util/threads-win32.c: Allocate
  thread arguments on the heap
This commit is contained in:
Daniel P. Berrange 2010-12-01 11:23:07 +00:00
parent 33e38e7710
commit 9c65609247
2 changed files with 27 additions and 5 deletions

View File

@ -26,6 +26,8 @@
# include <sys/syscall.h>
#endif
#include "memory.h"
/* Nothing special required for pthreads */
int virThreadInitialize(void)
@ -143,6 +145,7 @@ static void *virThreadHelper(void *data)
{
struct virThreadArgs *args = data;
args->func(args->opaque);
VIR_FREE(args);
return NULL;
}
@ -151,17 +154,25 @@ int virThreadCreate(virThreadPtr thread,
virThreadFunc func,
void *opaque)
{
struct virThreadArgs args = { func, opaque };
struct virThreadArgs *args;
pthread_attr_t attr;
pthread_attr_init(&attr);
if (VIR_ALLOC(args) < 0)
return -1;
args->func = func;
args->opaque = opaque;
if (!joinable)
pthread_attr_setdetachstate(&attr, 1);
int ret = pthread_create(&thread->thread, &attr, virThreadHelper, &args);
int ret = pthread_create(&thread->thread, &attr, virThreadHelper, args);
if (ret != 0) {
VIR_FREE(args);
errno = ret;
return -1;
}
/* New thread owns 'args' in success case, so don't free */
return 0;
}

View File

@ -230,6 +230,8 @@ static void virThreadHelperDaemon(void *data)
TlsSetValue(selfkey, NULL);
CloseHandle(self.thread);
VIR_FREE(args);
}
static unsigned int __stdcall virThreadHelperJoinable(void *data)
@ -249,6 +251,8 @@ static unsigned int __stdcall virThreadHelperJoinable(void *data)
TlsSetValue(selfkey, NULL);
CloseHandle(self.thread);
VIR_FREE(args);
return 0;
}
@ -257,17 +261,24 @@ int virThreadCreate(virThreadPtr thread,
virThreadFunc func,
void *opaque)
{
struct virThreadArgs args = { func, opaque };
struct virThreadArgs *args;
if (VIR_ALLOC(args) < 0)
return -1;
args->func = func;
args->opaque = opaque;
thread->joinable = joinable;
if (joinable) {
thread->thread = (HANDLE)_beginthreadex(NULL, 0,
virThreadHelperJoinable,
&args, 0, NULL);
args, 0, NULL);
if (thread->thread == 0)
return -1;
} else {
thread->thread = (HANDLE)_beginthread(virThreadHelperDaemon,
0, &args);
0, args);
if (thread->thread == (HANDLE)-1L)
return -1;
}