* Makefile.in (DLL_OFILES): Add tls_pbuf.o.
* autoload.cc (CreateDesktopW): Replace CreateDesktopA. (CreateWindowStationW): Replace CreateWindowStationA. (GetUserObjectInformationW): Replace GetUserObjectInformationA. * cygheap.h (cwdstuff::get): Assume default buffer size NT_MAX_PATH. * cygtls.cc (_cygtls::remove): Free temporary TLS path buffers. * cygtls.h (TP_NUM_C_BUFS): Define. (TP_NUM_W_BUFS): Define. (class tls_pathbuf): New class to store pointers to thread local temporary path buffers. (_local_storage::pathbufs): New member. * environ.cc (win_env::add_cache): Use temporary TLS path buffer instead of stack based buffer. (posify): Get temporary outenv buffer from calling function. (environ_init): Create temporary TLS path buffer for posify. (build_env): Create Windows environment block as WCHAR buffer. * environ.h (build_env): Change declaration accordingly. * external.cc (sync_winenv): Accommodate build_env change. * fhandler_console.cc (fhandler_console::need_invisible): Use GetUserObjectInformationW and CreateWindowStationW. * fhandler_process.cc (format_process_maps): Use temporary TLS path buffer instead of stack based buffer. * fork.cc (frok::parent): Convert to use CreateProcessW. * path.cc: Throughout use temporary TLS path buffers instead of stack based buffer. Replace checks for CYG_MAX_PATH by checks for NT_MAX_PATH. (getfileattr): New function to replace GetFileAttributesA. (normalize_win32_path): Remove Win32 and NT long path prefixes. (getwd): Assume PATH_MAX + 1 buffer per SUSv3. * path.h (class path_conv): Set path buffer to size NT_MAX_PATH. (iswdrive): Define. * pinfo.cc (commune_process): Use temporary TLS path buffer instead of stack based buffer. * registry.cc (get_registry_hive_path): Ditto. (load_registry_hive): Ditto. * spawn.cc (spawn_guts): Convert to use CreateProcessW and CreateProcessAsUserW. (av::fixup): Open/close file using NtOpenFile/NtClose. * syscalls.cc (mknod_worker): Allow PATH_MAX file name. (mknod32): Ditto. (getusershell): Ditto. * tls_pbuf.cc: New file implementing tls_pathbuf and tmp_pathbuf methods. * tls_pbuf.h: New header for files using tmp_pathbuf. * tlsoffsets.h: Regenerate. * winsup.h (NT_MAX_PATH): Define as 32767 to avoid USHORT overflow.
This commit is contained in:
@ -18,6 +18,7 @@ details. */
|
||||
#include <limits.h>
|
||||
#include <wingdi.h>
|
||||
#include <winuser.h>
|
||||
#include <wchar.h>
|
||||
#include <ctype.h>
|
||||
#include "cygerrno.h"
|
||||
#include <sys/cygwin.h>
|
||||
@ -33,6 +34,7 @@ details. */
|
||||
#include "registry.h"
|
||||
#include "environ.h"
|
||||
#include "cygtls.h"
|
||||
#include "tls_pbuf.h"
|
||||
#include "winf.h"
|
||||
#include "ntdll.h"
|
||||
|
||||
@ -301,18 +303,19 @@ spawn_guts (const char * prog_arg, const char *const *argv,
|
||||
av newargv;
|
||||
linebuf one_line;
|
||||
child_info_spawn ch;
|
||||
char *envblock = NULL;
|
||||
PWCHAR envblock = NULL;
|
||||
path_conv real_path;
|
||||
bool reset_sendsig = false;
|
||||
|
||||
const char *runpath;
|
||||
tmp_pathbuf tp;
|
||||
PWCHAR runpath = tp.w_get ();
|
||||
int c_flags;
|
||||
bool wascygexec;
|
||||
cygheap_exec_info *moreinfo;
|
||||
|
||||
bool null_app_name = false;
|
||||
STARTUPINFO si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL,
|
||||
NULL, NULL, NULL};
|
||||
STARTUPINFOW si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL,
|
||||
NULL, NULL, NULL};
|
||||
int looped = 0;
|
||||
HANDLE orig_wr_proc_pipe = NULL;
|
||||
|
||||
@ -333,7 +336,8 @@ spawn_guts (const char * prog_arg, const char *const *argv,
|
||||
else
|
||||
chtype = PROC_EXEC;
|
||||
|
||||
moreinfo = (cygheap_exec_info *) ccalloc_abort (HEAP_1_EXEC, 1, sizeof (cygheap_exec_info));
|
||||
moreinfo = (cygheap_exec_info *) ccalloc_abort (HEAP_1_EXEC, 1,
|
||||
sizeof (cygheap_exec_info));
|
||||
moreinfo->old_title = NULL;
|
||||
|
||||
/* CreateProcess takes one long string that is the command line (sigh).
|
||||
@ -382,7 +386,8 @@ spawn_guts (const char * prog_arg, const char *const *argv,
|
||||
{
|
||||
if (wascygexec)
|
||||
newargv.dup_all ();
|
||||
else if (!one_line.fromargv (newargv, real_path.get_win32 (), real_path.iscygexec ()))
|
||||
else if (!one_line.fromargv (newargv, real_path.get_win32 (),
|
||||
real_path.iscygexec ()))
|
||||
{
|
||||
res = -1;
|
||||
goto out;
|
||||
@ -395,12 +400,14 @@ spawn_guts (const char * prog_arg, const char *const *argv,
|
||||
|
||||
if (mode != _P_OVERLAY ||
|
||||
!DuplicateHandle (hMainProc, myself.shared_handle (), hMainProc,
|
||||
&moreinfo->myself_pinfo, 0,
|
||||
TRUE, DUPLICATE_SAME_ACCESS))
|
||||
&moreinfo->myself_pinfo, 0, TRUE,
|
||||
DUPLICATE_SAME_ACCESS))
|
||||
moreinfo->myself_pinfo = NULL;
|
||||
else
|
||||
VerifyHandle (moreinfo->myself_pinfo);
|
||||
}
|
||||
WCHAR wone_line[one_line.ix + 1];
|
||||
sys_mbstowcs (wone_line, one_line.ix + 1, one_line.buf);
|
||||
|
||||
PROCESS_INFORMATION pi;
|
||||
pi.hProcess = pi.hThread = NULL;
|
||||
@ -418,7 +425,7 @@ spawn_guts (const char * prog_arg, const char *const *argv,
|
||||
|
||||
c_flags = GetPriorityClass (hMainProc);
|
||||
sigproc_printf ("priority class %d", c_flags);
|
||||
c_flags |= CREATE_SEPARATE_WOW_VDM;
|
||||
c_flags |= CREATE_SEPARATE_WOW_VDM | CREATE_UNICODE_ENVIRONMENT;
|
||||
|
||||
if (mode == _P_DETACH)
|
||||
c_flags |= DETACHED_PROCESS;
|
||||
@ -444,8 +451,9 @@ spawn_guts (const char * prog_arg, const char *const *argv,
|
||||
generating its own pids again? */
|
||||
if (cygheap->pid_handle)
|
||||
/* already done previously */;
|
||||
else if (DuplicateHandle (hMainProc, hMainProc, hMainProc, &cygheap->pid_handle,
|
||||
PROCESS_QUERY_INFORMATION, TRUE, 0))
|
||||
else if (DuplicateHandle (hMainProc, hMainProc, hMainProc,
|
||||
&cygheap->pid_handle, PROCESS_QUERY_INFORMATION,
|
||||
TRUE, 0))
|
||||
ProtectHandleINH (cygheap->pid_handle);
|
||||
else
|
||||
system_printf ("duplicate to pid_handle failed, %E");
|
||||
@ -456,19 +464,22 @@ spawn_guts (const char * prog_arg, const char *const *argv,
|
||||
So we have to start the child in suspend state, unfortunately, to avoid
|
||||
a race condition. */
|
||||
if (!newargv.win16_exe
|
||||
&& (!ch.iscygwin () || mode != _P_OVERLAY || cygheap->fdtab.need_fixup_before ()))
|
||||
&& (!ch.iscygwin () || mode != _P_OVERLAY
|
||||
|| cygheap->fdtab.need_fixup_before ()))
|
||||
c_flags |= CREATE_SUSPENDED;
|
||||
|
||||
runpath = null_app_name ? NULL : real_path.get_win32 ();
|
||||
runpath = null_app_name ? NULL : real_path.get_wide_win32_path (runpath);
|
||||
|
||||
syscall_printf ("null_app_name %d (%s, %.9500s)", null_app_name, runpath, one_line.buf);
|
||||
syscall_printf ("null_app_name %d (%W, %.9500W)", null_app_name,
|
||||
runpath, wone_line);
|
||||
|
||||
cygbench ("spawn-guts");
|
||||
|
||||
if (!real_path.iscygexec())
|
||||
cygheap->fdtab.set_file_pointers_for_exec ();
|
||||
|
||||
moreinfo->envp = build_env (envp, envblock, moreinfo->envc, real_path.iscygexec ());
|
||||
moreinfo->envp = build_env (envp, envblock, moreinfo->envc,
|
||||
real_path.iscygexec ());
|
||||
if (!moreinfo->envp || !envblock)
|
||||
{
|
||||
set_errno (E2BIG);
|
||||
@ -496,16 +507,16 @@ loop:
|
||||
&& cygheap->user.saved_gid == cygheap->user.real_gid
|
||||
&& !cygheap->user.groups.issetgroups ()))
|
||||
{
|
||||
rc = CreateProcess (runpath, /* image name - with full path */
|
||||
one_line.buf, /* what was passed to exec */
|
||||
&sec_none_nih,/* process security attrs */
|
||||
&sec_none_nih,/* thread security attrs */
|
||||
TRUE, /* inherit handles from parent */
|
||||
c_flags,
|
||||
envblock, /* environment */
|
||||
NULL,
|
||||
&si,
|
||||
&pi);
|
||||
rc = CreateProcessW (runpath, /* image name - with full path */
|
||||
wone_line, /* what was passed to exec */
|
||||
&sec_none_nih, /* process security attrs */
|
||||
&sec_none_nih, /* thread security attrs */
|
||||
TRUE, /* inherit handles from parent */
|
||||
c_flags,
|
||||
envblock, /* environment */
|
||||
NULL,
|
||||
&si,
|
||||
&pi);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -513,7 +524,7 @@ loop:
|
||||
if (mode == _P_OVERLAY)
|
||||
myself.set_acl();
|
||||
|
||||
char wstname[1024] = { '\0' };
|
||||
WCHAR wstname[1024] = { L'\0' };
|
||||
HWINSTA hwst_orig = NULL, hwst = NULL;
|
||||
HDESK hdsk_orig = NULL, hdsk = NULL;
|
||||
PSECURITY_ATTRIBUTES sa;
|
||||
@ -521,16 +532,16 @@ loop:
|
||||
|
||||
hwst_orig = GetProcessWindowStation ();
|
||||
hdsk_orig = GetThreadDesktop (GetCurrentThreadId ());
|
||||
GetUserObjectInformation (hwst_orig, UOI_NAME, wstname, 1024, &n);
|
||||
GetUserObjectInformationW (hwst_orig, UOI_NAME, wstname, 1024, &n);
|
||||
/* Prior to Vista it was possible to start a service with the
|
||||
"Interact with desktop" flag. This started the service in the
|
||||
interactive window station of the console. A big security
|
||||
risk, but we don't want to disable this behaviour for older
|
||||
OSes because it's still heavily used by some users. They have
|
||||
been warned. */
|
||||
if (!ascii_strcasematch (wstname, "WinSta0"))
|
||||
if (wcscasecmp (wstname, L"WinSta0") != 0)
|
||||
{
|
||||
char sid[128];
|
||||
WCHAR sid[128];
|
||||
|
||||
sa = sec_user ((PSECURITY_ATTRIBUTES) alloca (1024),
|
||||
cygheap->user.sid ());
|
||||
@ -540,34 +551,34 @@ loop:
|
||||
make sense in terms of security to create a new window
|
||||
station for every logon of the same user. It just fills up
|
||||
the system with window stations for no good reason. */
|
||||
hwst = CreateWindowStationA (cygheap->user.get_windows_id (sid), 0,
|
||||
hwst = CreateWindowStationW (cygheap->user.get_windows_id (sid), 0,
|
||||
GENERIC_READ | GENERIC_WRITE, sa);
|
||||
if (!hwst)
|
||||
system_printf ("CreateWindowStation failed, %E");
|
||||
else if (!SetProcessWindowStation (hwst))
|
||||
system_printf ("SetProcessWindowStation failed, %E");
|
||||
else if (!(hdsk = CreateDesktopA ("Default", NULL, NULL, 0,
|
||||
else if (!(hdsk = CreateDesktopW (L"Default", NULL, NULL, 0,
|
||||
GENERIC_ALL, sa)))
|
||||
system_printf ("CreateDesktop failed, %E");
|
||||
else
|
||||
{
|
||||
stpcpy (stpcpy (wstname, sid), "\\Default");
|
||||
wcpcpy (wcpcpy (wstname, sid), L"\\Default");
|
||||
si.lpDesktop = wstname;
|
||||
debug_printf ("Desktop: %s", si.lpDesktop);
|
||||
debug_printf ("Desktop: %W", si.lpDesktop);
|
||||
}
|
||||
}
|
||||
|
||||
rc = CreateProcessAsUser (cygheap->user.primary_token (),
|
||||
runpath, /* image name - with full path */
|
||||
one_line.buf, /* what was passed to exec */
|
||||
&sec_none_nih, /* process security attrs */
|
||||
&sec_none_nih, /* thread security attrs */
|
||||
TRUE, /* inherit handles from parent */
|
||||
c_flags,
|
||||
envblock, /* environment */
|
||||
NULL,
|
||||
&si,
|
||||
&pi);
|
||||
rc = CreateProcessAsUserW (cygheap->user.primary_token (),
|
||||
runpath, /* image name - with full path */
|
||||
wone_line, /* what was passed to exec */
|
||||
&sec_none_nih, /* process security attrs */
|
||||
&sec_none_nih, /* thread security attrs */
|
||||
TRUE, /* inherit handles from parent */
|
||||
c_flags,
|
||||
envblock, /* environment */
|
||||
NULL,
|
||||
&si,
|
||||
&pi);
|
||||
if (hwst)
|
||||
{
|
||||
SetProcessWindowStation (hwst_orig);
|
||||
@ -952,16 +963,22 @@ av::fixup (const char *prog_arg, path_conv& real_path, const char *ext)
|
||||
char *pgm = NULL;
|
||||
char *arg1 = NULL;
|
||||
char *ptr, *buf;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
IO_STATUS_BLOCK io;
|
||||
HANDLE h;
|
||||
NTSTATUS status;
|
||||
|
||||
HANDLE h = CreateFile (real_path.get_win32 (), GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
&sec_none_nih, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL, 0);
|
||||
if (h == INVALID_HANDLE_VALUE)
|
||||
status = NtOpenFile (&h, SYNCHRONIZE | GENERIC_READ,
|
||||
real_path.get_object_attr (attr, sec_none_nih),
|
||||
&io, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
FILE_SYNCHRONOUS_IO_NONALERT
|
||||
| FILE_OPEN_FOR_BACKUP_INTENT
|
||||
| FILE_NON_DIRECTORY_FILE);
|
||||
if (!NT_SUCCESS (status))
|
||||
goto err;
|
||||
|
||||
HANDLE hm = CreateFileMapping (h, &sec_none_nih, PAGE_READONLY, 0, 0, NULL);
|
||||
CloseHandle (h);
|
||||
NtClose (h);
|
||||
if (!hm)
|
||||
{
|
||||
/* ERROR_FILE_INVALID indicates very likely an empty file. */
|
||||
|
Reference in New Issue
Block a user