1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-29 11:41:21 +03:00

Fix for test "malloc_usable_size: expected 7 but got 11"

[BZ #17581] The checking chain of unused chunks was terminated by a hash of
the block pointer, which was sometimes confused with the chunk length byte.
The chain is now terminated by a NULL byte.
This commit is contained in:
James Lemke
2014-11-26 13:45:24 -08:00
parent a8a7d7d212
commit 08f1e1d2bc
3 changed files with 54 additions and 37 deletions

View File

@ -1,3 +1,11 @@
2014-12-01 James Lemke <jwlemke@codesourcery.com>
[BZ #17581]
* malloc/hooks.c
(mem2mem_check): Add a terminator to the chain of checking blocks.
(malloc_check_get_size): Use it here.
(mem2chunk_check): Ditto.
2014-12-01 Rajalakshmi Srinivasaraghavan <raji@linux.vnet.ibm.com> 2014-12-01 Rajalakshmi Srinivasaraghavan <raji@linux.vnet.ibm.com>
* sysdeps/powerpc/powerpc64/strtok.S: New file. * sysdeps/powerpc/powerpc64/strtok.S: New file.

4
NEWS
View File

@ -12,8 +12,8 @@ Version 2.21
6652, 12926, 13862, 14132, 14138, 14171, 14498, 15215, 15884, 16469, 6652, 12926, 13862, 14132, 14138, 14171, 14498, 15215, 15884, 16469,
16619, 16740, 16857, 17192, 17266, 17344, 17363, 17370, 17371, 17411, 16619, 16740, 16857, 17192, 17266, 17344, 17363, 17370, 17371, 17411,
17460, 17475, 17485, 17501, 17506, 17508, 17522, 17555, 17570, 17571, 17460, 17475, 17485, 17501, 17506, 17508, 17522, 17555, 17570, 17571,
17572, 17573, 17574, 17582, 17583, 17584, 17585, 17589, 17594, 17608, 17572, 17573, 17574, 17581, 17582, 17583, 17584, 17585, 17589, 17594,
17616, 17625, 17633. 17608, 17616, 17625, 17633.
* CVE-2104-7817 The wordexp function could ignore the WRDE_NOCMD flag * CVE-2104-7817 The wordexp function could ignore the WRDE_NOCMD flag
under certain input conditions resulting in the execution of a shell for under certain input conditions resulting in the execution of a shell for

View File

@ -90,32 +90,36 @@ __malloc_check_init (void)
#define MAGICBYTE(p) ((((size_t) p >> 3) ^ ((size_t) p >> 11)) & 0xFF) #define MAGICBYTE(p) ((((size_t) p >> 3) ^ ((size_t) p >> 11)) & 0xFF)
/* Visualize the chunk as being partitioned into blocks of 256 bytes from the /* Visualize the chunk as being partitioned into blocks of 255 bytes from the
highest address of the chunk, downwards. The beginning of each block tells highest address of the chunk, downwards. The end of each block tells us
us the size of the previous block, up to the actual size of the requested the size of that block, up to the actual size of the requested memory.
memory. Our magic byte is right at the end of the requested size, so we The last block has a length of zero and is followed by the magic byte.
must reach it with this iteration, otherwise we have witnessed a memory Our magic byte is right at the end of the requested size. If we don't
corruption. */ reach it with this iteration we have witnessed a memory corruption. */
static size_t static size_t
malloc_check_get_size (mchunkptr p) malloc_check_get_size (mchunkptr p)
{ {
size_t size; size_t total_sz, size;
unsigned char c; unsigned char c;
unsigned char magic = MAGICBYTE (p); unsigned char magic = MAGICBYTE (p);
assert (using_malloc_checking == 1); assert (using_malloc_checking == 1);
for (size = chunksize (p) - 1 + (chunk_is_mmapped (p) ? 0 : SIZE_SZ); /* Validate the length-byte chain. */
(c = ((unsigned char *) p)[size]) != magic; total_sz = chunksize (p) + (chunk_is_mmapped (p) ? 0 : SIZE_SZ);
for (size = total_sz - 1;
(c = ((unsigned char *) p)[size]) != 0;
size -= c) size -= c)
{ {
if (c <= 0 || size < (c + 2 * SIZE_SZ)) if (size <= c + 2 * SIZE_SZ)
break;
}
if (c != 0 || ((unsigned char *) p)[--size] != magic)
{ {
malloc_printerr (check_action, "malloc_check_get_size: memory corruption", malloc_printerr (check_action, "malloc_check_get_size: memory corruption",
chunk2mem (p)); chunk2mem (p));
return 0; return 0;
} }
}
/* chunk2mem size. */ /* chunk2mem size. */
return size - 2 * SIZE_SZ; return size - 2 * SIZE_SZ;
@ -130,23 +134,25 @@ mem2mem_check (void *ptr, size_t sz)
{ {
mchunkptr p; mchunkptr p;
unsigned char *m_ptr = ptr; unsigned char *m_ptr = ptr;
size_t i; size_t user_sz, block_sz, i;
if (!ptr) if (!ptr)
return ptr; return ptr;
p = mem2chunk (ptr); p = mem2chunk (ptr);
for (i = chunksize (p) - (chunk_is_mmapped (p) ? 2 * SIZE_SZ + 1 : SIZE_SZ + 1); user_sz = chunksize (p) + (chunk_is_mmapped (p) ? 0 : SIZE_SZ);
i > sz; user_sz -= 2 * SIZE_SZ;
i -= 0xFF) for (i = user_sz - 1; i > sz; i -= block_sz)
{ {
if (i - sz < 0x100) block_sz = i - (sz + 1);
{ if (block_sz > 0xff)
m_ptr[i] = (unsigned char) (i - sz); block_sz = 0xff;
m_ptr[i] = (unsigned char) block_sz;
if (block_sz == 0)
break; break;
} }
m_ptr[i] = 0xFF;
}
m_ptr[sz] = MAGICBYTE (p); m_ptr[sz] = MAGICBYTE (p);
return (void *) m_ptr; return (void *) m_ptr;
} }
@ -166,11 +172,12 @@ mem2chunk_check (void *mem, unsigned char **magic_p)
return NULL; return NULL;
p = mem2chunk (mem); p = mem2chunk (mem);
sz = chunksize (p);
magic = MAGICBYTE (p);
if (!chunk_is_mmapped (p)) if (!chunk_is_mmapped (p))
{ {
/* Must be a chunk in conventional heap memory. */ /* Must be a chunk in conventional heap memory. */
int contig = contiguous (&main_arena); int contig = contiguous (&main_arena);
sz = chunksize (p);
if ((contig && if ((contig &&
((char *) p < mp_.sbrk_base || ((char *) p < mp_.sbrk_base ||
((char *) p + sz) >= (mp_.sbrk_base + main_arena.system_mem))) || ((char *) p + sz) >= (mp_.sbrk_base + main_arena.system_mem))) ||
@ -180,12 +187,13 @@ mem2chunk_check (void *mem, unsigned char **magic_p)
next_chunk (prev_chunk (p)) != p))) next_chunk (prev_chunk (p)) != p)))
return NULL; return NULL;
magic = MAGICBYTE (p); for (sz += SIZE_SZ - 1; (c = ((unsigned char *) p)[sz]) != 0; sz -= c)
for (sz += SIZE_SZ - 1; (c = ((unsigned char *) p)[sz]) != magic; sz -= c)
{ {
if (c <= 0 || sz < (c + 2 * SIZE_SZ)) if (sz <= c + 2 * SIZE_SZ)
return NULL; break;
} }
if (c != 0 || ((unsigned char *) p)[--sz] != magic)
return NULL;
} }
else else
{ {
@ -201,15 +209,16 @@ mem2chunk_check (void *mem, unsigned char **magic_p)
offset < 0x2000) || offset < 0x2000) ||
!chunk_is_mmapped (p) || (p->size & PREV_INUSE) || !chunk_is_mmapped (p) || (p->size & PREV_INUSE) ||
((((unsigned long) p - p->prev_size) & page_mask) != 0) || ((((unsigned long) p - p->prev_size) & page_mask) != 0) ||
((sz = chunksize (p)), ((p->prev_size + sz) & page_mask) != 0)) ((p->prev_size + sz) & page_mask) != 0)
return NULL; return NULL;
magic = MAGICBYTE (p); for (sz -= 1; (c = ((unsigned char *) p)[sz]) != 0; sz -= c)
for (sz -= 1; (c = ((unsigned char *) p)[sz]) != magic; sz -= c)
{ {
if (c <= 0 || sz < (c + 2 * SIZE_SZ)) if (sz <= c + 2 * SIZE_SZ)
return NULL; break;
} }
if (c != 0 || ((unsigned char *) p)[--sz] != magic)
return NULL;
} }
((unsigned char *) p)[sz] ^= 0xFF; ((unsigned char *) p)[sz] ^= 0xFF;
if (magic_p) if (magic_p)