Security fixes for CVE-2012-6089 and CVE-2012-6090,

Multiple (stack-based) buffer overflows in patch canonisation code and when expanding file-names with long paths

Patches taken from upstream
This commit is contained in:
jasper 2013-01-08 13:36:47 +00:00
parent e540fcf160
commit f09c09f5c0
4 changed files with 207 additions and 1 deletions

View File

@ -1,4 +1,4 @@
# $OpenBSD: Makefile,v 1.44 2012/12/20 15:52:36 landry Exp $
# $OpenBSD: Makefile,v 1.45 2013/01/08 13:36:47 jasper Exp $
BROKEN-mips64 = undefined reference to `__sync_fetch_and_add_8'
BROKEN-hppa = undefined reference to `__sync_fetch_and_add_4'
@ -9,6 +9,7 @@ COMMENT = Prolog for the real world
V = 6.2.2
DISTNAME = pl-$V
PKGNAME = swi-prolog-$V
REVISION = 0
CATEGORIES = lang
SHARED_LIBS = pl 4.0

View File

@ -0,0 +1,25 @@
$OpenBSD: patch-src_os_pl-buffer_h,v 1.1 2013/01/08 13:36:47 jasper Exp $
From a9a6fc8a2a9cf3b9154b490a4b1ffaa8be4d723c Mon Sep 17 00:00:00 2001
From: Jan Wielemaker <J.Wielemaker@cs.vu.nl>
Date: Sun, 16 Dec 2012 18:13:17 +0100
Subject: [PATCH] FIXED: Possible buffer overrun in patch canonisation code.
Pushes pointers on an automatic array without checking for overflow.
Can be used for DoS attacks. Will be extremely hard to make it execute
arbitrary code.
Fixes CVE-2012-6089, patch from upstream:
http://www.swi-prolog.org/git/pl.git/commit/a9a6fc8a2a9cf3b9154b490a4b1ffaa8be4d723c
--- src/os/pl-buffer.h.orig Thu Sep 27 20:43:34 2012
+++ src/os/pl-buffer.h Tue Jan 8 14:11:56 2013
@@ -101,6 +101,8 @@ f__allocFromBuffer(Buffer b, size_t bytes)
sizeof((b)->static_buffer))
#define emptyBuffer(b) ((b)->top = (b)->base)
#define isEmptyBuffer(b) ((b)->top == (b)->base)
+#define popBuffer(b,type) \
+ ((b)->top -= sizeof(type), *(type*)(b)->top)
#define discardBuffer(b) \
do \

View File

@ -0,0 +1,108 @@
$OpenBSD: patch-src_os_pl-glob_c,v 1.1 2013/01/08 13:36:47 jasper Exp $
From b2c88972e7515ada025e97e7d3ce3e34f81cf33e Mon Sep 17 00:00:00 2001
From: Jan Wielemaker <J.Wielemaker@cs.vu.nl>
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.
Fixes CVE-2012-6090, patch from upstream:
http://www.swi-prolog.org/git/pl.git/commitdiff/b2c88972e7515ada025e97e7d3ce3e34f81cf33e
--- src/os/pl-glob.c.orig Thu Sep 27 20:43:34 2012
+++ src/os/pl-glob.c Tue Jan 8 14:13:33 2013
@@ -424,6 +424,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);
@@ -442,20 +443,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;
+ const char *entry = expand_entry(info, info->start);
+ size_t plen = strlen(entry);
- 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);
+ 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;
@@ -490,8 +496,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 */
@@ -503,12 +510,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++] = '/';
@@ -522,12 +533,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);

View File

@ -0,0 +1,72 @@
$OpenBSD: patch-src_os_pl-os_c,v 1.1 2013/01/08 13:36:47 jasper Exp $
From a9a6fc8a2a9cf3b9154b490a4b1ffaa8be4d723c Mon Sep 17 00:00:00 2001
From: Jan Wielemaker <J.Wielemaker@cs.vu.nl>
Date: Sun, 16 Dec 2012 18:13:17 +0100
Subject: [PATCH] FIXED: Possible buffer overrun in patch canonisation code.
Pushes pointers on an automatic array without checking for overflow.
Can be used for DoS attacks. Will be extremely hard to make it execute
arbitrary code.
Fixes CVE-2012-6089, patch from upstream:
http://www.swi-prolog.org/git/pl.git/commit/a9a6fc8a2a9cf3b9154b490a4b1ffaa8be4d723c
--- src/os/pl-os.c.orig Thu Sep 27 20:43:34 2012
+++ src/os/pl-os.c Tue Jan 8 14:11:56 2013
@@ -1057,8 +1057,7 @@ cleanupExpand(void)
char *
canoniseFileName(char *path)
{ char *out = path, *in = path, *start = path;
- char *osave[100];
- int osavep = 0;
+ tmp_buffer saveb;
#ifdef O_HASDRIVES /* C: */
if ( in[1] == ':' && isLetter(in[0]) )
@@ -1097,7 +1096,8 @@ canoniseFileName(char *path)
in += 2;
if ( in[0] == '/' )
*out++ = '/';
- osave[osavep++] = out;
+ initBuffer(&saveb);
+ addBuffer(&saveb, out, char*);
while(*in)
{ if (*in == '/')
@@ -1113,15 +1113,15 @@ canoniseFileName(char *path)
}
if ( in[2] == EOS ) /* delete trailing /. */
{ *out = EOS;
- return path;
+ goto out;
}
if ( in[2] == '.' && (in[3] == '/' || in[3] == EOS) )
- { if ( osavep > 0 ) /* delete /foo/../ */
- { out = osave[--osavep];
+ { if ( !isEmptyBuffer(&saveb) ) /* delete /foo/../ */
+ { out = popBuffer(&saveb, char*);
in += 3;
if ( in[0] == EOS && out > start+1 )
{ out[-1] = EOS; /* delete trailing / */
- return path;
+ goto out;
}
goto again;
} else if ( start[0] == '/' && out == start+1 )
@@ -1135,11 +1135,14 @@ canoniseFileName(char *path)
in++;
if ( out > path && out[-1] != '/' )
*out++ = '/';
- osave[osavep++] = out;
+ addBuffer(&saveb, out, char*);
} else
*out++ = *in++;
}
*out++ = *in++;
+
+out:
+ discardBuffer(&saveb);
return path;
}