kernel: mmu: always use before/after guard pages for k_mem_map()
When we start allowing unmapping of memory region, there is no exact way to know if k_mem_map() is called with guard page option specified or not. So just unconditionally enable guard pages on both sides of the memory region to hopefully catch access violations. Signed-off-by: Daniel Leung <daniel.leung@intel.com>
This commit is contained in:
parent
cb0e3ede11
commit
fe48f5a920
2 changed files with 23 additions and 13 deletions
|
@ -278,8 +278,11 @@ void z_phys_unmap(uint8_t *virt, size_t size);
|
||||||
* Zephyr treats page faults on this guard page as a fatal K_ERR_STACK_CHK_FAIL
|
* Zephyr treats page faults on this guard page as a fatal K_ERR_STACK_CHK_FAIL
|
||||||
* if it determines it immediately precedes a stack buffer, this is
|
* if it determines it immediately precedes a stack buffer, this is
|
||||||
* implemented in the architecture layer.
|
* implemented in the architecture layer.
|
||||||
|
*
|
||||||
|
* DEPRECATED: k_mem_map() will always allocate guard pages, so this bit
|
||||||
|
* no longer has any effect.
|
||||||
*/
|
*/
|
||||||
#define K_MEM_MAP_GUARD BIT(18)
|
#define K_MEM_MAP_GUARD __DEPRECATED_MACRO BIT(18)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the amount of free memory available
|
* Return the amount of free memory available
|
||||||
|
@ -320,6 +323,10 @@ size_t k_mem_free_get(void);
|
||||||
* parameter, and any base address for re-mapping purposes must be page-
|
* parameter, and any base address for re-mapping purposes must be page-
|
||||||
* aligned.
|
* aligned.
|
||||||
*
|
*
|
||||||
|
* Note that the allocation includes two guard pages immediately before
|
||||||
|
* and after the requested region. The total size of the allocation will be
|
||||||
|
* the requested size plus the size of these two guard pages.
|
||||||
|
*
|
||||||
* Many K_MEM_MAP_* flags have been implemented to alter the behavior of this
|
* Many K_MEM_MAP_* flags have been implemented to alter the behavior of this
|
||||||
* function, with details in the documentation for these flags.
|
* function, with details in the documentation for these flags.
|
||||||
*
|
*
|
||||||
|
|
27
kernel/mmu.c
27
kernel/mmu.c
|
@ -348,10 +348,9 @@ static int map_anon_page(void *addr, uint32_t flags)
|
||||||
void *k_mem_map(size_t size, uint32_t flags)
|
void *k_mem_map(size_t size, uint32_t flags)
|
||||||
{
|
{
|
||||||
uint8_t *dst;
|
uint8_t *dst;
|
||||||
size_t total_size = size;
|
size_t total_size;
|
||||||
int ret;
|
int ret;
|
||||||
k_spinlock_key_t key;
|
k_spinlock_key_t key;
|
||||||
bool guard = (flags & K_MEM_MAP_GUARD) != 0U;
|
|
||||||
uint8_t *pos;
|
uint8_t *pos;
|
||||||
|
|
||||||
__ASSERT(!(((flags & K_MEM_PERM_USER) != 0U) &&
|
__ASSERT(!(((flags & K_MEM_PERM_USER) != 0U) &&
|
||||||
|
@ -366,22 +365,26 @@ void *k_mem_map(size_t size, uint32_t flags)
|
||||||
|
|
||||||
key = k_spin_lock(&z_mm_lock);
|
key = k_spin_lock(&z_mm_lock);
|
||||||
|
|
||||||
if (guard) {
|
/* Need extra for the guard pages (before and after) which we
|
||||||
/* Need extra virtual page for the guard which we
|
* won't map.
|
||||||
* won't map
|
*/
|
||||||
*/
|
total_size = size + CONFIG_MMU_PAGE_SIZE * 2;
|
||||||
total_size += CONFIG_MMU_PAGE_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
dst = virt_region_get(total_size);
|
dst = virt_region_get(total_size);
|
||||||
if (dst == NULL) {
|
if (dst == NULL) {
|
||||||
/* Address space has no free region */
|
/* Address space has no free region */
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (guard) {
|
|
||||||
/* Skip over the guard page in returned address. */
|
/* Unmap both guard pages to make sure accessing them
|
||||||
dst += CONFIG_MMU_PAGE_SIZE;
|
* will generate fault.
|
||||||
}
|
*/
|
||||||
|
arch_mem_unmap(dst, CONFIG_MMU_PAGE_SIZE);
|
||||||
|
arch_mem_unmap(dst + CONFIG_MMU_PAGE_SIZE + size,
|
||||||
|
CONFIG_MMU_PAGE_SIZE);
|
||||||
|
|
||||||
|
/* Skip over the "before" guard page in returned address. */
|
||||||
|
dst += CONFIG_MMU_PAGE_SIZE;
|
||||||
|
|
||||||
VIRT_FOREACH(dst, size, pos) {
|
VIRT_FOREACH(dst, size, pos) {
|
||||||
ret = map_anon_page(pos, flags);
|
ret = map_anon_page(pos, flags);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue