* 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:
Corinna Vinschen
2008-03-07 11:24:51 +00:00
parent d8e218442b
commit 752b16ce35
22 changed files with 467 additions and 203 deletions

View File

@ -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. */