* Throughout, use __try/__except/__endtry blocks, rather than myfault

handler.
	* cygtls.cc (_cygtls::remove): Accommodate the fact that pathbufs
	has been moved from _local_storage to _cygtls.
	* cygtls.h (class tls_pathbuf): Add comment to hint to gendef usage
	of counters.  Change type of counters to uint32_t for clarity.
	Remove _cygtls as friend class.
	(struct _local_storage): Move pathbufs from here...
	(struct _cygtls): ...to here, allowing to access it from _sigbe.
	(class san): Only define on 32 bit.  Remove errno, _c_cnt and _w_cnt
	members.
	(san::setup): Drop parameter.  Don't initialize removed members.
	(san::leave): Don't set removed members.
	(class myfault): Only define on 32 bit.
	(myfault::faulted): Only keep implementation not taking any parameter.
	Drop argument in call to sebastian.setup.
	(__try/__leave/__except/__endtry): Implement to support real SEH.  For
	now stick to SJLJ on 32 bit.
	* dcrt0.cc (dll_crt0_0): Drop 64 bit call to
	exception::install_myfault_handler.
	* exception.h (exception_handler): Define with EXCEPTION_DISPOSITION
	as return type.
	(PDISPATCHER_CONTEXT): Define as void * on 32 bit.  Define as pointer
	to _DISPATCHER_CONTEXT on 64 bit.
	(class exception): Define separately for 32 and 64 bit.
	(exception::myfault): Add handler for myfault SEH handling on 64 bit.
	(exception::exception): Fix mangled method name to account for change
	in type of last parameter.
	(exception::install_myfault_handler): Remove.
	* exceptions.cc (exception::myfault_handle): Remove.
	(exception::myfault): New SEH handler for 64 bit.
	* gendef (_sigbe): Set tls_pathbuf counters to 0 explicitely when
	returning to the caller.
	* ntdll.h: Move a comment to a better place.
	(struct _SCOPE_TABLE): Define on 64 bit.
	* thread.cc (verifyable_object_isvalid): Remove gcc 4.7 workaround.
	* tls_pbuf.cc (tls_pbuf): Fix to accommodate new place of pathbufs.
	(tls_pathbuf::destroy): Change type of loop variables to uint32_t.
	* tls_pbuf.h (class tmp_pathbuf): Change type of buffer counters to
	uint32_t.  Accommodate new place of pathbufs.
	* tlsoffsets.h: Regenerate.
	* tlsoffsets64.h: Regenerate.
This commit is contained in:
Corinna Vinschen 2014-08-22 09:21:33 +00:00
parent 33ed7bb5bc
commit 3f3bd10104
41 changed files with 6383 additions and 5924 deletions

View File

@ -1,3 +1,48 @@
2014-08-21 Corinna Vinschen <corinna@vinschen.de>
* Throughout, use __try/__except/__endtry blocks, rather than myfault
handler.
* cygtls.cc (_cygtls::remove): Accommodate the fact that pathbufs
has been moved from _local_storage to _cygtls.
* cygtls.h (class tls_pathbuf): Add comment to hint to gendef usage
of counters. Change type of counters to uint32_t for clarity.
Remove _cygtls as friend class.
(struct _local_storage): Move pathbufs from here...
(struct _cygtls): ...to here, allowing to access it from _sigbe.
(class san): Only define on 32 bit. Remove errno, _c_cnt and _w_cnt
members.
(san::setup): Drop parameter. Don't initialize removed members.
(san::leave): Don't set removed members.
(class myfault): Only define on 32 bit.
(myfault::faulted): Only keep implementation not taking any parameter.
Drop argument in call to sebastian.setup.
(__try/__leave/__except/__endtry): Implement to support real SEH. For
now stick to SJLJ on 32 bit.
* dcrt0.cc (dll_crt0_0): Drop 64 bit call to
exception::install_myfault_handler.
* exception.h (exception_handler): Define with EXCEPTION_DISPOSITION
as return type.
(PDISPATCHER_CONTEXT): Define as void * on 32 bit. Define as pointer
to _DISPATCHER_CONTEXT on 64 bit.
(class exception): Define separately for 32 and 64 bit.
(exception::myfault): Add handler for myfault SEH handling on 64 bit.
(exception::exception): Fix mangled method name to account for change
in type of last parameter.
(exception::install_myfault_handler): Remove.
* exceptions.cc (exception::myfault_handle): Remove.
(exception::myfault): New SEH handler for 64 bit.
* gendef (_sigbe): Set tls_pathbuf counters to 0 explicitely when
returning to the caller.
* ntdll.h: Move a comment to a better place.
(struct _SCOPE_TABLE): Define on 64 bit.
* thread.cc (verifyable_object_isvalid): Remove gcc 4.7 workaround.
* tls_pbuf.cc (tls_pbuf): Fix to accommodate new place of pathbufs.
(tls_pathbuf::destroy): Change type of loop variables to uint32_t.
* tls_pbuf.h (class tmp_pathbuf): Change type of buffer counters to
uint32_t. Accommodate new place of pathbufs.
* tlsoffsets.h: Regenerate.
* tlsoffsets64.h: Regenerate.
2014-08-21 Corinna Vinschen <corinna@vinschen.de> 2014-08-21 Corinna Vinschen <corinna@vinschen.de>
* miscfuncs.cc (__import_address): Cover the first dereference to imp * miscfuncs.cc (__import_address): Cover the first dereference to imp

View File

@ -638,10 +638,7 @@ init_cygheap::find_tls (int sig, bool& issig_wait)
_cygtls *t = NULL; _cygtls *t = NULL;
issig_wait = false; issig_wait = false;
myfault efault; __try
if (efault.faulted ())
threadlist[ix]->remove (INFINITE);
else
{ {
ix = -1; ix = -1;
/* Scan thread list looking for valid signal-delivery candidates */ /* Scan thread list looking for valid signal-delivery candidates */
@ -652,11 +649,15 @@ init_cygheap::find_tls (int sig, bool& issig_wait)
{ {
t = cygheap->threadlist[ix]; t = cygheap->threadlist[ix];
issig_wait = true; issig_wait = true;
goto out; __leave;
} }
else if (!t && !sigismember (&(threadlist[ix]->sigmask), sig)) else if (!t && !sigismember (&(threadlist[ix]->sigmask), sig))
t = cygheap->threadlist[ix]; t = cygheap->threadlist[ix];
} }
out: __except (NO_ERROR)
{
threadlist[ix]->remove (INFINITE);
}
__endtry
return t; return t;
} }

View File

@ -193,7 +193,7 @@ _cygtls::remove (DWORD wait)
free_local (servent_buf); free_local (servent_buf);
free_local (hostent_buf); free_local (hostent_buf);
/* Free temporary TLS path buffers. */ /* Free temporary TLS path buffers. */
locals.pathbufs.destroy (); pathbufs.destroy ();
/* Close timer handle. */ /* Close timer handle. */
if (locals.cw_timer) if (locals.cw_timer)
NtClose (locals.cw_timer); NtClose (locals.cw_timer);

View File

@ -44,18 +44,21 @@ details. */
#else #else
#pragma pack(push,4) #pragma pack(push,4)
#endif #endif
/* Defined here to support auto rebuild of tlsoffsets.h. */ /* Defined here to support auto rebuild of tlsoffsets.h. */
class tls_pathbuf class tls_pathbuf
{ {
int c_cnt; /* Make sure that c_cnt and w_cnt are always the first two members of this
int w_cnt; class, and never change the size (32 bit), unless you also change the
mov statements in sigbe! */
uint32_t c_cnt;
uint32_t w_cnt;
char *c_buf[TP_NUM_C_BUFS]; char *c_buf[TP_NUM_C_BUFS];
WCHAR *w_buf[TP_NUM_W_BUFS]; WCHAR *w_buf[TP_NUM_W_BUFS];
public: public:
void destroy (); void destroy ();
friend class tmp_pathbuf; friend class tmp_pathbuf;
friend class _cygtls;
friend class san; friend class san;
}; };
@ -129,8 +132,6 @@ struct _local_storage
/* thread.cc */ /* thread.cc */
HANDLE cw_timer; HANDLE cw_timer;
/* All functions requiring temporary path buffers. */
tls_pathbuf pathbufs;
char ttybuf[32]; char ttybuf[32];
}; };
@ -188,6 +189,7 @@ public:
struct pthread *tid; struct pthread *tid;
class cygthread *_ctinfo; class cygthread *_ctinfo;
class san *andreas; class san *andreas;
tls_pathbuf pathbufs;
waitq wq; waitq wq;
int sig; int sig;
unsigned incyg; unsigned incyg;
@ -281,34 +283,25 @@ const int CYGTLS_PADSIZE = 12700;
extern PVOID _tlsbase __asm__ ("%fs:4"); extern PVOID _tlsbase __asm__ ("%fs:4");
extern PVOID _tlstop __asm__ ("%fs:8"); extern PVOID _tlstop __asm__ ("%fs:8");
#endif #endif
#define _my_tls (*((_cygtls *) ((char *)_tlsbase - CYGTLS_PADSIZE))) #define _my_tls (*((_cygtls *) ((char *)_tlsbase - CYGTLS_PADSIZE)))
extern _cygtls *_main_tls; extern _cygtls *_main_tls;
extern _cygtls *_sig_tls; extern _cygtls *_sig_tls;
#ifndef __x86_64__
class san class san
{ {
san *_clemente; san *_clemente;
jmp_buf _context; jmp_buf _context;
int _errno;
unsigned _c_cnt;
unsigned _w_cnt;
public: public:
int setup (int myerrno = 0) __attribute__ ((always_inline)) int setup () __attribute__ ((always_inline))
{ {
_clemente = _my_tls.andreas; _clemente = _my_tls.andreas;
_my_tls.andreas = this; _my_tls.andreas = this;
_errno = myerrno;
_c_cnt = _my_tls.locals.pathbufs.c_cnt;
_w_cnt = _my_tls.locals.pathbufs.w_cnt;
return __sjfault (_context); return __sjfault (_context);
} }
void leave () __attribute__ ((always_inline)) void leave () __attribute__ ((always_inline))
{ {
if (_errno)
set_errno (_errno);
/* Restore tls_pathbuf counters in case of error. */
_my_tls.locals.pathbufs.c_cnt = _c_cnt;
_my_tls.locals.pathbufs.w_cnt = _w_cnt;
__ljfault (_context, 1); __ljfault (_context, 1);
} }
void reset () __attribute__ ((always_inline)) void reset () __attribute__ ((always_inline))
@ -324,17 +317,73 @@ public:
~myfault () __attribute__ ((always_inline)) { sebastian.reset (); } ~myfault () __attribute__ ((always_inline)) { sebastian.reset (); }
inline int faulted () __attribute__ ((always_inline)) inline int faulted () __attribute__ ((always_inline))
{ {
return sebastian.setup (0); return sebastian.setup ();
}
inline int faulted (void const *obj, int myerrno = 0) __attribute__ ((always_inline))
{
return !obj || !(*(const char **) obj) || sebastian.setup (myerrno);
}
inline int faulted (int myerrno) __attribute__ ((always_inline))
{
return sebastian.setup (myerrno);
} }
}; };
#endif
/* Exception handling macros. These are required because SEH differs a lot
between 32 and 64 bit. Essentially, on 64 bit, we have to create compile
time SEH tables which define the handler and try/except labels, while on
32 bit we can simply set up an SJLJ handler within the myfault class. */
#define __mem_barrier __asm__ __volatile__ ("" ::: "memory")
#ifdef __x86_64__
#define __try \
{ \
__label__ __l_try, __l_except, __l_endtry; \
__mem_barrier; \
__asm__ goto ("\n" \
" .seh_handler _ZN9exception7myfaultEP17_EXCEPTION_RECORDPvP8_CONTEXTP19_DISPATCHER_CONTEXT, @except \n" \
" .seh_handlerdata \n" \
" .long 1 \n" \
" .rva %l[__l_try],%l[__l_endtry],%l[__l_except],%l[__l_except] \n" \
" .seh_code \n" \
: : : : __l_try, __l_endtry, __l_except); \
{ \
__l_try: \
__mem_barrier;
#define __leave \
goto __l_endtry
#define __except(__errno) \
goto __l_endtry; \
} \
{ \
__l_except: \
__mem_barrier; \
if (__errno) \
set_errno (__errno);
#define __endtry \
} \
__l_endtry: \
__mem_barrier; \
}
#else /* !__x86_64__ */
#define __try \
{ \
myfault efault; \
if (!efault.faulted ()) \
{
#define __leave \
goto __l_endtry
#define __except(__errno) \
goto __l_endtry; \
} \
{ \
if (__errno) \
set_errno (__errno);
#define __endtry \
} \
__l_endtry: \
__mem_barrier; \
}
#endif /* __x86_64__ */
class set_signal_arrived class set_signal_arrived
{ {

View File

@ -796,10 +796,6 @@ dll_crt0_0 ()
_main_tls = &_my_tls; _main_tls = &_my_tls;
#ifdef __x86_64__
exception::install_myfault_handler ();
#endif
/* Initialize signal processing here, early, in the hopes that the creation /* Initialize signal processing here, early, in the hopes that the creation
of a thread early in the process will cause more predictability in memory of a thread early in the process will cause more predictability in memory
layout for the main thread. */ layout for the main thread. */

View File

@ -28,16 +28,16 @@ details. */
extern "C" int extern "C" int
dirfd (DIR *dir) dirfd (DIR *dir)
{ {
myfault efault; __try
if (efault.faulted (EFAULT))
return -1;
if (dir->__d_cookie != __DIRENT_COOKIE)
{ {
set_errno (EINVAL); if (dir->__d_cookie == __DIRENT_COOKIE)
syscall_printf ("-1 = dirfd (%p)", dir);
return -1;
}
return dir->__d_fd; return dir->__d_fd;
syscall_printf ("-1 = dirfd (%p)", dir);
set_errno (EINVAL);
}
__except (EFAULT) {}
__endtry
return -1;
} }
/* Symbol kept for backward compatibility. Don't remove. Don't declare /* Symbol kept for backward compatibility. Don't remove. Don't declare
@ -93,21 +93,22 @@ fdopendir (int fd)
static int static int
readdir_worker (DIR *dir, dirent *de) readdir_worker (DIR *dir, dirent *de)
{ {
myfault efault; int res = 0;
if (efault.faulted ())
return EFAULT;
__try
{
if (dir->__d_cookie != __DIRENT_COOKIE) if (dir->__d_cookie != __DIRENT_COOKIE)
{ {
syscall_printf ("%p = readdir (%p)", NULL, dir); syscall_printf ("%p = readdir (%p)", NULL, dir);
return EBADF; res = EBADF;
__leave;
} }
de->d_ino = 0; de->d_ino = 0;
de->d_type = DT_UNKNOWN; de->d_type = DT_UNKNOWN;
memset (&de->__d_unused1, 0, sizeof (de->__d_unused1)); memset (&de->__d_unused1, 0, sizeof (de->__d_unused1));
int res = ((fhandler_base *) dir->__fh)->readdir (dir, de); res = ((fhandler_base *) dir->__fh)->readdir (dir, de);
if (res == ENMFILE) if (res == ENMFILE)
{ {
@ -141,7 +142,8 @@ readdir_worker (DIR *dir, dirent *de)
} }
if (is_dot_dot && !(dir->__flags & dirent_isroot)) if (is_dot_dot && !(dir->__flags & dirent_isroot))
de->d_ino = readdir_get_ino (((fhandler_base *) dir->__fh)->get_name (), de->d_ino = readdir_get_ino (((fhandler_base *)
dir->__fh)->get_name (),
true); true);
else else
{ {
@ -165,7 +167,12 @@ readdir_worker (DIR *dir, dirent *de)
/* This fills out the old 32 bit d_ino field for old applications, /* This fills out the old 32 bit d_ino field for old applications,
build under Cygwin before 1.5.x. */ build under Cygwin before 1.5.x. */
de->__d_internal1 = de->d_ino; de->__d_internal1 = de->d_ino;
}
__except (NO_ERROR)
{
res = EFAULT;
}
__endtry
return res; return res;
} }
@ -200,16 +207,15 @@ readdir_r (DIR *__restrict dir, dirent *__restrict de, dirent **__restrict ode)
extern "C" long extern "C" long
telldir (DIR *dir) telldir (DIR *dir)
{ {
myfault efault; __try
if (efault.faulted (EFAULT))
return -1;
if (dir->__d_cookie != __DIRENT_COOKIE)
{ {
set_errno (EBADF); if (dir->__d_cookie == __DIRENT_COOKIE)
return -1;
}
return ((fhandler_base *) dir->__fh)->telldir (dir); return ((fhandler_base *) dir->__fh)->telldir (dir);
set_errno (EBADF);
}
__except (EFAULT) {}
__endtry
return -1;
} }
/* telldir was never defined using off_t in POSIX, only in early versions /* telldir was never defined using off_t in POSIX, only in early versions
@ -225,14 +231,17 @@ telldir64 (DIR *dir)
extern "C" void extern "C" void
seekdir (DIR *dir, long loc) seekdir (DIR *dir, long loc)
{ {
myfault efault; __try
if (efault.faulted (EFAULT)) {
return; if (dir->__d_cookie == __DIRENT_COOKIE)
{
if (dir->__d_cookie != __DIRENT_COOKIE)
return;
dir->__flags &= dirent_info_mask; dir->__flags &= dirent_info_mask;
return ((fhandler_base *) dir->__fh)->seekdir (dir, loc); ((fhandler_base *) dir->__fh)->seekdir (dir, loc);
}
set_errno (EINVAL); /* Diagnosis */
}
__except (EFAULT) {}
__endtry
} }
/* seekdir was never defined using off_t in POSIX, only in early versions /* seekdir was never defined using off_t in POSIX, only in early versions
@ -248,31 +257,27 @@ seekdir64 (DIR *dir, off_t loc)
extern "C" void extern "C" void
rewinddir (DIR *dir) rewinddir (DIR *dir)
{ {
myfault efault; __try
if (efault.faulted (EFAULT)) {
return; if (dir->__d_cookie == __DIRENT_COOKIE)
{
if (dir->__d_cookie != __DIRENT_COOKIE)
return;
dir->__flags &= dirent_info_mask; dir->__flags &= dirent_info_mask;
return ((fhandler_base *) dir->__fh)->rewinddir (dir); ((fhandler_base *) dir->__fh)->rewinddir (dir);
}
set_errno (EINVAL); /* Diagnosis */
}
__except (EFAULT) {}
__endtry
} }
/* closedir: POSIX 5.1.2.1 */ /* closedir: POSIX 5.1.2.1 */
extern "C" int extern "C" int
closedir (DIR *dir) closedir (DIR *dir)
{ {
myfault efault; __try
if (efault.faulted (EFAULT)) {
return -1; if (dir->__d_cookie == __DIRENT_COOKIE)
if (dir->__d_cookie != __DIRENT_COOKIE)
{ {
set_errno (EBADF);
syscall_printf ("%R = closedir(%p)", -1, dir);
return -1;
}
/* Reset the marker in case the caller tries to use `dir' again. */ /* Reset the marker in case the caller tries to use `dir' again. */
dir->__d_cookie = 0; dir->__d_cookie = 0;
@ -284,6 +289,13 @@ closedir (DIR *dir)
free (dir); free (dir);
syscall_printf ("%R = closedir(%p)", res, dir); syscall_printf ("%R = closedir(%p)", res, dir);
return res; return res;
}
set_errno (EBADF);
}
__except (EFAULT) {}
__endtry
syscall_printf ("%R = closedir(%p)", -1, dir);
return -1;
} }
/* mkdir: POSIX 5.4.1.1 */ /* mkdir: POSIX 5.4.1.1 */
@ -294,10 +306,8 @@ mkdir (const char *dir, mode_t mode)
fhandler_base *fh = NULL; fhandler_base *fh = NULL;
tmp_pathbuf tp; tmp_pathbuf tp;
myfault efault; __try
if (efault.faulted (EFAULT)) {
return -1;
/* POSIX says mkdir("symlink-to-missing/") should create the /* POSIX says mkdir("symlink-to-missing/") should create the
directory "missing", but Linux rejects it with EEXIST. Copy directory "missing", but Linux rejects it with EEXIST. Copy
Linux behavior for now. */ Linux behavior for now. */
@ -305,7 +315,7 @@ mkdir (const char *dir, mode_t mode)
if (!*dir) if (!*dir)
{ {
set_errno (ENOENT); set_errno (ENOENT);
goto done; __leave;
} }
if (isdirsep (dir[strlen (dir) - 1])) if (isdirsep (dir[strlen (dir) - 1]))
{ {
@ -317,7 +327,7 @@ mkdir (const char *dir, mode_t mode)
*p-- = '\0'; *p-- = '\0';
} }
if (!(fh = build_fh_name (dir, PC_SYM_NOFOLLOW))) if (!(fh = build_fh_name (dir, PC_SYM_NOFOLLOW)))
goto done; /* errno already set */; __leave; /* errno already set */;
if (fh->error ()) if (fh->error ())
{ {
@ -329,8 +339,9 @@ mkdir (const char *dir, mode_t mode)
else if (!fh->mkdir (mode)) else if (!fh->mkdir (mode))
res = 0; res = 0;
delete fh; delete fh;
}
done: __except (EFAULT) {}
__endtry
syscall_printf ("%R = mkdir(%s, %d)", res, dir, mode); syscall_printf ("%R = mkdir(%s, %d)", res, dir, mode);
return res; return res;
} }
@ -342,12 +353,10 @@ rmdir (const char *dir)
int res = -1; int res = -1;
fhandler_base *fh = NULL; fhandler_base *fh = NULL;
myfault efault; __try
if (efault.faulted (EFAULT)) {
return -1;
if (!(fh = build_fh_name (dir, PC_SYM_NOFOLLOW))) if (!(fh = build_fh_name (dir, PC_SYM_NOFOLLOW)))
goto done; /* errno already set */; __leave; /* errno already set */;
if (fh->error ()) if (fh->error ())
{ {
@ -362,10 +371,10 @@ rmdir (const char *dir)
set_errno (ENOTEMPTY); set_errno (ENOTEMPTY);
else if (!fh->rmdir ()) else if (!fh->rmdir ())
res = 0; res = 0;
delete fh; delete fh;
}
done: __except (EFAULT) {}
__endtry
syscall_printf ("%R = rmdir(%s)", res, dir); syscall_printf ("%R = rmdir(%s)", res, dir);
return res; return res;
} }

View File

@ -2,7 +2,7 @@
process's environment. process's environment.
Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc. 2008, 2009, 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
This software is a copyrighted work licensed under the terms of the This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for Cygwin license. Please consult the file "CYGWIN_LICENSE" for
@ -664,9 +664,8 @@ _addenv (const char *name, const char *value, int overwrite)
extern "C" int extern "C" int
putenv (char *str) putenv (char *str)
{ {
myfault efault; __try
if (efault.faulted (EFAULT)) {
return -1;
if (*str) if (*str)
{ {
char *eq = strchr (str, '='); char *eq = strchr (str, '=');
@ -677,6 +676,10 @@ putenv (char *str)
unsetenv (str); unsetenv (str);
} }
return 0; return 0;
}
__except (EFAULT) {}
__endtry
return -1;
} }
/* Set the value of the environment variable "name" to be /* Set the value of the environment variable "name" to be
@ -684,15 +687,18 @@ putenv (char *str)
extern "C" int extern "C" int
setenv (const char *name, const char *value, int overwrite) setenv (const char *name, const char *value, int overwrite)
{ {
myfault efault; __try
if (efault.faulted (EFAULT)) {
return -1;
if (!name || !*name || strchr (name, '=')) if (!name || !*name || strchr (name, '='))
{ {
set_errno (EINVAL); set_errno (EINVAL);
return -1; __leave;
} }
return _addenv (name, value, !!overwrite); return _addenv (name, value, !!overwrite);
}
__except (EFAULT) {}
__endtry
return -1;
} }
/* Delete environment variable "name". */ /* Delete environment variable "name". */
@ -701,13 +707,13 @@ unsetenv (const char *name)
{ {
register char **e; register char **e;
int offset; int offset;
myfault efault;
if (efault.faulted (EFAULT)) __try
return -1; {
if (!name || *name == '\0' || strchr (name, '=')) if (!name || *name == '\0' || strchr (name, '='))
{ {
set_errno (EINVAL); set_errno (EINVAL);
return -1; __leave;
} }
while (my_findenv (name, &offset)) /* if set multiple times */ while (my_findenv (name, &offset)) /* if set multiple times */
@ -717,6 +723,10 @@ unsetenv (const char *name)
break; break;
return 0; return 0;
}
__except (EFAULT) {}
__endtry
return -1;
} }
/* Minimal list of Windows vars which must be converted to uppercase. /* Minimal list of Windows vars which must be converted to uppercase.
@ -822,12 +832,10 @@ environ_init (char **envp, int envc)
bool envp_passed_in; bool envp_passed_in;
bool got_something_from_registry; bool got_something_from_registry;
static char NO_COPY cygterm[] = "TERM=cygwin"; static char NO_COPY cygterm[] = "TERM=cygwin";
myfault efault;
tmp_pathbuf tp; tmp_pathbuf tp;
if (efault.faulted ()) __try
api_fatal ("internal error reading the windows environment - too many environment variables?"); {
char *tmpbuf = tp.t_get (); char *tmpbuf = tp.t_get ();
got_something_from_registry = regopt (L"default", tmpbuf); got_something_from_registry = regopt (L"default", tmpbuf);
if (myself->progname[0]) if (myself->progname[0])
@ -897,7 +905,7 @@ environ_init (char **envp, int envc)
envp[i] = NULL; envp[i] = NULL;
FreeEnvironmentStringsW (rawenv); FreeEnvironmentStringsW (rawenv);
out: out:
findenv_func = (char * (*)(const char*, int*)) my_findenv; findenv_func = (char * (*)(const char*, int*)) my_findenv;
__cygwin_environ = envp; __cygwin_environ = envp;
update_envptrs (); update_envptrs ();
@ -912,6 +920,13 @@ out:
parse_options (NULL); /* possibly export registry settings to parse_options (NULL); /* possibly export registry settings to
environment */ environment */
MALLOC_CHECK; MALLOC_CHECK;
}
__except (NO_ERROR)
{
api_fatal ("internal error reading the windows environment "
"- too many environment variables?");
}
__endtry
} }
/* Function called by qsort to sort environment strings. */ /* Function called by qsort to sort environment strings. */

View File

@ -94,8 +94,10 @@ to install your own exception filter. This one is documented.
a teensy bit of detail of the innards of exception handling (i.e. what we a teensy bit of detail of the innards of exception handling (i.e. what we
have to do). */ have to do). */
typedef int (exception_handler) (EXCEPTION_RECORD *, struct _exception_list *, typedef EXCEPTION_DISPOSITION (exception_handler) (EXCEPTION_RECORD *,
CONTEXT *, void *); struct _exception_list *,
CONTEXT *,
void *);
typedef struct _exception_list typedef struct _exception_list
{ {
@ -104,70 +106,53 @@ typedef struct _exception_list
} exception_list; } exception_list;
extern exception_list *_except_list asm ("%fs:0"); extern exception_list *_except_list asm ("%fs:0");
#else typedef void *PDISPATCHER_CONTEXT;
typedef void exception_list;
#endif /* !__x86_64 */
class exception class exception
{ {
#ifdef __x86_64__
static LONG myfault_handle (LPEXCEPTION_POINTERS ep);
#else
exception_list el; exception_list el;
exception_list *save; exception_list *save;
#endif /* __x86_64__ */ static EXCEPTION_DISPOSITION handle (EXCEPTION_RECORD *, exception_list *,
static int handle (EXCEPTION_RECORD *, exception_list *, CONTEXT *, void *); CONTEXT *, PDISPATCHER_CONTEXT);
public: public:
exception () __attribute__ ((always_inline)) exception () __attribute__ ((always_inline))
{ {
/* Install SEH handler. */ /* Install SEH handler. */
save = _except_list;
el.handler = handle;
el.prev = _except_list;
_except_list = &el;
};
~exception () __attribute__ ((always_inline)) { _except_list = save; }
};
#else
#define exception_list void
typedef struct _DISPATCHER_CONTEXT *PDISPATCHER_CONTEXT;
class exception
{
#ifdef __x86_64__ #ifdef __x86_64__
static EXCEPTION_DISPOSITION myfault (EXCEPTION_RECORD *, exception_list *,
CONTEXT *, PDISPATCHER_CONTEXT);
#endif
static EXCEPTION_DISPOSITION handle (EXCEPTION_RECORD *, exception_list *,
CONTEXT *, PDISPATCHER_CONTEXT);
public:
exception () __attribute__ ((always_inline))
{
/* Install SEH handler. */
asm volatile ("\n\ asm volatile ("\n\
1: \n\ 1: \n\
.seh_handler \ .seh_handler \
_ZN9exception6handleEP17_EXCEPTION_RECORDPvP8_CONTEXTS2_, \ _ZN9exception6handleEP17_EXCEPTION_RECORDPvP8_CONTEXTP19_DISPATCHER_CONTEXT, \
@except \n\ @except \n\
.seh_handlerdata \n\ .seh_handlerdata \n\
.long 1 \n\ .long 1 \n\
.rva 1b, 2f, 2f, 2f \n\ .rva 1b, 2f, 2f, 2f \n\
.seh_code \n"); .seh_code \n");
#else
save = _except_list;
el.handler = handle;
el.prev = _except_list;
_except_list = &el;
#endif /* __x86_64__ */
}; };
#ifdef __x86_64__
static void install_myfault_handler () __attribute__ ((always_inline))
{
/* Install myfault exception handler as VEH. Here's what happens:
Some Windows DLLs (advapi32, for instance) are using SEH to catch
exceptions inside its own functions. If we install a VEH handler
to catch all exceptions, our Cygwin VEH handler would illegitimatly
handle exceptions inside of Windows DLLs which are usually handled
by its own SEH handler. So, for standard exceptions we use an SEH
handler as installed in the constructor above so as not to override
the SEH handlers in Windows DLLs.
But we have a special case, myfault handling. The myfault handling
catches exceptions inside of the Cygwin DLL, some of them entirely
expected as in verifyable_object_isvalid. The ultimately right thing
to do would be to install SEH handlers for each of these cases.
But there are two problems with that:
1. It would be a massive and, partially unreliable change in the
calling functions due to the incomplete SEH support in GCC.
2. It doesn't always work. Certain DLLs appear to call Cygwin
functions during DLL initialization while the SEH handler is
not installed in the active call frame. For these cases we
need a more generic approach.
So, what we do here is to install a myfault VEH handler. This
function is called from dll_crt0_0, so the myfault handler is
available very early. */
AddVectoredExceptionHandler (1, myfault_handle);
}
~exception () __attribute__ ((always_inline)) ~exception () __attribute__ ((always_inline))
{ {
asm volatile ("\n\ asm volatile ("\n\
@ -175,11 +160,10 @@ public:
2: \n\ 2: \n\
nop \n"); nop \n");
} }
#else
~exception () __attribute__ ((always_inline)) { _except_list = save; }
#endif /* !__x86_64__ */
}; };
#endif /* !__x86_64 */
class cygwin_exception class cygwin_exception
{ {
PUINT_PTR framep; PUINT_PTR framep;

View File

@ -341,10 +341,9 @@ void
cygwin_exception::dumpstack () cygwin_exception::dumpstack ()
{ {
static bool already_dumped; static bool already_dumped;
myfault efault;
if (efault.faulted ())
return;
__try
{
if (already_dumped || cygheap->rlim_core == 0Ul) if (already_dumped || cygheap->rlim_core == 0Ul)
return; return;
already_dumped = true; already_dumped = true;
@ -366,13 +365,17 @@ cygwin_exception::dumpstack ()
small_printf (_AFMT " " _AFMT, thestack.sf.AddrFrame.Offset, small_printf (_AFMT " " _AFMT, thestack.sf.AddrFrame.Offset,
thestack.sf.AddrPC.Offset); thestack.sf.AddrPC.Offset);
for (unsigned j = 0; j < NPARAMS; j++) for (unsigned j = 0; j < NPARAMS; j++)
small_printf ("%s" _AFMT, j == 0 ? " (" : ", ", thestack.sf.Params[j]); small_printf ("%s" _AFMT, j == 0 ? " (" : ", ",
thestack.sf.Params[j]);
small_printf (")\r\n"); small_printf (")\r\n");
} }
small_printf ("End of stack trace%s\n", small_printf ("End of stack trace%s\n",
i == 16 ? " (more stack frames may be present)" : ""); i == 16 ? " (more stack frames may be present)" : "");
if (h) if (h)
NtClose (h); NtClose (h);
}
__except (NO_ERROR) {}
__endtry
} }
bool bool
@ -549,40 +552,24 @@ rtl_unwind (exception_list *frame, PEXCEPTION_RECORD e)
#endif /* __x86_64 */ #endif /* __x86_64 */
#ifdef __x86_64__ #ifdef __x86_64__
/* myfault vectored exception handler */ /* myfault exception handler. */
LONG EXCEPTION_DISPOSITION
exception::myfault_handle (LPEXCEPTION_POINTERS ep) exception::myfault (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in,
PDISPATCHER_CONTEXT dispatch)
{ {
_cygtls& me = _my_tls; PSCOPE_TABLE table = (PSCOPE_TABLE) dispatch->HandlerData;
RtlUnwindEx (frame,
if (me.andreas) (char *) dispatch->ImageBase + table->ScopeRecord[0].JumpTarget,
{ e, 0, in, dispatch->HistoryTable);
/* Only handle the minimum amount of exceptions the myfault handler /* NOTREACHED, make gcc happy. */
was designed for. */ return ExceptionContinueSearch;
switch (ep->ExceptionRecord->ExceptionCode)
{
case STATUS_ACCESS_VIOLATION:
case STATUS_DATATYPE_MISALIGNMENT:
#if 0
/* PAGE_GUARD-based stack commits are based on structured exception
handling. Short-circuiting STATUS_STACK_OVERFLOW in a vectored
exception handler disables that, which can ultimately result in
a spurious SEGV. */
case STATUS_STACK_OVERFLOW:
#endif
case STATUS_ARRAY_BOUNDS_EXCEEDED:
me.andreas->leave (); /* Return from a "san" caught fault */
default:
break;
}
}
return EXCEPTION_CONTINUE_SEARCH;
} }
#endif /* __x86_64 */ #endif
/* Main exception handler. */ /* Main exception handler. */
int EXCEPTION_DISPOSITION
exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, void *) exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in,
PDISPATCHER_CONTEXT dispatch)
{ {
static bool NO_COPY debugging; static bool NO_COPY debugging;
_cygtls& me = _my_tls; _cygtls& me = _my_tls;

View File

@ -1,7 +1,7 @@
/* fcntl.cc: fcntl syscall /* fcntl.cc: fcntl syscall
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2008, 2009, Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2008, 2009,
2010, 2011, 2012, 2013 Red Hat, Inc. 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -28,14 +28,13 @@ fcntl64 (int fd, int cmd, ...)
pthread_testcancel (); pthread_testcancel ();
debug_printf ("fcntl(%d, %d, ...)", fd, cmd); __try
myfault efault; {
if (efault.faulted (EFAULT))
return -1;
debug_printf ("fcntl(%d, %d, ...)", fd, cmd);
cygheap_fdget cfd (fd, true); cygheap_fdget cfd (fd, true);
if (cfd < 0) if (cfd < 0)
goto done; __leave;
/* FIXME? All numerical args to fcntl are defined as long on Linux. /* FIXME? All numerical args to fcntl are defined as long on Linux.
This relies on a really dirty trick on x86_64: A 32 bit mov to This relies on a really dirty trick on x86_64: A 32 bit mov to
@ -48,8 +47,8 @@ fcntl64 (int fd, int cmd, ...)
However, the POSIX standard defines all numerical args as type int. However, the POSIX standard defines all numerical args as type int.
If we take that literally, we had a (small) problem on 64 bit, since If we take that literally, we had a (small) problem on 64 bit, since
sizeof (void*) != sizeof (int). If we would like to follow POSIX sizeof (void*) != sizeof (int). If we would like to follow POSIX more
more closely than Linux, we'd have to call va_arg on a per cmd basis. */ closely than Linux, we'd have to call va_arg on a per cmd basis. */
va_start (args, cmd); va_start (args, cmd);
arg = va_arg (args, intptr_t); arg = va_arg (args, intptr_t);
@ -74,7 +73,9 @@ fcntl64 (int fd, int cmd, ...)
res = cfd->fcntl (cmd, arg); res = cfd->fcntl (cmd, arg);
break; break;
} }
done: }
__except (EFAULT) {}
__endtry
syscall_printf ("%R = fcntl(%d, %d, %ly)", res, fd, cmd, arg); syscall_printf ("%R = fcntl(%d, %d, %ly)", res, fd, cmd, arg);
return res; return res;
} }
@ -91,10 +92,8 @@ _fcntl (int fd, int cmd, ...)
struct __flock32 *src = NULL; struct __flock32 *src = NULL;
struct flock dst; struct flock dst;
myfault efault; __try
if (efault.faulted (EFAULT)) {
return -1;
va_start (args, cmd); va_start (args, cmd);
arg = va_arg (args, intptr_t); arg = va_arg (args, intptr_t);
va_end (args); va_end (args);
@ -118,5 +117,9 @@ _fcntl (int fd, int cmd, ...)
src->l_pid = (short) dst.l_pid; src->l_pid = (short) dst.l_pid;
} }
return res; return res;
}
__except (EFAULT)
__endtry
return -1;
} }
#endif #endif

View File

@ -2293,9 +2293,8 @@ fhandler_socket::getpeereid (pid_t *pid, uid_t *euid, gid_t *egid)
return -1; return -1;
} }
myfault efault; __try
if (efault.faulted (EFAULT)) {
return -1;
if (pid) if (pid)
*pid = sec_peer_pid; *pid = sec_peer_pid;
if (euid) if (euid)
@ -2303,4 +2302,8 @@ fhandler_socket::getpeereid (pid_t *pid, uid_t *euid, gid_t *egid)
if (egid) if (egid)
*egid = sec_peer_gid; *egid = sec_peer_gid;
return 0; return 0;
}
__except (EFAULT) {}
__endtry
return -1;
} }

View File

@ -2,7 +2,7 @@
classes. classes.
Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
2010, 2011, 2012, 2013 Red Hat, Inc. 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -977,9 +977,8 @@ mtinfo_drive::set_options (HANDLE mt, int32_t options)
int int
mtinfo_drive::ioctl (HANDLE mt, unsigned int cmd, void *buf) mtinfo_drive::ioctl (HANDLE mt, unsigned int cmd, void *buf)
{ {
myfault efault; __try
if (efault.faulted ()) {
return ERROR_NOACCESS;
if (cmd == MTIOCTOP) if (cmd == MTIOCTOP)
{ {
struct mtop *op = (struct mtop *) buf; struct mtop *op = (struct mtop *) buf;
@ -1129,7 +1128,12 @@ mtinfo_drive::ioctl (HANDLE mt, unsigned int cmd, void *buf)
get_status (mt, (struct mtget *) buf); get_status (mt, (struct mtget *) buf);
else if (cmd == MTIOCPOS && !get_pos (mt)) else if (cmd == MTIOCPOS && !get_pos (mt))
((struct mtpos *) buf)->mt_blkno = (long) block; ((struct mtpos *) buf)->mt_blkno = (long) block;
}
__except (NO_ERROR)
{
lasterr = ERROR_NOACCESS;
}
__endtry
return lasterr; return lasterr;
} }

View File

@ -1761,13 +1761,11 @@ flock (int fd, int operation)
int cmd; int cmd;
struct flock fl = { 0, SEEK_SET, 0, 0, 0 }; struct flock fl = { 0, SEEK_SET, 0, 0, 0 };
myfault efault; __try
if (efault.faulted (EFAULT)) {
return -1;
cygheap_fdget cfd (fd, true); cygheap_fdget cfd (fd, true);
if (cfd < 0) if (cfd < 0)
goto done; __leave;
cmd = (operation & LOCK_NB) ? F_SETLK : F_SETLKW; cmd = (operation & LOCK_NB) ? F_SETLK : F_SETLKW;
switch (operation & (~LOCK_NB)) switch (operation & (~LOCK_NB))
@ -1783,7 +1781,7 @@ flock (int fd, int operation)
break; break;
default: default:
set_errno (EINVAL); set_errno (EINVAL);
goto done; __leave;
} }
if (!cfd->mandatory_locking ()) if (!cfd->mandatory_locking ())
fl.l_type |= F_FLOCK; fl.l_type |= F_FLOCK;
@ -1791,7 +1789,9 @@ flock (int fd, int operation)
: cfd->lock (cmd, &fl); : cfd->lock (cmd, &fl);
if ((res == -1) && ((get_errno () == EAGAIN) || (get_errno () == EACCES))) if ((res == -1) && ((get_errno () == EAGAIN) || (get_errno () == EACCES)))
set_errno (EWOULDBLOCK); set_errno (EWOULDBLOCK);
done: }
__except (EFAULT) {}
__endtry
syscall_printf ("%R = flock(%d, %d)", res, fd, operation); syscall_printf ("%R = flock(%d, %d)", res, fd, operation);
return res; return res;
} }
@ -1805,13 +1805,11 @@ lockf (int filedes, int function, off_t size)
pthread_testcancel (); pthread_testcancel ();
myfault efault; __try
if (efault.faulted (EFAULT)) {
return -1;
cygheap_fdget cfd (filedes, true); cygheap_fdget cfd (filedes, true);
if (cfd < 0) if (cfd < 0)
goto done; __leave;
fl.l_start = 0; fl.l_start = 0;
fl.l_len = size; fl.l_len = size;
@ -1834,21 +1832,23 @@ lockf (int filedes, int function, off_t size)
case F_TEST: case F_TEST:
fl.l_type = F_WRLCK; fl.l_type = F_WRLCK;
if (cfd->lock (F_GETLK, &fl) == -1) if (cfd->lock (F_GETLK, &fl) == -1)
goto done; __leave;
if (fl.l_type == F_UNLCK || fl.l_pid == getpid ()) if (fl.l_type == F_UNLCK || fl.l_pid == getpid ())
res = 0; res = 0;
else else
errno = EAGAIN; errno = EAGAIN;
goto done; __leave;
/* NOTREACHED */ /* NOTREACHED */
default: default:
errno = EINVAL; errno = EINVAL;
goto done; __leave;
/* NOTREACHED */ /* NOTREACHED */
} }
res = cfd->mandatory_locking () ? cfd->mand_lock (cmd, &fl) res = cfd->mandatory_locking () ? cfd->mand_lock (cmd, &fl)
: cfd->lock (cmd, &fl); : cfd->lock (cmd, &fl);
done: }
__except (EFAULT) {}
__endtry
syscall_printf ("%R = lockf(%d, %d, %D)", res, filedes, function, size); syscall_printf ("%R = lockf(%d, %d, %D)", res, filedes, function, size);
return res; return res;
} }

View File

@ -1,5 +1,5 @@
#!/usr/bin/perl #!/usr/bin/perl
# Copyright 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2011, 2012, 2013 # Copyright 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2011, 2012, 2013, 2014
# Red Hat, Inc. # Red Hat, Inc.
# #
# This file is part of Cygwin. # This file is part of Cygwin.
@ -181,6 +181,8 @@ _sigbe: # return here after cygwin syscall
movq -8(%r11),%r11 # get return address from signal stack movq -8(%r11),%r11 # get return address from signal stack
decl $tls::incyg(%r10) decl $tls::incyg(%r10)
decl $tls::stacklock(%r10) # release lock decl $tls::stacklock(%r10) # release lock
leaq $tls::pathbufs(%r10),%r10 # Address of tls_pathbufs
movq \$0,(%r10) # Set c_cnt and w_cnt to 0
jmp *%r11 # "return" to caller jmp *%r11 # "return" to caller
.seh_endproc .seh_endproc
@ -445,6 +447,9 @@ __sigbe: # return here after cygwin syscall
xchgl %eax,4(%esp) # swap return address with saved eax xchgl %eax,4(%esp) # swap return address with saved eax
decl $tls::incyg(%ebx) decl $tls::incyg(%ebx)
decl $tls::stacklock(%ebx) # release lock decl $tls::stacklock(%ebx) # release lock
leal $tls::pathbufs(%ebx),%ebx # Address of tls_pathbufs
movl \$0,(%ebx) # Set c_cnt to 0
movl \$0,4(%ebx) # Set w_cnt to 0
popl %ebx popl %ebx
ret ret

View File

@ -249,8 +249,7 @@ getprogname (void)
extern "C" void extern "C" void
setprogname (const char *newprogname) setprogname (const char *newprogname)
{ {
myfault efault; __try
if (!efault.faulted (EFAULT))
{ {
/* Per BSD man page, setprogname keeps a pointer to the last /* Per BSD man page, setprogname keeps a pointer to the last
path component of the argument. It does *not* copy the path component of the argument. It does *not* copy the
@ -261,6 +260,8 @@ setprogname (const char *newprogname)
else else
__progname = (char *)newprogname; __progname = (char *)newprogname;
} }
__except (EFAULT) {}
__endtry
} }
extern "C" void extern "C" void

View File

@ -319,10 +319,8 @@ cygwin_rexec (char **ahost, unsigned short rport, char *name, char *pass,
char c; char c;
static char ahostbuf[INTERNET_MAX_HOST_NAME_LENGTH + 1]; static char ahostbuf[INTERNET_MAX_HOST_NAME_LENGTH + 1];
myfault efault; __try
if (efault.faulted (EFAULT)) {
return -1;
hp = cygwin_gethostbyname(*ahost); hp = cygwin_gethostbyname(*ahost);
if (hp == 0) { if (hp == 0) {
cygwin_herror(*ahost); cygwin_herror(*ahost);
@ -407,5 +405,8 @@ bad:
if (port) if (port)
(void) close(*fd2p); (void) close(*fd2p);
(void) close(s); (void) close(s);
}
__except (EFAULT) {}
__endtry
return (-1); return (-1);
} }

View File

@ -202,9 +202,8 @@ check_iovec (const struct iovec *iov, int iovcnt, bool forwrite)
return -1; return -1;
} }
myfault efault; __try
if (efault.faulted (EFAULT)) {
return -1;
size_t tot = 0; size_t tot = 0;
@ -213,7 +212,7 @@ check_iovec (const struct iovec *iov, int iovcnt, bool forwrite)
if (iov->iov_len > SSIZE_MAX || (tot += iov->iov_len) > SSIZE_MAX) if (iov->iov_len > SSIZE_MAX || (tot += iov->iov_len) > SSIZE_MAX)
{ {
set_errno (EINVAL); set_errno (EINVAL);
return -1; __leave;
} }
volatile char *p = ((char *) iov->iov_base) + iov->iov_len - 1; volatile char *p = ((char *) iov->iov_base) + iov->iov_len - 1;
@ -231,6 +230,10 @@ check_iovec (const struct iovec *iov, int iovcnt, bool forwrite)
assert (tot <= SSIZE_MAX); assert (tot <= SSIZE_MAX);
return (ssize_t) tot; return (ssize_t) tot;
}
__except (EFAULT)
__endtry
return -1;
} }
/* Try hard to schedule another thread. /* Try hard to schedule another thread.
@ -512,18 +515,23 @@ slashify (const char *src, char *dst, bool trailing_slash_p)
void * __reg1 void * __reg1
__import_address (void *imp) __import_address (void *imp)
{ {
myfault efault; __try
if (efault.faulted ()) {
return NULL; if (*((uint16_t *) imp) == 0x25ff)
if (*((uint16_t *) imp) != 0x25ff) {
return NULL;
const char *ptr = (const char *) imp; const char *ptr = (const char *) imp;
#ifdef __x86_64__ #ifdef __x86_64__
const uintptr_t *jmpto = (uintptr_t *) (ptr + 6 + *(int32_t *)(ptr + 2)); const uintptr_t *jmpto = (uintptr_t *)
(ptr + 6 + *(int32_t *)(ptr + 2));
#else #else
const uintptr_t *jmpto = (uintptr_t *) *((uintptr_t *) (ptr + 2)); const uintptr_t *jmpto = (uintptr_t *) *((uintptr_t *) (ptr + 2));
#endif #endif
return (void *) *jmpto; return (void *) *jmpto;
}
}
__except (NO_ERROR) {}
__endtry
return NULL;
} }
/* CygwinCreateThread. /* CygwinCreateThread.

View File

@ -1700,10 +1700,9 @@ mount (const char *win32_path, const char *posix_path, unsigned flags)
isn't really supported except from fstab? */ isn't really supported except from fstab? */
int res = -1; int res = -1;
myfault efault; __try
if (efault.faulted (EFAULT)) {
/* errno set */; if (!*posix_path)
else if (!*posix_path)
set_errno (EINVAL); set_errno (EINVAL);
else if (strpbrk (posix_path, "\\:")) else if (strpbrk (posix_path, "\\:"))
set_errno (EINVAL); set_errno (EINVAL);
@ -1738,12 +1737,17 @@ mount (const char *win32_path, const char *posix_path, unsigned flags)
flags = (MOUNT_BIND | conv_flags) flags = (MOUNT_BIND | conv_flags)
& ~(MOUNT_IMMUTABLE | MOUNT_AUTOMATIC); & ~(MOUNT_IMMUTABLE | MOUNT_AUTOMATIC);
} }
/* Make sure all mounts are user mounts, even those added via mount -a. */ /* Make sure all mounts are user mounts, even those added via
mount -a. */
flags &= ~MOUNT_SYSTEM; flags &= ~MOUNT_SYSTEM;
res = mount_table->add_item (w32_path, posix_path, flags); res = mount_table->add_item (w32_path, posix_path, flags);
} }
syscall_printf ("%R = mount(%s, %s, %y)", res, win32_path, posix_path, flags); syscall_printf ("%R = mount(%s, %s, %y)",
res, win32_path, posix_path, flags);
}
__except (EFAULT) {}
__endtry
return res; return res;
} }
@ -1755,15 +1759,18 @@ mount (const char *win32_path, const char *posix_path, unsigned flags)
extern "C" int extern "C" int
umount (const char *path) umount (const char *path)
{ {
myfault efault; __try
if (efault.faulted (EFAULT)) {
return -1;
if (!*path) if (!*path)
{ {
set_errno (EINVAL); set_errno (EINVAL);
return -1; __leave;
} }
return cygwin_umount (path, 0); return cygwin_umount (path, 0);
}
__except (EFAULT) {}
__endtry
return -1;
} }
/* cygwin_umount: This is like umount but takes an additional flags /* cygwin_umount: This is like umount but takes an additional flags

View File

@ -1,6 +1,6 @@
/* msg.cc: XSI IPC interface for Cygwin. /* msg.cc: XSI IPC interface for Cygwin.
Copyright 2002, 2003, 2004, 2005, 2008, 2009 Red Hat, Inc. Copyright 2002, 2003, 2004, 2005, 2008, 2009, 2014 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -91,11 +91,9 @@ client_request_msg::client_request_msg (int msqid,
extern "C" int extern "C" int
msgctl (int msqid, int cmd, struct msqid_ds *buf) msgctl (int msqid, int cmd, struct msqid_ds *buf)
{ {
syscall_printf ("msgctl (msqid = %d, cmd = %y, buf = %p)", syscall_printf ("msgctl (msqid = %d, cmd = %y, buf = %p)", msqid, cmd, buf);
msqid, cmd, buf); __try
myfault efault; {
if (efault.faulted (EFAULT))
return -1;
switch (cmd) switch (cmd)
{ {
case IPC_STAT: case IPC_STAT:
@ -111,7 +109,7 @@ msgctl (int msqid, int cmd, struct msqid_ds *buf)
default: default:
syscall_printf ("-1 [%d] = msgctl ()", EINVAL); syscall_printf ("-1 [%d] = msgctl ()", EINVAL);
set_errno (EINVAL); set_errno (EINVAL);
return -1; __leave;
} }
client_request_msg request (msqid, cmd, buf); client_request_msg request (msqid, cmd, buf);
if (request.make_request () == -1 || request.retval () == -1) if (request.make_request () == -1 || request.retval () == -1)
@ -120,9 +118,13 @@ msgctl (int msqid, int cmd, struct msqid_ds *buf)
set_errno (request.error_code ()); set_errno (request.error_code ());
if (request.error_code () == ENOSYS) if (request.error_code () == ENOSYS)
raise (SIGSYS); raise (SIGSYS);
return -1; __leave;
} }
return request.retval (); return request.retval ();
}
__except (EFAULT) {}
__endtry
return -1;
} }
extern "C" int extern "C" int
@ -147,9 +149,8 @@ msgrcv (int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg)
syscall_printf ("msgrcv (msqid = %d, msgp = %p, msgsz = %ld, " syscall_printf ("msgrcv (msqid = %d, msgp = %p, msgsz = %ld, "
"msgtyp = %d, msgflg = %y)", "msgtyp = %d, msgflg = %y)",
msqid, msgp, msgsz, msgtyp, msgflg); msqid, msgp, msgsz, msgtyp, msgflg);
myfault efault; __try
if (efault.faulted (EFAULT)) {
return -1;
client_request_msg request (msqid, msgp, msgsz, msgtyp, msgflg); client_request_msg request (msqid, msgp, msgsz, msgtyp, msgflg);
if (request.make_request () == -1 || request.rcvval () == -1) if (request.make_request () == -1 || request.rcvval () == -1)
{ {
@ -157,9 +158,13 @@ msgrcv (int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg)
set_errno (request.error_code ()); set_errno (request.error_code ());
if (request.error_code () == ENOSYS) if (request.error_code () == ENOSYS)
raise (SIGSYS); raise (SIGSYS);
return -1; __leave;
} }
return request.rcvval (); return request.rcvval ();
}
__except (EFAULT) {}
__endtry
return -1;
} }
extern "C" int extern "C" int
@ -167,9 +172,8 @@ msgsnd (int msqid, const void *msgp, size_t msgsz, int msgflg)
{ {
syscall_printf ("msgsnd (msqid = %d, msgp = %p, msgsz = %ld, msgflg = %y)", syscall_printf ("msgsnd (msqid = %d, msgp = %p, msgsz = %ld, msgflg = %y)",
msqid, msgp, msgsz, msgflg); msqid, msgp, msgsz, msgflg);
myfault efault; __try
if (efault.faulted (EFAULT)) {
return -1;
client_request_msg request (msqid, msgp, msgsz, msgflg); client_request_msg request (msqid, msgp, msgsz, msgflg);
if (request.make_request () == -1 || request.retval () == -1) if (request.make_request () == -1 || request.retval () == -1)
{ {
@ -177,7 +181,11 @@ msgsnd (int msqid, const void *msgp, size_t msgsz, int msgflg)
set_errno (request.error_code ()); set_errno (request.error_code ());
if (request.error_code () == ENOSYS) if (request.error_code () == ENOSYS)
raise (SIGSYS); raise (SIGSYS);
return -1; __leave;
} }
return request.retval (); return request.retval ();
}
__except (EFAULT) {}
__endtry
return -1;
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/* ntdll.h. Contains ntdll specific stuff not defined elsewhere. /* ntdll.h. Contains ntdll specific stuff not defined elsewhere.
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
2011, 2012, 2013 Red Hat, Inc. 2011, 2012, 2013, 2014 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -1180,8 +1180,19 @@ typedef enum _SECTION_INHERIT
typedef VOID (APIENTRY *PTIMER_APC_ROUTINE)(PVOID, ULONG, ULONG); typedef VOID (APIENTRY *PTIMER_APC_ROUTINE)(PVOID, ULONG, ULONG);
/* Function declarations for ntdll.dll. These don't appear in any #ifdef __x86_64__
standard Win32 header. */ typedef struct _SCOPE_TABLE
{
ULONG Count;
struct
{
ULONG BeginAddress;
ULONG EndAddress;
ULONG HandlerAddress;
ULONG JumpTarget;
} ScopeRecord[1];
} SCOPE_TABLE, *PSCOPE_TABLE;
#endif
#ifdef __cplusplus #ifdef __cplusplus
/* This is the mapping of the KUSER_SHARED_DATA structure into the user /* This is the mapping of the KUSER_SHARED_DATA structure into the user
@ -1190,6 +1201,9 @@ typedef VOID (APIENTRY *PTIMER_APC_ROUTINE)(PVOID, ULONG, ULONG);
static volatile KUSER_SHARED_DATA &SharedUserData static volatile KUSER_SHARED_DATA &SharedUserData
= *(volatile KUSER_SHARED_DATA *) 0x7ffe0000; = *(volatile KUSER_SHARED_DATA *) 0x7ffe0000;
/* Function declarations for ntdll.dll. These don't appear in any
standard Win32 header. */
extern "C" extern "C"
{ {
#endif #endif

View File

@ -60,10 +60,8 @@ read_ea (HANDLE hdl, path_conv &pc, const char *name, char *value, size_t size)
EA in the file is returned twice. */ EA in the file is returned twice. */
char lastname[MAX_EA_NAME_LEN]; char lastname[MAX_EA_NAME_LEN];
myfault efault; __try
if (efault.faulted (EFAULT)) {
goto out;
pc.get_object_attr (attr, sec_none_nih); pc.get_object_attr (attr, sec_none_nih);
debug_printf ("read_ea (%S, %s, %p, %lu)", debug_printf ("read_ea (%S, %s, %p, %lu)",
@ -75,11 +73,12 @@ read_ea (HANDLE hdl, path_conv &pc, const char *name, char *value, size_t size)
if (!hdl) if (!hdl)
{ {
status = NtOpenFile (&h, READ_CONTROL | FILE_READ_EA, &attr, &io, status = NtOpenFile (&h, READ_CONTROL | FILE_READ_EA, &attr, &io,
FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT); FILE_SHARE_VALID_FLAGS,
FILE_OPEN_FOR_BACKUP_INTENT);
if (!NT_SUCCESS (status)) if (!NT_SUCCESS (status))
{ {
__seterrno_from_nt_status (status); __seterrno_from_nt_status (status);
goto out; __leave;
} }
hdl = NULL; hdl = NULL;
} }
@ -97,7 +96,7 @@ read_ea (HANDLE hdl, path_conv &pc, const char *name, char *value, size_t size)
else else
{ {
set_errno (ENOTSUP); set_errno (ENOTSUP);
goto out; __leave;
} }
if ((nlen = strlen (name)) >= MAX_EA_NAME_LEN) if ((nlen = strlen (name)) >= MAX_EA_NAME_LEN)
@ -123,7 +122,8 @@ read_ea (HANDLE hdl, path_conv &pc, const char *name, char *value, size_t size)
break; break;
} }
status = NtOpenFile (&h, READ_CONTROL | FILE_READ_EA, &attr, &io, status = NtOpenFile (&h, READ_CONTROL | FILE_READ_EA, &attr, &io,
FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT); FILE_SHARE_VALID_FLAGS,
FILE_OPEN_FOR_BACKUP_INTENT);
if (!NT_SUCCESS (status)) if (!NT_SUCCESS (status))
break; break;
hdl = NULL; hdl = NULL;
@ -140,23 +140,25 @@ read_ea (HANDLE hdl, path_conv &pc, const char *name, char *value, size_t size)
break; break;
case STATUS_NOT_FOUND: case STATUS_NOT_FOUND:
/* STATUS_NOT_FOUND is returned when calling NtQueryEaFile on NFS. /* STATUS_NOT_FOUND is returned when calling NtQueryEaFile on NFS.
In theory this should mean that the file just has no EAs, but in In theory this should mean that the file just has no EAs, but
fact NFS doesn't support EAs, other than the EAs which are used in fact NFS doesn't support EAs, other than the EAs which are
for NFS requests. We're playing safe and convert STATUS_NOT_FOUND used for NFS requests. We're playing safe and convert
to ENOATTR, unless we're on NFS, where we convert it to ENOTSUP. */ STATUS_NOT_FOUND to ENOATTR, unless we're on NFS, where we
convert it to ENOTSUP. */
set_errno (pc.fs_is_nfs () ? ENOTSUP : ENOATTR); set_errno (pc.fs_is_nfs () ? ENOTSUP : ENOATTR);
break; break;
case STATUS_NONEXISTENT_EA_ENTRY: case STATUS_NONEXISTENT_EA_ENTRY:
/* Actually STATUS_NONEXISTENT_EA_ENTRY is either never generated, or /* Actually STATUS_NONEXISTENT_EA_ENTRY is either never generated,
it was only generated in some old and long forgotton NT version. or it was only generated in some old and long forgotton NT
See below. For safty reasons, we handle it here, nevertheless. */ version. See below. For safty reasons, we handle it here,
nevertheless. */
set_errno (ENOATTR); set_errno (ENOATTR);
break; break;
default: default:
__seterrno_from_nt_status (status); __seterrno_from_nt_status (status);
break; break;
} }
goto out; __leave;
} }
if (name) if (name)
{ {
@ -168,14 +170,14 @@ read_ea (HANDLE hdl, path_conv &pc, const char *name, char *value, size_t size)
if (!fea->EaValueLength) if (!fea->EaValueLength)
{ {
set_errno (ENOATTR); set_errno (ENOATTR);
goto out; __leave;
} }
if (size > 0) if (size > 0)
{ {
if (size < fea->EaValueLength) if (size < fea->EaValueLength)
{ {
set_errno (ERANGE); set_errno (ERANGE);
goto out; __leave;
} }
memcpy (value, fea->EaName + fea->EaNameLength + 1, memcpy (value, fea->EaName + fea->EaNameLength + 1,
fea->EaValueLength); fea->EaValueLength);
@ -193,7 +195,7 @@ read_ea (HANDLE hdl, path_conv &pc, const char *name, char *value, size_t size)
if ((size_t) ret + fea->EaNameLength + 1 > size) if ((size_t) ret + fea->EaNameLength + 1 > size)
{ {
set_errno (ERANGE); set_errno (ERANGE);
goto out; __leave;
} }
/* For compatibility with Linux, we always prepend "user." to /* For compatibility with Linux, we always prepend "user." to
the attribute name, so effectively we only support user the attribute name, so effectively we only support user
@ -201,10 +203,11 @@ read_ea (HANDLE hdl, path_conv &pc, const char *name, char *value, size_t size)
char tmpbuf[MAX_EA_NAME_LEN * 2]; char tmpbuf[MAX_EA_NAME_LEN * 2];
char *tp = stpcpy (tmpbuf, "user."); char *tp = stpcpy (tmpbuf, "user.");
stpcpy (tp, fea->EaName); stpcpy (tp, fea->EaName);
/* NTFS stores all EA names in uppercase unfortunately. To keep /* NTFS stores all EA names in uppercase unfortunately. To
compatibility with ext/xfs EA namespaces and accompanying keep compatibility with ext/xfs EA namespaces and
tools, which expect the namespaces to be lower case, we return accompanying tools, which expect the namespaces to be
EA names in lowercase if the file is on a native NTFS. */ lower case, we return EA names in lowercase if the file
is on a native NTFS. */
if (pc.fs_is_ntfs ()) if (pc.fs_is_ntfs ())
strlwr (tp); strlwr (tp);
tp = stpcpy (value, tmpbuf) + 1; tp = stpcpy (value, tmpbuf) + 1;
@ -219,8 +222,9 @@ read_ea (HANDLE hdl, path_conv &pc, const char *name, char *value, size_t size)
} }
while (NT_SUCCESS (status) && strcmp (lastname, fea->EaName) != 0); while (NT_SUCCESS (status) && strcmp (lastname, fea->EaName) != 0);
} }
}
out: __except (EFAULT) {}
__endtry
if (!hdl) if (!hdl)
CloseHandle (h); CloseHandle (h);
debug_printf ("%d = read_ea(%S, %s, %p, %lu)", debug_printf ("%d = read_ea(%S, %s, %p, %lu)",
@ -241,10 +245,8 @@ write_ea (HANDLE hdl, path_conv &pc, const char *name, const char *value,
ULONG flen; ULONG flen;
size_t nlen; size_t nlen;
myfault efault; __try
if (efault.faulted (EFAULT)) {
goto out;
pc.get_object_attr (attr, sec_none_nih); pc.get_object_attr (attr, sec_none_nih);
debug_printf ("write_ea (%S, %s, %p, %lu, %d)", debug_printf ("write_ea (%S, %s, %p, %lu, %d)",
@ -256,11 +258,12 @@ write_ea (HANDLE hdl, path_conv &pc, const char *name, const char *value,
if (!hdl) if (!hdl)
{ {
status = NtOpenFile (&h, READ_CONTROL | FILE_WRITE_EA, &attr, &io, status = NtOpenFile (&h, READ_CONTROL | FILE_WRITE_EA, &attr, &io,
FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT); FILE_SHARE_VALID_FLAGS,
FILE_OPEN_FOR_BACKUP_INTENT);
if (!NT_SUCCESS (status)) if (!NT_SUCCESS (status))
{ {
__seterrno_from_nt_status (status); __seterrno_from_nt_status (status);
goto out; __leave;
} }
hdl = NULL; hdl = NULL;
} }
@ -270,11 +273,11 @@ write_ea (HANDLE hdl, path_conv &pc, const char *name, const char *value,
if (!ascii_strncasematch (name, "user.", 5)) if (!ascii_strncasematch (name, "user.", 5))
{ {
set_errno (ENOTSUP); set_errno (ENOTSUP);
goto out; __leave;
} }
/* removexattr is supposed to fail with ENOATTR if the requested EA is not /* removexattr is supposed to fail with ENOATTR if the requested EA is
available. This is equivalent to the XATTR_REPLACE flag for setxattr. */ not available. This is equivalent to XATTR_REPLACE for setxattr. */
if (!value) if (!value)
flags = XATTR_REPLACE; flags = XATTR_REPLACE;
@ -283,16 +286,16 @@ write_ea (HANDLE hdl, path_conv &pc, const char *name, const char *value,
if (flags != XATTR_CREATE && flags != XATTR_REPLACE) if (flags != XATTR_CREATE && flags != XATTR_REPLACE)
{ {
set_errno (EINVAL); set_errno (EINVAL);
goto out; __leave;
} }
ssize_t rret = read_ea (hdl, pc, name, NULL, 0); ssize_t rret = read_ea (hdl, pc, name, NULL, 0);
if (flags == XATTR_CREATE && rret > 0) if (flags == XATTR_CREATE && rret > 0)
{ {
set_errno (EEXIST); set_errno (EEXIST);
goto out; __leave;
} }
if (flags == XATTR_REPLACE && rret < 0) if (flags == XATTR_REPLACE && rret < 0)
goto out; __leave;
} }
/* Skip "user." prefix. */ /* Skip "user." prefix. */
@ -301,7 +304,7 @@ write_ea (HANDLE hdl, path_conv &pc, const char *name, const char *value,
if ((nlen = strlen (name)) >= MAX_EA_NAME_LEN) if ((nlen = strlen (name)) >= MAX_EA_NAME_LEN)
{ {
set_errno (EINVAL); set_errno (EINVAL);
goto out; __leave;
} }
flen = sizeof (FILE_FULL_EA_INFORMATION) + nlen + 1 + size; flen = sizeof (FILE_FULL_EA_INFORMATION) + nlen + 1 + size;
fea = (PFILE_FULL_EA_INFORMATION) alloca (flen); fea = (PFILE_FULL_EA_INFORMATION) alloca (flen);
@ -322,7 +325,8 @@ write_ea (HANDLE hdl, path_conv &pc, const char *name, const char *value,
break; break;
} }
status = NtOpenFile (&h, READ_CONTROL | FILE_WRITE_EA, &attr, &io, status = NtOpenFile (&h, READ_CONTROL | FILE_WRITE_EA, &attr, &io,
FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT); FILE_SHARE_VALID_FLAGS,
FILE_OPEN_FOR_BACKUP_INTENT);
if (!NT_SUCCESS (status)) if (!NT_SUCCESS (status))
break; break;
hdl = NULL; hdl = NULL;
@ -332,15 +336,15 @@ write_ea (HANDLE hdl, path_conv &pc, const char *name, const char *value,
switch (status) switch (status)
{ {
case STATUS_EA_TOO_LARGE: case STATUS_EA_TOO_LARGE:
/* STATUS_EA_TOO_LARGE has a matching Win32 error ERROR_EA_TABLE_FULL. /* STATUS_EA_TOO_LARGE has a matching Win32 error code
For some unknown reason RtlNtStatusToDosError does not translate ERROR_EA_TABLE_FULL. For some reason RtlNtStatusToDosError
STATUS_EA_TOO_LARGE to ERROR_EA_TABLE_FULL, but instead to does not translate STATUS_EA_TOO_LARGE to ERROR_EA_TABLE_FULL,
ERROR_EA_LIST_INCONSISTENT. This error code is also returned for but instead to ERROR_EA_LIST_INCONSISTENT. This error code is
STATUS_EA_LIST_INCONSISTENT, which means the incoming EA list is... also returned for STATUS_EA_LIST_INCONSISTENT, which means the
inconsistent. For obvious reasons we translate incoming EA list is... inconsistent. For obvious reasons we
ERROR_EA_LIST_INCONSISTENT to EINVAL, so we have to handle translate ERROR_EA_LIST_INCONSISTENT to EINVAL, so we have to
STATUS_EA_TOO_LARGE explicitely here, to get the correct mapping handle STATUS_EA_TOO_LARGE explicitely here, to get the correct
to ENOSPC. */ mapping to ENOSPC. */
set_errno (ENOSPC); set_errno (ENOSPC);
break; break;
case STATUS_INVALID_DEVICE_REQUEST: case STATUS_INVALID_DEVICE_REQUEST:
@ -353,8 +357,9 @@ write_ea (HANDLE hdl, path_conv &pc, const char *name, const char *value,
} }
else else
ret = 0; ret = 0;
}
out: __except (EFAULT) {}
__endtry
if (!hdl) if (!hdl)
CloseHandle (h); CloseHandle (h);
debug_printf ("%d = write_ea(%S, %s, %p, %lu, %d)", debug_printf ("%d = write_ea(%S, %s, %p, %lu, %d)",

View File

@ -651,12 +651,8 @@ path_conv::check (const char *src, unsigned opt,
} }
#endif #endif
myfault efault; __try
if (efault.faulted ())
{ {
error = EFAULT;
return;
}
int loop = 0; int loop = 0;
path_flags = 0; path_flags = 0;
known_suffix = NULL; known_suffix = NULL;
@ -706,9 +702,9 @@ path_conv::check (const char *src, unsigned opt,
error = 0; error = 0;
} }
/* Detect if the user was looking for a directory. We have to strip the /* Detect if the user was looking for a directory. We have to strip
trailing slash initially while trying to add extensions but take it the trailing slash initially while trying to add extensions but
into account during processing */ take it into account during processing */
if (tail > path_copy + 2 && isslash (tail[-1])) if (tail > path_copy + 2 && isslash (tail[-1]))
{ {
need_directory = 1; need_directory = 1;
@ -748,8 +744,8 @@ path_conv::check (const char *src, unsigned opt,
} }
/* Convert to native path spec sans symbolic link info. */ /* Convert to native path spec sans symbolic link info. */
error = mount_table->conv_to_win32_path (path_copy, full_path, dev, error = mount_table->conv_to_win32_path (path_copy, full_path,
&sym.pflags); dev, &sym.pflags);
if (error) if (error)
return; return;
@ -765,7 +761,8 @@ path_conv::check (const char *src, unsigned opt,
if (iscygdrive_dev (dev)) if (iscygdrive_dev (dev))
{ {
if (!component) if (!component)
fileattr = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_READONLY; fileattr = FILE_ATTRIBUTE_DIRECTORY
| FILE_ATTRIBUTE_READONLY;
else else
{ {
fileattr = getfileattr (THIS_path, fileattr = getfileattr (THIS_path,
@ -776,12 +773,14 @@ path_conv::check (const char *src, unsigned opt,
} }
else if (isdev_dev (dev)) else if (isdev_dev (dev))
{ {
/* Just make sure that the path handling goes on as with FH_FS. */ /* Make sure that the path handling goes on as with FH_FS. */
} }
else if (isvirtual_dev (dev)) else if (isvirtual_dev (dev))
{ {
/* FIXME: Calling build_fhandler here is not the right way to handle this. */ /* FIXME: Calling build_fhandler here is not the right way to
fhandler_virtual *fh = (fhandler_virtual *) build_fh_dev (dev, path_copy); handle this. */
fhandler_virtual *fh = (fhandler_virtual *)
build_fh_dev (dev, path_copy);
virtual_ftype_t file_type; virtual_ftype_t file_type;
if (!fh) if (!fh)
file_type = virt_none; file_type = virt_none;
@ -832,8 +831,8 @@ path_conv::check (const char *src, unsigned opt,
case virt_blk: case virt_blk:
/* Block special device. If the trailing slash has been /* Block special device. If the trailing slash has been
requested, the target is the root directory of the requested, the target is the root directory of the
filesystem on this block device. So we convert this to filesystem on this block device. So we convert this
a real file and attach the backslash. */ to a real file and attach the backslash. */
if (component == 0 && need_directory) if (component == 0 && need_directory)
{ {
dev.parse (FH_FS); dev.parse (FH_FS);
@ -856,7 +855,7 @@ path_conv::check (const char *src, unsigned opt,
path_flags |= PATH_RO; path_flags |= PATH_RO;
goto out; goto out;
} }
/* devn should not be a device. If it is, then stop parsing now. */ /* devn should not be a device. If it is, then stop parsing. */
else if (dev != FH_FS) else if (dev != FH_FS)
{ {
fileattr = 0; fileattr = 0;
@ -886,11 +885,11 @@ path_conv::check (const char *src, unsigned opt,
if (is_msdos) if (is_msdos)
sym.pflags |= PATH_NOPOSIX | PATH_NOACL; sym.pflags |= PATH_NOPOSIX | PATH_NOACL;
is_fs_via_procsys: is_fs_via_procsys:
symlen = sym.check (full_path, suff, fs, conv_handle); symlen = sym.check (full_path, suff, fs, conv_handle);
is_virtual_symlink: is_virtual_symlink:
if (sym.isdevice) if (sym.isdevice)
{ {
@ -928,15 +927,15 @@ is_virtual_symlink:
} }
else if (isdev_dev (dev)) else if (isdev_dev (dev))
{ {
/* If we're looking for a file below /dev, which doesn't exist, /* If we're looking for a non-existing file below /dev,
make sure that the device type is converted to FH_FS, so that make sure that the device type is converted to FH_FS, so
subsequent code handles the file correctly. that subsequent code handles the file correctly. Unless
Unless /dev itself doesn't exist on disk. In that case /dev /dev itself doesn't exist on disk. In that case /dev
is handled as virtual filesystem, and virtual filesystems are is handled as virtual filesystem, and virtual filesystems
read-only. The PC_KEEP_HANDLE check allows to check for are read-only. The PC_KEEP_HANDLE check allows to check
a call from an informational system call. In that case we for a call from an informational system call. In that
just stick to ENOENT, and the device type doesn't matter case we just stick to ENOENT, and the device type doesn't
anyway. */ matter anyway. */
if (sym.error == ENOENT && !(opt & PC_KEEP_HANDLE)) if (sym.error == ENOENT && !(opt & PC_KEEP_HANDLE))
sym.error = EROFS; sym.error = EROFS;
else else
@ -968,9 +967,11 @@ is_virtual_symlink:
saw_symlinks = 1; saw_symlinks = 1;
if (component == 0 && !need_directory if (component == 0 && !need_directory
&& (!(opt & PC_SYM_FOLLOW) && (!(opt & PC_SYM_FOLLOW)
|| (is_rep_symlink () && (opt & PC_SYM_NOFOLLOW_REP)))) || (is_rep_symlink ()
&& (opt & PC_SYM_NOFOLLOW_REP))))
{ {
set_symlink (symlen); // last component of path is a symlink. /* last component of path is a symlink. */
set_symlink (symlen);
if (opt & PC_SYM_CONTENTS) if (opt & PC_SYM_CONTENTS)
{ {
strcpy (THIS_path, sym.contents); strcpy (THIS_path, sym.contents);
@ -979,8 +980,8 @@ is_virtual_symlink:
add_ext = true; add_ext = true;
goto out; goto out;
} }
/* Following a symlink we can't trust the collected filesystem /* Following a symlink we can't trust the collected
information any longer. */ filesystem information any longer. */
fs.clear (); fs.clear ();
/* Close handle, if we have any. Otherwise we're collecting /* Close handle, if we have any. Otherwise we're collecting
handles while following symlinks. */ handles while following symlinks. */
@ -994,7 +995,7 @@ is_virtual_symlink:
} }
/* No existing file found. */ /* No existing file found. */
virtual_component_retry: virtual_component_retry:
/* Find the new "tail" of the path, e.g. in '/for/bar/baz', /* Find the new "tail" of the path, e.g. in '/for/bar/baz',
/baz is the tail. */ /baz is the tail. */
if (tail != path_end) if (tail != path_end)
@ -1021,14 +1022,16 @@ virtual_component_retry:
MALLOC_CHECK; MALLOC_CHECK;
/* Place the link content, possibly with head and/or tail, in tmp_buf */ /* Place the link content, possibly with head and/or tail,
in tmp_buf */
char *headptr; char *headptr;
if (isabspath (sym.contents)) if (isabspath (sym.contents))
headptr = tmp_buf; /* absolute path */ headptr = tmp_buf; /* absolute path */
else else
{ {
/* Copy the first part of the path (with ending /) and point to the end. */ /* Copy the first part of the path (with ending /) and point to
the end. */
char *prevtail = tail; char *prevtail = tail;
while (--prevtail > path_copy && *prevtail != '/') {} while (--prevtail > path_copy && *prevtail != '/') {}
int headlen = prevtail - path_copy + 1;; int headlen = prevtail - path_copy + 1;;
@ -1070,7 +1073,7 @@ virtual_component_retry:
if (!(opt & PC_SYM_CONTENTS)) if (!(opt & PC_SYM_CONTENTS))
add_ext = true; add_ext = true;
out: out:
set_path (THIS_path); set_path (THIS_path);
if (add_ext) if (add_ext)
add_ext_from_sym (sym); add_ext_from_sym (sym);
@ -1098,7 +1101,8 @@ out:
else if (!need_directory || error) else if (!need_directory || error)
/* nothing to do */; /* nothing to do */;
else if (fileattr == INVALID_FILE_ATTRIBUTES) else if (fileattr == INVALID_FILE_ATTRIBUTES)
strcat (modifiable_path (), "\\"); /* Reattach trailing dirsep in native path. */ /* Reattach trailing dirsep in native path. */
strcat (modifiable_path (), "\\");
else if (fileattr & FILE_ATTRIBUTE_DIRECTORY) else if (fileattr & FILE_ATTRIBUTE_DIRECTORY)
path_flags &= ~PATH_SYMLINK; path_flags &= ~PATH_SYMLINK;
else else
@ -1123,21 +1127,24 @@ out:
} }
} }
/* If FS hasn't been checked already in symlink_info::check, do so now. */ /* If FS hasn't been checked already in symlink_info::check,
do so now. */
if (fs.inited ()|| fs.update (get_nt_native_path (), NULL)) if (fs.inited ()|| fs.update (get_nt_native_path (), NULL))
{ {
/* Incoming DOS paths are treated like DOS paths in native /* Incoming DOS paths are treated like DOS paths in native
Windows applications. No ACLs, just default settings. */ Windows applications. No ACLs, just default settings. */
if (is_msdos) if (is_msdos)
fs.has_acls (false); fs.has_acls (false);
debug_printf ("this->path(%s), has_acls(%d)", path, fs.has_acls ()); debug_printf ("this->path(%s), has_acls(%d)",
path, fs.has_acls ());
/* CV: We could use this->has_acls() but I want to make sure that /* CV: We could use this->has_acls() but I want to make sure that
we don't forget that the PATH_NOACL flag must be taken into we don't forget that the PATH_NOACL flag must be taken into
account here. */ account here. */
if (!(path_flags & PATH_NOACL) && fs.has_acls ()) if (!(path_flags & PATH_NOACL) && fs.has_acls ())
set_exec (0); /* We really don't know if this is executable or not here set_exec (0); /* We really don't know if this is executable or
but set it to not executable since it will be figured out not here but set it to not executable since
later by anything which cares about this. */ it will be figured out later by anything
which cares about this. */
} }
/* If the FS has been found to have unrelibale inodes, note /* If the FS has been found to have unrelibale inodes, note
that in path_flags. */ that in path_flags. */
@ -1206,6 +1213,12 @@ out:
strcpy (last_src, src); strcpy (last_src, src);
} }
#endif #endif
}
__except (NO_ERROR)
{
error = EFAULT;
}
__endtry
} }
path_conv::~path_conv () path_conv::~path_conv ()
@ -1688,19 +1701,18 @@ symlink_worker (const char *oldpath, const char *newpath, bool isdevice)
/* POSIX says that empty 'newpath' is invalid input while empty /* POSIX says that empty 'newpath' is invalid input while empty
'oldpath' is valid -- it's symlink resolver job to verify if 'oldpath' is valid -- it's symlink resolver job to verify if
symlink contents point to existing filesystem object */ symlink contents point to existing filesystem object */
myfault efault; __try
if (efault.faulted (EFAULT)) {
goto done;
if (!*oldpath || !*newpath) if (!*oldpath || !*newpath)
{ {
set_errno (ENOENT); set_errno (ENOENT);
goto done; __leave;
} }
if (strlen (oldpath) > SYMLINK_MAX) if (strlen (oldpath) > SYMLINK_MAX)
{ {
set_errno (ENAMETOOLONG); set_errno (ENAMETOOLONG);
goto done; __leave;
} }
/* Trailing dirsep is a no-no. */ /* Trailing dirsep is a no-no. */
@ -1716,8 +1728,8 @@ symlink_worker (const char *oldpath, const char *newpath, bool isdevice)
/* We need the normalized full path below. */ /* We need the normalized full path below. */
win32_newpath.check (newpath, check_opt, stat_suffixes); win32_newpath.check (newpath, check_opt, stat_suffixes);
/* Default symlink type is determined by global allow_winsymlinks variable. /* Default symlink type is determined by global allow_winsymlinks
Device files are always shortcuts. */ variable. Device files are always shortcuts. */
wsym_type = isdevice ? WSYM_lnk : allow_winsymlinks; wsym_type = isdevice ? WSYM_lnk : allow_winsymlinks;
/* NFS has its own, dedicated way to create symlinks. */ /* NFS has its own, dedicated way to create symlinks. */
if (win32_newpath.fs_is_nfs ()) if (win32_newpath.fs_is_nfs ())
@ -1733,11 +1745,11 @@ symlink_worker (const char *oldpath, const char *newpath, bool isdevice)
if (wincap.max_sys_priv () < SE_CREATE_SYMBOLIC_LINK_PRIVILEGE) if (wincap.max_sys_priv () < SE_CREATE_SYMBOLIC_LINK_PRIVILEGE)
{ {
set_errno (EPERM); set_errno (EPERM);
goto done; __leave;
} }
wsym_type = WSYM_nativestrict; wsym_type = WSYM_nativestrict;
} }
/* Don't try native symlinks on filesystems not supporting reparse points. */ /* Don't try native symlinks on FSes not supporting reparse points. */
else if ((wsym_type == WSYM_native || wsym_type == WSYM_nativestrict) else if ((wsym_type == WSYM_native || wsym_type == WSYM_nativestrict)
&& !(win32_newpath.fs_flags () & FILE_SUPPORTS_REPARSE_POINTS)) && !(win32_newpath.fs_flags () & FILE_SUPPORTS_REPARSE_POINTS))
wsym_type = WSYM_sysfile; wsym_type = WSYM_sysfile;
@ -1754,7 +1766,7 @@ symlink_worker (const char *oldpath, const char *newpath, bool isdevice)
if (win32_newpath.error) if (win32_newpath.error)
{ {
set_errno (win32_newpath.error); set_errno (win32_newpath.error);
goto done; __leave;
} }
syscall_printf ("symlink (%s, %S) wsym_type %d", oldpath, syscall_printf ("symlink (%s, %S) wsym_type %d", oldpath,
@ -1764,12 +1776,12 @@ symlink_worker (const char *oldpath, const char *newpath, bool isdevice)
|| win32_newpath.is_auto_device ()) || win32_newpath.is_auto_device ())
{ {
set_errno (EEXIST); set_errno (EEXIST);
goto done; __leave;
} }
if (has_trailing_dirsep && !win32_newpath.exists ()) if (has_trailing_dirsep && !win32_newpath.exists ())
{ {
set_errno (ENOENT); set_errno (ENOENT);
goto done; __leave;
} }
/* Handle NFS and native symlinks in their own functions. */ /* Handle NFS and native symlinks in their own functions. */
@ -1777,17 +1789,17 @@ symlink_worker (const char *oldpath, const char *newpath, bool isdevice)
{ {
case WSYM_nfs: case WSYM_nfs:
res = symlink_nfs (oldpath, win32_newpath); res = symlink_nfs (oldpath, win32_newpath);
goto done; __leave;
case WSYM_native: case WSYM_native:
case WSYM_nativestrict: case WSYM_nativestrict:
res = symlink_native (oldpath, win32_newpath); res = symlink_native (oldpath, win32_newpath);
if (!res) if (!res)
goto done; __leave;
/* Strictly native? Too bad. */ /* Strictly native? Too bad. */
if (wsym_type == WSYM_nativestrict) if (wsym_type == WSYM_nativestrict)
{ {
__seterrno (); __seterrno ();
goto done; __leave;
} }
/* Otherwise, fall back to default symlink type. */ /* Otherwise, fall back to default symlink type. */
wsym_type = WSYM_sysfile; wsym_type = WSYM_sysfile;
@ -1810,9 +1822,9 @@ symlink_worker (const char *oldpath, const char *newpath, bool isdevice)
going to be. */ going to be. */
IShellFolder *psl; IShellFolder *psl;
/* The symlink target is relative to the directory in which /* The symlink target is relative to the directory in which the
the symlink gets created, not relative to the cwd. Therefore symlink gets created, not relative to the cwd. Therefore we
we have to mangle the path quite a bit before calling path_conv. */ have to mangle the path quite a bit before calling path_conv.*/
if (isabspath (oldpath)) if (isabspath (oldpath))
win32_oldpath.check (oldpath, win32_oldpath.check (oldpath,
PC_SYM_NOFOLLOW, PC_SYM_NOFOLLOW,
@ -1822,9 +1834,11 @@ symlink_worker (const char *oldpath, const char *newpath, bool isdevice)
len = strrchr (win32_newpath.normalized_path, '/') len = strrchr (win32_newpath.normalized_path, '/')
- win32_newpath.normalized_path + 1; - win32_newpath.normalized_path + 1;
char *absoldpath = tp.t_get (); char *absoldpath = tp.t_get ();
stpcpy (stpncpy (absoldpath, win32_newpath.normalized_path, len), stpcpy (stpncpy (absoldpath, win32_newpath.normalized_path,
len),
oldpath); oldpath);
win32_oldpath.check (absoldpath, PC_SYM_NOFOLLOW, stat_suffixes); win32_oldpath.check (absoldpath, PC_SYM_NOFOLLOW,
stat_suffixes);
} }
if (SUCCEEDED (SHGetDesktopFolder (&psl))) if (SUCCEEDED (SHGetDesktopFolder (&psl)))
{ {
@ -1839,8 +1853,9 @@ symlink_worker (const char *oldpath, const char *newpath, bool isdevice)
if (wc[1] != L':') /* native UNC path */ if (wc[1] != L':') /* native UNC path */
*(wc += 2) = L'\\'; *(wc += 2) = L'\\';
HRESULT res; HRESULT res;
if (SUCCEEDED (res = psl->ParseDisplayName (NULL, NULL, wc, NULL, if (SUCCEEDED (res = psl->ParseDisplayName (NULL, NULL, wc,
&pidl, NULL))) NULL, &pidl,
NULL)))
{ {
ITEMIDLIST *p; ITEMIDLIST *p;
@ -1924,7 +1939,8 @@ symlink_worker (const char *oldpath, const char *newpath, bool isdevice)
cp += 2; cp += 2;
*(PWCHAR) cp = 0xfeff; /* BOM */ *(PWCHAR) cp = 0xfeff; /* BOM */
cp += 2; cp += 2;
*plen = sys_mbstowcs ((PWCHAR) cp, NT_MAX_PATH, oldpath) * sizeof (WCHAR); *plen = sys_mbstowcs ((PWCHAR) cp, NT_MAX_PATH, oldpath)
* sizeof (WCHAR);
cp += *plen; cp += *plen;
} }
else else
@ -1935,7 +1951,8 @@ symlink_worker (const char *oldpath, const char *newpath, bool isdevice)
*(PWCHAR) cp = 0xfeff; /* BOM */ *(PWCHAR) cp = 0xfeff; /* BOM */
cp += 2; cp += 2;
/* Note that the terminating nul is written. */ /* Note that the terminating nul is written. */
cp += sys_mbstowcs ((PWCHAR) cp, NT_MAX_PATH, oldpath) * sizeof (WCHAR); cp += sys_mbstowcs ((PWCHAR) cp, NT_MAX_PATH, oldpath)
* sizeof (WCHAR);
} }
OBJECT_ATTRIBUTES attr; OBJECT_ATTRIBUTES attr;
@ -1948,22 +1965,24 @@ symlink_worker (const char *oldpath, const char *newpath, bool isdevice)
if (isdevice && win32_newpath.exists ()) if (isdevice && win32_newpath.exists ())
{ {
status = NtOpenFile (&fh, FILE_WRITE_ATTRIBUTES, status = NtOpenFile (&fh, FILE_WRITE_ATTRIBUTES,
win32_newpath.get_object_attr (attr, sec_none_nih), win32_newpath.get_object_attr (attr,
sec_none_nih),
&io, 0, FILE_OPEN_FOR_BACKUP_INTENT); &io, 0, FILE_OPEN_FOR_BACKUP_INTENT);
if (!NT_SUCCESS (status)) if (!NT_SUCCESS (status))
{ {
__seterrno_from_nt_status (status); __seterrno_from_nt_status (status);
goto done; __leave;
} }
status = NtSetAttributesFile (fh, FILE_ATTRIBUTE_NORMAL); status = NtSetAttributesFile (fh, FILE_ATTRIBUTE_NORMAL);
NtClose (fh); NtClose (fh);
if (!NT_SUCCESS (status)) if (!NT_SUCCESS (status))
{ {
__seterrno_from_nt_status (status); __seterrno_from_nt_status (status);
goto done; __leave;
} }
} }
else if (!isdevice && win32_newpath.has_acls () && !win32_newpath.isremote ()) else if (!isdevice && win32_newpath.has_acls ()
&& !win32_newpath.isremote ())
/* If the filesystem supports ACLs, we will overwrite the DACL after the /* If the filesystem supports ACLs, we will overwrite the DACL after the
call to NtCreateFile. This requires a handle with READ_CONTROL and call to NtCreateFile. This requires a handle with READ_CONTROL and
WRITE_DAC access, otherwise get_file_sd and set_file_sd both have to WRITE_DAC access, otherwise get_file_sd and set_file_sd both have to
@ -1986,13 +2005,14 @@ symlink_worker (const char *oldpath, const char *newpath, bool isdevice)
if (!NT_SUCCESS (status)) if (!NT_SUCCESS (status))
{ {
__seterrno_from_nt_status (status); __seterrno_from_nt_status (status);
goto done; __leave;
} }
if (win32_newpath.has_acls ()) if (win32_newpath.has_acls ())
set_file_attribute (fh, win32_newpath, ILLEGAL_UID, ILLEGAL_GID, set_file_attribute (fh, win32_newpath, ILLEGAL_UID, ILLEGAL_GID,
(io.Information == FILE_CREATED ? S_JUSTCREATED : 0) (io.Information == FILE_CREATED ? S_JUSTCREATED : 0)
| S_IFLNK | STD_RBITS | STD_WBITS); | S_IFLNK | STD_RBITS | STD_WBITS);
status = NtWriteFile (fh, NULL, NULL, NULL, &io, buf, cp - buf, NULL, NULL); status = NtWriteFile (fh, NULL, NULL, NULL, &io, buf, cp - buf,
NULL, NULL);
if (NT_SUCCESS (status) && io.Information == (ULONG) (cp - buf)) if (NT_SUCCESS (status) && io.Information == (ULONG) (cp - buf))
{ {
status = NtSetAttributesFile (fh, wsym_type == WSYM_lnk status = NtSetAttributesFile (fh, wsym_type == WSYM_lnk
@ -2009,11 +2029,14 @@ symlink_worker (const char *oldpath, const char *newpath, bool isdevice)
status = NtSetInformationFile (fh, &io, &fdi, sizeof fdi, status = NtSetInformationFile (fh, &io, &fdi, sizeof fdi,
FileDispositionInformation); FileDispositionInformation);
if (!NT_SUCCESS (status)) if (!NT_SUCCESS (status))
debug_printf ("Setting delete dispostion failed, status = %y", status); debug_printf ("Setting delete dispostion failed, status = %y",
status);
} }
NtClose (fh); NtClose (fh);
done: }
__except (EFAULT) {}
__endtry
syscall_printf ("%d = symlink_worker(%s, %s, %d)", syscall_printf ("%d = symlink_worker(%s, %s, %d)",
res, oldpath, newpath, isdevice); res, oldpath, newpath, isdevice);
if (has_trailing_dirsep) if (has_trailing_dirsep)
@ -3109,13 +3132,16 @@ extern "C" char *
getcwd (char *buf, size_t ulen) getcwd (char *buf, size_t ulen)
{ {
char* res = NULL; char* res = NULL;
myfault efault;
if (efault.faulted (EFAULT)) __try
/* errno set */; {
else if (ulen == 0 && buf) if (ulen == 0 && buf)
set_errno (EINVAL); set_errno (EINVAL);
else else
res = cygheap->cwd.get (buf, 1, 1, ulen); res = cygheap->cwd.get (buf, 1, 1, ulen);
}
__except (EFAULT) {}
__endtry
return res; return res;
} }
@ -3150,28 +3176,28 @@ get_current_dir_name (void)
extern "C" int extern "C" int
chdir (const char *in_dir) chdir (const char *in_dir)
{ {
myfault efault; int res = -1;
if (efault.faulted (EFAULT))
return -1; __try
{
if (!*in_dir) if (!*in_dir)
{ {
set_errno (ENOENT); set_errno (ENOENT);
return -1; __leave;
} }
syscall_printf ("dir '%s'", in_dir); syscall_printf ("dir '%s'", in_dir);
/* Convert path. First argument ensures that we don't check for NULL/empty/invalid /* Convert path. First argument ensures that we don't check for
again. */ NULL/empty/invalid again. */
path_conv path (PC_NONULLEMPTY, in_dir, PC_SYM_FOLLOW | PC_POSIX); path_conv path (PC_NONULLEMPTY, in_dir, PC_SYM_FOLLOW | PC_POSIX);
if (path.error) if (path.error)
{ {
set_errno (path.error); set_errno (path.error);
syscall_printf ("-1 = chdir (%s)", in_dir); syscall_printf ("-1 = chdir (%s)", in_dir);
return -1; __leave;
} }
int res = -1;
const char *posix_cwd = NULL; const char *posix_cwd = NULL;
dev_t devn = path.get_device (); dev_t devn = path.get_device ();
if (!path.exists ()) if (!path.exists ())
@ -3198,10 +3224,16 @@ chdir (const char *in_dir)
if (!res) if (!res)
res = cygheap->cwd.set (&path, posix_cwd); res = cygheap->cwd.set (&path, posix_cwd);
/* Note that we're accessing cwd.posix without a lock here. I didn't think /* Note that we're accessing cwd.posix without a lock here.
it was worth locking just for strace. */ I didn't think it was worth locking just for strace. */
syscall_printf ("%R = chdir() cygheap->cwd.posix '%s' native '%S'", res, syscall_printf ("%R = chdir() cygheap->cwd.posix '%s' native '%S'", res,
cygheap->cwd.get_posix (), path.get_nt_native_path ()); cygheap->cwd.get_posix (), path.get_nt_native_path ());
}
__except (EFAULT)
{
res = -1;
}
__endtry
MALLOC_CHECK; MALLOC_CHECK;
return res; return res;
} }
@ -3239,10 +3271,6 @@ cygwin_conv_path (cygwin_conv_path_t what, const void *from, void *to,
size_t size) size_t size)
{ {
tmp_pathbuf tp; tmp_pathbuf tp;
myfault efault;
if (efault.faulted (EFAULT))
return -1;
path_conv p; path_conv p;
size_t lsiz = 0; size_t lsiz = 0;
char *buf = NULL; char *buf = NULL;
@ -3250,11 +3278,14 @@ cygwin_conv_path (cygwin_conv_path_t what, const void *from, void *to,
int error = 0; int error = 0;
bool relative = !!(what & CCP_RELATIVE); bool relative = !!(what & CCP_RELATIVE);
what &= CCP_CONVTYPE_MASK; what &= CCP_CONVTYPE_MASK;
int ret = -1;
__try
{
if (!from) if (!from)
{ {
set_errno (EINVAL); set_errno (EINVAL);
return -1; __leave;
} }
switch (what) switch (what)
@ -3265,7 +3296,10 @@ cygwin_conv_path (cygwin_conv_path_t what, const void *from, void *to,
PC_POSIX | PC_SYM_FOLLOW | PC_SYM_NOFOLLOW_REP PC_POSIX | PC_SYM_FOLLOW | PC_SYM_NOFOLLOW_REP
| PC_NO_ACCESS_CHECK | PC_NOWARN | (relative ? PC_NOFULL : 0)); | PC_NO_ACCESS_CHECK | PC_NOWARN | (relative ? PC_NOFULL : 0));
if (p.error) if (p.error)
return_with_errno (p.error); {
set_errno (p.error);
__leave;
}
PUNICODE_STRING up = p.get_nt_native_path (); PUNICODE_STRING up = p.get_nt_native_path ();
buf = tp.c_get (); buf = tp.c_get ();
sys_wcstombs (buf, NT_MAX_PATH, sys_wcstombs (buf, NT_MAX_PATH,
@ -3306,7 +3340,10 @@ cygwin_conv_path (cygwin_conv_path_t what, const void *from, void *to,
PC_POSIX | PC_SYM_FOLLOW | PC_SYM_NOFOLLOW_REP PC_POSIX | PC_SYM_FOLLOW | PC_SYM_NOFOLLOW_REP
| PC_NO_ACCESS_CHECK | PC_NOWARN | (relative ? PC_NOFULL : 0)); | PC_NO_ACCESS_CHECK | PC_NOWARN | (relative ? PC_NOFULL : 0));
if (p.error) if (p.error)
return_with_errno (p.error); {
set_errno (p.error);
__leave;
}
/* Relative Windows paths are always restricted to MAX_PATH chars. */ /* Relative Windows paths are always restricted to MAX_PATH chars. */
if (relative && !isabspath (p.get_win32 ()) if (relative && !isabspath (p.get_win32 ())
&& sys_mbstowcs (NULL, 0, p.get_win32 ()) > MAX_PATH) && sys_mbstowcs (NULL, 0, p.get_win32 ()) > MAX_PATH)
@ -3315,7 +3352,10 @@ cygwin_conv_path (cygwin_conv_path_t what, const void *from, void *to,
p.check ((const char *) from, PC_POSIX | PC_SYM_FOLLOW p.check ((const char *) from, PC_POSIX | PC_SYM_FOLLOW
| PC_NO_ACCESS_CHECK | PC_NOWARN); | PC_NO_ACCESS_CHECK | PC_NOWARN);
if (p.error) if (p.error)
return_with_errno (p.error); {
set_errno (p.error);
__leave;
}
} }
lsiz = p.get_wide_win32_path_len () + 1; lsiz = p.get_wide_win32_path_len () + 1;
path = p.get_nt_native_path ()->Buffer; path = p.get_nt_native_path ()->Buffer;
@ -3362,7 +3402,10 @@ cygwin_conv_path (cygwin_conv_path_t what, const void *from, void *to,
error = mount_table->conv_to_posix_path ((const char *) from, buf, error = mount_table->conv_to_posix_path ((const char *) from, buf,
relative); relative);
if (error) if (error)
return_with_errno (error); {
set_errno (p.error);
__leave;
}
lsiz = strlen (buf) + 1; lsiz = strlen (buf) + 1;
break; break;
case CCP_WIN_W_TO_POSIX: case CCP_WIN_W_TO_POSIX:
@ -3370,19 +3413,25 @@ cygwin_conv_path (cygwin_conv_path_t what, const void *from, void *to,
error = mount_table->conv_to_posix_path ((const PWCHAR) from, buf, error = mount_table->conv_to_posix_path ((const PWCHAR) from, buf,
relative); relative);
if (error) if (error)
return_with_errno (error); {
set_errno (error);
__leave;
}
lsiz = strlen (buf) + 1; lsiz = strlen (buf) + 1;
break; break;
default: default:
set_errno (EINVAL); set_errno (EINVAL);
return -1; __leave;
} }
if (!size) if (!size)
return lsiz; {
ret = lsiz;
__leave;
}
if (size < lsiz) if (size < lsiz)
{ {
set_errno (ENOSPC); set_errno (ENOSPC);
return -1; __leave;
} }
switch (what) switch (what)
{ {
@ -3395,7 +3444,11 @@ cygwin_conv_path (cygwin_conv_path_t what, const void *from, void *to,
wcpcpy ((PWCHAR) to, path); wcpcpy ((PWCHAR) to, path);
break; break;
} }
return 0; ret = 0;
}
__except (EFAULT) {}
__endtry
return ret;
} }
extern "C" void * extern "C" void *
@ -3454,6 +3507,9 @@ cygwin_conv_to_full_posix_path (const char *path, char *posix_path)
extern "C" char * extern "C" char *
realpath (const char *__restrict path, char *__restrict resolved) realpath (const char *__restrict path, char *__restrict resolved)
{ {
tmp_pathbuf tp;
char *tpath;
/* Make sure the right errno is returned if path is NULL. */ /* Make sure the right errno is returned if path is NULL. */
if (!path) if (!path)
{ {
@ -3463,15 +3519,11 @@ realpath (const char *__restrict path, char *__restrict resolved)
/* Guard reading from a potentially invalid path and writing to a /* Guard reading from a potentially invalid path and writing to a
potentially invalid resolved. */ potentially invalid resolved. */
tmp_pathbuf tp; __try
myfault efault; {
if (efault.faulted (EFAULT))
return NULL;
/* Win32 drive letter paths have to be converted to a POSIX path first, /* Win32 drive letter paths have to be converted to a POSIX path first,
because path_conv leaves the incoming path untouched except for because path_conv leaves the incoming path untouched except for
converting backslashes to forward slashes. */ converting backslashes to forward slashes. */
char *tpath;
if (isdrive (path)) if (isdrive (path))
{ {
tpath = tp.c_get (); tpath = tp.c_get ();
@ -3491,7 +3543,8 @@ realpath (const char *__restrict path, char *__restrict resolved)
{ {
if (!resolved) if (!resolved)
{ {
resolved = (char *) malloc (strlen (real_path.normalized_path) + 1); resolved = (char *)
malloc (strlen (real_path.normalized_path) + 1);
if (!resolved) if (!resolved)
return NULL; return NULL;
} }
@ -3505,6 +3558,9 @@ realpath (const char *__restrict path, char *__restrict resolved)
if (resolved) if (resolved)
resolved[0] = '\0'; resolved[0] = '\0';
set_errno (real_path.error ?: ENOENT); set_errno (real_path.error ?: ENOENT);
}
__except (EFAULT) {}
__endtry
return NULL; return NULL;
} }

View File

@ -1,7 +1,7 @@
/* poll.cc. Implements poll(2) via usage of select(2) call. /* poll.cc. Implements poll(2) via usage of select(2) call.
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011,
2012 Red Hat, Inc. 2012, 2014 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -143,9 +143,8 @@ ppoll (struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts,
int timeout; int timeout;
sigset_t oldset = _my_tls.sigmask; sigset_t oldset = _my_tls.sigmask;
myfault efault; __try
if (efault.faulted (EFAULT)) {
return -1;
timeout = (timeout_ts == NULL) timeout = (timeout_ts == NULL)
? -1 ? -1
: (timeout_ts->tv_sec * 1000 + timeout_ts->tv_nsec / 1000000); : (timeout_ts->tv_sec * 1000 + timeout_ts->tv_nsec / 1000000);
@ -155,4 +154,8 @@ ppoll (struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts,
if (sigmask) if (sigmask)
set_signal_mask (_my_tls.sigmask, oldset); set_signal_mask (_my_tls.sigmask, oldset);
return ret; return ret;
}
__except (EFAULT) {}
__endtry
return -1;
} }

View File

@ -1,6 +1,6 @@
/* posix_ipc.cc: POSIX IPC API for Cygwin. /* posix_ipc.cc: POSIX IPC API for Cygwin.
Copyright 2007, 2008, 2009, 2010, 2011, 2012 Red Hat, Inc. Copyright 2007, 2008, 2009, 2010, 2011, 2012, 2014 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -414,17 +414,17 @@ extern "C" void *mmap64 (void *, size_t, int, int, int, off_t);
extern "C" mqd_t extern "C" mqd_t
mq_open (const char *name, int oflag, ...) mq_open (const char *name, int oflag, ...)
{ {
int i, fd = -1, nonblock, created; int i, fd = -1, nonblock, created = 0;
long msgsize, index; long msgsize, index;
off_t filesize = 0; off_t filesize = 0;
va_list ap; va_list ap;
mode_t mode; mode_t mode;
int8_t *mptr; int8_t *mptr = (int8_t *) MAP_FAILED;
struct stat statbuff; struct stat statbuff;
struct mq_hdr *mqhdr; struct mq_hdr *mqhdr;
struct msg_hdr *msghdr; struct msg_hdr *msghdr;
struct mq_attr *attr; struct mq_attr *attr;
struct mq_info *mqinfo; struct mq_info *mqinfo = NULL;
LUID luid; LUID luid;
size_t len = strlen (name); size_t len = strlen (name);
@ -433,18 +433,13 @@ mq_open (const char *name, int oflag, ...)
if (!check_path (mqname, mqueue, name, len)) if (!check_path (mqname, mqueue, name, len))
return (mqd_t) -1; return (mqd_t) -1;
myfault efault; __try
if (efault.faulted (EFAULT)) {
return (mqd_t) -1;
oflag &= (O_CREAT | O_EXCL | O_NONBLOCK); oflag &= (O_CREAT | O_EXCL | O_NONBLOCK);
created = 0;
nonblock = oflag & O_NONBLOCK; nonblock = oflag & O_NONBLOCK;
oflag &= ~O_NONBLOCK; oflag &= ~O_NONBLOCK;
mptr = (int8_t *) MAP_FAILED;
mqinfo = NULL;
again: again:
if (oflag & O_CREAT) if (oflag & O_CREAT)
{ {
va_start (ap, oflag); /* init ap to final named argument */ va_start (ap, oflag); /* init ap to final named argument */
@ -453,7 +448,8 @@ again:
va_end (ap); va_end (ap);
/* Open and specify O_EXCL and user-execute */ /* Open and specify O_EXCL and user-execute */
fd = open (mqname, oflag | O_EXCL | O_RDWR | O_CLOEXEC, mode | S_IXUSR); fd = open (mqname, oflag | O_EXCL | O_RDWR | O_CLOEXEC,
mode | S_IXUSR);
if (fd < 0) if (fd < 0)
{ {
if (errno == EEXIST && (oflag & O_EXCL) == 0) if (errno == EEXIST && (oflag & O_EXCL) == 0)
@ -472,26 +468,28 @@ again:
|| attr->mq_msgsize <= 0 || attr->mq_msgsize > 1048576) || attr->mq_msgsize <= 0 || attr->mq_msgsize > 1048576)
{ {
set_errno (EINVAL); set_errno (EINVAL);
goto err; __leave;
} }
/* Calculate and set the file size */ /* Calculate and set the file size */
msgsize = MSGSIZE (attr->mq_msgsize); msgsize = MSGSIZE (attr->mq_msgsize);
filesize = sizeof (struct mq_hdr) filesize = sizeof (struct mq_hdr)
+ (attr->mq_maxmsg * (sizeof (struct msg_hdr) + msgsize)); + (attr->mq_maxmsg * (sizeof (struct msg_hdr) + msgsize));
if (lseek64 (fd, filesize - 1, SEEK_SET) == -1) if (lseek64 (fd, filesize - 1, SEEK_SET) == -1)
goto err; __leave;
if (write (fd, "", 1) == -1) if (write (fd, "", 1) == -1)
goto err; __leave;
/* Memory map the file */ /* Memory map the file */
mptr = (int8_t *) mmap64 (NULL, (size_t) filesize, PROT_READ | PROT_WRITE, mptr = (int8_t *) mmap64 (NULL, (size_t) filesize,
PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0); MAP_SHARED, fd, 0);
if (mptr == (int8_t *) MAP_FAILED) if (mptr == (int8_t *) MAP_FAILED)
goto err; __leave;
/* Allocate one mq_info{} for the queue */ /* Allocate one mq_info{} for the queue */
if (!(mqinfo = (struct mq_info *) calloc (1, sizeof (struct mq_info)))) if (!(mqinfo = (struct mq_info *)
goto err; calloc (1, sizeof (struct mq_info))))
__leave;
mqinfo->mqi_hdr = mqhdr = (struct mq_hdr *) mptr; mqinfo->mqi_hdr = mqhdr = (struct mq_hdr *) mptr;
mqinfo->mqi_magic = MQI_MAGIC; mqinfo->mqi_magic = MQI_MAGIC;
mqinfo->mqi_flags = nonblock; mqinfo->mqi_flags = nonblock;
@ -524,30 +522,36 @@ again:
/* Initialize mutex & condition variables */ /* Initialize mutex & condition variables */
i = ipc_mutex_init (&mqinfo->mqi_lock, mqhdr->mqh_uname); i = ipc_mutex_init (&mqinfo->mqi_lock, mqhdr->mqh_uname);
if (i != 0) if (i != 0)
goto pthreaderr; {
set_errno (i);
__leave;
}
i = ipc_cond_init (&mqinfo->mqi_waitsend, mqhdr->mqh_uname, 'S'); i = ipc_cond_init (&mqinfo->mqi_waitsend, mqhdr->mqh_uname, 'S');
if (i != 0) if (i != 0)
goto pthreaderr; {
set_errno (i);
__leave;
}
i = ipc_cond_init (&mqinfo->mqi_waitrecv, mqhdr->mqh_uname, 'R'); i = ipc_cond_init (&mqinfo->mqi_waitrecv, mqhdr->mqh_uname, 'R');
if (i != 0) if (i != 0)
goto pthreaderr; {
set_errno (i);
__leave;
}
/* Initialization complete, turn off user-execute bit */ /* Initialization complete, turn off user-execute bit */
if (fchmod (fd, mode) == -1) if (fchmod (fd, mode) == -1)
goto err; __leave;
close (fd); close (fd);
return ((mqd_t) mqinfo); return ((mqd_t) mqinfo);
} }
exists: exists:
/* Open the file then memory map */ /* Open the file then memory map */
if ((fd = open (mqname, O_RDWR | O_CLOEXEC)) < 0) if ((fd = open (mqname, O_RDWR | O_CLOEXEC)) < 0)
{ {
if (errno == ENOENT && (oflag & O_CREAT)) if (errno == ENOENT && (oflag & O_CREAT))
goto again; goto again;
goto err; __leave;
} }
/* Make certain initialization is complete */ /* Make certain initialization is complete */
for (i = 0; i < MAX_TRIES; i++) for (i = 0; i < MAX_TRIES; i++)
@ -560,7 +564,7 @@ exists:
fd = -1; fd = -1;
goto again; goto again;
} }
goto err; __leave;
} }
if ((statbuff.st_mode & S_IXUSR) == 0) if ((statbuff.st_mode & S_IXUSR) == 0)
break; break;
@ -569,29 +573,29 @@ exists:
if (i == MAX_TRIES) if (i == MAX_TRIES)
{ {
set_errno (ETIMEDOUT); set_errno (ETIMEDOUT);
goto err; __leave;
} }
filesize = statbuff.st_size; filesize = statbuff.st_size;
mptr = (int8_t *) mmap64 (NULL, (size_t) filesize, PROT_READ | PROT_WRITE, mptr = (int8_t *) mmap64 (NULL, (size_t) filesize, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0); MAP_SHARED, fd, 0);
if (mptr == (int8_t *) MAP_FAILED) if (mptr == (int8_t *) MAP_FAILED)
goto err; __leave;
close (fd); close (fd);
fd = -1; fd = -1;
/* Allocate one mq_info{} for each open */ /* Allocate one mq_info{} for each open */
if (!(mqinfo = (struct mq_info *) calloc (1, sizeof (struct mq_info)))) if (!(mqinfo = (struct mq_info *) calloc (1, sizeof (struct mq_info))))
goto err; __leave;
mqinfo->mqi_hdr = mqhdr = (struct mq_hdr *) mptr; mqinfo->mqi_hdr = mqhdr = (struct mq_hdr *) mptr;
if (mqhdr->mqh_magic != MQI_MAGIC) if (mqhdr->mqh_magic != MQI_MAGIC)
{ {
system_printf ( system_printf (
"Old message queue \"%s\" detected!\n" "Old message queue \"%s\" detected!\n"
"This file is not usable as message queue anymore due to changes in the " "This file is not usable as message queue anymore due to changes in the "
"internal file layout. Please remove the file and try again.", mqname); "internal file layout. Please remove the file and try again.", mqname);
set_errno (EACCES); set_errno (EACCES);
goto err; __leave;
} }
mqinfo->mqi_magic = MQI_MAGIC; mqinfo->mqi_magic = MQI_MAGIC;
mqinfo->mqi_flags = nonblock; mqinfo->mqi_flags = nonblock;
@ -599,24 +603,28 @@ exists:
/* Initialize mutex & condition variable */ /* Initialize mutex & condition variable */
i = ipc_mutex_init (&mqinfo->mqi_lock, mqhdr->mqh_uname); i = ipc_mutex_init (&mqinfo->mqi_lock, mqhdr->mqh_uname);
if (i != 0) if (i != 0)
goto pthreaderr; {
set_errno (i);
__leave;
}
i = ipc_cond_init (&mqinfo->mqi_waitsend, mqhdr->mqh_uname, 'S'); i = ipc_cond_init (&mqinfo->mqi_waitsend, mqhdr->mqh_uname, 'S');
if (i != 0) if (i != 0)
goto pthreaderr; {
set_errno (i);
__leave;
}
i = ipc_cond_init (&mqinfo->mqi_waitrecv, mqhdr->mqh_uname, 'R'); i = ipc_cond_init (&mqinfo->mqi_waitrecv, mqhdr->mqh_uname, 'R');
if (i != 0) if (i != 0)
goto pthreaderr; {
set_errno (i);
__leave;
}
return (mqd_t) mqinfo; return (mqd_t) mqinfo;
}
pthreaderr: __except (EFAULT) {}
errno = i; __endtry
err:
/* Don't let following function calls change errno */ /* Don't let following function calls change errno */
save_errno save; save_errno save;
if (created) if (created)
unlink (mqname); unlink (mqname);
if (mptr != (int8_t *) MAP_FAILED) if (mptr != (int8_t *) MAP_FAILED)
@ -644,22 +652,20 @@ mq_getattr (mqd_t mqd, struct mq_attr *mqstat)
struct mq_fattr *attr; struct mq_fattr *attr;
struct mq_info *mqinfo; struct mq_info *mqinfo;
myfault efault; __try
if (efault.faulted (EBADF)) {
return -1;
mqinfo = (struct mq_info *) mqd; mqinfo = (struct mq_info *) mqd;
if (mqinfo->mqi_magic != MQI_MAGIC) if (mqinfo->mqi_magic != MQI_MAGIC)
{ {
set_errno (EBADF); set_errno (EBADF);
return -1; __leave;
} }
mqhdr = mqinfo->mqi_hdr; mqhdr = mqinfo->mqi_hdr;
attr = &mqhdr->mqh_attr; attr = &mqhdr->mqh_attr;
if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0) if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0)
{ {
errno = n; errno = n;
return -1; __leave;
} }
mqstat->mq_flags = mqinfo->mqi_flags; /* per-open */ mqstat->mq_flags = mqinfo->mqi_flags; /* per-open */
mqstat->mq_maxmsg = attr->mq_maxmsg; /* remaining three per-queue */ mqstat->mq_maxmsg = attr->mq_maxmsg; /* remaining three per-queue */
@ -668,6 +674,10 @@ mq_getattr (mqd_t mqd, struct mq_attr *mqstat)
ipc_mutex_unlock (mqinfo->mqi_lock); ipc_mutex_unlock (mqinfo->mqi_lock);
return 0; return 0;
}
__except (EBADF) {}
__endtry
return -1;
} }
extern "C" int extern "C" int
@ -678,22 +688,20 @@ mq_setattr (mqd_t mqd, const struct mq_attr *mqstat, struct mq_attr *omqstat)
struct mq_fattr *attr; struct mq_fattr *attr;
struct mq_info *mqinfo; struct mq_info *mqinfo;
myfault efault; __try
if (efault.faulted (EBADF)) {
return -1;
mqinfo = (struct mq_info *) mqd; mqinfo = (struct mq_info *) mqd;
if (mqinfo->mqi_magic != MQI_MAGIC) if (mqinfo->mqi_magic != MQI_MAGIC)
{ {
set_errno (EBADF); set_errno (EBADF);
return -1; __leave;
} }
mqhdr = mqinfo->mqi_hdr; mqhdr = mqinfo->mqi_hdr;
attr = &mqhdr->mqh_attr; attr = &mqhdr->mqh_attr;
if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0) if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0)
{ {
errno = n; errno = n;
return -1; __leave;
} }
if (omqstat != NULL) if (omqstat != NULL)
@ -711,6 +719,10 @@ mq_setattr (mqd_t mqd, const struct mq_attr *mqstat, struct mq_attr *omqstat)
ipc_mutex_unlock (mqinfo->mqi_lock); ipc_mutex_unlock (mqinfo->mqi_lock);
return 0; return 0;
}
__except (EBADF) {}
__endtry
return -1;
} }
extern "C" int extern "C" int
@ -721,21 +733,19 @@ mq_notify (mqd_t mqd, const struct sigevent *notification)
struct mq_hdr *mqhdr; struct mq_hdr *mqhdr;
struct mq_info *mqinfo; struct mq_info *mqinfo;
myfault efault; __try
if (efault.faulted (EBADF)) {
return -1;
mqinfo = (struct mq_info *) mqd; mqinfo = (struct mq_info *) mqd;
if (mqinfo->mqi_magic != MQI_MAGIC) if (mqinfo->mqi_magic != MQI_MAGIC)
{ {
set_errno (EBADF); set_errno (EBADF);
return -1; __leave;
} }
mqhdr = mqinfo->mqi_hdr; mqhdr = mqinfo->mqi_hdr;
if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0) if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0)
{ {
errno = n; errno = n;
return -1; __leave;
} }
pid = getpid (); pid = getpid ();
@ -752,7 +762,7 @@ mq_notify (mqd_t mqd, const struct sigevent *notification)
{ {
set_errno (EBUSY); set_errno (EBUSY);
ipc_mutex_unlock (mqinfo->mqi_lock); ipc_mutex_unlock (mqinfo->mqi_lock);
return -1; __leave;
} }
} }
mqhdr->mqh_pid = pid; mqhdr->mqh_pid = pid;
@ -760,6 +770,10 @@ mq_notify (mqd_t mqd, const struct sigevent *notification)
} }
ipc_mutex_unlock (mqinfo->mqi_lock); ipc_mutex_unlock (mqinfo->mqi_lock);
return 0; return 0;
}
__except (EBADF) {}
__endtry
return -1;
} }
static int static int
@ -773,24 +787,24 @@ _mq_send (mqd_t mqd, const char *ptr, size_t len, unsigned int prio,
struct mq_hdr *mqhdr; struct mq_hdr *mqhdr;
struct mq_fattr *attr; struct mq_fattr *attr;
struct msg_hdr *msghdr, *nmsghdr, *pmsghdr; struct msg_hdr *msghdr, *nmsghdr, *pmsghdr;
struct mq_info *mqinfo; struct mq_info *mqinfo = NULL;
bool ipc_mutex_locked = false;
int ret = -1;
pthread_testcancel (); pthread_testcancel ();
myfault efault; __try
if (efault.faulted (EBADF)) {
return -1;
mqinfo = (struct mq_info *) mqd; mqinfo = (struct mq_info *) mqd;
if (mqinfo->mqi_magic != MQI_MAGIC) if (mqinfo->mqi_magic != MQI_MAGIC)
{ {
set_errno (EBADF); set_errno (EBADF);
return -1; __leave;
} }
if (prio > MQ_PRIO_MAX) if (prio > MQ_PRIO_MAX)
{ {
set_errno (EINVAL); set_errno (EINVAL);
return -1; __leave;
} }
mqhdr = mqinfo->mqi_hdr; /* struct pointer */ mqhdr = mqinfo->mqi_hdr; /* struct pointer */
@ -799,13 +813,13 @@ _mq_send (mqd_t mqd, const char *ptr, size_t len, unsigned int prio,
if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0) if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0)
{ {
errno = n; errno = n;
return -1; __leave;
} }
ipc_mutex_locked = true;
if (len > (size_t) attr->mq_msgsize) if (len > (size_t) attr->mq_msgsize)
{ {
set_errno (EMSGSIZE); set_errno (EMSGSIZE);
goto err; __leave;
} }
if (attr->mq_curmsgs == 0) if (attr->mq_curmsgs == 0)
{ {
@ -813,7 +827,8 @@ _mq_send (mqd_t mqd, const char *ptr, size_t len, unsigned int prio,
{ {
sigev = &mqhdr->mqh_event; sigev = &mqhdr->mqh_event;
if (sigev->sigev_notify == SIGEV_SIGNAL) if (sigev->sigev_notify == SIGEV_SIGNAL)
sigqueue (mqhdr->mqh_pid, sigev->sigev_signo, sigev->sigev_value); sigqueue (mqhdr->mqh_pid, sigev->sigev_signo,
sigev->sigev_value);
mqhdr->mqh_pid = 0; /* unregister */ mqhdr->mqh_pid = 0; /* unregister */
} }
} }
@ -823,17 +838,17 @@ _mq_send (mqd_t mqd, const char *ptr, size_t len, unsigned int prio,
if (mqinfo->mqi_flags & O_NONBLOCK) if (mqinfo->mqi_flags & O_NONBLOCK)
{ {
set_errno (EAGAIN); set_errno (EAGAIN);
goto err; __leave;
} }
/* Wait for room for one message on the queue */ /* Wait for room for one message on the queue */
while (attr->mq_curmsgs >= attr->mq_maxmsg) while (attr->mq_curmsgs >= attr->mq_maxmsg)
{ {
int ret = ipc_cond_timedwait (mqinfo->mqi_waitsend, mqinfo->mqi_lock, int ret = ipc_cond_timedwait (mqinfo->mqi_waitsend,
abstime); mqinfo->mqi_lock, abstime);
if (ret != 0) if (ret != 0)
{ {
set_errno (ret); set_errno (ret);
return -1; __leave;
} }
} }
} }
@ -875,11 +890,13 @@ _mq_send (mqd_t mqd, const char *ptr, size_t len, unsigned int prio,
attr->mq_curmsgs++; attr->mq_curmsgs++;
ipc_mutex_unlock (mqinfo->mqi_lock); ipc_mutex_unlock (mqinfo->mqi_lock);
return 0; ret = 0;
}
err: __except (EBADF) {}
__endtry
if (ipc_mutex_locked)
ipc_mutex_unlock (mqinfo->mqi_lock); ipc_mutex_unlock (mqinfo->mqi_lock);
return -1; return ret;
} }
extern "C" int extern "C" int
@ -902,23 +919,21 @@ _mq_receive (mqd_t mqd, char *ptr, size_t maxlen, unsigned int *priop,
int n; int n;
long index; long index;
int8_t *mptr; int8_t *mptr;
ssize_t len; ssize_t len = -1;
struct mq_hdr *mqhdr; struct mq_hdr *mqhdr;
struct mq_fattr *attr; struct mq_fattr *attr;
struct msg_hdr *msghdr; struct msg_hdr *msghdr;
struct mq_info *mqinfo; struct mq_info *mqinfo = (struct mq_info *) mqd;
bool ipc_mutex_locked = false;
pthread_testcancel (); pthread_testcancel ();
myfault efault; __try
if (efault.faulted (EBADF)) {
return -1;
mqinfo = (struct mq_info *) mqd;
if (mqinfo->mqi_magic != MQI_MAGIC) if (mqinfo->mqi_magic != MQI_MAGIC)
{ {
set_errno (EBADF); set_errno (EBADF);
return -1; __leave;
} }
mqhdr = mqinfo->mqi_hdr; /* struct pointer */ mqhdr = mqinfo->mqi_hdr; /* struct pointer */
mptr = (int8_t *) mqhdr; /* byte pointer */ mptr = (int8_t *) mqhdr; /* byte pointer */
@ -926,31 +941,31 @@ _mq_receive (mqd_t mqd, char *ptr, size_t maxlen, unsigned int *priop,
if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0) if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0)
{ {
errno = n; errno = n;
return -1; __leave;
} }
ipc_mutex_locked = true;
if (maxlen < (size_t) attr->mq_msgsize) if (maxlen < (size_t) attr->mq_msgsize)
{ {
set_errno (EMSGSIZE); set_errno (EMSGSIZE);
goto err; __leave;
} }
if (attr->mq_curmsgs == 0) /* queue is empty */ if (attr->mq_curmsgs == 0) /* queue is empty */
{ {
if (mqinfo->mqi_flags & O_NONBLOCK) if (mqinfo->mqi_flags & O_NONBLOCK)
{ {
set_errno (EAGAIN); set_errno (EAGAIN);
goto err; __leave;
} }
/* Wait for a message to be placed onto queue */ /* Wait for a message to be placed onto queue */
mqhdr->mqh_nwait++; mqhdr->mqh_nwait++;
while (attr->mq_curmsgs == 0) while (attr->mq_curmsgs == 0)
{ {
int ret = ipc_cond_timedwait (mqinfo->mqi_waitrecv, mqinfo->mqi_lock, int ret = ipc_cond_timedwait (mqinfo->mqi_waitrecv,
abstime); mqinfo->mqi_lock, abstime);
if (ret != 0) if (ret != 0)
{ {
set_errno (ret); set_errno (ret);
return -1; __leave;
} }
} }
mqhdr->mqh_nwait--; mqhdr->mqh_nwait--;
@ -976,11 +991,12 @@ _mq_receive (mqd_t mqd, char *ptr, size_t maxlen, unsigned int *priop,
attr->mq_curmsgs--; attr->mq_curmsgs--;
ipc_mutex_unlock (mqinfo->mqi_lock); ipc_mutex_unlock (mqinfo->mqi_lock);
return len; }
__except (EBADF) {}
err: __endtry
if (ipc_mutex_locked)
ipc_mutex_unlock (mqinfo->mqi_lock); ipc_mutex_unlock (mqinfo->mqi_lock);
return -1; return len;
} }
extern "C" ssize_t extern "C" ssize_t
@ -1004,27 +1020,25 @@ mq_close (mqd_t mqd)
struct mq_fattr *attr; struct mq_fattr *attr;
struct mq_info *mqinfo; struct mq_info *mqinfo;
myfault efault; __try
if (efault.faulted (EBADF)) {
return -1;
mqinfo = (struct mq_info *) mqd; mqinfo = (struct mq_info *) mqd;
if (mqinfo->mqi_magic != MQI_MAGIC) if (mqinfo->mqi_magic != MQI_MAGIC)
{ {
set_errno (EBADF); set_errno (EBADF);
return -1; __leave;
} }
mqhdr = mqinfo->mqi_hdr; mqhdr = mqinfo->mqi_hdr;
attr = &mqhdr->mqh_attr; attr = &mqhdr->mqh_attr;
if (mq_notify (mqd, NULL)) /* unregister calling process */ if (mq_notify (mqd, NULL)) /* unregister calling process */
return -1; __leave;
msgsize = MSGSIZE (attr->mq_msgsize); msgsize = MSGSIZE (attr->mq_msgsize);
filesize = sizeof (struct mq_hdr) filesize = sizeof (struct mq_hdr)
+ (attr->mq_maxmsg * (sizeof (struct msg_hdr) + msgsize)); + (attr->mq_maxmsg * (sizeof (struct msg_hdr) + msgsize));
if (munmap (mqinfo->mqi_hdr, filesize) == -1) if (munmap (mqinfo->mqi_hdr, filesize) == -1)
return -1; __leave;
mqinfo->mqi_magic = 0; /* just in case */ mqinfo->mqi_magic = 0; /* just in case */
ipc_cond_close (mqinfo->mqi_waitsend); ipc_cond_close (mqinfo->mqi_waitsend);
@ -1032,6 +1046,10 @@ mq_close (mqd_t mqd)
ipc_mutex_close (mqinfo->mqi_lock); ipc_mutex_close (mqinfo->mqi_lock);
free (mqinfo); free (mqinfo);
return 0; return 0;
}
__except (EBADF) {}
__endtry
return -1;
} }
extern "C" int extern "C" int
@ -1062,7 +1080,7 @@ struct sem_finfo
extern "C" sem_t * extern "C" sem_t *
sem_open (const char *name, int oflag, ...) sem_open (const char *name, int oflag, ...)
{ {
int i, fd = -1, created; int i, fd = -1, created = 0;
va_list ap; va_list ap;
mode_t mode = 0; mode_t mode = 0;
unsigned int value = 0; unsigned int value = 0;
@ -1078,14 +1096,11 @@ sem_open (const char *name, int oflag, ...)
if (!check_path (semname, semaphore, name, len)) if (!check_path (semname, semaphore, name, len))
return SEM_FAILED; return SEM_FAILED;
myfault efault; __try
if (efault.faulted (EFAULT)) {
return SEM_FAILED;
created = 0;
oflag &= (O_CREAT | O_EXCL); oflag &= (O_CREAT | O_EXCL);
again: again:
if (oflag & O_CREAT) if (oflag & O_CREAT)
{ {
va_start (ap, oflag); /* init ap to final named argument */ va_start (ap, oflag); /* init ap to final named argument */
@ -1094,7 +1109,8 @@ again:
va_end (ap); va_end (ap);
/* Open and specify O_EXCL and user-execute */ /* Open and specify O_EXCL and user-execute */
fd = open (semname, oflag | O_EXCL | O_RDWR | O_CLOEXEC, mode | S_IXUSR); fd = open (semname, oflag | O_EXCL | O_RDWR | O_CLOEXEC,
mode | S_IXUSR);
if (fd < 0) if (fd < 0)
{ {
if (errno == EEXIST && (oflag & O_EXCL) == 0) if (errno == EEXIST && (oflag & O_EXCL) == 0)
@ -1107,24 +1123,25 @@ again:
sf.value = value; sf.value = value;
sf.hash = hash_path_name (0, semname); sf.hash = hash_path_name (0, semname);
if (write (fd, &sf, sizeof sf) != sizeof sf) if (write (fd, &sf, sizeof sf) != sizeof sf)
goto err; __leave;
sem = semaphore::open (sf.hash, sf.luid, fd, oflag, mode, value, wasopen); sem = semaphore::open (sf.hash, sf.luid, fd, oflag, mode, value,
wasopen);
if (sem == SEM_FAILED) if (sem == SEM_FAILED)
goto err; __leave;
/* Initialization complete, turn off user-execute bit */ /* Initialization complete, turn off user-execute bit */
if (fchmod (fd, mode) == -1) if (fchmod (fd, mode) == -1)
goto err; __leave;
/* Don't close (fd); */ /* Don't close (fd); */
return sem; return sem;
} }
exists: exists:
/* Open the file and fetch the semaphore name. */ /* Open the file and fetch the semaphore name. */
if ((fd = open (semname, O_RDWR | O_CLOEXEC)) < 0) if ((fd = open (semname, O_RDWR | O_CLOEXEC)) < 0)
{ {
if (errno == ENOENT && (oflag & O_CREAT)) if (errno == ENOENT && (oflag & O_CREAT))
goto again; goto again;
goto err; __leave;
} }
/* Make certain initialization is complete */ /* Make certain initialization is complete */
for (i = 0; i < MAX_TRIES; i++) for (i = 0; i < MAX_TRIES; i++)
@ -1137,7 +1154,7 @@ exists:
fd = -1; fd = -1;
goto again; goto again;
} }
goto err; __leave;
} }
if ((statbuff.st_mode & S_IXUSR) == 0) if ((statbuff.st_mode & S_IXUSR) == 0)
break; break;
@ -1146,16 +1163,17 @@ exists:
if (i == MAX_TRIES) if (i == MAX_TRIES)
{ {
set_errno (ETIMEDOUT); set_errno (ETIMEDOUT);
goto err; __leave;
} }
if (file.lock (fd, sizeof sf)) if (file.lock (fd, sizeof sf))
goto err; __leave;
if (read (fd, &sf, sizeof sf) != sizeof sf) if (read (fd, &sf, sizeof sf) != sizeof sf)
goto err; __leave;
sem = semaphore::open (sf.hash, sf.luid, fd, oflag, mode, sf.value, wasopen); sem = semaphore::open (sf.hash, sf.luid, fd, oflag, mode, sf.value,
wasopen);
file.unlock (fd); file.unlock (fd);
if (sem == SEM_FAILED) if (sem == SEM_FAILED)
goto err; __leave;
/* If wasopen is set, the semaphore was already opened and we already have /* If wasopen is set, the semaphore was already opened and we already have
an open file descriptor pointing to the file. This means, we have to an open file descriptor pointing to the file. This means, we have to
close the file descriptor created in this call. It won't be stored close the file descriptor created in this call. It won't be stored
@ -1163,11 +1181,13 @@ exists:
if (wasopen) if (wasopen)
close (fd); close (fd);
return sem; return sem;
}
err: __except (EFAULT) {}
__endtry
/* Don't let following function calls change errno */ /* Don't let following function calls change errno */
save_errno save; save_errno save;
if (fd >= 0)
file.unlock (fd); file.unlock (fd);
if (created) if (created)
unlink (semname); unlink (semname);

View File

@ -1,7 +1,7 @@
/* resource.cc: getrusage () and friends. /* resource.cc: getrusage () and friends.
Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005, 2008, 2009, 2010, Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005, 2008, 2009, 2010,
2011, 2012, 2013 Red Hat, Inc. 2011, 2012, 2013, 2014 Red Hat, Inc.
Written by Steve Chamberlain (sac@cygnus.com), Doug Evans (dje@cygnus.com), Written by Steve Chamberlain (sac@cygnus.com), Doug Evans (dje@cygnus.com),
Geoffrey Noer (noer@cygnus.com) of Cygnus Support. Geoffrey Noer (noer@cygnus.com) of Cygnus Support.
@ -116,10 +116,8 @@ getrlimit (int resource, struct rlimit *rlp)
{ {
MEMORY_BASIC_INFORMATION m; MEMORY_BASIC_INFORMATION m;
myfault efault; __try
if (efault.faulted (EFAULT)) {
return -1;
rlp->rlim_cur = RLIM_INFINITY; rlp->rlim_cur = RLIM_INFINITY;
rlp->rlim_max = RLIM_INFINITY; rlp->rlim_max = RLIM_INFINITY;
@ -151,18 +149,18 @@ getrlimit (int resource, struct rlimit *rlp)
break; break;
default: default:
set_errno (EINVAL); set_errno (EINVAL);
return -1; __leave;
} }
return 0; return 0;
}
__except (EFAULT) {}
__endtry
return -1;
} }
extern "C" int extern "C" int
setrlimit (int resource, const struct rlimit *rlp) setrlimit (int resource, const struct rlimit *rlp)
{ {
myfault efault;
if (efault.faulted (EFAULT))
return -1;
struct rlimit oldlimits; struct rlimit oldlimits;
/* Check if the request is to actually change the resource settings. /* Check if the request is to actually change the resource settings.
@ -170,6 +168,8 @@ setrlimit (int resource, const struct rlimit *rlp)
if (getrlimit (resource, &oldlimits) < 0) if (getrlimit (resource, &oldlimits) < 0)
return -1; return -1;
__try
{
if (oldlimits.rlim_cur == rlp->rlim_cur && if (oldlimits.rlim_cur == rlp->rlim_cur &&
oldlimits.rlim_max == rlp->rlim_max) oldlimits.rlim_max == rlp->rlim_max)
/* No change in resource requirements, succeed immediately */ /* No change in resource requirements, succeed immediately */
@ -178,7 +178,7 @@ setrlimit (int resource, const struct rlimit *rlp)
if (rlp->rlim_cur > rlp->rlim_max) if (rlp->rlim_cur > rlp->rlim_max)
{ {
set_errno (EINVAL); set_errno (EINVAL);
return -1; __leave;
} }
switch (resource) switch (resource)
@ -192,7 +192,11 @@ setrlimit (int resource, const struct rlimit *rlp)
break; break;
default: default:
set_errno (EINVAL); set_errno (EINVAL);
return -1; __leave;
} }
return 0; return 0;
}
__except (EFAULT)
__endtry
return -1;
} }

View File

@ -1,7 +1,7 @@
/* select.cc /* select.cc
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2007, 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc. 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -230,9 +230,8 @@ pselect(int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
struct timeval tv; struct timeval tv;
sigset_t oldset = _my_tls.sigmask; sigset_t oldset = _my_tls.sigmask;
myfault efault; __try
if (efault.faulted (EFAULT)) {
return -1;
if (ts) if (ts)
{ {
tv.tv_sec = ts->tv_sec; tv.tv_sec = ts->tv_sec;
@ -245,6 +244,10 @@ pselect(int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
if (set) if (set)
set_signal_mask (_my_tls.sigmask, oldset); set_signal_mask (_my_tls.sigmask, oldset);
return ret; return ret;
}
__except (EFAULT) {}
__endtry
return -1;
} }
/* Call cleanup functions for all inspected fds. Gets rid of any /* Call cleanup functions for all inspected fds. Gets rid of any

View File

@ -1,6 +1,6 @@
/* sem.cc: XSI IPC interface for Cygwin. /* sem.cc: XSI IPC interface for Cygwin.
Copyright 2002, 2003, 2004, 2005, 2008, 2009, 2012 Red Hat, Inc. Copyright 2002, 2003, 2004, 2005, 2008, 2009, 2012, 2014 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -85,9 +85,8 @@ semctl (int semid, int semnum, int cmd, ...)
} }
syscall_printf ("semctl (semid = %d, semnum = %d, cmd = %d, arg = %p)", syscall_printf ("semctl (semid = %d, semnum = %d, cmd = %d, arg = %p)",
semid, semnum, cmd, arg.buf); semid, semnum, cmd, arg.buf);
myfault efault; __try
if (efault.faulted (EFAULT)) {
return -1;
client_request_sem request (semid, semnum, cmd, &arg); client_request_sem request (semid, semnum, cmd, &arg);
if (request.make_request () == -1 || request.retval () == -1) if (request.make_request () == -1 || request.retval () == -1)
{ {
@ -95,9 +94,13 @@ semctl (int semid, int semnum, int cmd, ...)
set_errno (request.error_code ()); set_errno (request.error_code ());
if (request.error_code () == ENOSYS) if (request.error_code () == ENOSYS)
raise (SIGSYS); raise (SIGSYS);
return -1; __leave;
} }
return request.retval (); return request.retval ();
}
__except (EFAULT) {}
__endtry
return -1;
} }
extern "C" int extern "C" int
@ -122,9 +125,8 @@ semop (int semid, struct sembuf *sops, size_t nsops)
{ {
syscall_printf ("semop (semid = %d, sops = %p, nsops = %ld)", syscall_printf ("semop (semid = %d, sops = %p, nsops = %ld)",
semid, sops, nsops); semid, sops, nsops);
myfault efault; __try
if (efault.faulted (EFAULT)) {
return -1;
client_request_sem request (semid, sops, nsops); client_request_sem request (semid, sops, nsops);
if (request.make_request () == -1 || request.retval () == -1) if (request.make_request () == -1 || request.retval () == -1)
{ {
@ -132,7 +134,11 @@ semop (int semid, struct sembuf *sops, size_t nsops)
set_errno (request.error_code ()); set_errno (request.error_code ());
if (request.error_code () == ENOSYS) if (request.error_code () == ENOSYS)
raise (SIGSYS); raise (SIGSYS);
return -1; __leave;
} }
return request.retval (); return request.retval ();
}
__except (EFAULT) {}
__endtry
return -1;
} }

View File

@ -260,9 +260,8 @@ shmctl (int shmid, int cmd, struct shmid_ds *buf)
{ {
syscall_printf ("shmctl (shmid = %d, cmd = %d, buf = %p)", syscall_printf ("shmctl (shmid = %d, cmd = %d, buf = %p)",
shmid, cmd, buf); shmid, cmd, buf);
myfault efault; __try
if (efault.faulted (EFAULT)) {
return -1;
client_request_shm request (shmid, cmd, buf); client_request_shm request (shmid, cmd, buf);
if (request.make_request () == -1 || request.retval () == -1) if (request.make_request () == -1 || request.retval () == -1)
{ {
@ -270,7 +269,7 @@ shmctl (int shmid, int cmd, struct shmid_ds *buf)
set_errno (request.error_code ()); set_errno (request.error_code ());
if (request.error_code () == ENOSYS) if (request.error_code () == ENOSYS)
raise (SIGSYS); raise (SIGSYS);
return -1; __leave;
} }
if (cmd == IPC_RMID) if (cmd == IPC_RMID)
{ {
@ -285,7 +284,8 @@ shmctl (int shmid, int cmd, struct shmid_ds *buf)
only if it's not in use anymore. */ only if it's not in use anymore. */
if (ssh_entry->ref_count <= 0) if (ssh_entry->ref_count <= 0)
{ {
SLIST_REMOVE (&ssh_list, ssh_entry, shm_shmid_list, ssh_next); SLIST_REMOVE (&ssh_list, ssh_entry, shm_shmid_list,
ssh_next);
CloseHandle (ssh_entry->hdl); CloseHandle (ssh_entry->hdl);
delete ssh_entry; delete ssh_entry;
} }
@ -295,6 +295,10 @@ shmctl (int shmid, int cmd, struct shmid_ds *buf)
SLIST_UNLOCK (); SLIST_UNLOCK ();
} }
return request.retval (); return request.retval ();
}
__except (EFAULT) {}
__endtry
return -1;
} }
extern "C" int extern "C" int

View File

@ -1,7 +1,7 @@
/* signal.cc /* signal.cc
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2007, 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc. 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
Written by Steve Chamberlain of Cygnus Support, sac@cygnus.com Written by Steve Chamberlain of Cygnus Support, sac@cygnus.com
Significant changes by Sergey Okhapkin <sos@prospect.com.ru> Significant changes by Sergey Okhapkin <sos@prospect.com.ru>
@ -197,10 +197,8 @@ handle_sigprocmask (int how, const sigset_t *set, sigset_t *oldset, sigset_t& op
return EINVAL; return EINVAL;
} }
myfault efault; __try
if (efault.faulted (EFAULT)) {
return EFAULT;
if (oldset) if (oldset)
*oldset = opmask; *oldset = opmask;
@ -224,6 +222,12 @@ handle_sigprocmask (int how, const sigset_t *set, sigset_t *oldset, sigset_t& op
} }
set_signal_mask (opmask, newmask); set_signal_mask (opmask, newmask);
} }
}
__except (EFAULT)
{
return EFAULT;
}
__endtry
return 0; return 0;
} }
@ -382,8 +386,7 @@ sigaction_worker (int sig, const struct sigaction *newact,
struct sigaction *oldact, bool isinternal) struct sigaction *oldact, bool isinternal)
{ {
int res = -1; int res = -1;
myfault efault; __try
if (!efault.faulted (EFAULT))
{ {
sig_dispatch_pending (); sig_dispatch_pending ();
/* check that sig is in right range */ /* check that sig is in right range */
@ -394,14 +397,17 @@ sigaction_worker (int sig, const struct sigaction *newact,
struct sigaction oa = global_sigs[sig]; struct sigaction oa = global_sigs[sig];
if (!newact) if (!newact)
sigproc_printf ("signal %d, newact %p, oa %p", sig, newact, oa, oa.sa_handler); sigproc_printf ("signal %d, newact %p, oa %p",
sig, newact, oa, oa.sa_handler);
else else
{ {
sigproc_printf ("signal %d, newact %p (handler %p), oa %p", sig, newact, newact->sa_handler, oa, oa.sa_handler); sigproc_printf ("signal %d, newact %p (handler %p), oa %p",
sig, newact, newact->sa_handler, oa,
oa.sa_handler);
if (sig == SIGKILL || sig == SIGSTOP) if (sig == SIGKILL || sig == SIGSTOP)
{ {
set_errno (EINVAL); set_errno (EINVAL);
goto out; __leave;
} }
struct sigaction na = *newact; struct sigaction na = *newact;
struct sigaction& gs = global_sigs[sig]; struct sigaction& gs = global_sigs[sig];
@ -430,8 +436,8 @@ sigaction_worker (int sig, const struct sigaction *newact,
res = 0; res = 0;
} }
} }
__except (EFAULT) {}
out: __endtry
return res; return res;
} }
@ -560,24 +566,20 @@ sigwait (const sigset_t *set, int *sig_ptr)
extern "C" int extern "C" int
sigwaitinfo (const sigset_t *set, siginfo_t *info) sigwaitinfo (const sigset_t *set, siginfo_t *info)
{ {
int res = -1;
pthread_testcancel (); pthread_testcancel ();
myfault efault; __try
if (efault.faulted (EFAULT)) {
return -1;
set_signal_mask (_my_tls.sigwait_mask, *set); set_signal_mask (_my_tls.sigwait_mask, *set);
sig_dispatch_pending (true); sig_dispatch_pending (true);
int res;
switch (cygwait (NULL, cw_infinite, cw_sig_eintr | cw_cancel | cw_cancel_self)) switch (cygwait (NULL, cw_infinite, cw_sig_eintr | cw_cancel | cw_cancel_self))
{ {
case WAIT_SIGNALED: case WAIT_SIGNALED:
if (!sigismember (set, _my_tls.infodata.si_signo)) if (!sigismember (set, _my_tls.infodata.si_signo))
{
set_errno (EINTR); set_errno (EINTR);
res = -1;
}
else else
{ {
_my_tls.lock (); _my_tls.lock ();
@ -592,9 +594,13 @@ sigwaitinfo (const sigset_t *set, siginfo_t *info)
break; break;
default: default:
__seterrno (); __seterrno ();
break;
}
}
__except (EFAULT) {
res = -1; res = -1;
} }
__endtry
sigproc_printf ("returning signal %d", res); sigproc_printf ("returning signal %d", res);
return res; return res;
} }

View File

@ -1,7 +1,7 @@
/* spawn.cc /* spawn.cc
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2007, 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc. 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -330,18 +330,10 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
STARTUPINFOW si = {}; STARTUPINFOW si = {};
int looped = 0; int looped = 0;
myfault efault;
system_call_handle system_call (mode == _P_SYSTEM); system_call_handle system_call (mode == _P_SYSTEM);
if (efault.faulted ())
{
if (get_errno () == ENOMEM)
set_errno (E2BIG);
else
set_errno (EFAULT);
res = -1;
goto out;
}
__try
{
child_info_types chtype; child_info_types chtype;
if (mode == _P_OVERLAY) if (mode == _P_OVERLAY)
chtype = _CH_EXEC; chtype = _CH_EXEC;
@ -363,13 +355,13 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
{ {
set_errno (err); set_errno (err);
res = -1; res = -1;
goto out; __leave;
} }
res = newargv.setup (prog_arg, real_path, ext, ac, argv, p_type_exec); res = newargv.setup (prog_arg, real_path, ext, ac, argv, p_type_exec);
if (res) if (res)
goto out; __leave;
if (!real_path.iscygexec () && ::cygheap->cwd.get_error ()) if (!real_path.iscygexec () && ::cygheap->cwd.get_error ())
{ {
@ -378,7 +370,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
::cygheap->cwd.get_error_desc ()); ::cygheap->cwd.get_error_desc ());
set_errno (::cygheap->cwd.get_error ()); set_errno (::cygheap->cwd.get_error ());
res = -1; res = -1;
goto out; __leave;
} }
if (ac == 3 && argv[1][0] == '/' && tolower (argv[1][1]) == 'c' && if (ac == 3 && argv[1][0] == '/' && tolower (argv[1][1]) == 'c' &&
@ -410,7 +402,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
real_path.iscygexec ())) real_path.iscygexec ()))
{ {
res = -1; res = -1;
goto out; __leave;
} }
@ -530,7 +522,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
{ {
set_errno (ENAMETOOLONG); set_errno (ENAMETOOLONG);
res = -1; res = -1;
goto out; __leave;
} }
} }
@ -545,7 +537,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
{ {
set_errno (E2BIG); set_errno (E2BIG);
res = -1; res = -1;
goto out; __leave;
} }
set (chtype, real_path.iscygexec ()); set (chtype, real_path.iscygexec ());
__stdin = in__stdin; __stdin = in__stdin;
@ -600,7 +592,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
SetHandleInformation (my_wr_proc_pipe, HANDLE_FLAG_INHERIT, 0); SetHandleInformation (my_wr_proc_pipe, HANDLE_FLAG_INHERIT, 0);
parent_winpid = GetCurrentProcessId (); parent_winpid = GetCurrentProcessId ();
loop: loop:
/* When ruid != euid we create the new process under the current original /* When ruid != euid we create the new process under the current original
account and impersonate in child, this way maintaining the different account and impersonate in child, this way maintaining the different
effective vs. real ids. effective vs. real ids.
@ -737,7 +729,7 @@ loop:
::cygheap->user.reimpersonate (); ::cygheap->user.reimpersonate ();
res = -1; res = -1;
goto out; __leave;
} }
/* The CREATE_SUSPENDED case is handled below */ /* The CREATE_SUSPENDED case is handled below */
@ -783,7 +775,7 @@ loop:
if (get_errno () != ENOMEM) if (get_errno () != ENOMEM)
set_errno (EAGAIN); set_errno (EAGAIN);
res = -1; res = -1;
goto out; __leave;
} }
child->dwProcessId = pi.dwProcessId; child->dwProcessId = pi.dwProcessId;
child.hProcess = pi.hProcess; child.hProcess = pi.hProcess;
@ -805,7 +797,7 @@ loop:
CloseHandle (pi.hProcess); CloseHandle (pi.hProcess);
ForceCloseHandle (pi.hThread); ForceCloseHandle (pi.hThread);
res = -1; res = -1;
goto out; __leave;
} }
} }
@ -874,8 +866,16 @@ loop:
default: default:
break; break;
} }
}
out: __except (NO_ERROR)
{
if (get_errno () == ENOMEM)
set_errno (E2BIG);
else
set_errno (EFAULT);
res = -1;
}
__endtry
this->cleanup (); this->cleanup ();
if (envblock) if (envblock)
free (envblock); free (envblock);
@ -1137,14 +1137,8 @@ av::setup (const char *prog_arg, path_conv& real_path, const char *ext,
} }
{ {
myfault efault; __try
if (efault.faulted ())
{ {
UnmapViewOfFile (buf);
CloseHandle (hm);
real_path.set_cygexec (false);
break;
}
if (buf[0] == 'M' && buf[1] == 'Z') if (buf[0] == 'M' && buf[1] == 'Z')
{ {
WORD subsys; WORD subsys;
@ -1160,6 +1154,15 @@ av::setup (const char *prog_arg, path_conv& real_path, const char *ext,
break; break;
} }
} }
__except (NO_ERROR)
{
UnmapViewOfFile (buf);
CloseHandle (hm);
real_path.set_cygexec (false);
break;
}
__endtry
}
CloseHandle (hm); CloseHandle (hm);
debug_printf ("%s is possibly a script", real_path.get_win32 ()); debug_printf ("%s is possibly a script", real_path.get_win32 ());

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/* thread.cc: Locking and threading module functions /* thread.cc: Locking and threading module functions
Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
2009, 2010, 2011, 2012, 2013 Red Hat, Inc. 2009, 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -122,28 +122,29 @@ __cygwin_lock_unlock (_LOCK_T *lock)
paranoid_printf ("threadcount %d. unlocked", MT_INTERFACE->threadcount); paranoid_printf ("threadcount %d. unlocked", MT_INTERFACE->threadcount);
} }
#if __GNUC__ == 4 && __GNUC_MINOR__ >= 7
/* FIXME: Temporarily workaround gcc 4.7+ bug. */
static verifyable_object_state
#else
static inline verifyable_object_state static inline verifyable_object_state
#endif
verifyable_object_isvalid (void const *objectptr, thread_magic_t magic, void *static_ptr1, verifyable_object_isvalid (void const *objectptr, thread_magic_t magic, void *static_ptr1,
void *static_ptr2, void *static_ptr3) void *static_ptr2, void *static_ptr3)
{ {
myfault efault; verifyable_object_state state = INVALID_OBJECT;
if (efault.faulted (objectptr))
return INVALID_OBJECT; __try
{
if (!objectptr || !(*(const char **) objectptr))
__leave;
verifyable_object **object = (verifyable_object **) objectptr; verifyable_object **object = (verifyable_object **) objectptr;
if ((static_ptr1 && *object == static_ptr1) || if ((static_ptr1 && *object == static_ptr1) ||
(static_ptr2 && *object == static_ptr2) || (static_ptr2 && *object == static_ptr2) ||
(static_ptr3 && *object == static_ptr3)) (static_ptr3 && *object == static_ptr3))
return VALID_STATIC_OBJECT; state = VALID_STATIC_OBJECT;
if ((*object)->magic != magic) else if ((*object)->magic == magic)
return INVALID_OBJECT; state = VALID_OBJECT;
return VALID_OBJECT; }
__except (NO_ERROR) {}
__endtry
return state;
} }
/* static members */ /* static members */
@ -2684,18 +2685,20 @@ pthread_cond::init (pthread_cond_t *cond, const pthread_condattr_t *attr)
return EAGAIN; return EAGAIN;
} }
myfault efault; int ret = 0;
if (efault.faulted ())
__try
{
*cond = new_cond;
}
__except (NO_ERROR)
{ {
delete new_cond; delete new_cond;
cond_initialization_lock.unlock (); ret = EINVAL;
return EINVAL;
} }
__endtry
*cond = new_cond;
cond_initialization_lock.unlock (); cond_initialization_lock.unlock ();
return ret;
return 0;
} }
extern "C" int extern "C" int
@ -2747,12 +2750,10 @@ pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
struct timespec tp; struct timespec tp;
LARGE_INTEGER timeout; LARGE_INTEGER timeout;
myfault efault;
if (efault.faulted ())
return EINVAL;
pthread_testcancel (); pthread_testcancel ();
__try
{
int err = __pthread_cond_wait_init (cond, mutex); int err = __pthread_cond_wait_init (cond, mutex);
if (err) if (err)
return err; return err;
@ -2761,7 +2762,7 @@ pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
if (abstime->tv_sec < 0 if (abstime->tv_sec < 0
|| abstime->tv_nsec < 0 || abstime->tv_nsec < 0
|| abstime->tv_nsec > 999999999) || abstime->tv_nsec > 999999999)
return EINVAL; __leave;
clock_gettime ((*cond)->clock_id, &tp); clock_gettime ((*cond)->clock_id, &tp);
@ -2786,6 +2787,10 @@ pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
break; break;
} }
return (*cond)->wait (*mutex, &timeout); return (*cond)->wait (*mutex, &timeout);
}
__except (NO_ERROR) {}
__endtry
return EINVAL;
} }
extern "C" int extern "C" int
@ -2910,18 +2915,20 @@ pthread_rwlock::init (pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr
return EAGAIN; return EAGAIN;
} }
myfault efault; int ret = 0;
if (efault.faulted ())
__try
{
*rwlock = new_rwlock;
}
__except (NO_ERROR)
{ {
delete new_rwlock; delete new_rwlock;
rwlock_initialization_lock.unlock (); ret = EINVAL;
return EINVAL;
} }
__endtry
*rwlock = new_rwlock;
rwlock_initialization_lock.unlock (); rwlock_initialization_lock.unlock ();
return ret;
return 0;
} }
extern "C" int extern "C" int
@ -3133,15 +3140,17 @@ pthread_mutex::init (pthread_mutex_t *mutex,
new_mutex->type = PTHREAD_MUTEX_ERRORCHECK; new_mutex->type = PTHREAD_MUTEX_ERRORCHECK;
} }
myfault efault; __try
if (efault.faulted ()) {
*mutex = new_mutex;
}
__except (NO_ERROR)
{ {
delete new_mutex; delete new_mutex;
mutex_initialization_lock.unlock (); mutex_initialization_lock.unlock ();
return EINVAL; return EINVAL;
} }
__endtry
*mutex = new_mutex;
} }
mutex_initialization_lock.unlock (); mutex_initialization_lock.unlock ();
pthread_printf ("*mutex %p, attr %p, initializer %p", *mutex, attr, initializer); pthread_printf ("*mutex %p, attr %p, initializer %p", *mutex, attr, initializer);
@ -3230,16 +3239,17 @@ pthread_spinlock::init (pthread_spinlock_t *spinlock, int pshared)
return EAGAIN; return EAGAIN;
} }
myfault efault; __try
if (efault.faulted ()) {
*spinlock = new_spinlock;
}
__except (NO_ERROR)
{ {
delete new_spinlock; delete new_spinlock;
return EINVAL; return EINVAL;
} }
__endtry
*spinlock = new_spinlock;
pthread_printf ("*spinlock %p, pshared %d", *spinlock, pshared); pthread_printf ("*spinlock %p, pshared %d", *spinlock, pshared);
return 0; return 0;
} }
@ -3502,17 +3512,8 @@ semaphore::_timedwait (const struct timespec *abstime)
{ {
LARGE_INTEGER timeout; LARGE_INTEGER timeout;
myfault efault; __try
if (efault.faulted ())
{ {
/* According to SUSv3, abstime need not be checked for validity,
if the semaphore can be locked immediately. */
if (!_trywait ())
return 0;
set_errno (EINVAL);
return -1;
}
timeout.QuadPart = abstime->tv_sec * NSPERSEC timeout.QuadPart = abstime->tv_sec * NSPERSEC
+ (abstime->tv_nsec + 99) / 100 + FACTOR; + (abstime->tv_nsec + 99) / 100 + FACTOR;
@ -3531,6 +3532,18 @@ semaphore::_timedwait (const struct timespec *abstime)
__seterrno (); __seterrno ();
return -1; return -1;
} }
}
__except (NO_ERROR)
{
/* According to SUSv3, abstime need not be checked for validity,
if the semaphore can be locked immediately. */
if (_trywait ())
{
set_errno (EINVAL);
return -1;
}
}
__endtry
return 0; return 0;
} }
@ -3761,36 +3774,38 @@ semaphore::post (sem_t *sem)
int int
semaphore::getvalue (sem_t *sem, int *sval) semaphore::getvalue (sem_t *sem, int *sval)
{ {
myfault efault; __try
if (efault.faulted () || !is_good_object (sem))
{ {
if (is_good_object (sem))
return (*sem)->_getvalue (sval);
}
__except (NO_ERROR) {}
__endtry
set_errno (EINVAL); set_errno (EINVAL);
return -1; return -1;
}
return (*sem)->_getvalue (sval);
} }
int int
semaphore::getinternal (sem_t *sem, int *sfd, unsigned long long *shash, semaphore::getinternal (sem_t *sem, int *sfd, unsigned long long *shash,
LUID *sluid, unsigned int *sval) LUID *sluid, unsigned int *sval)
{ {
myfault efault; __try
if (efault.faulted () || !is_good_object (sem))
{ {
set_errno (EINVAL); if (!is_good_object (sem))
return -1; __leave;
}
if ((*sfd = (*sem)->fd) < 0) if ((*sfd = (*sem)->fd) < 0)
{ __leave;
set_errno (EINVAL);
return -1;
}
*shash = (*sem)->hash; *shash = (*sem)->hash;
*sluid = (*sem)->luid; *sluid = (*sem)->luid;
/* POSIX defines the value in calls to sem_init/sem_open as unsigned, but /* POSIX defines the value in calls to sem_init/sem_open as unsigned,
the sem_getvalue gets a pointer to int to return the value. Go figure! */ but the sem_getvalue gets a pointer to int to return the value.
Go figure! */
return (*sem)->_getvalue ((int *)sval); return (*sem)->_getvalue ((int *)sval);
}
__except (NO_ERROR) {}
__endtry
set_errno (EINVAL);
return -1;
} }
/* pthread_null */ /* pthread_null */

View File

@ -1,6 +1,6 @@
/* timer.cc /* timer.cc
Copyright 2004, 2005, 2006, 2008, 2010, 2011, 2012, 2013 Red Hat, Inc. Copyright 2004, 2005, 2006, 2008, 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -219,17 +219,18 @@ it_bad (const timespec& t)
int int
timer_tracker::settime (int in_flags, const itimerspec *value, itimerspec *ovalue) timer_tracker::settime (int in_flags, const itimerspec *value, itimerspec *ovalue)
{ {
int ret = -1;
__try
{
if (!value) if (!value)
{ {
set_errno (EINVAL); set_errno (EINVAL);
return -1; __leave;
} }
myfault efault; if (it_bad (value->it_value) || it_bad (value->it_interval))
if (efault.faulted (EFAULT) __leave;
|| it_bad (value->it_value)
|| it_bad (value->it_interval))
return -1;
long long now = in_flags & TIMER_ABSTIME ? 0 : gtod.usecs (); long long now = in_flags & TIMER_ABSTIME ? 0 : gtod.usecs ();
@ -256,8 +257,11 @@ timer_tracker::settime (int in_flags, const itimerspec *value, itimerspec *ovalu
ResetEvent (syncthread); ResetEvent (syncthread);
new cygthread (timer_thread, this, "itimer", syncthread); new cygthread (timer_thread, this, "itimer", syncthread);
} }
ret = 0;
return 0; }
__except (EFAULT) {}
__endtry
return ret;
} }
void void
@ -280,10 +284,10 @@ timer_tracker::gettime (itimerspec *ovalue)
extern "C" int extern "C" int
timer_gettime (timer_t timerid, struct itimerspec *ovalue) timer_gettime (timer_t timerid, struct itimerspec *ovalue)
{ {
myfault efault; int ret = -1;
if (efault.faulted (EFAULT))
return -1;
__try
{
timer_tracker *tt = (timer_tracker *) timerid; timer_tracker *tt = (timer_tracker *) timerid;
if (tt->magic != TT_MAGIC) if (tt->magic != TT_MAGIC)
{ {
@ -292,17 +296,21 @@ timer_gettime (timer_t timerid, struct itimerspec *ovalue)
} }
tt->gettime (ovalue); tt->gettime (ovalue);
return 0; ret = 0;
}
__except (EFAULT) {}
__endtry
return ret;
} }
extern "C" int extern "C" int
timer_create (clockid_t clock_id, struct sigevent *__restrict evp, timer_create (clockid_t clock_id, struct sigevent *__restrict evp,
timer_t *__restrict timerid) timer_t *__restrict timerid)
{ {
myfault efault; int ret = -1;
if (efault.faulted (EFAULT))
return -1;
__try
{
if (CLOCKID_IS_PROCESS (clock_id) || CLOCKID_IS_THREAD (clock_id)) if (CLOCKID_IS_PROCESS (clock_id) || CLOCKID_IS_THREAD (clock_id))
{ {
set_errno (ENOTSUP); set_errno (ENOTSUP);
@ -316,7 +324,11 @@ timer_create (clockid_t clock_id, struct sigevent *__restrict evp,
} }
*timerid = (timer_t) new timer_tracker (clock_id, evp); *timerid = (timer_t) new timer_tracker (clock_id, evp);
return 0; ret = 0;
}
__except (EFAULT) {}
__endtry
return ret;
} }
extern "C" int extern "C" int
@ -324,30 +336,35 @@ timer_settime (timer_t timerid, int flags,
const struct itimerspec *__restrict value, const struct itimerspec *__restrict value,
struct itimerspec *__restrict ovalue) struct itimerspec *__restrict ovalue)
{ {
int ret = -1;
__try
{
timer_tracker *tt = (timer_tracker *) timerid; timer_tracker *tt = (timer_tracker *) timerid;
myfault efault;
if (efault.faulted (EFAULT))
return -1;
if (tt->magic != TT_MAGIC) if (tt->magic != TT_MAGIC)
{ {
set_errno (EINVAL); set_errno (EINVAL);
return -1; __leave;
} }
ret = tt->settime (flags, value, ovalue);
return tt->settime (flags, value, ovalue); }
__except (EFAULT) {}
__endtry
return ret;
} }
extern "C" int extern "C" int
timer_delete (timer_t timerid) timer_delete (timer_t timerid)
{ {
int ret = -1;
__try
{
timer_tracker *in_tt = (timer_tracker *) timerid; timer_tracker *in_tt = (timer_tracker *) timerid;
myfault efault;
if (efault.faulted (EFAULT))
return -1;
if (in_tt->magic != TT_MAGIC) if (in_tt->magic != TT_MAGIC)
{ {
set_errno (EINVAL); set_errno (EINVAL);
return -1; __leave;
} }
lock_timer_tracker here; lock_timer_tracker here;
@ -356,10 +373,15 @@ timer_delete (timer_t timerid)
{ {
tt->next = in_tt->next; tt->next = in_tt->next;
delete in_tt; delete in_tt;
return 0; ret = 0;
__leave;
} }
set_errno (EINVAL); set_errno (EINVAL);
return 0; ret = 0;
}
__except (EFAULT) {}
__endtry
return ret;
} }
void void
@ -412,18 +434,13 @@ setitimer (int which, const struct itimerval *__restrict value,
extern "C" int extern "C" int
getitimer (int which, struct itimerval *ovalue) getitimer (int which, struct itimerval *ovalue)
{ {
int ret; int ret = -1;
if (which != ITIMER_REAL) if (which != ITIMER_REAL)
{
set_errno (EINVAL); set_errno (EINVAL);
ret = -1;
}
else else
{ {
myfault efault; __try
if (efault.faulted (EFAULT))
ret = -1;
else
{ {
struct itimerspec spec_ovalue; struct itimerspec spec_ovalue;
ret = timer_gettime ((timer_t) &ttstart, &spec_ovalue); ret = timer_gettime ((timer_t) &ttstart, &spec_ovalue);
@ -435,6 +452,8 @@ getitimer (int which, struct itimerval *ovalue)
ovalue->it_value.tv_usec = spec_ovalue.it_value.tv_nsec / 1000; ovalue->it_value.tv_usec = spec_ovalue.it_value.tv_nsec / 1000;
} }
} }
__except (EFAULT) {}
__endtry
} }
syscall_printf ("%R = getitimer()", ret); syscall_printf ("%R = getitimer()", ret);
return ret; return ret;

View File

@ -1,7 +1,7 @@
/* times.cc /* times.cc
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2007, 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc. 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -59,14 +59,13 @@ __to_clock_t (PLARGE_INTEGER src, int flag)
extern "C" clock_t extern "C" clock_t
times (struct tms *buf) times (struct tms *buf)
{ {
myfault efault;
if (efault.faulted (EFAULT))
return ((clock_t) -1);
static SYSTEM_TIMEOFDAY_INFORMATION stodi; static SYSTEM_TIMEOFDAY_INFORMATION stodi;
KERNEL_USER_TIMES kut; KERNEL_USER_TIMES kut;
LARGE_INTEGER ticks; LARGE_INTEGER ticks;
clock_t tc = (clock_t) -1;
__try
{
/* Fetch boot time if we haven't already. */ /* Fetch boot time if we haven't already. */
if (!stodi.BootTime.QuadPart) if (!stodi.BootTime.QuadPart)
NtQuerySystemInformation (SystemTimeOfDayInformation, NtQuerySystemInformation (SystemTimeOfDayInformation,
@ -79,7 +78,7 @@ times (struct tms *buf)
/* uptime */ /* uptime */
ticks.QuadPart -= stodi.BootTime.QuadPart; ticks.QuadPart -= stodi.BootTime.QuadPart;
/* ticks is in in 100ns, convert to clock ticks. */ /* ticks is in in 100ns, convert to clock ticks. */
clock_t tc = (clock_t) (ticks.QuadPart * CLOCKS_PER_SEC / NSPERSEC); tc = (clock_t) (ticks.QuadPart * CLOCKS_PER_SEC / NSPERSEC);
buf->tms_stime = __to_clock_t (&kut.KernelTime, 0); buf->tms_stime = __to_clock_t (&kut.KernelTime, 0);
buf->tms_utime = __to_clock_t (&kut.UserTime, 0); buf->tms_utime = __to_clock_t (&kut.UserTime, 0);
@ -87,7 +86,12 @@ times (struct tms *buf)
buf->tms_cstime = __to_clock_t (&kut.KernelTime, 1); buf->tms_cstime = __to_clock_t (&kut.KernelTime, 1);
timeval_to_filetime (&myself->rusage_children.ru_utime, &kut.UserTime); timeval_to_filetime (&myself->rusage_children.ru_utime, &kut.UserTime);
buf->tms_cutime = __to_clock_t (&kut.UserTime, 1); buf->tms_cutime = __to_clock_t (&kut.UserTime, 1);
}
__except (EFAULT)
{
tc = (clock_t) -1;
}
__endtry
syscall_printf ("%D = times(%p)", tc, buf); syscall_printf ("%D = times(%p)", tc, buf);
return tc; return tc;
} }
@ -100,12 +104,10 @@ settimeofday (const struct timeval *tv, const struct timezone *tz)
{ {
SYSTEMTIME st; SYSTEMTIME st;
struct tm *ptm; struct tm *ptm;
int res; int res = -1;
myfault efault;
if (efault.faulted (EFAULT))
return -1;
__try
{
if (tv->tv_usec < 0 || tv->tv_usec >= 1000000) if (tv->tv_usec < 0 || tv->tv_usec >= 1000000)
{ {
set_errno (EINVAL); set_errno (EINVAL);
@ -127,7 +129,12 @@ settimeofday (const struct timeval *tv, const struct timezone *tz)
if (res) if (res)
set_errno (EPERM); set_errno (EPERM);
}
__except (EFAULT)
{
res = -1;
}
__endtry
syscall_printf ("%R = settimeofday(%p, %p)", res, tv, tz); syscall_printf ("%R = settimeofday(%p, %p)", res, tv, tz);
return res; return res;
} }

View File

@ -8,17 +8,16 @@ details. */
#include <winsup.h> #include <winsup.h>
#include <malloc.h> #include <malloc.h>
#include "cygtls.h"
#include "tls_pbuf.h" #include "tls_pbuf.h"
#define tls_pbuf _my_tls.locals.pathbufs #define tls_pbuf _my_tls.pathbufs
void void
tls_pathbuf::destroy () tls_pathbuf::destroy ()
{ {
for (unsigned i = 0; i < TP_NUM_C_BUFS && c_buf[i]; ++i) for (uint32_t i = 0; i < TP_NUM_C_BUFS && c_buf[i]; ++i)
free (c_buf[i]); free (c_buf[i]);
for (unsigned i = 0; i < TP_NUM_W_BUFS && w_buf[i]; ++i) for (uint32_t i = 0; i < TP_NUM_W_BUFS && w_buf[i]; ++i)
free (w_buf[i]); free (w_buf[i]);
} }

View File

@ -10,20 +10,20 @@ details. */
class tmp_pathbuf class tmp_pathbuf
{ {
unsigned c_buf_old; uint32_t c_buf_old;
unsigned w_buf_old; uint32_t w_buf_old;
public: public:
tmp_pathbuf () __attribute__ ((always_inline)) tmp_pathbuf () __attribute__ ((always_inline))
: c_buf_old (_my_tls.locals.pathbufs.c_cnt), : c_buf_old (_my_tls.pathbufs.c_cnt),
w_buf_old (_my_tls.locals.pathbufs.w_cnt) w_buf_old (_my_tls.pathbufs.w_cnt)
{} {}
~tmp_pathbuf () __attribute__ ((always_inline)) ~tmp_pathbuf () __attribute__ ((always_inline))
{ {
_my_tls.locals.pathbufs.c_cnt = c_buf_old; _my_tls.pathbufs.c_cnt = c_buf_old;
_my_tls.locals.pathbufs.w_cnt = w_buf_old; _my_tls.pathbufs.w_cnt = w_buf_old;
} }
inline bool check_usage (unsigned c_need, unsigned w_need) inline bool check_usage (uint32_t c_need, uint32_t w_need)
{ {
return c_need + c_buf_old < TP_NUM_C_BUFS return c_need + c_buf_old < TP_NUM_C_BUFS
&& w_need + w_buf_old < TP_NUM_W_BUFS; && w_need + w_buf_old < TP_NUM_W_BUFS;

View File

@ -3,44 +3,46 @@
//; $tls::start_offset = -12700; //; $tls::start_offset = -12700;
//; $tls::locals = -12700; //; $tls::locals = -12700;
//; $tls::plocals = 0; //; $tls::plocals = 0;
//; $tls::local_clib = -10980; //; $tls::local_clib = -11388;
//; $tls::plocal_clib = 1720; //; $tls::plocal_clib = 1312;
//; $tls::__dontuse = -10980; //; $tls::__dontuse = -11388;
//; $tls::p__dontuse = 1720; //; $tls::p__dontuse = 1312;
//; $tls::func = -9892; //; $tls::func = -10300;
//; $tls::pfunc = 2808; //; $tls::pfunc = 2400;
//; $tls::saved_errno = -9888; //; $tls::saved_errno = -10296;
//; $tls::psaved_errno = 2812; //; $tls::psaved_errno = 2404;
//; $tls::sa_flags = -9884; //; $tls::sa_flags = -10292;
//; $tls::psa_flags = 2816; //; $tls::psa_flags = 2408;
//; $tls::oldmask = -9880; //; $tls::oldmask = -10288;
//; $tls::poldmask = 2820; //; $tls::poldmask = 2412;
//; $tls::deltamask = -9876; //; $tls::deltamask = -10284;
//; $tls::pdeltamask = 2824; //; $tls::pdeltamask = 2416;
//; $tls::errno_addr = -9872; //; $tls::errno_addr = -10280;
//; $tls::perrno_addr = 2828; //; $tls::perrno_addr = 2420;
//; $tls::sigmask = -9868; //; $tls::sigmask = -10276;
//; $tls::psigmask = 2832; //; $tls::psigmask = 2424;
//; $tls::sigwait_mask = -9864; //; $tls::sigwait_mask = -10272;
//; $tls::psigwait_mask = 2836; //; $tls::psigwait_mask = 2428;
//; $tls::sigwait_info = -9860; //; $tls::sigwait_info = -10268;
//; $tls::psigwait_info = 2840; //; $tls::psigwait_info = 2432;
//; $tls::signal_arrived = -9856; //; $tls::signal_arrived = -10264;
//; $tls::psignal_arrived = 2844; //; $tls::psignal_arrived = 2436;
//; $tls::will_wait_for_signal = -9852; //; $tls::will_wait_for_signal = -10260;
//; $tls::pwill_wait_for_signal = 2848; //; $tls::pwill_wait_for_signal = 2440;
//; $tls::thread_context = -9848; //; $tls::thread_context = -10256;
//; $tls::pthread_context = 2852; //; $tls::pthread_context = 2444;
//; $tls::thread_id = -9636; //; $tls::thread_id = -10044;
//; $tls::pthread_id = 3064; //; $tls::pthread_id = 2656;
//; $tls::infodata = -9632; //; $tls::infodata = -10040;
//; $tls::pinfodata = 3068; //; $tls::pinfodata = 2660;
//; $tls::tid = -9484; //; $tls::tid = -9892;
//; $tls::ptid = 3216; //; $tls::ptid = 2808;
//; $tls::_ctinfo = -9480; //; $tls::_ctinfo = -9888;
//; $tls::p_ctinfo = 3220; //; $tls::p_ctinfo = 2812;
//; $tls::andreas = -9476; //; $tls::andreas = -9884;
//; $tls::pandreas = 3224; //; $tls::pandreas = 2816;
//; $tls::pathbufs = -9880;
//; $tls::ppathbufs = 2820;
//; $tls::wq = -9472; //; $tls::wq = -9472;
//; $tls::pwq = 3228; //; $tls::pwq = 3228;
//; $tls::sig = -9444; //; $tls::sig = -9444;
@ -61,44 +63,46 @@
#define tls_locals (-12700) #define tls_locals (-12700)
#define tls_plocals (0) #define tls_plocals (0)
#define tls_local_clib (-10980) #define tls_local_clib (-11388)
#define tls_plocal_clib (1720) #define tls_plocal_clib (1312)
#define tls___dontuse (-10980) #define tls___dontuse (-11388)
#define tls_p__dontuse (1720) #define tls_p__dontuse (1312)
#define tls_func (-9892) #define tls_func (-10300)
#define tls_pfunc (2808) #define tls_pfunc (2400)
#define tls_saved_errno (-9888) #define tls_saved_errno (-10296)
#define tls_psaved_errno (2812) #define tls_psaved_errno (2404)
#define tls_sa_flags (-9884) #define tls_sa_flags (-10292)
#define tls_psa_flags (2816) #define tls_psa_flags (2408)
#define tls_oldmask (-9880) #define tls_oldmask (-10288)
#define tls_poldmask (2820) #define tls_poldmask (2412)
#define tls_deltamask (-9876) #define tls_deltamask (-10284)
#define tls_pdeltamask (2824) #define tls_pdeltamask (2416)
#define tls_errno_addr (-9872) #define tls_errno_addr (-10280)
#define tls_perrno_addr (2828) #define tls_perrno_addr (2420)
#define tls_sigmask (-9868) #define tls_sigmask (-10276)
#define tls_psigmask (2832) #define tls_psigmask (2424)
#define tls_sigwait_mask (-9864) #define tls_sigwait_mask (-10272)
#define tls_psigwait_mask (2836) #define tls_psigwait_mask (2428)
#define tls_sigwait_info (-9860) #define tls_sigwait_info (-10268)
#define tls_psigwait_info (2840) #define tls_psigwait_info (2432)
#define tls_signal_arrived (-9856) #define tls_signal_arrived (-10264)
#define tls_psignal_arrived (2844) #define tls_psignal_arrived (2436)
#define tls_will_wait_for_signal (-9852) #define tls_will_wait_for_signal (-10260)
#define tls_pwill_wait_for_signal (2848) #define tls_pwill_wait_for_signal (2440)
#define tls_thread_context (-9848) #define tls_thread_context (-10256)
#define tls_pthread_context (2852) #define tls_pthread_context (2444)
#define tls_thread_id (-9636) #define tls_thread_id (-10044)
#define tls_pthread_id (3064) #define tls_pthread_id (2656)
#define tls_infodata (-9632) #define tls_infodata (-10040)
#define tls_pinfodata (3068) #define tls_pinfodata (2660)
#define tls_tid (-9484) #define tls_tid (-9892)
#define tls_ptid (3216) #define tls_ptid (2808)
#define tls__ctinfo (-9480) #define tls__ctinfo (-9888)
#define tls_p_ctinfo (3220) #define tls_p_ctinfo (2812)
#define tls_andreas (-9476) #define tls_andreas (-9884)
#define tls_pandreas (3224) #define tls_pandreas (2816)
#define tls_pathbufs (-9880)
#define tls_ppathbufs (2820)
#define tls_wq (-9472) #define tls_wq (-9472)
#define tls_pwq (3228) #define tls_pwq (3228)
#define tls_sig (-9444) #define tls_sig (-9444)

View File

@ -3,44 +3,46 @@
//; $tls::start_offset = -12800; //; $tls::start_offset = -12800;
//; $tls::locals = -12800; //; $tls::locals = -12800;
//; $tls::plocals = 0; //; $tls::plocals = 0;
//; $tls::local_clib = -10624; //; $tls::local_clib = -11432;
//; $tls::plocal_clib = 2176; //; $tls::plocal_clib = 1368;
//; $tls::__dontuse = -10624; //; $tls::__dontuse = -11432;
//; $tls::p__dontuse = 2176; //; $tls::p__dontuse = 1368;
//; $tls::func = -8736; //; $tls::func = -9544;
//; $tls::pfunc = 4064; //; $tls::pfunc = 3256;
//; $tls::saved_errno = -8728; //; $tls::saved_errno = -9536;
//; $tls::psaved_errno = 4072; //; $tls::psaved_errno = 3264;
//; $tls::sa_flags = -8724; //; $tls::sa_flags = -9532;
//; $tls::psa_flags = 4076; //; $tls::psa_flags = 3268;
//; $tls::oldmask = -8720; //; $tls::oldmask = -9528;
//; $tls::poldmask = 4080; //; $tls::poldmask = 3272;
//; $tls::deltamask = -8712; //; $tls::deltamask = -9520;
//; $tls::pdeltamask = 4088; //; $tls::pdeltamask = 3280;
//; $tls::errno_addr = -8704; //; $tls::errno_addr = -9512;
//; $tls::perrno_addr = 4096; //; $tls::perrno_addr = 3288;
//; $tls::sigmask = -8696; //; $tls::sigmask = -9504;
//; $tls::psigmask = 4104; //; $tls::psigmask = 3296;
//; $tls::sigwait_mask = -8688; //; $tls::sigwait_mask = -9496;
//; $tls::psigwait_mask = 4112; //; $tls::psigwait_mask = 3304;
//; $tls::sigwait_info = -8680; //; $tls::sigwait_info = -9488;
//; $tls::psigwait_info = 4120; //; $tls::psigwait_info = 3312;
//; $tls::signal_arrived = -8672; //; $tls::signal_arrived = -9480;
//; $tls::psignal_arrived = 4128; //; $tls::psignal_arrived = 3320;
//; $tls::will_wait_for_signal = -8664; //; $tls::will_wait_for_signal = -9472;
//; $tls::pwill_wait_for_signal = 4136; //; $tls::pwill_wait_for_signal = 3328;
//; $tls::thread_context = -8656; //; $tls::thread_context = -9464;
//; $tls::pthread_context = 4144; //; $tls::pthread_context = 3336;
//; $tls::thread_id = -7824; //; $tls::thread_id = -8632;
//; $tls::pthread_id = 4976; //; $tls::pthread_id = 4168;
//; $tls::infodata = -7820; //; $tls::infodata = -8628;
//; $tls::pinfodata = 4980; //; $tls::pinfodata = 4172;
//; $tls::tid = -7672; //; $tls::tid = -8480;
//; $tls::ptid = 5128; //; $tls::ptid = 4320;
//; $tls::_ctinfo = -7664; //; $tls::_ctinfo = -8472;
//; $tls::p_ctinfo = 5136; //; $tls::p_ctinfo = 4328;
//; $tls::andreas = -7656; //; $tls::andreas = -8464;
//; $tls::pandreas = 5144; //; $tls::pandreas = 4336;
//; $tls::pathbufs = -8456;
//; $tls::ppathbufs = 4344;
//; $tls::wq = -7648; //; $tls::wq = -7648;
//; $tls::pwq = 5152; //; $tls::pwq = 5152;
//; $tls::sig = -7600; //; $tls::sig = -7600;
@ -61,44 +63,46 @@
#define tls_locals (-12800) #define tls_locals (-12800)
#define tls_plocals (0) #define tls_plocals (0)
#define tls_local_clib (-10624) #define tls_local_clib (-11432)
#define tls_plocal_clib (2176) #define tls_plocal_clib (1368)
#define tls___dontuse (-10624) #define tls___dontuse (-11432)
#define tls_p__dontuse (2176) #define tls_p__dontuse (1368)
#define tls_func (-8736) #define tls_func (-9544)
#define tls_pfunc (4064) #define tls_pfunc (3256)
#define tls_saved_errno (-8728) #define tls_saved_errno (-9536)
#define tls_psaved_errno (4072) #define tls_psaved_errno (3264)
#define tls_sa_flags (-8724) #define tls_sa_flags (-9532)
#define tls_psa_flags (4076) #define tls_psa_flags (3268)
#define tls_oldmask (-8720) #define tls_oldmask (-9528)
#define tls_poldmask (4080) #define tls_poldmask (3272)
#define tls_deltamask (-8712) #define tls_deltamask (-9520)
#define tls_pdeltamask (4088) #define tls_pdeltamask (3280)
#define tls_errno_addr (-8704) #define tls_errno_addr (-9512)
#define tls_perrno_addr (4096) #define tls_perrno_addr (3288)
#define tls_sigmask (-8696) #define tls_sigmask (-9504)
#define tls_psigmask (4104) #define tls_psigmask (3296)
#define tls_sigwait_mask (-8688) #define tls_sigwait_mask (-9496)
#define tls_psigwait_mask (4112) #define tls_psigwait_mask (3304)
#define tls_sigwait_info (-8680) #define tls_sigwait_info (-9488)
#define tls_psigwait_info (4120) #define tls_psigwait_info (3312)
#define tls_signal_arrived (-8672) #define tls_signal_arrived (-9480)
#define tls_psignal_arrived (4128) #define tls_psignal_arrived (3320)
#define tls_will_wait_for_signal (-8664) #define tls_will_wait_for_signal (-9472)
#define tls_pwill_wait_for_signal (4136) #define tls_pwill_wait_for_signal (3328)
#define tls_thread_context (-8656) #define tls_thread_context (-9464)
#define tls_pthread_context (4144) #define tls_pthread_context (3336)
#define tls_thread_id (-7824) #define tls_thread_id (-8632)
#define tls_pthread_id (4976) #define tls_pthread_id (4168)
#define tls_infodata (-7820) #define tls_infodata (-8628)
#define tls_pinfodata (4980) #define tls_pinfodata (4172)
#define tls_tid (-7672) #define tls_tid (-8480)
#define tls_ptid (5128) #define tls_ptid (4320)
#define tls__ctinfo (-7664) #define tls__ctinfo (-8472)
#define tls_p_ctinfo (5136) #define tls_p_ctinfo (4328)
#define tls_andreas (-7656) #define tls_andreas (-8464)
#define tls_pandreas (5144) #define tls_pandreas (4336)
#define tls_pathbufs (-8456)
#define tls_ppathbufs (4344)
#define tls_wq (-7648) #define tls_wq (-7648)
#define tls_pwq (5152) #define tls_pwq (5152)
#define tls_sig (-7600) #define tls_sig (-7600)

View File

@ -217,10 +217,15 @@ getlogin_r (char *name, size_t namesize)
size_t len = strlen (login) + 1; size_t len = strlen (login) + 1;
if (len > namesize) if (len > namesize)
return ERANGE; return ERANGE;
myfault efault; __try
if (efault.faulted ()) {
return EFAULT;
strncpy (name, login, len); strncpy (name, login, len);
}
__except (NO_ERROR)
{
return EFAULT;
}
__endtry
return 0; return 0;
} }

View File

@ -1,7 +1,7 @@
/* uname.cc /* uname.cc
Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2013 Red Hat, Inc. 2006, 2007, 2008, 2013, 2014 Red Hat, Inc.
Written by Steve Chamberlain of Cygnus Support, sac@cygnus.com Written by Steve Chamberlain of Cygnus Support, sac@cygnus.com
Rewritten by Geoffrey Noer of Cygnus Solutions, noer@cygnus.com Rewritten by Geoffrey Noer of Cygnus Solutions, noer@cygnus.com
@ -22,10 +22,8 @@ uname (struct utsname *name)
{ {
SYSTEM_INFO sysinfo; SYSTEM_INFO sysinfo;
myfault efault; __try
if (efault.faulted (EFAULT)) {
return -1;
char *snp = strstr (cygwin_version.dll_build_date, "SNP"); char *snp = strstr (cygwin_version.dll_build_date, "SNP");
memset (name, 0, sizeof (*name)); memset (name, 0, sizeof (*name));
@ -90,6 +88,11 @@ uname (struct utsname *name)
strcpy (name->machine, "unknown"); strcpy (name->machine, "unknown");
break; break;
} }
}
__except (EFAULT)
{
return -1;
}
__endtry
return 0; return 0;
} }