* 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>
|
2011-10-24 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* syscalls.cc (unlink_nt): Fix a bug which overwrites the NT status
|
* syscalls.cc (unlink_nt): Fix a bug which overwrites the NT status
|
||||||
|
|
|
@ -10,6 +10,7 @@ details. */
|
||||||
|
|
||||||
#include "winsup.h"
|
#include "winsup.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <sys/param.h>
|
||||||
#include "ntdll.h"
|
#include "ntdll.h"
|
||||||
#include "cygerrno.h"
|
#include "cygerrno.h"
|
||||||
#include "security.h"
|
#include "security.h"
|
||||||
|
@ -226,7 +227,7 @@ out:
|
||||||
|
|
||||||
// Top level routine to find the EXE's imports and redirect them
|
// Top level routine to find the EXE's imports and redirect them
|
||||||
void *
|
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;
|
HMODULE hm = fn ? GetModuleHandle (NULL) : (HMODULE) name;
|
||||||
PIMAGE_NT_HEADERS pExeNTHdr = PEHeaderFromHModule (hm);
|
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
|
DWORD importRVA = pExeNTHdr->OptionalHeader.DataDirectory
|
||||||
[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
|
[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
|
||||||
|
DWORD importRVASize = pExeNTHdr->OptionalHeader.DataDirectory
|
||||||
|
[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
|
||||||
if (!importRVA)
|
if (!importRVA)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
long delta = fn ? 0 : rvadelta (pExeNTHdr, importRVA);
|
long delta = fn ? 0 : rvadelta (pExeNTHdr, importRVA);
|
||||||
if (delta < 0)
|
if (delta < 0)
|
||||||
return false;
|
return false;
|
||||||
|
importRVA -= delta;
|
||||||
|
|
||||||
// Convert imports RVA to a usable pointer
|
// 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;
|
function_hook fh;
|
||||||
fh.origfn = NULL;
|
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
|
// Iterate through each import descriptor, and redirect if appropriate
|
||||||
for (PIMAGE_IMPORT_DESCRIPTOR pd = pdfirst; pd->FirstThunk; pd++)
|
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;
|
continue;
|
||||||
if (!fn)
|
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;
|
i = -1;
|
||||||
while (!fh.origfn && (fh.name = makename (name, buf, i, 1)))
|
while (!fh.origfn && (fh.name = makename (name, buf, i, 1)))
|
||||||
RedirectIAT (fh, pd, hm);
|
RedirectIAT (fh, pd, hm);
|
||||||
|
@ -267,6 +294,9 @@ hook_or_detect_cygwin (const char *name, const void *fn, WORD& subsys)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (map)
|
||||||
|
UnmapViewOfFile (map);
|
||||||
|
|
||||||
while (!fh.origfn && (fh.name = makename (name, buf, i, -1)))
|
while (!fh.origfn && (fh.name = makename (name, buf, i, -1)))
|
||||||
get_export (fh);
|
get_export (fh);
|
||||||
|
|
||||||
|
|
|
@ -1059,6 +1059,7 @@ av::fixup (const char *prog_arg, path_conv& real_path, const char *ext,
|
||||||
IO_STATUS_BLOCK io;
|
IO_STATUS_BLOCK io;
|
||||||
HANDLE h;
|
HANDLE h;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
LARGE_INTEGER size;
|
||||||
|
|
||||||
status = NtOpenFile (&h, SYNCHRONIZE | GENERIC_READ,
|
status = NtOpenFile (&h, SYNCHRONIZE | GENERIC_READ,
|
||||||
real_path.get_object_attr (attr, sec_none_nih),
|
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))
|
if (!NT_SUCCESS (status))
|
||||||
{
|
{
|
||||||
/* File is not readable? Doesn't mean it's not executable.
|
/* 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. */
|
a cygwin executable and go ahead. */
|
||||||
if (status == STATUS_ACCESS_DENIED && real_path.has_acls ()
|
if (status == STATUS_ACCESS_DENIED && real_path.has_acls ()
|
||||||
&& check_file_access (real_path, X_OK, true) == 0)
|
&& 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;
|
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);
|
NtClose (h);
|
||||||
if (!hm)
|
if (!hm)
|
||||||
{
|
{
|
||||||
|
@ -1092,16 +1101,22 @@ av::fixup (const char *prog_arg, path_conv& real_path, const char *ext,
|
||||||
}
|
}
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
buf = (char *) MapViewOfFile(hm, FILE_MAP_READ, 0, 0, 0);
|
/* Try to map the first 64K of the image. That's enough for the local
|
||||||
CloseHandle (hm);
|
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)
|
if (!buf)
|
||||||
goto err;
|
{
|
||||||
|
CloseHandle (hm);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
myfault efault;
|
myfault efault;
|
||||||
if (efault.faulted ())
|
if (efault.faulted ())
|
||||||
{
|
{
|
||||||
UnmapViewOfFile (buf);
|
UnmapViewOfFile (buf);
|
||||||
|
CloseHandle (hm);
|
||||||
real_path.set_cygexec (false);
|
real_path.set_cygexec (false);
|
||||||
break;
|
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);
|
unsigned off = (unsigned char) buf[0x18] | (((unsigned char) buf[0x19]) << 8);
|
||||||
win16_exe = off < sizeof (IMAGE_DOS_HEADER);
|
win16_exe = off < sizeof (IMAGE_DOS_HEADER);
|
||||||
if (!win16_exe)
|
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
|
else
|
||||||
real_path.set_cygexec (false);
|
real_path.set_cygexec (false);
|
||||||
UnmapViewOfFile (buf);
|
UnmapViewOfFile (buf);
|
||||||
|
CloseHandle (hm);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
CloseHandle (hm);
|
||||||
|
|
||||||
debug_printf ("%s is possibly a script", real_path.get_win32 ());
|
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)));
|
__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 __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 */
|
/* Time related */
|
||||||
void __stdcall totimeval (struct timeval *, FILETIME *, int, int);
|
void __stdcall totimeval (struct timeval *, FILETIME *, int, int);
|
||||||
|
|
Loading…
Reference in New Issue