summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/path.cc
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2014-04-18 14:29:49 +0000
committerCorinna Vinschen <corinna@vinschen.de>2014-04-18 14:29:49 +0000
commit7ae3e6b3d47492b938966b923c4065b76cf8762a (patch)
tree36cd1c4b49e440ee70369e0d002eaec3c2fcd0d9 /winsup/cygwin/path.cc
parentd98d7f397389cca8f96318a1644431012a6211be (diff)
downloadcygnal-7ae3e6b3d47492b938966b923c4065b76cf8762a.tar.gz
cygnal-7ae3e6b3d47492b938966b923c4065b76cf8762a.tar.bz2
cygnal-7ae3e6b3d47492b938966b923c4065b76cf8762a.zip
* cygtls.h (TP_NUM_C_BUFS): Raise to 50 to allow SYMLOOP_MAX recursions
path_conv <-> normalize_posix_path, plus a bit of buffer. (TP_NUM_W_BUFS): Ditto. (class san): Change type of _c_cnt and _w_cnt to unsigned. * path.cc (normalize_posix_path): Guard recursion into path_conv against tmp_pathbuf overflow. Generate normalized path in call to path_conv. If the path is valid, replace dst with the normalized_path from path_conv call. Add comment to explain why we're doing this. * tls_pbuf.cc (tls_pathbuf::destroy): Only free buffers until the first buffer pointer is NULL. (tmp_pathbuf::c_get): Simplify error message. (tmp_pathbuf::w_get): Ditto. * tls_pbuf.h (class tmp_pathbuf): Change type of c_buf_old and w_buf_old to unsigned. (tmp_pathbuf::check_usage): New inline method to check if we have enough tmp_pathbuf buffers left to call a function using tmp_pathbuf buffers. * tlsoffsets.h: Regenerate. * tlsoffsets64.h: Regenerate.
Diffstat (limited to 'winsup/cygwin/path.cc')
-rw-r--r--winsup/cygwin/path.cc24
1 files changed, 23 insertions, 1 deletions
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 4990328a2..631b169a0 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -311,9 +311,31 @@ normalize_posix_path (const char *src, char *dst, char *&tail)
{
*tail = 0;
debug_printf ("checking %s before '..'", dst);
- path_conv head (dst);
+ /* In conjunction with native and NFS symlinks,
+ this call can result in a recursion which eats
+ up our tmp_pathbuf buffers. This in turn results
+ in a api_fatal call. To avoid that, we're
+ checking our remaining buffers and return an
+ error code instead. Note that this only happens
+ if the path contains 15 or more relative native/NFS
+ symlinks with a ".." in the target path. */
+ tmp_pathbuf tp;
+ if (!tp.check_usage (4, 3))
+ return ELOOP;
+ path_conv head (dst, PC_SYM_FOLLOW | PC_POSIX);
if (!head.isdir())
return ENOENT;
+ /* At this point, dst is a normalized path. If the
+ normalized path created by path_conv does not
+ match the normalized path we're just testing, then
+ the path in dst contains native symlinks. If we
+ just plunge along, removing the previous path
+ component, we may end up removing a symlink from
+ the path and the resulting path will be invalid.
+ So we replace dst with what we found in head
+ instead. All the work replacing symlinks has been
+ done in that path anyway, so why repeat it? */
+ tail = stpcpy (dst, head.normalized_path);
}
check_parent = false;
}