Cause:
A recent change to the C library localization code (BZ#951493) introduced a case where a pointer was not checked for NULL prior to being accessed.
Consequence:
This could result in a program crashing.
Fix/Result:
A check has been added to ensure that the pointer is non-NULL before accessing it, preventing a possible program crash. (BZ#957089/BZ#816647)
Created attachment 741879[details]
Patch for avoiding NULL pointer dereference
> * Fri Apr 12 2013 Siddhesh Poyarekar <siddhesh> - 2.5-107.4
> - Add missing patch to avoid use after free (#816647).
Unfortunately, glibc-rh816647-2.patch introduced NULL pointer dereference when
initial malloc() fails. We have to check that malloc() has succeeded before
accessing it.
Comment 5RHEL Program Management
2013-05-01 16:58:46 UTC
This request was evaluated by Red Hat Product Management for inclusion
in a Red Hat Enterprise Linux release. Product Management has
requested further review of this request by Red Hat Engineering, for
potential inclusion in a Red Hat Enterprise Linux release for currently
deployed products. This request is not yet committed for inclusion in
a release.
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.
For information on the advisory, and where to find the updated
files, follow the link below.
If the solution does not work for you, open a new bug report.
http://rhn.redhat.com/errata/RHBA-2013-1308.html
Version-Release number of selected component (if applicable): glibc-2.5-107.el5_9.4 Description of problem: newmem != NULL check is needed before accessing newmem->next. (Described in the comment below.) --- old/intl/dcigettext.c +++ new/intl/dcigettext.c @@ -1155,50 +1155,51 @@ _nl_find_msg (domain_file, domainbinding resize_freemem: /* We must allocate a new buffer or resize the old one. */ if (malloc_count > 0) { ++malloc_count; freemem_size = malloc_count * INITIAL_BLOCK_SIZE; newmem = (transmem_block_t *) realloc (transmem_list, freemem_size); # ifdef _LIBC if (newmem != NULL) - transmem_list = transmem_list->next; + transmem_list = newmem; else { struct transmem_list *old = transmem_list; transmem_list = transmem_list->next; free (old); } # endif } else { malloc_count = 1; freemem_size = INITIAL_BLOCK_SIZE; newmem = (transmem_block_t *) malloc (freemem_size); +# ifdef _LIBC + /* Add the block to the list of blocks we have to free + at some point. */ + newmem->next = transmem_list; /***** Need newmem!=NULL check first.*****/ + transmem_list = newmem; +# endif } if (__builtin_expect (newmem == NULL, 0)) { freemem = NULL; freemem_size = 0; __libc_lock_unlock (lock); return (char *) -1; } # ifdef _LIBC - /* Add the block to the list of blocks we have to free - at some point. */ - newmem->next = transmem_list; - transmem_list = newmem; - freemem = (unsigned char *) newmem->data; freemem_size -= offsetof (struct transmem_list, data); # else transmem_list = newmem; freemem = newmem; # endif outbuf = freemem + sizeof (size_t); }