* 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:
parent
4c28f4392a
commit
be2280986d
@ -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
|
||||
|
@ -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)
|
||||
return (void *) "found it"; // just checking if executable used cygwin1.dll
|
||||
{
|
||||
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);
|
||||
|
||||
|
@ -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)
|
||||
goto err;
|
||||
{
|
||||
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 ());
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user