r4541 - in glibc-package/trunk/debian: . patches patches/any
Author: aurel32
Date: 2011-02-26 17:05:56 +0000 (Sat, 26 Feb 2011)
New Revision: 4541
Added:
glibc-package/trunk/debian/patches/any/cvs-fnmatch-alloca.patch
Modified:
glibc-package/trunk/debian/changelog
glibc-package/trunk/debian/patches/series
Log:
* Add patches/any/cvs-fnmatch-alloca.patch from upstream to a memory
corruption in fnmatch() that can lead to code execution. Closes:
#615120.
Modified: glibc-package/trunk/debian/changelog
===================================================================
--- glibc-package/trunk/debian/changelog 2011-02-26 14:36:08 UTC (rev 4540)
+++ glibc-package/trunk/debian/changelog 2011-02-26 17:05:56 UTC (rev 4541)
@@ -2,6 +2,9 @@
[ Aurelien Jarno ]
* Re-enable build failure in case of testsuite regressions.
+ * Add patches/any/cvs-fnmatch-alloca.patch from upstream to a memory
+ corruption in fnmatch() that can lead to code execution. Closes:
+ #615120.
[ Samuel Thibault ]
* patches/any/submitted-sched_h.diff: Synchronize bits/sched.h with
Added: glibc-package/trunk/debian/patches/any/cvs-fnmatch-alloca.patch
===================================================================
--- glibc-package/trunk/debian/patches/any/cvs-fnmatch-alloca.patch (rev 0)
+++ glibc-package/trunk/debian/patches/any/cvs-fnmatch-alloca.patch 2011-02-26 17:05:56 UTC (rev 4541)
@@ -0,0 +1,446 @@
+2010-11-11 Andreas Schwab <schwab@redhat.com>
+
+ * posix/fnmatch_loop.c (NEW_PATTERN): Fix use of alloca.
+
+2010-08-09 Ulrich Drepper <drepper@redhat.com>
+
+ [BZ #11883]
+ * posix/fnmatch.c: Keep track of alloca use and fall back on malloc.
+ * posix/fnmatch_loop.c: Likewise.
+
+diff a/posix/fnmatch.c b/posix/fnmatch.c
+--- a/posix/fnmatch.c
++++ b/posix/fnmatch.c
+@@ -1,4 +1,4 @@
+-/* Copyright (C) 1991,1992,1993,1996,1997,1998,1999,2000,2001,2002,2003,2007
++/* Copyright (C) 1991,1992,1993,1996,1997,1998,1999,2000,2001,2002,2003,2007,2010
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+@@ -41,6 +41,12 @@
+ # include <stdlib.h>
+ #endif
+
++#ifdef _LIBC
++# include <alloca.h>
++#else
++# define alloca_account(size., var) alloca (size)
++#endif
++
+ /* For platform which support the ISO C amendement 1 functionality we
+ support user defined character classes. */
+ #if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+@@ -330,8 +336,11 @@ fnmatch (pattern, string, flags)
+ mbstate_t ps;
+ size_t n;
+ const char *p;
++ wchar_t *wpattern_malloc = NULL;
+ wchar_t *wpattern;
++ wchar_t *wstring_malloc = NULL;
+ wchar_t *wstring;
++ size_t alloca_used = 0;
+
+ /* Convert the strings into wide characters. */
+ memset (&ps, '\0', sizeof (ps));
+@@ -343,7 +352,8 @@ fnmatch (pattern, string, flags)
+ #endif
+ if (__builtin_expect (n < 1024, 1))
+ {
+- wpattern = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t));
++ wpattern = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t),
++ alloca_used);
+ n = mbsrtowcs (wpattern, &p, n + 1, &ps);
+ if (__builtin_expect (n == (size_t) -1, 0))
+ /* Something wrong.
+@@ -365,8 +375,11 @@ fnmatch (pattern, string, flags)
+ XXX Do we have to set `errno' to something which mbsrtows hasn't
+ already done? */
+ return -1;
+- wpattern = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t));
++ wpattern_malloc = wpattern
++ = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t));
+ assert (mbsinit (&ps));
++ if (wpattern == NULL)
++ return -2;
+ (void) mbsrtowcs (wpattern, &pattern, n + 1, &ps);
+ }
+
+@@ -379,13 +392,18 @@ fnmatch (pattern, string, flags)
+ p = string;
+ if (__builtin_expect (n < 1024, 1))
+ {
+- wstring = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t));
++ wstring = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t),
++ alloca_used);
+ n = mbsrtowcs (wstring, &p, n + 1, &ps);
+ if (__builtin_expect (n == (size_t) -1, 0))
+- /* Something wrong.
+- XXX Do we have to set `errno' to something which mbsrtows hasn't
+- already done? */
+- return -1;
++ {
++ /* Something wrong.
++ XXX Do we have to set `errno' to something which
++ mbsrtows hasn't already done? */
++ free_return:
++ free (wpattern_malloc);
++ return -1;
++ }
+ if (p)
+ {
+ memset (&ps, '\0', sizeof (ps));
+@@ -400,19 +418,32 @@ fnmatch (pattern, string, flags)
+ /* Something wrong.
+ XXX Do we have to set `errno' to something which mbsrtows hasn't
+ already done? */
+- return -1;
+- wstring = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t));
++ goto free_return;
++
++ wstring_malloc = wstring
++ = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t));
++ if (wstring == NULL)
++ {
++ free (wpattern_malloc);
++ return -2;
++ }
+ assert (mbsinit (&ps));
+ (void) mbsrtowcs (wstring, &string, n + 1, &ps);
+ }
+
+- return internal_fnwmatch (wpattern, wstring, wstring + n,
+- flags & FNM_PERIOD, flags, NULL);
++ int res = internal_fnwmatch (wpattern, wstring, wstring + n,
++ flags & FNM_PERIOD, flags, NULL,
++ alloca_used);
++
++ free (wstring_malloc);
++ free (wpattern_malloc);
++
++ return res;
+ }
+ # endif /* mbstate_t and mbsrtowcs or _LIBC. */
+
+ return internal_fnmatch (pattern, string, string + strlen (string),
+- flags & FNM_PERIOD, flags, NULL);
++ flags & FNM_PERIOD, flags, NULL, 0);
+ }
+
+ # ifdef _LIBC
+diff a/posix/fnmatch_loop.c b/posix/fnmatch_loop.c
+--- a/posix/fnmatch_loop.c
++++ b/posix/fnmatch_loop.c
+@@ -1,4 +1,4 @@
+-/* Copyright (C) 1991-1993,1996-2001,2003-2005,2007
++/* Copyright (C) 1991-1993,1996-2001,2003-2005,2007,2010
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+@@ -28,22 +28,24 @@ struct STRUCT
+ it matches, nonzero if not. */
+ static int FCT (const CHAR *pattern, const CHAR *string,
+ const CHAR *string_end, int no_leading_period, int flags,
+- struct STRUCT *ends)
++ struct STRUCT *ends, size_t alloca_used)
+ internal_function;
+ static int EXT (INT opt, const CHAR *pattern, const CHAR *string,
+- const CHAR *string_end, int no_leading_period, int flags)
++ const CHAR *string_end, int no_leading_period, int flags,
++ size_t alloca_used)
+ internal_function;
+ static const CHAR *END (const CHAR *patternp) internal_function;
+
+ static int
+ internal_function
+-FCT (pattern, string, string_end, no_leading_period, flags, ends)
++FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used)
+ const CHAR *pattern;
+ const CHAR *string;
+ const CHAR *string_end;
+ int no_leading_period;
+ int flags;
+ struct STRUCT *ends;
++ size_t alloca_used;
+ {
+ register const CHAR *p = pattern, *n = string;
+ register UCHAR c;
+@@ -67,10 +69,8 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends)
+ case L('?'):
+ if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
+ {
+- int res;
+-
+- res = EXT (c, p, n, string_end, no_leading_period,
+- flags);
++ int res = EXT (c, p, n, string_end, no_leading_period,
++ flags, alloca_used);
+ if (res != -1)
+ return res;
+ }
+@@ -99,10 +99,8 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends)
+ case L('*'):
+ if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
+ {
+- int res;
+-
+- res = EXT (c, p, n, string_end, no_leading_period,
+- flags);
++ int res = EXT (c, p, n, string_end, no_leading_period,
++ flags, alloca_used);
+ if (res != -1)
+ return res;
+ }
+@@ -191,7 +189,7 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends)
+
+ for (--p; n < endp; ++n, no_leading_period = 0)
+ if (FCT (p, n, string_end, no_leading_period, flags2,
+- &end) == 0)
++ &end, alloca_used) == 0)
+ goto found;
+ }
+ else if (c == L('/') && (flags & FNM_FILE_NAME))
+@@ -200,7 +198,7 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends)
+ ++n;
+ if (n < string_end && *n == L('/')
+ && (FCT (p, n + 1, string_end, flags & FNM_PERIOD, flags,
+- NULL) == 0))
++ NULL, alloca_used) == 0))
+ return 0;
+ }
+ else
+@@ -214,7 +212,7 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends)
+ for (--p; n < endp; ++n, no_leading_period = 0)
+ if (FOLD ((UCHAR) *n) == c
+ && (FCT (p, n, string_end, no_leading_period, flags2,
+- &end) == 0))
++ &end, alloca_used) == 0))
+ {
+ found:
+ if (end.pattern == NULL)
+@@ -749,7 +747,7 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends)
+ _NL_COLLATE_SYMB_EXTRAMB);
+
+ /* Locate the character in the hashing
+- table. */
++ table. */
+ hash = elem_hash (str, c1);
+
+ idx = 0;
+@@ -971,9 +969,8 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends)
+ case L('!'):
+ if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
+ {
+- int res;
+-
+- res = EXT (c, p, n, string_end, no_leading_period, flags);
++ int res = EXT (c, p, n, string_end, no_leading_period, flags,
++ alloca_used);
+ if (res != -1)
+ return res;
+ }
+@@ -1052,26 +1049,32 @@ END (const CHAR *pattern)
+ static int
+ internal_function
+ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
+- int no_leading_period, int flags)
++ int no_leading_period, int flags, size_t alloca_used)
+ {
+ const CHAR *startp;
+ int level;
+ struct patternlist
+ {
+ struct patternlist *next;
++ CHAR malloced;
+ CHAR str[0];
+ } *list = NULL;
+ struct patternlist **lastp = &list;
+ size_t pattern_len = STRLEN (pattern);
++ int any_malloced = 0;
+ const CHAR *p;
+ const CHAR *rs;
++ int retval = 0;
+
+ /* Parse the pattern. Store the individual parts in the list. */
+ level = 0;
+ for (startp = p = pattern + 1; level >= 0; ++p)
+ if (*p == L('\0'))
+- /* This is an invalid pattern. */
+- return -1;
++ {
++ /* This is an invalid pattern. */
++ retval = -1;
++ goto out;
++ }
+ else if (*p == L('['))
+ {
+ /* Handle brackets special. */
+@@ -1088,8 +1091,11 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
+ /* Skip over all characters of the list. */
+ while (*p != L(']'))
+ if (*p++ == L('\0'))
+- /* This is no valid pattern. */
+- return -1;
++ {
++ /* This is no valid pattern. */
++ retval = -1;
++ goto out;
++ }
+ }
+ else if ((*p == L('?') || *p == L('*') || *p == L('+') || *p == L('@')
+ || *p == L('!')) && p[1] == L('('))
+@@ -1102,15 +1108,25 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
+ /* This means we found the end of the pattern. */
+ #define NEW_PATTERN \
+ struct patternlist *newp; \
+- \
+- if (opt == L('?') || opt == L('@')) \
+- newp = alloca (sizeof (struct patternlist) \
+- + (pattern_len * sizeof (CHAR))); \
++ size_t slen = (opt == L('?') || opt == L('@') \
++ ? pattern_len : (p - startp + 1)); \
++ slen = sizeof (struct patternlist) + (slen * sizeof (CHAR)); \
++ int malloced = ! __libc_use_alloca (alloca_used + slen); \
++ if (__builtin_expect (malloced, 0)) \
++ { \
++ newp = malloc (slen); \
++ if (newp == NULL) \
++ { \
++ retval = -2; \
++ goto out; \
++ } \
++ any_malloced = 1; \
++ } \
+ else \
+- newp = alloca (sizeof (struct patternlist) \
+- + ((p - startp + 1) * sizeof (CHAR))); \
+- *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L('\0'); \
++ newp = alloca_account (slen, alloca_used); \
+ newp->next = NULL; \
++ newp->malloced = malloced; \
++ *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L('\0'); \
+ *lastp = newp; \
+ lastp = &newp->next
+ NEW_PATTERN;
+@@ -1131,8 +1147,9 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
+ switch (opt)
+ {
+ case L('*'):
+- if (FCT (p, string, string_end, no_leading_period, flags, NULL) == 0)
+- return 0;
++ if (FCT (p, string, string_end, no_leading_period, flags, NULL,
++ alloca_used) == 0)
++ goto success;
+ /* FALLTHROUGH */
+
+ case L('+'):
+@@ -1143,7 +1160,7 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
+ current pattern. */
+ if (FCT (list->str, string, rs, no_leading_period,
+ flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
+- NULL) == 0
++ NULL, alloca_used) == 0
+ /* This was successful. Now match the rest with the rest
+ of the pattern. */
+ && (FCT (p, rs, string_end,
+@@ -1151,7 +1168,7 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
+ ? no_leading_period
+ : rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0,
+ flags & FNM_FILE_NAME
+- ? flags : flags & ~FNM_PERIOD, NULL) == 0
++ ? flags : flags & ~FNM_PERIOD, NULL, alloca_used) == 0
+ /* This didn't work. Try the whole pattern. */
+ || (rs != string
+ && FCT (pattern - 1, rs, string_end,
+@@ -1160,18 +1177,21 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
+ : (rs[-1] == '/' && NO_LEADING_PERIOD (flags)
+ ? 1 : 0),
+ flags & FNM_FILE_NAME
+- ? flags : flags & ~FNM_PERIOD, NULL) == 0)))
++ ? flags : flags & ~FNM_PERIOD, NULL,
++ alloca_used) == 0)))
+ /* It worked. Signal success. */
+- return 0;
++ goto success;
+ }
+ while ((list = list->next) != NULL);
+
+ /* None of the patterns lead to a match. */
+- return FNM_NOMATCH;
++ retval = FNM_NOMATCH;
++ break;
+
+ case L('?'):
+- if (FCT (p, string, string_end, no_leading_period, flags, NULL) == 0)
+- return 0;
++ if (FCT (p, string, string_end, no_leading_period, flags, NULL,
++ alloca_used) == 0)
++ goto success;
+ /* FALLTHROUGH */
+
+ case L('@'):
+@@ -1183,13 +1203,14 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
+ if (FCT (STRCAT (list->str, p), string, string_end,
+ no_leading_period,
+ flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
+- NULL) == 0)
++ NULL, alloca_used) == 0)
+ /* It worked. Signal success. */
+- return 0;
++ goto success;
+ while ((list = list->next) != NULL);
+
+ /* None of the patterns lead to a match. */
+- return FNM_NOMATCH;
++ retval = FNM_NOMATCH;
++ break;
+
+ case L('!'):
+ for (rs = string; rs <= string_end; ++rs)
+@@ -1199,7 +1220,7 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
+ for (runp = list; runp != NULL; runp = runp->next)
+ if (FCT (runp->str, string, rs, no_leading_period,
+ flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
+- NULL) == 0)
++ NULL, alloca_used) == 0)
+ break;
+
+ /* If none of the patterns matched see whether the rest does. */
+@@ -1209,21 +1230,34 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
+ ? no_leading_period
+ : rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0,
+ flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
+- NULL) == 0))
++ NULL, alloca_used) == 0))
+ /* This is successful. */
+- return 0;
++ goto success;
+ }
+
+ /* None of the patterns together with the rest of the pattern
+ lead to a match. */
+- return FNM_NOMATCH;
++ retval = FNM_NOMATCH;
++ break;
+
+ default:
+ assert (! "Invalid extended matching operator");
++ retval = -1;
+ break;
+ }
+
+- return -1;
++ success:
++ out:
++ if (any_malloced)
++ while (list != NULL)
++ {
++ struct patternlist *old = list;
++ list = list->next;
++ if (old->malloced)
++ free (old);
++ }
++
++ return retval;
+ }
+
+
Modified: glibc-package/trunk/debian/patches/series
===================================================================
--- glibc-package/trunk/debian/patches/series 2011-02-26 14:36:08 UTC (rev 4540)
+++ glibc-package/trunk/debian/patches/series 2011-02-26 17:05:56 UTC (rev 4541)
@@ -270,3 +270,4 @@
any/cvs-audit-suid.diff
any/cvs-dont-expand-dst-twice.diff
any/cvs-ignore-origin-privileged.diff
+any/cvs-fnmatch-alloca.patch
Reply to: