* cygtls.cc (dll_cmp): New comparison function for bsearch.

(well_known_dlls): New array containing well-known DLLs.
	(_cygtls::call2): Add code for BLODA detection.
	* net.cc (fdsock): Ditto.
This commit is contained in:
Corinna Vinschen 2012-02-27 11:55:27 +00:00
parent d723fb604d
commit 07a6b9dd22
3 changed files with 93 additions and 13 deletions

View File

@ -1,3 +1,10 @@
2012-02-27 Corinna Vinschen <corinna@vinschen.de>
* cygtls.cc (dll_cmp): New comparison function for bsearch.
(well_known_dlls): New array containing well-known DLLs.
(_cygtls::call2): Add code for BLODA detection.
* net.cc (fdsock): Ditto.
2012-02-26 Corinna Vinschen <corinna@vinschen.de>
* environ.cc (enum settings): Add setbool. Rename justset to setdword

View File

@ -1,6 +1,7 @@
/* cygtls.cc
Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Red Hat, Inc.
Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
2012 Red Hat, Inc.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
@ -62,10 +63,68 @@ _cygtls::call (DWORD (*func) (void *, void *), void *arg)
_my_tls.call2 (func, arg, buf);
}
static int
dll_cmp (const void *a, const void *b)
{
return wcscasecmp ((const wchar_t *) a, *(const wchar_t **) b);
}
/* Keep sorted!
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,
for instance, contains the thread called on every Ctrl-C keypress
in a console window. The DLLs in this list are not recognized as
BLODAs. */
const wchar_t *well_known_dlls[] =
{
L"kernel32.dll",
L"mswsock.dll",
L"ntdll.dll",
L"ws2_32.dll",
};
void
_cygtls::call2 (DWORD (*func) (void *, void *), void *arg, void *buf)
{
init_thread (buf, func);
/* 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 thread_wrapper in miscfuncs.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 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);
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);
}
}
DWORD res = func (arg, buf);
remove (INFINITE);
/* Don't call ExitThread on the main thread since we may have been

View File

@ -1,7 +1,7 @@
/* net.cc: network-related routines.
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011 Red Hat, Inc.
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Red Hat, Inc.
This file is part of Cygwin.
@ -532,19 +532,33 @@ fdsock (cygheap_fdmanip& fd, const device *dev, SOCKET soc)
sizeof (base_soc), &bret, NULL, NULL);
if (ret)
debug_printf ("WSAIoctl: %lu", WSAGetLastError ());
else if (base_soc != soc
&& GetHandleInformation ((HANDLE) base_soc, &flags)
&& (flags & HANDLE_FLAG_INHERIT))
else if (base_soc != soc)
{
if (!DuplicateHandle (GetCurrentProcess (), (HANDLE) base_soc,
GetCurrentProcess (), (PHANDLE) &base_soc,
0, TRUE, DUPLICATE_SAME_ACCESS))
debug_printf ("DuplicateHandle failed, %E");
else
/* LSPs are often BLODAs as well. So we print an info about
detecting an LSP if BLODA detection is desired. */
if (detect_bloda)
{
closesocket (soc);
soc = base_soc;
fixup = false;
WSAPROTOCOL_INFO prot;
memset (&prot, 0, sizeof prot);
::getsockopt (soc, SOL_SOCKET, SO_PROTOCOL_INFO, (char *) &prot,
(size = sizeof prot, &size));
small_printf ("\n\nPotential BLODA detected! Layered Socket "
"Service Provider:\n %s\n\n", prot.szProtocol);
}
if (GetHandleInformation ((HANDLE) base_soc, &flags)
&& (flags & HANDLE_FLAG_INHERIT))
{
if (!DuplicateHandle (GetCurrentProcess (), (HANDLE) base_soc,
GetCurrentProcess (), (PHANDLE) &base_soc,
0, TRUE, DUPLICATE_SAME_ACCESS))
debug_printf ("DuplicateHandle failed, %E");
else
{
closesocket (soc);
soc = base_soc;
fixup = false;
}
}
}
}