From 8b99158d663728a2b6eaa5850a581fe778d40936 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Sun, 24 Dec 2023 09:37:52 +0000 Subject: [PATCH] vm: fix overflow in memblock do_alloc when allocating large aligned blocks allocating a large power-of-2 block with memblock may cause the base pointer of a region to exceed the limit pointer after it has been aligned during the free region scan in do_alloc(). --- vm/memblock.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/vm/memblock.c b/vm/memblock.c index e92a4b7..cce6dbe 100644 --- a/vm/memblock.c +++ b/vm/memblock.c @@ -252,7 +252,12 @@ static phys_addr_t do_alloc(size_t size, phys_addr_t align) base += align; } - size_t region_size = it.it_limit - base + 1; + size_t region_size = 0; + + if (it.it_limit > base) { + region_size = it.it_limit - base + 1; + } + if (region_size >= size) { allocated_base = it.it_base; allocated_limit = base + size; @@ -376,8 +381,8 @@ void __next_memory_region(struct memblock_iter *it, struct memblock_type *type_a } /* we want the area that is overlapped by both - region M (m_start - m_end) : The region defined as system memory. - region R (r_start - r_end) : The region defined as free / outside of any reserved regions. + region M (m_start - m_end) : The region defined as system memory. + region R (r_start - r_end) : The region defined as free / outside of any reserved regions. */ it->it_base = MAX(m_start, r_start); it->it_limit = MIN(m_end, r_end);