On 2015-10-19 21:07, Aurelien Jarno wrote: > Package: release.debian.org > Severity: normal > Tags: wheezy > User: release.debian....@packages.debian.org > Usertags: pu > > Dear oldstable release team, > > I would like to update the eglibc package in wheezy to fix the known > security issues for which there is a patch available. The changes match > the security bugs opened by the security team, their severity wasn't > high enough to warrant a DSA. > > You'll find the corresponding diff against the current version in > wheezy below.
A new security bug has been found in a meantime. Therefore please find below a new diff. Thanks, Aurelien Index: debian/patches/any/cvs-CVE-2014-8121.diff =================================================================== --- debian/patches/any/cvs-CVE-2014-8121.diff (nonexistent) +++ debian/patches/any/cvs-CVE-2014-8121.diff (révision 6814) @@ -0,0 +1,17 @@ +2015-04-29 Florian Weimer <fwei...@redhat.com> + + [BZ #18007] + * nss/nss_files/files-XXX.c (CONCAT): Always enable stayopen. + (CVE-2014-8121) + +--- a/nss/nss_files/files-XXX.c ++++ b/nss/nss_files/files-XXX.c +@@ -134,7 +134,7 @@ CONCAT(_nss_files_set,ENTNAME) (int stayopen) + + __libc_lock_lock (lock); + +- status = internal_setent (stayopen); ++ status = internal_setent (1); + + if (status == NSS_STATUS_SUCCESS && fgetpos (stream, &position) < 0) + { Index: debian/patches/any/cvs-CVE-2015-1781.diff =================================================================== --- debian/patches/any/cvs-CVE-2015-1781.diff (nonexistent) +++ debian/patches/any/cvs-CVE-2015-1781.diff (révision 6814) @@ -0,0 +1,18 @@ +2015-04-21 Arjun Shankar <arjun...@lostca.se> + + [BZ #18287] + * resolv/nss_dns/dns-host.c (getanswer_r): Adjust buffer length + based on padding. (CVE-2015-1781) + +--- a/resolv/nss_dns/dns-host.c ++++ b/resolv/nss_dns/dns-host.c +@@ -615,7 +615,8 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, + int have_to_map = 0; + uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data); + buffer += pad; +- if (__builtin_expect (buflen < sizeof (struct host_data) + pad, 0)) ++ buflen = buflen > pad ? buflen - pad : 0; ++ if (__builtin_expect (buflen < sizeof (struct host_data), 0)) + { + /* The buffer is too small. */ + too_small: Index: debian/patches/any/cvs-_IO_wstr_overflow.diff =================================================================== --- debian/patches/any/cvs-_IO_wstr_overflow.diff (nonexistent) +++ debian/patches/any/cvs-_IO_wstr_overflow.diff (révision 6814) @@ -0,0 +1,31 @@ +2015-02-22 Paul Pluzhnikov <ppluzhni...@google.com> + + [BZ #17269] + * libio/wstrops.c (_IO_wstr_overflow): Guard against integer overflow + (enlarge_userbuf): Likewise. + +--- a/libio/wstrops.c ++++ b/libio/wstrops.c +@@ -96,8 +96,11 @@ _IO_wstr_overflow (fp, c) + wchar_t *old_buf = fp->_wide_data->_IO_buf_base; + size_t old_wblen = _IO_wblen (fp); + _IO_size_t new_size = 2 * old_wblen + 100; +- if (new_size < old_wblen) ++ ++ if (__builtin_expect ((new_size < old_wblen), 0) ++ || __builtin_expect ((new_size > SIZE_MAX / sizeof (wchar_t)), 0)) + return EOF; ++ + new_buf + = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size + * sizeof (wchar_t)); +@@ -187,6 +190,9 @@ enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading) + return 1; + + _IO_size_t newsize = offset + 100; ++ if (__builtin_expect ((newsize > SIZE_MAX / sizeof (wchar_t)), 0)) ++ return 1; ++ + wchar_t *oldbuf = wd->_IO_buf_base; + wchar_t *newbuf + = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (newsize Index: debian/patches/any/cvs-fnmatch-overflow.diff =================================================================== --- debian/patches/any/cvs-fnmatch-overflow.diff (nonexistent) +++ debian/patches/any/cvs-fnmatch-overflow.diff (révision 6814) @@ -0,0 +1,27 @@ +2015-02-26 Andreas Schwab <sch...@suse.de> + + [BZ #18032] + * posix/fnmatch_loop.c (FCT): Remove extra increment when skipping + over collating symbol inside a bracket expression. Minor cleanup. + +diff --git a/posix/fnmatch_loop.c b/posix/fnmatch_loop.c +index f79d051..f11d0f1 100644 +--- a/posix/fnmatch_loop.c ++++ b/posix/fnmatch_loop.c +@@ -951,14 +951,13 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used) + } + else if (c == L('[') && *p == L('.')) + { +- ++p; + while (1) + { + c = *++p; +- if (c == '\0') ++ if (c == L('\0')) + return FNM_NOMATCH; + +- if (*p == L('.') && p[1] == L(']')) ++ if (c == L('.') && p[1] == L(']')) + break; + } + p += 2; Index: debian/patches/any/cvs-ld_pointer_guard.diff =================================================================== --- debian/patches/any/cvs-ld_pointer_guard.diff (nonexistent) +++ debian/patches/any/cvs-ld_pointer_guard.diff (révision 6814) @@ -0,0 +1,62 @@ +2015-10-15 Florian Weimer <fwei...@redhat.com> + + [BZ #18928] + * sysdeps/generic/ldsodefs.h (struct rtld_global_ro): Remove + _dl_pointer_guard member. + * elf/rtld.c (_rtld_global_ro): Remove _dl_pointer_guard + initializer. + (security_init): Always set up pointer guard. + (process_envvars): Do not process LD_POINTER_GUARD. + +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -162,7 +162,6 @@ + ._dl_hwcap_mask = HWCAP_IMPORTANT, + ._dl_lazy = 1, + ._dl_fpu_control = _FPU_DEFAULT, +- ._dl_pointer_guard = 1, + + /* Function pointers. */ + ._dl_debug_printf = _dl_debug_printf, +@@ -857,15 +856,12 @@ + #endif + + /* Set up the pointer guard as well, if necessary. */ +- if (GLRO(dl_pointer_guard)) +- { +- uintptr_t pointer_chk_guard = _dl_setup_pointer_guard (_dl_random, +- stack_chk_guard); ++ uintptr_t pointer_chk_guard ++ = _dl_setup_pointer_guard (_dl_random, stack_chk_guard); + #ifdef THREAD_SET_POINTER_GUARD +- THREAD_SET_POINTER_GUARD (pointer_chk_guard); ++ THREAD_SET_POINTER_GUARD (pointer_chk_guard); + #endif +- __pointer_chk_guard_local = pointer_chk_guard; +- } ++ __pointer_chk_guard_local = pointer_chk_guard; + + /* We do not need the _dl_random value anymore. The less + information we leave behind, the better, so clear the +@@ -2607,9 +2603,6 @@ + GLRO(dl_use_load_bias) = envline[14] == '1' ? -1 : 0; + break; + } +- +- if (memcmp (envline, "POINTER_GUARD", 13) == 0) +- GLRO(dl_pointer_guard) = envline[14] != '0'; + break; + + case 14: +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -591,9 +591,6 @@ + /* List of auditing interfaces. */ + struct audit_ifaces *_dl_audit; + unsigned int _dl_naudit; +- +- /* 0 if internal pointer values should not be guarded, 1 if they should. */ +- EXTERN int _dl_pointer_guard; + }; + # define __rtld_global_attribute__ + # ifdef IS_IN_rtld Index: debian/patches/any/cvs-strxfrm-buffer-overflows.diff =================================================================== --- debian/patches/any/cvs-strxfrm-buffer-overflows.diff (nonexistent) +++ debian/patches/any/cvs-strxfrm-buffer-overflows.diff (révision 6822) @@ -0,0 +1,711 @@ +commit 0f9e585480edcdf1e30dc3d79e24b84aeee516fa +Author: Leonhard Holz <leonhard.h...@web.de> +Date: Tue Jan 13 11:33:56 2015 +0530 + + Fix memory handling in strxfrm_l [BZ #16009] + + [Modified from the original email by Siddhesh Poyarekar] + + This patch solves bug #16009 by implementing an additional path in + strxfrm that does not depend on caching the weight and rule indices. + + In detail the following changed: + + * The old main loop was factored out of strxfrm_l into the function + do_xfrm_cached to be able to alternativly use the non-caching version + do_xfrm. + + * strxfrm_l allocates a a fixed size array on the stack. If this is not + sufficiant to store the weight and rule indices, the non-caching path is + taken. As the cache size is not dependent on the input there can be no + problems with integer overflows or stack allocations greater than + __MAX_ALLOCA_CUTOFF. Note that malloc-ing is not possible because the + definition of strxfrm does not allow an oom errorhandling. + + * The uncached path determines the weight and rule index for every char + and for every pass again. + + * Passing all the locale data array by array resulted in very long + parameter lists, so I introduced a structure that holds them. + + * Checking for zero src string has been moved a bit upwards, it is + before the locale data initialization now. + + * To verify that the non-caching path works correct I added a test run + to localedata/sort-test.sh & localedata/xfrm-test.c where all strings + are patched up with spaces so that they are too large for the caching path. + +2015-01-13 Leonhard Holz <leonhard.h...@web.de> + + [BZ #16009] + * string/strxfrm_l.c (STRXFRM): Allocate fixed size cache for + weights and rules. Use do_xfrm_cached if data fits in cache, + do_xfrm otherwise. Moved former main loop to... + * (do_xfrm_cached): New function. + * (do_xfrm): Non-caching version of do_xfrm_cached. Uses + find_idx, find_position and stack_push. + * (find_idx): New function. + * (find_position): Likewise. + * localedata/sort-test.sh: Added test run for do_xfrm. + * localedata/xfrm-test.c (main): Added command line option + -nocache to run the test with strings that are too large for + the STRXFRM cache. + +--- a/localedata/sort-test.sh ++++ b/localedata/sort-test.sh +@@ -30,11 +30,17 @@ for l in $lang; do + ${common_objpfx}localedata/xfrm-test $id < $cns.in \ + > ${common_objpfx}localedata/$cns.xout || here=1 + cmp -s $cns.in ${common_objpfx}localedata/$cns.xout || here=1 ++ LOCPATH=${common_objpfx}localedata GCONV_PATH=${common_objpfx}/iconvdata \ ++ LC_ALL=$l ${run_program_prefix} \ ++ ${common_objpfx}localedata/xfrm-test $id -nocache < $cns.in \ ++ > ${common_objpfx}localedata/$cns.nocache.xout || here=1 ++ cmp -s $cns.in ${common_objpfx}localedata/$cns.nocache.xout || here=1 + if test $here -eq 0; then + echo "$l xfrm-test OK" + else + echo "$l xfrm-test FAIL" + diff -u $cns.in ${common_objpfx}localedata/$cns.xout | sed 's/^/ /' ++ diff -u $cns.in ${common_objpfx}localedata/$cns.nocache.xout | sed 's/^/ /' + status=1 + fi + done +--- a/localedata/xfrm-test.c ++++ b/localedata/xfrm-test.c +@@ -24,7 +24,10 @@ + #include <stdio.h> + #include <stdlib.h> + #include <string.h> ++#include <stdbool.h> + ++/* Keep in sync with string/strxfrm_l.c. */ ++#define SMALL_STR_SIZE 4095 + + struct lines + { +@@ -38,6 +41,7 @@ int + main (int argc, char *argv[]) + { + int result = 0; ++ bool nocache = false; + size_t nstrings, nstrings_max; + struct lines *strings; + char *line = NULL; +@@ -45,7 +49,18 @@ main (int argc, char *argv[]) + size_t n; + + if (argc < 2) +- error (1, 0, "usage: %s <random seed>", argv[0]); ++ error (1, 0, "usage: %s <random seed> [-nocache]", argv[0]); ++ ++ if (argc == 3) ++ { ++ if (strcmp (argv[2], "-nocache") == 0) ++ nocache = true; ++ else ++ { ++ printf ("Unknown option %s!\n", argv[2]); ++ exit (1); ++ } ++ } + + setlocale (LC_ALL, ""); + +@@ -60,9 +75,9 @@ main (int argc, char *argv[]) + + while (1) + { +- char saved, *newp; +- int needed; +- int l; ++ char saved, *word, *newp; ++ size_t l, line_len, needed; ++ + if (getline (&line, &len, stdin) < 0) + break; + +@@ -84,10 +99,35 @@ main (int argc, char *argv[]) + + saved = line[l]; + line[l] = '\0'; +- needed = strxfrm (NULL, line, 0); ++ ++ if (nocache) ++ { ++ line_len = strlen (line); ++ word = malloc (line_len + SMALL_STR_SIZE + 1); ++ if (word == NULL) ++ { ++ printf ("malloc failed: %m\n"); ++ exit (1); ++ } ++ memset (word, ' ', SMALL_STR_SIZE); ++ memcpy (word + SMALL_STR_SIZE, line, line_len); ++ word[line_len + SMALL_STR_SIZE] = '\0'; ++ } ++ else ++ word = line; ++ ++ needed = strxfrm (NULL, word, 0); + newp = malloc (needed + 1); +- strxfrm (newp, line, needed + 1); ++ if (newp == NULL) ++ { ++ printf ("malloc failed: %m\n"); ++ exit (1); ++ } ++ strxfrm (newp, word, needed + 1); + strings[nstrings].xfrm = newp; ++ ++ if (nocache) ++ free (word); + line[l] = saved; + ++nstrings; + } +--- a/string/strxfrm_l.c ++++ b/string/strxfrm_l.c +@@ -42,8 +42,23 @@ + #define CONCAT(a,b) CONCAT1(a,b) + #define CONCAT1(a,b) a##b + ++/* Maximum string size that is calculated with cached indices. Right now this ++ is an arbitrary value open to optimizations. SMALL_STR_SIZE * 4 has to be ++ lower than __MAX_ALLOCA_CUTOFF. Keep localedata/xfrm-test.c in sync. */ ++#define SMALL_STR_SIZE 4095 ++ + #include "../locale/localeinfo.h" + ++/* Group locale data for shorter parameter lists. */ ++typedef struct ++{ ++ uint_fast32_t nrules; ++ unsigned char *rulesets; ++ USTRING_TYPE *weights; ++ int32_t *table; ++ USTRING_TYPE *extra; ++ int32_t *indirect; ++} locale_data_t; + + #ifndef WIDE_CHAR_VERSION + +@@ -82,119 +97,328 @@ utf8_encode (char *buf, int val) + } + #endif + ++/* Find next weight and rule index. Inlined since called for every char. */ ++static __always_inline size_t ++find_idx (const USTRING_TYPE **us, int32_t *weight_idx, ++ unsigned char *rule_idx, const locale_data_t *l_data, const int pass) ++{ ++ const int32_t *table = l_data->table; ++ const int32_t *indirect = l_data->indirect; ++ const USTRING_TYPE *extra = l_data->extra; ++#include WEIGHT_H ++ int32_t tmp = findidx (us, -1); ++ *rule_idx = tmp >> 24; ++ int32_t idx = tmp & 0xffffff; ++ size_t len = l_data->weights[idx++]; + +-size_t +-STRXFRM (STRING_TYPE *dest, const STRING_TYPE *src, size_t n, __locale_t l) ++ /* Skip over indices of previous levels. */ ++ for (int i = 0; i < pass; i++) ++ { ++ idx += len; ++ len = l_data->weights[idx++]; ++ } ++ ++ *weight_idx = idx; ++ return len; ++} ++ ++static int ++find_position (const USTRING_TYPE *us, const locale_data_t *l_data, ++ const int pass) + { +- struct __locale_data *current = l->__locales[LC_COLLATE]; +-#if __OPTION_EGLIBC_LOCALE_CODE +- uint_fast32_t nrules = current->values[_NL_ITEM_INDEX (_NL_COLLATE_NRULES)].word; +-#else +- const uint_fast32_t nrules = 0; +-#endif +- /* We don't assign the following values right away since it might be +- unnecessary in case there are no rules. */ +- const unsigned char *rulesets; +- const int32_t *table; +- const USTRING_TYPE *weights; +- const USTRING_TYPE *extra; +- const int32_t *indirect; ++ int32_t weight_idx; ++ unsigned char rule_idx; ++ const USTRING_TYPE *usrc = us; ++ ++ find_idx (&usrc, &weight_idx, &rule_idx, l_data, pass); ++ return l_data->rulesets[rule_idx * l_data->nrules + pass] & sort_position; ++} ++ ++/* Do the transformation. */ ++static size_t ++do_xfrm (const USTRING_TYPE *usrc, STRING_TYPE *dest, size_t n, ++ const locale_data_t *l_data) ++{ ++ int32_t weight_idx; ++ unsigned char rule_idx; + uint_fast32_t pass; +- size_t needed; ++ size_t needed = 0; + size_t last_needed; +- const USTRING_TYPE *usrc; +- size_t srclen = STRLEN (src); +- int32_t *idxarr; +- unsigned char *rulearr; +- size_t idxmax; +- size_t idxcnt; +- int use_malloc; +- +-#include WEIGHT_H + +- if (nrules == 0) ++ /* Now the passes over the weights. */ ++ for (pass = 0; pass < l_data->nrules; ++pass) + { +- if (n != 0) +- STPNCPY (dest, src, MIN (srclen + 1, n)); ++ size_t backw_len = 0; ++ last_needed = needed; ++ const USTRING_TYPE *cur = usrc; ++ const USTRING_TYPE *backw_start = NULL; + +- return srclen; +- } ++ /* We assume that if a rule has defined `position' in one section ++ this is true for all of them. */ ++ int position = find_position (cur, l_data, pass); + +- rulesets = (const unsigned char *) +- current->values[_NL_ITEM_INDEX (_NL_COLLATE_RULESETS)].string; +- table = (const int32_t *) +- current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_TABLE,SUFFIX))].string; +- weights = (const USTRING_TYPE *) +- current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_WEIGHT,SUFFIX))].string; +- extra = (const USTRING_TYPE *) +- current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_EXTRA,SUFFIX))].string; +- indirect = (const int32_t *) +- current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_INDIRECT,SUFFIX))].string; +- use_malloc = 0; ++ if (position == 0) ++ { ++ while (*cur != L('\0')) ++ { ++ const USTRING_TYPE *pos = cur; ++ size_t len = find_idx (&cur, &weight_idx, &rule_idx, l_data, ++ pass); ++ int rule = l_data->rulesets[rule_idx * l_data->nrules + pass]; + +- assert (((uintptr_t) table) % __alignof__ (table[0]) == 0); +- assert (((uintptr_t) weights) % __alignof__ (weights[0]) == 0); +- assert (((uintptr_t) extra) % __alignof__ (extra[0]) == 0); +- assert (((uintptr_t) indirect) % __alignof__ (indirect[0]) == 0); ++ if ((rule & sort_forward) != 0) ++ { ++ /* Handle the pushed backward sequence. */ ++ if (backw_start != NULL) ++ { ++ for (size_t i = backw_len; i > 0; ) ++ { ++ int32_t weight_idx; ++ unsigned char rule_idx; ++ size_t len = find_idx (&backw_start, &weight_idx, ++ &rule_idx, l_data, pass); ++ if (needed + i < n) ++ for (size_t j = len; j > 0; j--) ++ dest[needed + i - j] = ++ l_data->weights[weight_idx++]; + +- /* Handle an empty string as a special case. */ +- if (srclen == 0) +- { +- if (n != 0) +- *dest = L('\0'); +- return 0; +- } ++ i -= len; ++ } + +- /* We need the elements of the string as unsigned values since they +- are used as indeces. */ +- usrc = (const USTRING_TYPE *) src; ++ needed += backw_len; ++ backw_start = NULL; ++ backw_len = 0; ++ } + +- /* Perform the first pass over the string and while doing this find +- and store the weights for each character. Since we want this to +- be as fast as possible we are using `alloca' to store the temporary +- values. But since there is no limit on the length of the string +- we have to use `malloc' if the string is too long. We should be +- very conservative here. */ +- if (! __libc_use_alloca (srclen)) +- { +- idxarr = (int32_t *) malloc ((srclen + 1) * (sizeof (int32_t) + 1)); +- rulearr = (unsigned char *) &idxarr[srclen]; ++ /* Now handle the forward element. */ ++ if (needed + len < n) ++ while (len-- > 0) ++ dest[needed++] = l_data->weights[weight_idx++]; ++ else ++ /* No more characters fit into the buffer. */ ++ needed += len; ++ } ++ else ++ { ++ /* Remember start of the backward sequence & track length. */ ++ if (backw_start == NULL) ++ backw_start = pos; ++ backw_len += len; ++ } ++ } + +- if (idxarr == NULL) +- /* No memory. Well, go with the stack then. + +- XXX Once this implementation is stable we will handle this +- differently. Instead of precomputing the indeces we will +- do this in time. This means, though, that this happens for +- every pass again. */ +- goto try_stack; +- use_malloc = 1; +- } +- else +- { +- try_stack: +- idxarr = (int32_t *) alloca (srclen * sizeof (int32_t)); +- rulearr = (unsigned char *) alloca (srclen + 1); ++ /* Handle the pushed backward sequence. */ ++ if (backw_start != NULL) ++ { ++ for (size_t i = backw_len; i > 0; ) ++ { ++ size_t len = find_idx (&backw_start, &weight_idx, &rule_idx, ++ l_data, pass); ++ if (needed + i < n) ++ for (size_t j = len; j > 0; j--) ++ dest[needed + i - j] = ++ l_data->weights[weight_idx++]; ++ ++ i -= len; ++ } ++ ++ needed += backw_len; ++ } ++ } ++ else ++ { ++ int val = 1; ++#ifndef WIDE_CHAR_VERSION ++ char buf[7]; ++ size_t buflen; ++#endif ++ size_t i; ++ ++ while (*cur != L('\0')) ++ { ++ const USTRING_TYPE *pos = cur; ++ size_t len = find_idx (&cur, &weight_idx, &rule_idx, l_data, ++ pass); ++ int rule = l_data->rulesets[rule_idx * l_data->nrules + pass]; ++ ++ if ((rule & sort_forward) != 0) ++ { ++ /* Handle the pushed backward sequence. */ ++ if (backw_start != NULL) ++ { ++ for (size_t p = backw_len; p > 0; p--) ++ { ++ size_t len; ++ int32_t weight_idx; ++ unsigned char rule_idx; ++ const USTRING_TYPE *backw_cur = backw_start; ++ ++ /* To prevent a warning init the used vars. */ ++ len = find_idx (&backw_cur, &weight_idx, ++ &rule_idx, l_data, pass); ++ ++ for (i = 1; i < p; i++) ++ len = find_idx (&backw_cur, &weight_idx, ++ &rule_idx, l_data, pass); ++ ++ if (len != 0) ++ { ++#ifdef WIDE_CHAR_VERSION ++ if (needed + 1 + len < n) ++ { ++ dest[needed] = val; ++ for (i = 0; i < len; ++i) ++ dest[needed + 1 + i] = ++ l_data->weights[weight_idx + i]; ++ } ++ needed += 1 + len; ++#else ++ buflen = utf8_encode (buf, val); ++ if (needed + buflen + len < n) ++ { ++ for (i = 0; i < buflen; ++i) ++ dest[needed + i] = buf[i]; ++ for (i = 0; i < len; ++i) ++ dest[needed + buflen + i] = ++ l_data->weights[weight_idx + i]; ++ } ++ needed += buflen + len; ++#endif ++ val = 1; ++ } ++ else ++ ++val; ++ } ++ ++ backw_start = NULL; ++ backw_len = 0; ++ } ++ ++ /* Now handle the forward element. */ ++ if (len != 0) ++ { ++#ifdef WIDE_CHAR_VERSION ++ if (needed + 1 + len < n) ++ { ++ dest[needed] = val; ++ for (i = 0; i < len; ++i) ++ dest[needed + 1 + i] = ++ l_data->weights[weight_idx + i]; ++ } ++ needed += 1 + len; ++#else ++ buflen = utf8_encode (buf, val); ++ if (needed + buflen + len < n) ++ { ++ for (i = 0; i < buflen; ++i) ++ dest[needed + i] = buf[i]; ++ for (i = 0; i < len; ++i) ++ dest[needed + buflen + i] = ++ l_data->weights[weight_idx + i]; ++ } ++ needed += buflen + len; ++#endif ++ val = 1; ++ } ++ else ++ ++val; ++ } ++ else ++ { ++ /* Remember start of the backward sequence & track length. */ ++ if (backw_start == NULL) ++ backw_start = pos; ++ backw_len++; ++ } ++ } ++ ++ /* Handle the pushed backward sequence. */ ++ if (backw_start != NULL) ++ { ++ for (size_t p = backw_len; p > 0; p--) ++ { ++ size_t len; ++ int32_t weight_idx; ++ unsigned char rule_idx; ++ const USTRING_TYPE *backw_cur = backw_start; ++ ++ /* To prevent a warning init the used vars. */ ++ len = find_idx (&backw_cur, &weight_idx, ++ &rule_idx, l_data, pass); ++ ++ for (i = 1; i < p; i++) ++ len = find_idx (&backw_cur, &weight_idx, ++ &rule_idx, l_data, pass); ++ ++ if (len != 0) ++ { ++#ifdef WIDE_CHAR_VERSION ++ if (needed + 1 + len < n) ++ { ++ dest[needed] = val; ++ for (i = 0; i < len; ++i) ++ dest[needed + 1 + i] = ++ l_data->weights[weight_idx + i]; ++ } ++ needed += 1 + len; ++#else ++ buflen = utf8_encode (buf, val); ++ if (needed + buflen + len < n) ++ { ++ for (i = 0; i < buflen; ++i) ++ dest[needed + i] = buf[i]; ++ for (i = 0; i < len; ++i) ++ dest[needed + buflen + i] = ++ l_data->weights[weight_idx + i]; ++ } ++ needed += buflen + len; ++#endif ++ val = 1; ++ } ++ else ++ ++val; ++ } ++ } ++ } ++ ++ /* Finally store the byte to separate the passes or terminate ++ the string. */ ++ if (needed < n) ++ dest[needed] = pass + 1 < l_data->nrules ? L('\1') : L('\0'); ++ ++needed; + } + +- idxmax = 0; +- do ++ /* This is a little optimization: many collation specifications have ++ a `position' rule at the end and if no non-ignored character ++ is found the last \1 byte is immediately followed by a \0 byte ++ signalling this. We can avoid the \1 byte(s). */ ++ if (needed > 2 && needed == last_needed + 1) + { +- int32_t tmp = findidx (&usrc, -1); +- rulearr[idxmax] = tmp >> 24; +- idxarr[idxmax] = tmp & 0xffffff; +- +- ++idxmax; ++ /* Remove the \1 byte. */ ++ if (--needed <= n) ++ dest[needed - 1] = L('\0'); + } +- while (*usrc != L('\0')); + +- /* This element is only read, the value never used but to determine +- another value which then is ignored. */ +- rulearr[idxmax] = '\0'; ++ /* Return the number of bytes/words we need, but don't count the NUL ++ byte/word at the end. */ ++ return needed - 1; ++} ++ ++/* Do the transformation using weight-index and rule cache. */ ++static size_t ++do_xfrm_cached (STRING_TYPE *dest, size_t n, const locale_data_t *l_data, ++ size_t idxmax, int32_t *idxarr, const unsigned char *rulearr) ++{ ++ uint_fast32_t nrules = l_data->nrules; ++ unsigned char *rulesets = l_data->rulesets; ++ USTRING_TYPE *weights = l_data->weights; ++ uint_fast32_t pass; ++ size_t needed = 0; ++ size_t last_needed; ++ size_t idxcnt; + +- /* Now the passes over the weights. We now use the indeces we found +- before. */ +- needed = 0; ++ /* Now the passes over the weights. */ + for (pass = 0; pass < nrules; ++pass) + { + size_t backw_stop = ~0ul; +@@ -440,14 +664,93 @@ STRXFRM (STRING_TYPE *dest, const STRING + dest[needed - 1] = L('\0'); + } + +- /* Free the memory if needed. */ +- if (use_malloc) +- free (idxarr); +- + /* Return the number of bytes/words we need, but don't count the NUL + byte/word at the end. */ + return needed - 1; + } ++ ++size_t ++STRXFRM (STRING_TYPE *dest, const STRING_TYPE *src, size_t n, __locale_t l) ++{ ++ locale_data_t l_data; ++ struct __locale_data *current = l->__locales[LC_COLLATE]; ++ const int32_t *table; ++ const int32_t *indirect; ++ const USTRING_TYPE *extra; ++#include WEIGHT_H ++ l_data.nrules = current->values[_NL_ITEM_INDEX (_NL_COLLATE_NRULES)].word; ++ ++ /* Handle byte comparison case. */ ++ if (l_data.nrules == 0) ++ { ++ size_t srclen = STRLEN (src); ++ ++ if (n != 0) ++ STPNCPY (dest, src, MIN (srclen + 1, n)); ++ ++ return srclen; ++ } ++ ++ /* Handle an empty string, code hereafter relies on strlen (src) > 0. */ ++ if (*src == L('\0')) ++ { ++ if (n != 0) ++ *dest = L('\0'); ++ return 0; ++ } ++ ++ /* Get the locale data. */ ++ l_data.rulesets = (unsigned char *) ++ current->values[_NL_ITEM_INDEX (_NL_COLLATE_RULESETS)].string; ++ l_data.table = (int32_t *) ++ current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_TABLE,SUFFIX))].string; ++ l_data.weights = (USTRING_TYPE *) ++ current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_WEIGHT,SUFFIX))].string; ++ l_data.extra = (USTRING_TYPE *) ++ current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_EXTRA,SUFFIX))].string; ++ l_data.indirect = (int32_t *) ++ current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_INDIRECT,SUFFIX))].string; ++ table = l_data.table; ++ indirect = l_data.indirect; ++ extra = l_data.extra; ++ ++ assert (((uintptr_t) l_data.table) % __alignof__ (l_data.table[0]) == 0); ++ assert (((uintptr_t) l_data.weights) % __alignof__ (l_data.weights[0]) == 0); ++ assert (((uintptr_t) l_data.extra) % __alignof__ (l_data.extra[0]) == 0); ++ assert (((uintptr_t) l_data.indirect) % __alignof__ (l_data.indirect[0]) == 0); ++ ++ /* We need the elements of the string as unsigned values since they ++ are used as indeces. */ ++ const USTRING_TYPE *usrc = (const USTRING_TYPE *) src; ++ ++ /* Allocate cache for small strings on the stack and fill it with weight and ++ rule indices. If the cache size is not sufficient, continue with the ++ uncached xfrm version. */ ++ size_t idxmax = 0; ++ const USTRING_TYPE *cur = usrc; ++ int32_t *idxarr = alloca (SMALL_STR_SIZE * sizeof (int32_t)); ++ unsigned char *rulearr = alloca (SMALL_STR_SIZE + 1); ++ ++ do ++ { ++ int32_t tmp = findidx (&cur, -1); ++ rulearr[idxmax] = tmp >> 24; ++ idxarr[idxmax] = tmp & 0xffffff; ++ ++ ++idxmax; ++ } ++ while (*cur != L('\0') && idxmax < SMALL_STR_SIZE); ++ ++ /* This element is only read, the value never used but to determine ++ another value which then is ignored. */ ++ rulearr[idxmax] = '\0'; ++ ++ /* Do the transformation. */ ++ if (*cur == L('\0')) ++ return do_xfrm_cached (dest, n, &l_data, idxmax, idxarr, rulearr); ++ else ++ return do_xfrm (usrc, dest, n, &l_data); ++} + libc_hidden_def (STRXFRM) + + #ifndef WIDE_CHAR_VERSION Index: debian/patches/series =================================================================== --- debian/patches/series (révision 6366) +++ debian/patches/series (copie de travail) @@ -403,3 +403,9 @@ any/cvs-posix_spawn_file_actions_addopen.diff any/cvs-getnetbyname.diff any/cvs-getaddrinfo-idn.diff +any/cvs-CVE-2015-1781.diff +any/cvs-CVE-2014-8121.diff +any/cvs-fnmatch-overflow.diff +any/cvs-_IO_wstr_overflow.diff +any/cvs-ld_pointer_guard.diff +any/cvs-strxfrm-buffer-overflows.diff Index: debian/changelog =================================================================== --- debian/changelog (révision 6366) +++ debian/changelog (copie de travail) @@ -1,3 +1,25 @@ +eglibc (2.13-38+deb7u9) wheezy; urgency=medium + + [ Aurelien Jarno ] + * patches/any/cvs-CVE-2015-1781.diff: new patch from upstream to fix + a buffer overflow in getanswer_r (CVE-2015-1781). Closes: #796105. + * patches/any/cvs-fnmatch-overflow.diff: new patch from upstream to fix + a buffer overflow (read past end of buffer) in internal_fnmatch. + * patches/any/cvs-_IO_wstr_overflow.diff: new patch from upstream to fix + an integer overlow in IO_wstr_overflow. + * patches/any/cvs-CVE-2014-8121.diff: new patch from upstream to fix + an unexpected closing of nss_files databases after lookups, causing + denial of service (CVE-2014-8121). Closes: #779587. + * patches/any/cvs-ld_pointer_guard.diff: new patch from upstream to + unconditionally disable LD_POINTER_GUARD. Closes: #798316, #801691. + + [ Raphaël Hertzog ] + * debian/patches/any/cvs-strxfrm-buffer-overflows.diff: new patch + from upstream to fix memory allocations issues that can lead to buffer + overflows on the stack. Closes: #803927. + + -- Aurelien Jarno <aure...@debian.org> Wed, 16 Dec 2015 00:00:15 +0100 + eglibc (2.13-38+deb7u8) wheezy-security; urgency=medium * debian/patches/any/cvs-wscanf.diff: new patch from upstream to fix a -- Aurelien Jarno GPG: 4096R/1DDD8C9B aurel...@aurel32.net http://www.aurel32.net