* 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:
parent
489bb390ce
commit
c6674b53d3
|
@ -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 "..".
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue