* dcrt0.cc (get_cygwin_startup_info): Change zeros to DWORD array.

Expect first DWORD in child_info struct being set to non-zero if
	wincap.needs_count_in_si_lpres2 is set.  Add comment to explain why.
	* fork.cc (frok::parent): Set ch.zero[0] to a sensible count value
	if wincap.needs_count_in_si_lpres2 is set.
	* spawn.cc (spawn_guts): Ditto.  Add filler bytes after ch on stack
	to accomodate needs_count_in_si_lpres2.
	* wincap.h: Define needs_count_in_si_lpres2 throughout.
	* wincap.cc: Ditto.
This commit is contained in:
Corinna Vinschen 2006-12-05 10:59:21 +00:00
parent 489bb390ce
commit c6674b53d3
6 changed files with 71 additions and 2 deletions

View File

@ -1,3 +1,15 @@
2006-12-04 Corinna Vinschen <corinna@vinschen.de>
* dcrt0.cc (get_cygwin_startup_info): Change zeros to DWORD array.
Expect first DWORD in child_info struct being set to non-zero if
wincap.needs_count_in_si_lpres2 is set. Add comment to explain why.
* fork.cc (frok::parent): Set ch.zero[0] to a sensible count value
if wincap.needs_count_in_si_lpres2 is set.
* spawn.cc (spawn_guts): Ditto. Add filler bytes after ch on stack
to accomodate needs_count_in_si_lpres2.
* wincap.h: Define needs_count_in_si_lpres2 throughout.
* wincap.cc: Ditto.
2006-11-29 Corinna Vinschen <corinna@vinschen.de>
* dir.cc (mkdir): Check last path component for "..".

View File

@ -590,10 +590,36 @@ child_info *
get_cygwin_startup_info ()
{
STARTUPINFO si;
char zeros[sizeof (child_proc_info->zero)] = {0};
DWORD zeros[sizeof (child_proc_info->zero)
/ sizeof (child_proc_info->zero[0])] = {0};
GetStartupInfo (&si);
child_info *res = (child_info *) si.lpReserved2;
/* It appears that when running under WOW64 on Vista 64, the first DWORD
value in the datastructure lpReserved2 is pointing to (zero[0] in
Cygwin), has to reflect the size of that datastructure as used in the
Microsoft C runtime (a count value, counting the number of elements in
two subsequent arrays, BYTE[count and HANDLE[count]), even though the C
runtime isn't used. Otherwise, if zero[0] is 0 or too small, the
datastructure gets overwritten.
This seems to be a bug in Vista's WOW64, which apparently copies the
lpReserved2 datastructure not using the cbReserved2 size information,
but using the information given in the first DWORD within lpReserved2
instead. Funny enough, 32 bit Vista doesn't care if zero[0] is 0 or a
non-0 count value, while older versions of Windows might crash if
zero[0] is set to a non-zero value, as observed at least on XP 64.
exec/spawn as well as fork write an appropriate value into zero[0] now,
depending on the wincap.needs_count_in_si_lpres2 flag. The value is
sizeof (child_info_*) / 5 which results in a count which covers the
full datastructure, plus not more than 4 extra bytes. This is ok as
long as the child_info structure is cosily stored within a bigger
datastructure. */
if (wincap.needs_count_in_si_lpres2 ())
zeros[0] = si.cbReserved2 / 5;
if (si.cbReserved2 < EXEC_MAGIC_SIZE || !res
|| memcmp (res->zero, zeros, sizeof (res->zero)) != 0)
res = NULL;

View File

@ -280,9 +280,14 @@ frok::parent (void *stack_here)
memset (&si, 0, sizeof (si));
si.cb = sizeof (STARTUPINFO);
si.lpReserved2 = (LPBYTE) &ch;
si.cbReserved2 = sizeof (ch);
/* See comment in dcrt0.cc, function get_cygwin_startup_info. */
if (wincap.needs_count_in_si_lpres2 ())
ch.zero[0] = sizeof (ch) / 5;
syscall_printf ("CreateProcess (%s, %s, 0, 0, 1, %p, 0, 0, %p, %p)",
myself->progname, myself->progname, c_flags, &si, &pi);
bool locked = __malloc_lock ();

View File

@ -298,7 +298,13 @@ spawn_guts (const char * prog_arg, const char *const *argv,
pthread_cleanup_push (do_cleanup, (void *) &cleanup);
av newargv;
linebuf one_line;
child_info_spawn ch;
/* Allocate slightly bigger for call to CreateProcess to accomodate
needs_count_in_si_lpres2. */
struct {
child_info_spawn ch;
char filler[4];
} _ch;
#define ch _ch.ch
char *envblock = NULL;
path_conv real_path;
@ -481,6 +487,10 @@ spawn_guts (const char * prog_arg, const char *const *argv,
si.lpReserved2 = (LPBYTE) &ch;
si.cbReserved2 = sizeof (ch);
/* See comment in dcrt0.cc, function get_cygwin_startup_info. */
if (wincap.needs_count_in_si_lpres2 ())
ch.zero[0] = sizeof (ch) / 5;
/* When ruid != euid we create the new process under the current original
account and impersonate in child, this way maintaining the different
effective vs. real ids.
@ -724,6 +734,7 @@ out:
free (envblock);
pthread_cleanup_pop (1);
return (int) res;
#undef ch
}
extern "C" int

View File

@ -70,6 +70,7 @@ static NO_COPY wincaps wincap_unknown = {
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
needs_count_in_si_lpres2:false,
};
static NO_COPY wincaps wincap_95 = {
@ -131,6 +132,7 @@ static NO_COPY wincaps wincap_95 = {
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
needs_count_in_si_lpres2:false,
};
static NO_COPY wincaps wincap_95osr2 = {
@ -192,6 +194,7 @@ static NO_COPY wincaps wincap_95osr2 = {
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
needs_count_in_si_lpres2:false,
};
static NO_COPY wincaps wincap_98 = {
@ -253,6 +256,7 @@ static NO_COPY wincaps wincap_98 = {
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
needs_count_in_si_lpres2:false,
};
static NO_COPY wincaps wincap_98se = {
@ -314,6 +318,7 @@ static NO_COPY wincaps wincap_98se = {
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
needs_count_in_si_lpres2:false,
};
static NO_COPY wincaps wincap_me = {
@ -375,6 +380,7 @@ static NO_COPY wincaps wincap_me = {
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
needs_count_in_si_lpres2:false,
};
static NO_COPY wincaps wincap_nt3 = {
@ -436,6 +442,7 @@ static NO_COPY wincaps wincap_nt3 = {
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:true,
needs_count_in_si_lpres2:false,
};
static NO_COPY wincaps wincap_nt4 = {
@ -497,6 +504,7 @@ static NO_COPY wincaps wincap_nt4 = {
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:true,
needs_count_in_si_lpres2:false,
};
static NO_COPY wincaps wincap_nt4sp4 = {
@ -558,6 +566,7 @@ static NO_COPY wincaps wincap_nt4sp4 = {
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:true,
needs_count_in_si_lpres2:false,
};
static NO_COPY wincaps wincap_2000 = {
@ -619,6 +628,7 @@ static NO_COPY wincaps wincap_2000 = {
has_buggy_restart_scan:true,
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:true,
needs_count_in_si_lpres2:false,
};
static NO_COPY wincaps wincap_xp = {
@ -680,6 +690,7 @@ static NO_COPY wincaps wincap_xp = {
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
needs_count_in_si_lpres2:false,
};
static NO_COPY wincaps wincap_2003 = {
@ -741,6 +752,7 @@ static NO_COPY wincaps wincap_2003 = {
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
needs_count_in_si_lpres2:false,
};
static NO_COPY wincaps wincap_vista = {
@ -802,6 +814,7 @@ static NO_COPY wincaps wincap_vista = {
has_buggy_restart_scan:false,
has_mandatory_integrity_control:true,
needs_logon_sid_in_sid_list:false,
needs_count_in_si_lpres2:true,
};
wincapc wincap __attribute__((section (".cygwin_dll_common"), shared));

View File

@ -71,6 +71,7 @@ struct wincaps
unsigned has_buggy_restart_scan : 1;
unsigned has_mandatory_integrity_control : 1;
unsigned needs_logon_sid_in_sid_list : 1;
unsigned needs_count_in_si_lpres2 : 1;
};
class wincapc
@ -148,6 +149,7 @@ public:
bool IMPLEMENT (has_buggy_restart_scan)
bool IMPLEMENT (has_mandatory_integrity_control)
bool IMPLEMENT (needs_logon_sid_in_sid_list)
bool IMPLEMENT (needs_count_in_si_lpres2)
#undef IMPLEMENT
};