From b631737eee7639d5b4a4189c6a5243f9d8bfebfa Mon Sep 17 00:00:00 2001 From: Dmytro Firsov Date: Fri, 3 May 2024 18:05:50 +0300 Subject: [PATCH] drivers: xen: gnttab: prevent double-free for grant refs Grant references are allocated with simple O(1) allocator, where every next free gref is stored in previous and first free gref is always stored in 0 element. Current implementation had a possibility for double-free of some gref, because it did not store any information about entries being claimed. It may led to invalid gref_list value. Add GNTTAB_GREF_USED value and mark all taken value to prevent double free in put_grant_entry(). Signed-off-by: Dmytro Firsov --- drivers/xen/gnttab.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/xen/gnttab.c b/drivers/xen/gnttab.c index 0396e933978fccd..e2a8312dc7bb9f7 100644 --- a/drivers/xen/gnttab.c +++ b/drivers/xen/gnttab.c @@ -38,6 +38,7 @@ LOG_MODULE_REGISTER(xen_gnttab); #define DT_GNTTAB_SIZE DT_REG_SIZE_BY_IDX(DT_INST(0, xen_xen), 0) #define GNT_ENTRIES_PER_FRAME (XEN_PAGE_SIZE / sizeof(grant_entry_v1_t)) +#define GNTTAB_GREF_USED (UINT32_MAX - 1) #define GNTTAB_LAST_GREF UINT32_MAX BUILD_ASSERT(!(DT_GNTTAB_SIZE % XEN_PAGE_SIZE), @@ -74,6 +75,7 @@ static grant_ref_t get_grant_entry(void) gref = gnttab.gref_list[0]; gnttab.gref_list[0] = gnttab.gref_list[gref]; + gnttab.gref_list[gref] = GNTTAB_GREF_USED; k_mutex_unlock(&gnttab.lock); return gref; @@ -82,6 +84,13 @@ static grant_ref_t get_grant_entry(void) static void put_grant_entry(grant_ref_t gref) { k_mutex_lock(&gnttab.lock, K_FOREVER); + if (gnttab.gref_list[gref] != GNTTAB_GREF_USED) { + k_mutex_unlock(&gnttab.lock); + LOG_WRN("Trying to put already free gref = %u", gref); + + return; + } + gnttab.gref_list[gref] = gnttab.gref_list[0]; gnttab.gref_list[0] = gref; k_mutex_unlock(&gnttab.lock);