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 <sch...@redhat.com> + + * posix/fnmatch_loop.c (NEW_PATTERN): Fix use of alloca. + +2010-08-09 Ulrich Drepper <drep...@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 -- To UNSUBSCRIBE, email to debian-glibc-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org Archive: http://lists.debian.org/e1ptnan-0002jj...@alioth.debian.org