* hookapi.cc (hook_or_detect_cygwin): Take additional handle

to a file mapping as parameter.  If this handle is not NULL,
	create another file mapping for the IAT.
	* spawn.cc (av::fixup): Only map the first 64K of an image and
	keep the mapping handle to use as argument to hook_or_detect_cygwin.
	* winsup.h (hook_or_detect_cygwin): Add mapping handle as default
	parameter in declaration.
This commit is contained in:
Corinna Vinschen 2011-10-25 16:35:58 +00:00
parent 4c28f4392a
commit be2280986d
4 changed files with 69 additions and 11 deletions

View File

@ -1,3 +1,13 @@
2011-10-25 Corinna Vinschen <corinna@vinschen.de>
* hookapi.cc (hook_or_detect_cygwin): Take additional handle
to a file mapping as parameter. If this handle is not NULL,
create another file mapping for the IAT.
* spawn.cc (av::fixup): Only map the first 64K of an image and
keep the mapping handle to use as argument to hook_or_detect_cygwin.
* winsup.h (hook_or_detect_cygwin): Add mapping handle as default
parameter in declaration.
2011-10-24 Corinna Vinschen <corinna@vinschen.de>
* syscalls.cc (unlink_nt): Fix a bug which overwrites the NT status

View File

@ -10,6 +10,7 @@ details. */
#include "winsup.h"
#include <stdlib.h>
#include <sys/param.h>
#include "ntdll.h"
#include "cygerrno.h"
#include "security.h"
@ -226,7 +227,7 @@ out:
// Top level routine to find the EXE's imports and redirect them
void *
hook_or_detect_cygwin (const char *name, const void *fn, WORD& subsys)
hook_or_detect_cygwin (const char *name, const void *fn, WORD& subsys, HANDLE h)
{
HMODULE hm = fn ? GetModuleHandle (NULL) : (HMODULE) name;
PIMAGE_NT_HEADERS pExeNTHdr = PEHeaderFromHModule (hm);
@ -238,15 +239,36 @@ hook_or_detect_cygwin (const char *name, const void *fn, WORD& subsys)
DWORD importRVA = pExeNTHdr->OptionalHeader.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
DWORD importRVASize = pExeNTHdr->OptionalHeader.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
if (!importRVA)
return false;
long delta = fn ? 0 : rvadelta (pExeNTHdr, importRVA);
if (delta < 0)
return false;
importRVA -= delta;
// Convert imports RVA to a usable pointer
PIMAGE_IMPORT_DESCRIPTOR pdfirst = rva (PIMAGE_IMPORT_DESCRIPTOR, hm, importRVA - delta);
PIMAGE_IMPORT_DESCRIPTOR pdfirst;
char *map = NULL;
DWORD offset = 0;
if (h && importRVA + importRVASize > wincap.allocation_granularity ())
{
/* If h is not NULL, the calling function only mapped at most the first
64K of the image. The IAT is usually at the end of the image, so
what we do here is to map the IAT into our address space if it doesn't
reside in the first 64K anyway. The offset must be a multiple of the
allocation granularity, though, so we have to map a bit more. */
offset = rounddown (importRVA, wincap.allocation_granularity ());
DWORD size = importRVA - offset + importRVASize;
map = (char *) MapViewOfFile (h, FILE_MAP_READ, 0, offset, size);
if (!map)
return false;
pdfirst = rva (PIMAGE_IMPORT_DESCRIPTOR, map, importRVA - offset);
}
else
pdfirst = rva (PIMAGE_IMPORT_DESCRIPTOR, hm, importRVA);
function_hook fh;
fh.origfn = NULL;
@ -256,10 +278,15 @@ hook_or_detect_cygwin (const char *name, const void *fn, WORD& subsys)
// Iterate through each import descriptor, and redirect if appropriate
for (PIMAGE_IMPORT_DESCRIPTOR pd = pdfirst; pd->FirstThunk; pd++)
{
if (!ascii_strcasematch (rva (PSTR, hm, pd->Name - delta), "cygwin1.dll"))
if (!ascii_strcasematch (rva (PSTR, map ?: (char *) hm,
pd->Name - delta - offset), "cygwin1.dll"))
continue;
if (!fn)
{
if (map)
UnmapViewOfFile (map);
return (void *) "found it"; // just checking if executable used cygwin1.dll
}
i = -1;
while (!fh.origfn && (fh.name = makename (name, buf, i, 1)))
RedirectIAT (fh, pd, hm);
@ -267,6 +294,9 @@ hook_or_detect_cygwin (const char *name, const void *fn, WORD& subsys)
break;
}
if (map)
UnmapViewOfFile (map);
while (!fh.origfn && (fh.name = makename (name, buf, i, -1)))
get_export (fh);

View File

@ -1059,6 +1059,7 @@ av::fixup (const char *prog_arg, path_conv& real_path, const char *ext,
IO_STATUS_BLOCK io;
HANDLE h;
NTSTATUS status;
LARGE_INTEGER size;
status = NtOpenFile (&h, SYNCHRONIZE | GENERIC_READ,
real_path.get_object_attr (attr, sec_none_nih),
@ -1069,7 +1070,7 @@ av::fixup (const char *prog_arg, path_conv& real_path, const char *ext,
if (!NT_SUCCESS (status))
{
/* File is not readable? Doesn't mean it's not executable.
Test for executablility and if so, just assume the file is
Test for executability and if so, just assume the file is
a cygwin executable and go ahead. */
if (status == STATUS_ACCESS_DENIED && real_path.has_acls ()
&& check_file_access (real_path, X_OK, true) == 0)
@ -1079,8 +1080,16 @@ av::fixup (const char *prog_arg, path_conv& real_path, const char *ext,
}
goto err;
}
if (!GetFileSizeEx (h, &size))
{
NtClose (h);
goto err;
}
if (size.QuadPart > wincap.allocation_granularity ())
size.LowPart = wincap.allocation_granularity ();
HANDLE hm = CreateFileMapping (h, &sec_none_nih, PAGE_READONLY, 0, 0, NULL);
HANDLE hm = CreateFileMapping (h, &sec_none_nih, PAGE_READONLY,
0, 0, NULL);
NtClose (h);
if (!hm)
{
@ -1092,16 +1101,22 @@ av::fixup (const char *prog_arg, path_conv& real_path, const char *ext,
}
goto err;
}
buf = (char *) MapViewOfFile(hm, FILE_MAP_READ, 0, 0, 0);
CloseHandle (hm);
/* Try to map the first 64K of the image. That's enough for the local
tests, and it's enough for hook_or_detect_cygwin to compute the IAT
address. */
buf = (char *) MapViewOfFile (hm, FILE_MAP_READ, 0, 0, size.LowPart);
if (!buf)
{
CloseHandle (hm);
goto err;
}
{
myfault efault;
if (efault.faulted ())
{
UnmapViewOfFile (buf);
CloseHandle (hm);
real_path.set_cygexec (false);
break;
}
@ -1111,13 +1126,16 @@ av::fixup (const char *prog_arg, path_conv& real_path, const char *ext,
unsigned off = (unsigned char) buf[0x18] | (((unsigned char) buf[0x19]) << 8);
win16_exe = off < sizeof (IMAGE_DOS_HEADER);
if (!win16_exe)
real_path.set_cygexec (!!hook_or_detect_cygwin (buf, NULL, subsys));
real_path.set_cygexec (!!hook_or_detect_cygwin (buf, NULL,
subsys, hm));
else
real_path.set_cygexec (false);
UnmapViewOfFile (buf);
CloseHandle (hm);
break;
}
}
CloseHandle (hm);
debug_printf ("%s is possibly a script", real_path.get_win32 ());

View File

@ -216,7 +216,7 @@ __ino64_t __stdcall hash_path_name (__ino64_t hash, PCWSTR name) __attribute__ (
__ino64_t __stdcall hash_path_name (__ino64_t hash, const char *name) __attribute__ ((regparm(2)));
void __stdcall nofinalslash (const char *src, char *dst) __attribute__ ((regparm(2)));
void *hook_or_detect_cygwin (const char *, const void *, WORD&) __attribute__ ((regparm (3)));
void *hook_or_detect_cygwin (const char *, const void *, WORD&, HANDLE h = NULL) __attribute__ ((regparm (3)));
/* Time related */
void __stdcall totimeval (struct timeval *, FILETIME *, int, int);