* 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:
		| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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; | ||||
| 		} | ||||
| 	    } | ||||
| 	} | ||||
|     } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user