From 212e2fcac834dec25a4fa0f4fd4652bfd19cdeea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= Date: Fri, 4 Jan 2013 13:35:27 +0100 Subject: [PATCH 2/2] Fix CVE-2012-6090 Upstream fix ported to 5.10.2: From b2c88972e7515ada025e97e7d3ce3e34f81cf33e Mon Sep 17 00:00:00 2001 From: Jan Wielemaker Date: Sun, 16 Dec 2012 17:29:37 +0100 Subject: [PATCH] SECURITY: Possible buffer overflows when expanding file-names with long paths. Affects expand_file_name/2. Can lead to crashes (DoS attacks) and possibly execution of arbitrary code if an attacker can control the names of the files searched for, e.g., if expand_file_name/2 is used in a directory to which an attacker can upload files for which he can control the name. --- src/pl-glob.c | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/src/pl-glob.c b/src/pl-glob.c index 417a69c..1fad6ca 100644 --- a/src/pl-glob.c +++ b/src/pl-glob.c @@ -423,6 +423,7 @@ expand(const char *pattern, GlobInfo info) compiled_pattern cbuf; char prefix[MAXPATHLEN]; /* before first pattern */ char patbuf[MAXPATHLEN]; /* pattern buffer */ + size_t prefix_len; int end, dot; initBuffer(&info->files); @@ -441,20 +442,25 @@ expand(const char *pattern, GlobInfo info) switch( (c=*s++) ) { case EOS: if ( s > pat ) /* something left and expanded */ - { un_escape(prefix, pat, s); + { size_t prefix_len; + + un_escape(prefix, pat, s); + prefix_len = strlen(prefix); end = info->end; for( ; info->start < end; info->start++ ) { char path[MAXPATHLEN]; - size_t plen; - - strcpy(path, expand_entry(info, info->start)); - plen = strlen(path); - if ( prefix[0] && plen > 0 && path[plen-1] != '/' ) - path[plen++] = '/'; - strcpy(&path[plen], prefix); - if ( end == 1 || AccessFile(path, ACCESS_EXIST) ) - add_path(path, info); + const char *entry = expand_entry(info, info->start); + size_t plen = strlen(entry); + + if ( plen+prefix_len+2 <= MAXPATHLEN ) + { strcpy(path, entry); + if ( prefix[0] && plen > 0 && path[plen-1] != '/' ) + path[plen++] = '/'; + strcpy(&path[plen], prefix); + if ( end == 1 || AccessFile(path, ACCESS_EXIST) ) + add_path(path, info); + } } } succeed; @@ -489,8 +495,9 @@ expand(const char *pattern, GlobInfo info) */ un_escape(prefix, pat, head); un_escape(patbuf, head, tail); + prefix_len = strlen(prefix); - if ( !compilePattern(patbuf, &cbuf) ) /* syntax error */ + if ( !compilePattern(patbuf, &cbuf) ) /* syntax error */ fail; dot = (patbuf[0] == '.'); /* do dots as well */ @@ -502,12 +509,16 @@ expand(const char *pattern, GlobInfo info) char path[MAXPATHLEN]; char tmp[MAXPATHLEN]; const char *current = expand_entry(info, info->start); + size_t clen = strlen(current); + + if ( clen+prefix_len+1 > sizeof(path) ) + continue; strcpy(path, current); - strcat(path, prefix); + strcpy(&path[clen], prefix); if ( (d=opendir(path[0] ? OsPath(path, tmp) : ".")) ) - { size_t plen = strlen(path); + { size_t plen = clen+prefix_len; if ( plen > 0 && path[plen-1] != '/' ) path[plen++] = '/'; @@ -521,12 +532,11 @@ expand(const char *pattern, GlobInfo info) matchPattern(e->d_name, &cbuf) ) { char newp[MAXPATHLEN]; - strcpy(newp, path); - strcpy(&newp[plen], e->d_name); -/* if ( !tail[0] || ExistsDirectory(newp) ) - Saves memory, but involves one more file-access -*/ + if ( plen+strlen(e->d_name)+1 < sizeof(newp) ) + { strcpy(newp, path); + strcpy(&newp[plen], e->d_name); add_path(newp, info); + } } } closedir(d); -- 1.7.11.7