bionic: fix integer overflows in chk_malloc(), leak_malloc(), and leak_memalign()
The allocation size in chk_malloc(), leak_malloc(), and leak_memalign()
functions may be rounded up to a small value, leading to buffer overflows.
The code only runs in debugging mode.
This patch complements commit 6f04a0f4 (CVE-2009-0607).
Change-Id: Id899bcd2bcd2ea2205e5753c433390710032dc83
Signed-off-by: Xi Wang <xi.wang@gmail.com>
			
			
This commit is contained in:
		@@ -25,26 +25,26 @@
 | 
				
			|||||||
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
					 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
				
			||||||
 * SUCH DAMAGE.
 | 
					 * SUCH DAMAGE.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <dlfcn.h>
 | 
				
			||||||
#include <errno.h>
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					#include <fcntl.h>
 | 
				
			||||||
#include <pthread.h>
 | 
					#include <pthread.h>
 | 
				
			||||||
 | 
					#include <stdarg.h>
 | 
				
			||||||
 | 
					#include <stddef.h>
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <arpa/inet.h>
 | 
					 | 
				
			||||||
#include <sys/socket.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
#include <errno.h>
 | 
					 | 
				
			||||||
#include <stddef.h>
 | 
					 | 
				
			||||||
#include <stdarg.h>
 | 
					 | 
				
			||||||
#include <fcntl.h>
 | 
					 | 
				
			||||||
#include <unwind.h>
 | 
					#include <unwind.h>
 | 
				
			||||||
#include <dlfcn.h>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <sys/socket.h>
 | 
					#include <arpa/inet.h>
 | 
				
			||||||
#include <sys/un.h>
 | 
					 | 
				
			||||||
#include <sys/select.h>
 | 
					#include <sys/select.h>
 | 
				
			||||||
#include <sys/types.h>
 | 
					#include <sys/socket.h>
 | 
				
			||||||
#include <sys/system_properties.h>
 | 
					#include <sys/system_properties.h>
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					#include <sys/un.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "dlmalloc.h"
 | 
					#include "dlmalloc.h"
 | 
				
			||||||
#include "logd.h"
 | 
					#include "logd.h"
 | 
				
			||||||
@@ -372,7 +372,11 @@ static int chk_mem_check(void*       mem,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void* chk_malloc(size_t bytes)
 | 
					void* chk_malloc(size_t bytes)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    char* buffer = (char*)dlmalloc(bytes + CHK_OVERHEAD_SIZE);
 | 
					    size_t size = bytes + CHK_OVERHEAD_SIZE;
 | 
				
			||||||
 | 
					    if (size < bytes) { // Overflow.
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    uint8_t* buffer = (uint8_t*) dlmalloc(size);
 | 
				
			||||||
    if (buffer) {
 | 
					    if (buffer) {
 | 
				
			||||||
        memset(buffer, CHK_SENTINEL_VALUE, bytes + CHK_OVERHEAD_SIZE);
 | 
					        memset(buffer, CHK_SENTINEL_VALUE, bytes + CHK_OVERHEAD_SIZE);
 | 
				
			||||||
        size_t offset = dlmalloc_usable_size(buffer) - sizeof(size_t);
 | 
					        size_t offset = dlmalloc_usable_size(buffer) - sizeof(size_t);
 | 
				
			||||||
@@ -505,7 +509,12 @@ void* leak_malloc(size_t bytes)
 | 
				
			|||||||
    // 1. allocate enough memory and include our header
 | 
					    // 1. allocate enough memory and include our header
 | 
				
			||||||
    // 2. set the base pointer to be right after our header
 | 
					    // 2. set the base pointer to be right after our header
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void* base = dlmalloc(bytes + sizeof(AllocationEntry));
 | 
					    size_t size = bytes + sizeof(AllocationEntry);
 | 
				
			||||||
 | 
					    if (size < bytes) { // Overflow.
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void* base = dlmalloc(size);
 | 
				
			||||||
    if (base != NULL) {
 | 
					    if (base != NULL) {
 | 
				
			||||||
        pthread_mutex_lock(&gAllocationsMutex);
 | 
					        pthread_mutex_lock(&gAllocationsMutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -615,6 +624,10 @@ void* leak_memalign(size_t alignment, size_t bytes)
 | 
				
			|||||||
    // we will align by at least MALLOC_ALIGNMENT bytes
 | 
					    // we will align by at least MALLOC_ALIGNMENT bytes
 | 
				
			||||||
    // and at most alignment-MALLOC_ALIGNMENT bytes
 | 
					    // and at most alignment-MALLOC_ALIGNMENT bytes
 | 
				
			||||||
    size_t size = (alignment-MALLOC_ALIGNMENT) + bytes;
 | 
					    size_t size = (alignment-MALLOC_ALIGNMENT) + bytes;
 | 
				
			||||||
 | 
					    if (size < bytes) { // Overflow.
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void* base = leak_malloc(size);
 | 
					    void* base = leak_malloc(size);
 | 
				
			||||||
    if (base != NULL) {
 | 
					    if (base != NULL) {
 | 
				
			||||||
        intptr_t ptr = (intptr_t)base;
 | 
					        intptr_t ptr = (intptr_t)base;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user