arm: flush cache to RAM on retype reset

This fixes a correctness and security issue where uncached user
mappings might see old data from before the clearMemory operation.

See also the discussion on GitHub issue #481

Signed-off-by: Gerwin Klein <gerwin.klein@proofcraft.systems>
This commit is contained in:
Gerwin Klein 2021-08-13 18:25:16 +10:00 committed by Gerwin Klein
parent 697430abf0
commit 10d6cc0ae9
3 changed files with 8 additions and 7 deletions

View file

@ -50,14 +50,15 @@ void cleanInvalidateL1Caches(void);
static inline void clearMemory(word_t *ptr, word_t bits)
{
memzero(ptr, BIT(bits));
cleanCacheRange_PoU((word_t)ptr, (word_t)ptr + BIT(bits) - 1,
cleanCacheRange_RAM((word_t)ptr, (word_t)ptr + BIT(bits) - 1,
addrFromPPtr(ptr));
}
static inline void clearMemoryRAM(word_t *ptr, word_t bits)
/* Cleaning memory before page table walker access */
static inline void clearMemory_PT(word_t *ptr, word_t bits)
{
memzero(ptr, BIT(bits));
cleanCacheRange_RAM((word_t)ptr, (word_t)ptr + BIT(bits) - 1,
cleanCacheRange_PoU((word_t)ptr, (word_t)ptr + BIT(bits) - 1,
addrFromPPtr(ptr));
}

View file

@ -1886,7 +1886,7 @@ static exception_t performPageTableInvocationUnmap(cap_t cap, cte_t *ctSlot)
cap_page_table_cap_get_capPTMappedASID(cap),
cap_page_table_cap_get_capPTMappedAddress(cap),
pt);
clearMemory((void *)pt, cap_get_capSizeBits(cap));
clearMemory_PT((void *)pt, cap_get_capSizeBits(cap));
}
cap_page_table_cap_ptr_set_capPTIsMapped(&(ctSlot->cap), 0);

View file

@ -1508,7 +1508,7 @@ static exception_t performUpperPageDirectoryInvocationUnmap(cap_t cap, cte_t *ct
pude_t *pud = PUD_PTR(cap_page_upper_directory_cap_get_capPUDBasePtr(cap));
unmapPageUpperDirectory(cap_page_upper_directory_cap_get_capPUDMappedASID(cap),
cap_page_upper_directory_cap_get_capPUDMappedAddress(cap), pud);
clearMemory((void *)pud, cap_get_capSizeBits(cap));
clearMemory_PT((void *)pud, cap_get_capSizeBits(cap));
}
cap_page_upper_directory_cap_ptr_set_capPUDIsMapped(&(ctSlot->cap), 0);
@ -1531,7 +1531,7 @@ static exception_t performPageDirectoryInvocationUnmap(cap_t cap, cte_t *ctSlot)
pde_t *pd = PD_PTR(cap_page_directory_cap_get_capPDBasePtr(cap));
unmapPageDirectory(cap_page_directory_cap_get_capPDMappedASID(cap),
cap_page_directory_cap_get_capPDMappedAddress(cap), pd);
clearMemory((void *)pd, cap_get_capSizeBits(cap));
clearMemory_PT((void *)pd, cap_get_capSizeBits(cap));
}
cap_page_directory_cap_ptr_set_capPDIsMapped(&(ctSlot->cap), 0);
@ -1553,7 +1553,7 @@ static exception_t performPageTableInvocationUnmap(cap_t cap, cte_t *ctSlot)
pte_t *pt = PT_PTR(cap_page_table_cap_get_capPTBasePtr(cap));
unmapPageTable(cap_page_table_cap_get_capPTMappedASID(cap),
cap_page_table_cap_get_capPTMappedAddress(cap), pt);
clearMemory((void *)pt, cap_get_capSizeBits(cap));
clearMemory_PT((void *)pt, cap_get_capSizeBits(cap));
}
cap_page_table_cap_ptr_set_capPTIsMapped(&(ctSlot->cap), 0);