mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-02-28 03:27:46 +08:00
* cygheap.cc (init_cygheap::find_tls): Add comment.
* cygtls.cc (well_known_dlls): Rephrase comment. (bloda_detect): New function. (_cygtls::call2): Call init_thread and bloda_detect for non-pthread threads only. (_cygtls::remove): Move remove_tls and remove_wq calls up to run first. * miscfuncs.cc (struct pthread_wrapper_arg): Rename from struct thread_wrapper_arg. (pthread_wrapper): Rename from thread_wrapper and drop "static". Fix comment. Drop call to _cygtls::remove. Call api_fatal rather than ExitThread. Explain why. * miscfuncs.h (pthread_wrapper): Declare pthread_wrapper. * thread.cc (pthread::exit): Add a FIXME comment. Call _cygtls::remove before calling ExitThread.
This commit is contained in:
parent
b3281dd194
commit
9d2eff6684
@ -1,3 +1,20 @@
|
|||||||
|
2014-11-28 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* cygheap.cc (init_cygheap::find_tls): Add comment.
|
||||||
|
* cygtls.cc (well_known_dlls): Rephrase comment.
|
||||||
|
(bloda_detect): New function.
|
||||||
|
(_cygtls::call2): Call init_thread and bloda_detect for non-pthread
|
||||||
|
threads only.
|
||||||
|
(_cygtls::remove): Move remove_tls and remove_wq calls up to run first.
|
||||||
|
* miscfuncs.cc (struct pthread_wrapper_arg): Rename from struct
|
||||||
|
thread_wrapper_arg.
|
||||||
|
(pthread_wrapper): Rename from thread_wrapper and drop "static". Fix
|
||||||
|
comment. Drop call to _cygtls::remove. Call api_fatal rather than
|
||||||
|
ExitThread. Explain why.
|
||||||
|
* miscfuncs.h (pthread_wrapper): Declare pthread_wrapper.
|
||||||
|
* thread.cc (pthread::exit): Add a FIXME comment. Call _cygtls::remove
|
||||||
|
before calling ExitThread.
|
||||||
|
|
||||||
2014-11-27 Corinna Vinschen <corinna@vinschen.de>
|
2014-11-27 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* mount.cc (mount_info::init): Take bool argument and allow to
|
* mount.cc (mount_info::init): Take bool argument and allow to
|
||||||
|
@ -673,6 +673,7 @@ init_cygheap::find_tls (int sig, bool& issig_wait)
|
|||||||
{
|
{
|
||||||
__try
|
__try
|
||||||
{
|
{
|
||||||
|
/* Only pthreads have tid set to non-0. */
|
||||||
if (!threadlist[ix]->tid)
|
if (!threadlist[ix]->tid)
|
||||||
continue;
|
continue;
|
||||||
else if (sigismember (&(threadlist[ix]->sigwait_mask), sig))
|
else if (sigismember (&(threadlist[ix]->sigwait_mask), sig))
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* cygtls.cc
|
/* cygtls.cc
|
||||||
|
|
||||||
Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012,
|
Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012,
|
||||||
2013 Red Hat, Inc.
|
2013, 2014 Red Hat, Inc.
|
||||||
|
|
||||||
This software is a copyrighted work licensed under the terms of the
|
This software is a copyrighted work licensed under the terms of the
|
||||||
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||||
@ -38,10 +38,9 @@ dll_cmp (const void *a, const void *b)
|
|||||||
|
|
||||||
/* Keep sorted!
|
/* Keep sorted!
|
||||||
This is a list of well-known core system DLLs which contain code
|
This is a list of well-known core system DLLs which contain code
|
||||||
whiuch is started in its own thread by the system. Kernel32.dll,
|
started in its own thread by the system. Kernel32.dll, for instance,
|
||||||
for instance, contains the thread called on every Ctrl-C keypress
|
contains the thread called on every Ctrl-C keypress in a console window.
|
||||||
in a console window. The DLLs in this list are not recognized as
|
The DLLs in this list are not recognized as BLODAs. */
|
||||||
BLODAs. */
|
|
||||||
const wchar_t *well_known_dlls[] =
|
const wchar_t *well_known_dlls[] =
|
||||||
{
|
{
|
||||||
L"advapi32.dll",
|
L"advapi32.dll",
|
||||||
@ -55,46 +54,58 @@ const wchar_t *well_known_dlls[] =
|
|||||||
L"ws2_32.dll",
|
L"ws2_32.dll",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Optional BLODA detection. The idea is that the function address is supposed
|
||||||
|
to be within Cygwin itself. This is also true for pthreads, since pthreads
|
||||||
|
are always calling pthread::thread_init_wrapper() in thread.cc. Therefore,
|
||||||
|
every function call to a function outside of the Cygwin DLL is potentially
|
||||||
|
a thread injected into the Cygwin process by some BLODA.
|
||||||
|
|
||||||
|
But that's too simple. Assuming the application itself calls CreateThread,
|
||||||
|
then this is a bad idea, but not really invalid. So we shouldn't print a
|
||||||
|
BLODA message if the address is within the loaded image of the application.
|
||||||
|
Also, ntdll.dll starts threads into the application which */
|
||||||
|
static void
|
||||||
|
bloda_detect (DWORD (*func) (void *, void *))
|
||||||
|
{
|
||||||
|
PIMAGE_DOS_HEADER img_start = (PIMAGE_DOS_HEADER)
|
||||||
|
GetModuleHandle (NULL);
|
||||||
|
PIMAGE_NT_HEADERS32 ntheader = (PIMAGE_NT_HEADERS32)
|
||||||
|
((PBYTE) img_start + img_start->e_lfanew);
|
||||||
|
void *img_end = (void *) ((PBYTE) img_start
|
||||||
|
+ ntheader->OptionalHeader.SizeOfImage);
|
||||||
|
if (((void *) func < (void *) cygwin_hmodule
|
||||||
|
|| (void *) func > (void *) cygheap)
|
||||||
|
&& ((void *) func < (void *) img_start || (void *) func >= img_end))
|
||||||
|
{
|
||||||
|
MEMORY_BASIC_INFORMATION mbi;
|
||||||
|
wchar_t modname[PATH_MAX];
|
||||||
|
|
||||||
|
VirtualQuery ((PVOID) func, &mbi, sizeof mbi);
|
||||||
|
GetModuleFileNameW ((HMODULE) mbi.AllocationBase, modname,
|
||||||
|
PATH_MAX);
|
||||||
|
/* Fetch basename and check against list of above system DLLs. */
|
||||||
|
const wchar_t *modbasename = wcsrchr (modname, L'\\') + 1;
|
||||||
|
if (!bsearch (modbasename, well_known_dlls,
|
||||||
|
sizeof well_known_dlls / sizeof well_known_dlls[0],
|
||||||
|
sizeof well_known_dlls[0], dll_cmp))
|
||||||
|
small_printf ("\n\nPotential BLODA detected! Thread function "
|
||||||
|
"called outside of Cygwin DLL:\n %W\n\n",
|
||||||
|
modname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cygtls::call2 (DWORD (*func) (void *, void *), void *arg, void *buf)
|
_cygtls::call2 (DWORD (*func) (void *, void *), void *arg, void *buf)
|
||||||
{
|
{
|
||||||
init_thread (buf, func);
|
/* If func is pthread_wrapper, the final stack hasn't been set up yet.
|
||||||
|
This only happens in pthread_wrapper itself. Thus it doesn't make
|
||||||
/* Optional BLODA detection. The idea is that the function address is
|
sense to call init_thread or perform BLODA detection. pthread_wrapper
|
||||||
supposed to be within Cygwin itself. This is also true for pthreads,
|
eventually calls init_thread by itself. */
|
||||||
since pthreads are always calling thread_wrapper in miscfuncs.cc.
|
if ((void *) func != (void *) pthread_wrapper)
|
||||||
Therefore, every function call to a function outside of the Cygwin DLL
|
|
||||||
is potentially a thread injected into the Cygwin process by some BLODA.
|
|
||||||
|
|
||||||
But that's a bit too simple. Assuming the application itself calls
|
|
||||||
CreateThread, then this is a bad idea, but not really invalid. So we
|
|
||||||
shouldn't print a BLODA message if the address is within the loaded
|
|
||||||
image of the application. Also, ntdll.dll starts threads into the
|
|
||||||
application which */
|
|
||||||
if (detect_bloda)
|
|
||||||
{
|
{
|
||||||
PIMAGE_DOS_HEADER img_start = (PIMAGE_DOS_HEADER) GetModuleHandle (NULL);
|
init_thread (buf, func);
|
||||||
PIMAGE_NT_HEADERS32 ntheader = (PIMAGE_NT_HEADERS32)
|
if (detect_bloda)
|
||||||
((PBYTE) img_start + img_start->e_lfanew);
|
bloda_detect (func);
|
||||||
void *img_end = (void *) ((PBYTE) img_start
|
|
||||||
+ ntheader->OptionalHeader.SizeOfImage);
|
|
||||||
if (((void *) func < (void *) cygwin_hmodule
|
|
||||||
|| (void *) func > (void *) cygheap)
|
|
||||||
&& ((void *) func < (void *) img_start || (void *) func >= img_end))
|
|
||||||
{
|
|
||||||
MEMORY_BASIC_INFORMATION mbi;
|
|
||||||
wchar_t modname[PATH_MAX];
|
|
||||||
|
|
||||||
VirtualQuery ((PVOID) func, &mbi, sizeof mbi);
|
|
||||||
GetModuleFileNameW ((HMODULE) mbi.AllocationBase, modname, PATH_MAX);
|
|
||||||
/* Fetch basename and check against list of above system DLLs. */
|
|
||||||
const wchar_t *modbasename = wcsrchr (modname, L'\\') + 1;
|
|
||||||
if (!bsearch (modbasename, well_known_dlls,
|
|
||||||
sizeof well_known_dlls / sizeof well_known_dlls[0],
|
|
||||||
sizeof well_known_dlls[0], dll_cmp))
|
|
||||||
small_printf ("\n\nPotential BLODA detected! Thread function "
|
|
||||||
"called outside of Cygwin DLL:\n %W\n\n", modname);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD res = func (arg, buf);
|
DWORD res = func (arg, buf);
|
||||||
@ -169,6 +180,9 @@ _cygtls::remove (DWORD wait)
|
|||||||
|
|
||||||
debug_printf ("wait %u", wait);
|
debug_printf ("wait %u", wait);
|
||||||
|
|
||||||
|
cygheap->remove_tls (this, INFINITE);
|
||||||
|
remove_wq (wait);
|
||||||
|
|
||||||
/* FIXME: Need some sort of atthreadexit function to allow things like
|
/* FIXME: Need some sort of atthreadexit function to allow things like
|
||||||
select to control this themselves. */
|
select to control this themselves. */
|
||||||
|
|
||||||
@ -197,8 +211,6 @@ _cygtls::remove (DWORD wait)
|
|||||||
/* Close timer handle. */
|
/* Close timer handle. */
|
||||||
if (locals.cw_timer)
|
if (locals.cw_timer)
|
||||||
NtClose (locals.cw_timer);
|
NtClose (locals.cw_timer);
|
||||||
cygheap->remove_tls (this, wait);
|
|
||||||
remove_wq (wait);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
|
@ -540,7 +540,7 @@ __import_address (void *imp)
|
|||||||
parameters we don't use and instead to add parameters we need to make
|
parameters we don't use and instead to add parameters we need to make
|
||||||
the function pthreads compatible. */
|
the function pthreads compatible. */
|
||||||
|
|
||||||
struct thread_wrapper_arg
|
struct pthread_wrapper_arg
|
||||||
{
|
{
|
||||||
LPTHREAD_START_ROUTINE func;
|
LPTHREAD_START_ROUTINE func;
|
||||||
PVOID arg;
|
PVOID arg;
|
||||||
@ -549,23 +549,20 @@ struct thread_wrapper_arg
|
|||||||
PBYTE stacklimit;
|
PBYTE stacklimit;
|
||||||
};
|
};
|
||||||
|
|
||||||
static DWORD WINAPI
|
DWORD WINAPI
|
||||||
thread_wrapper (PVOID arg)
|
pthread_wrapper (PVOID arg)
|
||||||
{
|
{
|
||||||
/* Just plain paranoia. */
|
/* Just plain paranoia. */
|
||||||
if (!arg)
|
if (!arg)
|
||||||
return ERROR_INVALID_PARAMETER;
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
/* The process is now threaded. Note the fact for later usage. */
|
/* The process is now threaded. Note for later usage by arc4random. */
|
||||||
__isthreaded = 1;
|
__isthreaded = 1;
|
||||||
|
|
||||||
/* Fetch thread wrapper info and free from cygheap. */
|
/* Fetch thread wrapper info and free from cygheap. */
|
||||||
thread_wrapper_arg wrapper_arg = *(thread_wrapper_arg *) arg;
|
pthread_wrapper_arg wrapper_arg = *(pthread_wrapper_arg *) arg;
|
||||||
cfree (arg);
|
cfree (arg);
|
||||||
|
|
||||||
/* Remove _cygtls from this stack since it won't be used anymore. */
|
|
||||||
_my_tls.remove (0);
|
|
||||||
|
|
||||||
/* Set stack values in TEB */
|
/* Set stack values in TEB */
|
||||||
PTEB teb = NtCurrentTeb ();
|
PTEB teb = NtCurrentTeb ();
|
||||||
teb->Tib.StackBase = wrapper_arg.stackbase;
|
teb->Tib.StackBase = wrapper_arg.stackbase;
|
||||||
@ -676,8 +673,9 @@ thread_wrapper (PVOID arg)
|
|||||||
: : [WRAPPER_ARG] "r" (&wrapper_arg),
|
: : [WRAPPER_ARG] "r" (&wrapper_arg),
|
||||||
[CYGTLS] "i" (CYGTLS_PADSIZE));
|
[CYGTLS] "i" (CYGTLS_PADSIZE));
|
||||||
#endif
|
#endif
|
||||||
/* Never return from here. */
|
/* pthread::thread_init_wrapper calls pthread::exit, which
|
||||||
ExitThread (0);
|
in turn calls ExitThread, so we should never arrive here. */
|
||||||
|
api_fatal ("Dumb thinko in pthread handling. Whip the developer.");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
@ -751,10 +749,10 @@ CygwinCreateThread (LPTHREAD_START_ROUTINE thread_func, PVOID thread_arg,
|
|||||||
PVOID real_stackaddr = NULL;
|
PVOID real_stackaddr = NULL;
|
||||||
ULONG real_stacksize = 0;
|
ULONG real_stacksize = 0;
|
||||||
ULONG real_guardsize = 0;
|
ULONG real_guardsize = 0;
|
||||||
thread_wrapper_arg *wrapper_arg;
|
pthread_wrapper_arg *wrapper_arg;
|
||||||
HANDLE thread = NULL;
|
HANDLE thread = NULL;
|
||||||
|
|
||||||
wrapper_arg = (thread_wrapper_arg *) ccalloc (HEAP_STR, 1,
|
wrapper_arg = (pthread_wrapper_arg *) ccalloc (HEAP_STR, 1,
|
||||||
sizeof *wrapper_arg);
|
sizeof *wrapper_arg);
|
||||||
if (!wrapper_arg)
|
if (!wrapper_arg)
|
||||||
{
|
{
|
||||||
@ -846,7 +844,7 @@ CygwinCreateThread (LPTHREAD_START_ROUTINE thread_func, PVOID thread_arg,
|
|||||||
reserve a 256K stack, not 64K, otherwise the thread creation might
|
reserve a 256K stack, not 64K, otherwise the thread creation might
|
||||||
crash the process due to a stack overflow. */
|
crash the process due to a stack overflow. */
|
||||||
thread = CreateThread (&sec_none_nih, 4 * PTHREAD_STACK_MIN,
|
thread = CreateThread (&sec_none_nih, 4 * PTHREAD_STACK_MIN,
|
||||||
thread_wrapper, wrapper_arg,
|
pthread_wrapper, wrapper_arg,
|
||||||
creation_flags | STACK_SIZE_PARAM_IS_A_RESERVATION,
|
creation_flags | STACK_SIZE_PARAM_IS_A_RESERVATION,
|
||||||
thread_id);
|
thread_id);
|
||||||
|
|
||||||
|
@ -66,6 +66,7 @@ ssize_t __reg3 check_iovec (const struct iovec *, int, bool);
|
|||||||
#define check_iovec_for_read(a, b) check_iovec ((a), (b), false)
|
#define check_iovec_for_read(a, b) check_iovec ((a), (b), false)
|
||||||
#define check_iovec_for_write(a, b) check_iovec ((a), (b), true)
|
#define check_iovec_for_write(a, b) check_iovec ((a), (b), true)
|
||||||
|
|
||||||
|
extern "C" DWORD WINAPI pthread_wrapper (PVOID arg);
|
||||||
extern "C" HANDLE WINAPI CygwinCreateThread (LPTHREAD_START_ROUTINE thread_func,
|
extern "C" HANDLE WINAPI CygwinCreateThread (LPTHREAD_START_ROUTINE thread_func,
|
||||||
PVOID thread_arg, PVOID stackaddr,
|
PVOID thread_arg, PVOID stackaddr,
|
||||||
ULONG stacksize, ULONG guardsize,
|
ULONG stacksize, ULONG guardsize,
|
||||||
|
@ -543,11 +543,13 @@ pthread::exit (void *value_ptr)
|
|||||||
{
|
{
|
||||||
if (is_main_tls)
|
if (is_main_tls)
|
||||||
{
|
{
|
||||||
|
/* FIXME: Needs locking. */
|
||||||
_cygtls *dummy = (_cygtls *) malloc (sizeof (_cygtls));
|
_cygtls *dummy = (_cygtls *) malloc (sizeof (_cygtls));
|
||||||
*dummy = *_main_tls;
|
*dummy = *_main_tls;
|
||||||
_main_tls = dummy;
|
_main_tls = dummy;
|
||||||
_main_tls->initialized = false;
|
_main_tls->initialized = 0;
|
||||||
}
|
}
|
||||||
|
cygtls->remove (INFINITE);
|
||||||
ExitThread (0);
|
ExitThread (0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user