zipl/boot: fix potential heap overflow in stage2

Current heap size in stage2 is three pages long [0x6000-0x9000] but
get_zeroed_page() assumes it is one page more which might lead to
a heap overflow which will corrupt data located at 0x9000 (stage3
parameters). Calculate the heap size of a stage at run-time
by using the symbols provided by linker.

Furthermore, validate the given address in free_page() to stop illegal
memory accesses.

Signed-off-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Alexander Egorenkov
2020-11-28 12:20:41 +01:00
committed by Jan Höppner
parent 2dca5d193f
commit 6c6e3a2b0e

View File

@@ -32,9 +32,10 @@ struct ex_table_entry {
};
#define MEM_ALLOC_START ((unsigned long) __heap_start)
#define MEM_ALLOC_CNT 4
#define MEM_ALLOC_END ((unsigned long) __heap_stop)
#define MEM_ALLOC_MAX 4
static uint8_t mem_page_alloc_vec[MEM_ALLOC_CNT];
static uint8_t mem_page_alloc_vec[MEM_ALLOC_MAX];
/*
* Initialize memory with value
@@ -417,10 +418,11 @@ void printf(const char *fmt, ...)
*/
unsigned long get_zeroed_page(void)
{
const int page_count = MIN(MEM_ALLOC_MAX, (int)((MEM_ALLOC_END - MEM_ALLOC_START) / PAGE_SIZE));
unsigned long addr;
int i;
for (i = 0; i < MEM_ALLOC_CNT; i++) {
for (i = 0; i < page_count; i++) {
if (mem_page_alloc_vec[i] != 0)
continue;
addr = MEM_ALLOC_START + i * PAGE_SIZE;
@@ -436,6 +438,9 @@ unsigned long get_zeroed_page(void)
*/
void free_page(unsigned long addr)
{
if (addr < MEM_ALLOC_START || addr >= MEM_ALLOC_END)
libc_stop(EINTERNAL);
mem_page_alloc_vec[(addr - MEM_ALLOC_START) / PAGE_SIZE] = 0;
}