* Makefile.in (DLL_OFILES): Add hookapi.o. Eliminate some cruft.
* cygheap.h (cygheap_types): Add new enum: HEAP_1_HOOK. (hook_chain): New struct. (init_cygheap::hooks): Define new element. * cygheap.cc (cygheap_fixup_in_child): Zero hook chain on exec. * dcrt0.cc (dll_crt0_1): Call ld_preload just before calling main function. * external.cc (cygwin_internal): Implement CW_HOOK. * fork.cc (fork_child): Call fixup_hooks_after_fork. * init.cc (cygwin_hmodule): Reinstate after a long absence. * include/sys/cygwin.h: Define CW_HOOK. * hookapi.cc: New file. * select.cc (start_thread_socket): Add debugging output. * fhandler_disk_file.cc (fhandler_disk_file::fchmod): gcc 4.x accommodation. * fhandler_socket.cc (fhandler_socket::connect): Make sure that err is initialized.
This commit is contained in:
parent
7e3fd32b1c
commit
b1d9a0bd41
|
@ -1,3 +1,25 @@
|
|||
2005-03-22 Christopher Faylor <cgf@timesys.com>
|
||||
|
||||
* Makefile.in (DLL_OFILES): Add hookapi.o. Eliminate some cruft.
|
||||
* cygheap.h (cygheap_types): Add new enum: HEAP_1_HOOK.
|
||||
(hook_chain): New struct.
|
||||
(init_cygheap::hooks): Define new element.
|
||||
* cygheap.cc (cygheap_fixup_in_child): Zero hook chain on exec.
|
||||
* dcrt0.cc (dll_crt0_1): Call ld_preload just before calling main function.
|
||||
* external.cc (cygwin_internal): Implement CW_HOOK.
|
||||
* fork.cc (fork_child): Call fixup_hooks_after_fork.
|
||||
* init.cc (cygwin_hmodule): Reinstate after a long absence.
|
||||
* include/sys/cygwin.h: Define CW_HOOK.
|
||||
* hookapi.cc: New file.
|
||||
|
||||
* select.cc (start_thread_socket): Add debugging output.
|
||||
|
||||
* fhandler_disk_file.cc (fhandler_disk_file::fchmod): gcc 4.x
|
||||
accommodation.
|
||||
|
||||
* fhandler_socket.cc (fhandler_socket::connect): Make sure that err is
|
||||
initialized.
|
||||
|
||||
2005-03-22 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* cygwin.din (__ctype_ptr): Export.
|
||||
|
|
|
@ -117,7 +117,7 @@ MALLOC_OFILES=@MALLOC_OFILES@
|
|||
DLL_IMPORTS:=$(w32api_lib)/libkernel32.a $(w32api_lib)/libadvapi32.a
|
||||
|
||||
MT_SAFE_OBJECTS:=
|
||||
# Please maintain this list in sorted order, with maximum files per 80 col line
|
||||
# Please maintain this list in sorted order, with maximum files per 85 col line
|
||||
#
|
||||
DLL_OFILES:=assert.o autoload.o bsdlib.o cxx.o cygheap.o cygthread.o cygtls.o \
|
||||
dcrt0.o debug.o delqueue.o devices.o dir.o dlfcn.o dll_init.o dtable.o \
|
||||
|
@ -127,12 +127,12 @@ DLL_OFILES:=assert.o autoload.o bsdlib.o cxx.o cygheap.o cygthread.o cygtls.o \
|
|||
fhandler_nodevice.o fhandler_proc.o fhandler_process.o \
|
||||
fhandler_random.o fhandler_raw.o fhandler_registry.o fhandler_serial.o \
|
||||
fhandler_socket.o fhandler_tape.o fhandler_termios.o \
|
||||
fhandler_tty.o fhandler_virtual.o fhandler_windows.o \
|
||||
fhandler_zero.o flock.o fnmatch.o fork.o getopt.o glob.o grp.o heap.o \
|
||||
fhandler_tty.o fhandler_virtual.o fhandler_windows.o fhandler_zero.o \
|
||||
flock.o fnmatch.o fork.o getopt.o glob.o grp.o heap.o hookapi.o \
|
||||
init.o ioctl.o ipc.o iruserok.o localtime.o malloc_wrapper.o miscfuncs.o \
|
||||
mmap.o msg.o net.o netdb.o ntea.o passwd.o path.o pinfo.o pipe.o \
|
||||
poll.o pthread.o regcomp.o regerror.o regexec.o regfree.o registry.o \
|
||||
resource.o scandir.o sched.o sec_acl.o sec_helper.o security.o \
|
||||
poll.o pthread.o regcomp.o regerror.o regexec.o regfree.o \
|
||||
registry.o resource.o scandir.o sched.o sec_acl.o sec_helper.o security.o \
|
||||
select.o sem.o shared.o shm.o sigfe.o signal.o sigproc.o smallprint.o \
|
||||
spawn.o strace.o strsep.o strsig.o sync.o syscalls.o sysconf.o \
|
||||
syslog.o termios.o thread.o timer.o times.o tty.o uinfo.o uname.o \
|
||||
|
@ -254,6 +254,7 @@ grp_CFLAGS:=-fomit-frame-pointer
|
|||
malloc_CFLAGS:=-fomit-frame-pointer
|
||||
malloc_wrapper_CFLAGS:=-fomit-frame-pointer
|
||||
miscfuncs_CFLAGS:=-fomit-frame-pointer
|
||||
net_CFLAGS:=-fomit-frame-pointer
|
||||
passwd_CFLAGS:=-fomit-frame-pointer
|
||||
regcomp_CFLAGS=-fomit-frame-pointer
|
||||
regerror_CFLAGS=-fomit-frame-pointer
|
||||
|
@ -267,7 +268,7 @@ uinfo_CFLAGS:=-fomit-frame-pointer
|
|||
endif
|
||||
|
||||
.PHONY: all force dll_ofiles install all_target install_target all_host install_host \
|
||||
install install-libs install-headers -lgcc
|
||||
install install-libs install-headers
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .cc .def .a .o .d .s
|
||||
|
@ -434,11 +435,6 @@ winver_stamp: mkvers.sh include/cygwin/version.h winver.rc $(DLL_OFILES)
|
|||
$(COMPILE_CXX) -o version.o version.cc && \
|
||||
touch $@
|
||||
|
||||
-lgcc:
|
||||
:
|
||||
|
||||
#
|
||||
|
||||
Makefile: cygwin.din
|
||||
|
||||
$(DEF_FILE): gendef cygwin.din $(srcdir)/tlsoffsets.h
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "child_info.h"
|
||||
#include "heap.h"
|
||||
#include "sync.h"
|
||||
#include "shared_info.h"
|
||||
#include "sigproc.h"
|
||||
|
||||
init_cygheap NO_COPY *cygheap;
|
||||
|
@ -185,6 +184,7 @@ cygheap_fixup_in_child (bool execed)
|
|||
|
||||
if (execed)
|
||||
{
|
||||
cygheap->hooks.next = NULL;
|
||||
cygheap->user_heap.base = NULL; /* We can allocate the heap anywhere */
|
||||
/* Walk the allocated memory chain looking for orphaned memory from
|
||||
previous execs */
|
||||
|
|
|
@ -21,6 +21,7 @@ enum cygheap_types
|
|||
HEAP_ARCHETYPES,
|
||||
HEAP_TLS,
|
||||
HEAP_1_START,
|
||||
HEAP_1_HOOK,
|
||||
HEAP_1_STR,
|
||||
HEAP_1_ARGV,
|
||||
HEAP_1_BUF,
|
||||
|
@ -262,6 +263,13 @@ struct user_heap_info
|
|||
unsigned chunk;
|
||||
};
|
||||
|
||||
struct hook_chain
|
||||
{
|
||||
void **loc;
|
||||
const void *func;
|
||||
struct hook_chain *next;
|
||||
};
|
||||
|
||||
struct init_cygheap
|
||||
{
|
||||
_cmalloc_entry *chain;
|
||||
|
@ -291,6 +299,7 @@ struct init_cygheap
|
|||
int open_fhs;
|
||||
pid_t pid; /* my pid */
|
||||
HANDLE pid_handle; /* handle for my pid */
|
||||
hook_chain hooks;
|
||||
void close_ctty ();
|
||||
};
|
||||
|
||||
|
|
|
@ -41,6 +41,8 @@ details. */
|
|||
|
||||
#define PREMAIN_LEN (sizeof (user_data->premain) / sizeof (user_data->premain[0]))
|
||||
|
||||
void ld_preload ();
|
||||
|
||||
HANDLE NO_COPY hMainProc = (HANDLE) -1;
|
||||
HANDLE NO_COPY hMainThread;
|
||||
|
||||
|
@ -857,6 +859,7 @@ dll_crt0_1 (char *)
|
|||
do this for noncygwin case since the signal thread is blocked due to
|
||||
LoadLibrary serialization. */
|
||||
wait_for_sigthread ();
|
||||
ld_preload ();
|
||||
if (user_data->main)
|
||||
exit (user_data->main (__argc, __argv, *user_data->envptr));
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@ details. */
|
|||
#include "pwdgrp.h"
|
||||
#include "cygtls.h"
|
||||
|
||||
void *hook_cygwin (const char *, const void *);
|
||||
|
||||
static external_pinfo *
|
||||
fillout_pinfo (pid_t pid, int winpid)
|
||||
{
|
||||
|
@ -298,6 +300,12 @@ cygwin_internal (cygwin_getinfo_types t, ...)
|
|||
}
|
||||
return p.binmode ();
|
||||
}
|
||||
case CW_HOOK:
|
||||
{
|
||||
const char *name = va_arg (arg, const char *);
|
||||
const void *hookfn = va_arg (arg, const void *);
|
||||
return (unsigned long) hook_cygwin (name, hookfn);
|
||||
}
|
||||
default:
|
||||
return (DWORD) -1;
|
||||
}
|
||||
|
|
|
@ -429,9 +429,9 @@ fhandler_disk_file::fchmod (mode_t mode)
|
|||
|
||||
/* if the mode we want has any write bits set, we can't be read only. */
|
||||
if (mode & (S_IWUSR | S_IWGRP | S_IWOTH))
|
||||
(DWORD) pc &= ~FILE_ATTRIBUTE_READONLY;
|
||||
pc &= (DWORD) ~FILE_ATTRIBUTE_READONLY;
|
||||
else
|
||||
(DWORD) pc |= FILE_ATTRIBUTE_READONLY;
|
||||
pc |= (DWORD) FILE_ATTRIBUTE_READONLY;
|
||||
|
||||
if (!SetFileAttributes (pc, pc))
|
||||
__seterrno ();
|
||||
|
|
|
@ -698,7 +698,9 @@ fhandler_socket::connect (const struct sockaddr *name, int namelen)
|
|||
|
||||
res = ::connect (get_socket (), (sockaddr *) &sin, namelen);
|
||||
|
||||
if (res)
|
||||
if (!res)
|
||||
err = 0;
|
||||
else
|
||||
{
|
||||
err = WSAGetLastError ();
|
||||
/* Special handling for connect to return the correct error code
|
||||
|
|
|
@ -154,6 +154,7 @@ sync_with_parent (const char *s, bool hang_self)
|
|||
static int __stdcall
|
||||
fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
|
||||
{
|
||||
extern void fixup_hooks_after_fork ();
|
||||
extern void fixup_timers_after_fork ();
|
||||
debug_printf ("child is running. pid %d, ppid %d, stack here %p",
|
||||
myself->pid, myself->ppid, __builtin_frame_address (0));
|
||||
|
@ -232,6 +233,7 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
|
|||
|
||||
pthread::atforkchild ();
|
||||
fixup_timers_after_fork ();
|
||||
fixup_hooks_after_fork ();
|
||||
cygbench ("fork-child");
|
||||
cygwin_finished_initializing = true;
|
||||
return 0;
|
||||
|
|
|
@ -0,0 +1,218 @@
|
|||
#include "winsup.h"
|
||||
#include "cygerrno.h"
|
||||
#include "security.h"
|
||||
#include "path.h"
|
||||
#include "fhandler.h"
|
||||
#include "dtable.h"
|
||||
#include "cygheap.h"
|
||||
#include <stdlib.h>
|
||||
#include <imagehlp.h>
|
||||
#include <alloca.h>
|
||||
|
||||
#define rva(coerce, base, addr) (coerce) ((char *) (base) + (addr))
|
||||
#define rvacyg(coerce, addr) rva (coerce, cygwin_hmodule, addr)
|
||||
|
||||
struct function_hook
|
||||
{
|
||||
const char *name; // Function name, e.g. "DirectDrawCreateEx".
|
||||
const void *hookfn; // Address of your function.
|
||||
void *origfn; // Stored by HookAPICalls, the address of the original function.
|
||||
};
|
||||
|
||||
/* Given an HMODULE, returns a pointer to the PE header */
|
||||
static PIMAGE_NT_HEADERS
|
||||
PEHeaderFromHModule (HMODULE hModule)
|
||||
{
|
||||
PIMAGE_NT_HEADERS pNTHeader = NULL;
|
||||
|
||||
if (PIMAGE_DOS_HEADER(hModule) ->e_magic != IMAGE_DOS_SIGNATURE)
|
||||
/* nothing */;
|
||||
else
|
||||
{
|
||||
pNTHeader = PIMAGE_NT_HEADERS (PBYTE (hModule)
|
||||
+ PIMAGE_DOS_HEADER (hModule) ->e_lfanew);
|
||||
if (pNTHeader->Signature != IMAGE_NT_SIGNATURE)
|
||||
pNTHeader = NULL;
|
||||
}
|
||||
|
||||
return pNTHeader;
|
||||
}
|
||||
|
||||
void *
|
||||
putmem (PIMAGE_THUNK_DATA pi, const void *hookfn)
|
||||
{
|
||||
|
||||
DWORD flOldProtect, flNewProtect, flDontCare;
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
|
||||
/* Get the current protection attributes */
|
||||
VirtualQuery (pi, &mbi, sizeof (mbi));
|
||||
|
||||
/* Remove ReadOnly and ExecuteRead attributes, add on ReadWrite flag */
|
||||
flNewProtect = mbi.Protect;
|
||||
flNewProtect &= ~(PAGE_READONLY | PAGE_EXECUTE_READ);
|
||||
flNewProtect |= PAGE_READWRITE;
|
||||
|
||||
if (!VirtualProtect (pi, sizeof (PVOID), flNewProtect, &flOldProtect) )
|
||||
return NULL;
|
||||
|
||||
void *origfn = (void *) pi->u1.Function;
|
||||
pi->u1.Function = (DWORD) hookfn;
|
||||
|
||||
(void) VirtualProtect (pi, sizeof (PVOID), flOldProtect, &flDontCare);
|
||||
return origfn;
|
||||
}
|
||||
|
||||
/* Builds stubs for and redirects the IAT for one DLL (pImportDesc) */
|
||||
|
||||
static bool
|
||||
RedirectIAT (function_hook& fh, PIMAGE_IMPORT_DESCRIPTOR pImportDesc,
|
||||
HMODULE hm)
|
||||
{
|
||||
// If no import names table, we can't redirect this, so bail
|
||||
if (pImportDesc->OriginalFirstThunk == 0)
|
||||
return false;
|
||||
|
||||
/* import address table */
|
||||
PIMAGE_THUNK_DATA pt = rva (PIMAGE_THUNK_DATA, hm, pImportDesc->FirstThunk);
|
||||
/* import names table */
|
||||
PIMAGE_THUNK_DATA pn = rva (PIMAGE_THUNK_DATA, hm, pImportDesc->OriginalFirstThunk);
|
||||
|
||||
/* Scan through the IAT, completing the stubs and redirecting the IAT
|
||||
entries to point to the stubs. */
|
||||
for (PIMAGE_THUNK_DATA pi = pt; pn->u1.Ordinal; pi++, pn++)
|
||||
{
|
||||
if (IMAGE_SNAP_BY_ORDINAL (pn->u1.Ordinal) )
|
||||
continue;
|
||||
|
||||
/* import by name */
|
||||
PIMAGE_IMPORT_BY_NAME pimp = rva (PIMAGE_IMPORT_BY_NAME, hm, pn->u1.AddressOfData);
|
||||
|
||||
if (strcmp (fh.name, (char *) pimp->Name) == 0)
|
||||
{
|
||||
fh.origfn = putmem (pi, fh.hookfn);
|
||||
if (!fh.origfn)
|
||||
return false;
|
||||
hook_chain *hc;
|
||||
for (hc = &cygheap->hooks; hc->next; hc = hc->next)
|
||||
continue;
|
||||
hc->next = (hook_chain *) cmalloc (HEAP_1_HOOK, sizeof (hook_chain));
|
||||
hc->next->loc = (void **) pi;
|
||||
hc->next->func = fh.hookfn;
|
||||
hc->next->next = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
get_export (function_hook& fh)
|
||||
{
|
||||
extern HMODULE cygwin_hmodule;
|
||||
PIMAGE_DOS_HEADER pdh = (PIMAGE_DOS_HEADER) cygwin_hmodule;
|
||||
if (pdh->e_magic != IMAGE_DOS_SIGNATURE)
|
||||
return;
|
||||
PIMAGE_NT_HEADERS pnt = (PIMAGE_NT_HEADERS) ((char *) pdh + pdh->e_lfanew);
|
||||
if (pnt->Signature != IMAGE_NT_SIGNATURE || pnt->FileHeader.SizeOfOptionalHeader == 0)
|
||||
return;
|
||||
PIMAGE_EXPORT_DIRECTORY pexp =
|
||||
rvacyg (PIMAGE_EXPORT_DIRECTORY,
|
||||
pnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
|
||||
if (!pexp)
|
||||
return;
|
||||
|
||||
PDWORD pfuncs = rvacyg (PDWORD, pexp->AddressOfFunctions);
|
||||
PDWORD pnames = rvacyg (PDWORD, pexp->AddressOfNames);
|
||||
for (DWORD i = 0; i < pexp->NumberOfNames; i++)
|
||||
if (strcmp (fh.name, rvacyg (char *, pnames[i])) == 0)
|
||||
{
|
||||
fh.origfn = rvacyg (void *, pfuncs[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *
|
||||
makename (const char *name, char *&buf, int& i, int inc)
|
||||
{
|
||||
i += inc;
|
||||
static const char *testers[] = {"NOTUSED", "64", "32"};
|
||||
if (i < 0 || i >= (int) (sizeof (testers) / sizeof (testers[0])))
|
||||
return NULL;
|
||||
if (i)
|
||||
{
|
||||
__small_sprintf (buf, "_%s%s", name, testers[i]);
|
||||
name = buf;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
// Top level routine to find the EXE's imports, and redirect them
|
||||
void *
|
||||
hook_cygwin (const char *name, const void *fn)
|
||||
{
|
||||
HMODULE hm = GetModuleHandle (NULL);
|
||||
PIMAGE_NT_HEADERS pExeNTHdr = PEHeaderFromHModule (hm);
|
||||
|
||||
if (!pExeNTHdr)
|
||||
return false;
|
||||
|
||||
DWORD importRVA = pExeNTHdr->OptionalHeader.DataDirectory
|
||||
[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
|
||||
if (!importRVA)
|
||||
return false;
|
||||
|
||||
// Convert imports RVA to a usable pointer
|
||||
PIMAGE_IMPORT_DESCRIPTOR pdfirst = rva (PIMAGE_IMPORT_DESCRIPTOR, hm, importRVA);
|
||||
|
||||
function_hook fh;
|
||||
fh.origfn = NULL;
|
||||
fh.hookfn = fn;
|
||||
char *buf = (char *) alloca (strlen (name) + strlen ("64") + sizeof ("_"));
|
||||
int i = -1;
|
||||
while (!fh.origfn && (fh.name = makename (name, buf, i, 1)))
|
||||
{
|
||||
// Iterate through each import descriptor, and redirect if appropriate
|
||||
for (PIMAGE_IMPORT_DESCRIPTOR pd = pdfirst; pd->FirstThunk; pd++)
|
||||
{
|
||||
PSTR modname = rva (PSTR, hm, pd->Name);
|
||||
if (strcasematch (modname, "cygwin1.dll"))
|
||||
RedirectIAT (fh, pd, hm);
|
||||
}
|
||||
}
|
||||
|
||||
while (!fh.origfn && (fh.name = makename (name, buf, i, -1)))
|
||||
get_export (fh);
|
||||
|
||||
return fh.origfn;
|
||||
}
|
||||
|
||||
void
|
||||
ld_preload ()
|
||||
{
|
||||
char *p = getenv ("LD_PRELOAD");
|
||||
if (!p)
|
||||
return;
|
||||
char *s = (char *) alloca (strlen (p) + 1);
|
||||
strcpy (s, p);
|
||||
char *here = NULL;
|
||||
for (p = strtok_r (s, " \t\n", &here); p; p = strtok_r (NULL, " \t\n", &here))
|
||||
{
|
||||
path_conv lib (p);
|
||||
if (!LoadLibrary (lib))
|
||||
{
|
||||
__seterrno ();
|
||||
api_fatal ("error while loading shared libraries: %s: "
|
||||
"cannot open shared object file: %s", p,
|
||||
strerror (get_errno ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fixup_hooks_after_fork ()
|
||||
{
|
||||
for (hook_chain *hc = &cygheap->hooks; (hc = hc->next); )
|
||||
putmem ((PIMAGE_THUNK_DATA) hc->loc, hc->func);
|
||||
}
|
|
@ -49,6 +49,7 @@ struct __cygwin_perfile
|
|||
|
||||
/* External interface stuff */
|
||||
|
||||
/* Always add at the bottom. Do not add new values in the middle. */
|
||||
typedef enum
|
||||
{
|
||||
CW_LOCK_PINFO,
|
||||
|
@ -78,7 +79,8 @@ typedef enum
|
|||
CW_GET_SHMLBA,
|
||||
CW_GET_UID_FROM_SID,
|
||||
CW_GET_GID_FROM_SID,
|
||||
CW_GET_BINMODE
|
||||
CW_GET_BINMODE,
|
||||
CW_HOOK
|
||||
} cygwin_getinfo_types;
|
||||
|
||||
#define CW_NEXTPID 0x80000000 /* or with pid to get next one */
|
||||
|
|
|
@ -108,6 +108,8 @@ respawn_wow64_process ()
|
|||
|
||||
extern void __stdcall dll_crt0_0 ();
|
||||
|
||||
HMODULE NO_COPY cygwin_hmodule;
|
||||
|
||||
extern "C" int WINAPI
|
||||
dll_entry (HANDLE h, DWORD reason, void *static_load)
|
||||
{
|
||||
|
@ -116,6 +118,7 @@ dll_entry (HANDLE h, DWORD reason, void *static_load)
|
|||
switch (reason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
cygwin_hmodule = (HMODULE) h;
|
||||
/* Is the stack at an unusual high address? Check if we're running on
|
||||
a 64 bit machine. If so, respawn. */
|
||||
if (&is_64bit_machine >= (PBOOL) 0x400000
|
||||
|
|
|
@ -1394,6 +1394,7 @@ start_thread_socket (select_record *me, select_stuff *stuff)
|
|||
SetHandleInformation ((HANDLE) si->exitsock, HANDLE_FLAG_INHERIT, 0);
|
||||
/* else
|
||||
too bad? */
|
||||
select_printf ("opened new socket %p", _my_tls.locals.exitsock);
|
||||
}
|
||||
|
||||
select_printf ("exitsock %p", si->exitsock);
|
||||
|
|
Loading…
Reference in New Issue