summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/path.cc
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2013-06-12 17:45:42 +0000
committerCorinna Vinschen <corinna@vinschen.de>2013-06-12 17:45:42 +0000
commit0b8722c2dba53724769ddfcf2fa39baf0ae253a7 (patch)
tree3f3b581fbc3cdc33c11a31cac9d419738353aabf /winsup/cygwin/path.cc
parentbb345ed1471114fe5b9b1a1fd561b3b6f4b1d645 (diff)
downloadcygnal-0b8722c2dba53724769ddfcf2fa39baf0ae253a7.tar.gz
cygnal-0b8722c2dba53724769ddfcf2fa39baf0ae253a7.tar.bz2
cygnal-0b8722c2dba53724769ddfcf2fa39baf0ae253a7.zip
* path.cc (normalize_posix_path): Fix long-standing problem which
allows to access files via ".." using an invalid POSIX path.
Diffstat (limited to 'winsup/cygwin/path.cc')
-rw-r--r--winsup/cygwin/path.cc17
1 files changed, 17 insertions, 0 deletions
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 16571b12e..e0fa37670 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -240,6 +240,7 @@ normalize_posix_path (const char *src, char *dst, char *&tail)
{
const char *in_src = src;
char *dst_start = dst;
+ bool check_parent = false;
syscall_printf ("src %s", src);
if ((isdrive (src) && isdirsep (src[2])) || *src == '\\')
@@ -278,6 +279,7 @@ normalize_posix_path (const char *src, char *dst, char *&tail)
*tail++ = *src++;
else
{
+ check_parent = true;
while (*++src)
{
if (isslash (*src))
@@ -301,6 +303,21 @@ normalize_posix_path (const char *src, char *dst, char *&tail)
break;
else
{
+ /* According to POSIX semantics all elements of path must
+ exist. To follow it, we must validate our path before
+ removing the trailing component. Check_parent is needed
+ for performance optimization, in order not to verify paths
+ which are already verified. For example this prevents
+ double check in case of foo/bar/../.. */
+ if (check_parent)
+ {
+ *tail = 0;
+ debug_printf ("checking %s before '..'", dst_start);
+ path_conv head (dst_start);
+ if (!head.isdir())
+ return ENOENT;
+ check_parent = false;
+ }
while (tail > dst_start && !isslash (*--tail))
continue;
src++;