Skip to content

Commit 01d3575

Browse files
mm: add sys_mm_drv_map_* functions with region check
the commit adds sys_mm_drv_map_page_safe and sys_mm_drv_map_region_safe functions, wrappers for sys_mm_drv_map_region and sys_mm_drv_map_region, with additional check if a mapped region fits into given memory range Using of those prevents collisions and/or hijacking of virtual memory Signed-off-by: Marcin Szkudlinski <[email protected]>
1 parent 3d461ee commit 01d3575

File tree

2 files changed

+68
-12
lines changed

2 files changed

+68
-12
lines changed

drivers/mm/mm_drv_common.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,37 @@
2929

3030
struct k_spinlock sys_mm_drv_common_lock;
3131

32+
int sys_mm_drv_map_region_safe(const struct sys_mm_drv_region *virtual_region,
33+
void *virt, uintptr_t phys, size_t size,
34+
uint32_t flags)
35+
{
36+
uintptr_t virtual_region_start = POINTER_TO_UINT(virtual_region->addr);
37+
uintptr_t virtual_region_end = virtual_region_start + virtual_region->size;
38+
39+
/* check if memory to be mapped is within given virtual region */
40+
if ((POINTER_TO_UINT(virt) >= virtual_region_start) &&
41+
(POINTER_TO_UINT(virt) + size < virtual_region_end)) {
42+
return sys_mm_drv_map_region(virt, phys, size, flags);
43+
}
44+
45+
return -EINVAL;
46+
}
47+
48+
int sys_mm_drv_map_page_safe(const struct sys_mm_drv_region *virtual_region,
49+
void *virt, uintptr_t phys, uint32_t flags)
50+
{
51+
uintptr_t virtual_region_start = POINTER_TO_UINT(virtual_region->addr);
52+
uintptr_t virtual_region_end = virtual_region_start + virtual_region->size;
53+
54+
/* check if memory to be mapped is within given virtual region */
55+
if ((POINTER_TO_UINT(virt) >= virtual_region_start) &&
56+
(POINTER_TO_UINT(virt) + CONFIG_MM_DRV_PAGE_SIZE < virtual_region_end)) {
57+
return sys_mm_drv_map_page(virt, phys, flags);
58+
}
59+
60+
return -EINVAL;
61+
}
62+
3263
bool sys_mm_drv_is_addr_array_aligned(uintptr_t *addr, size_t cnt)
3364
{
3465
size_t idx;

include/zephyr/drivers/mm/system_mm.h

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,18 @@ extern "C" {
5454
/** Reserved bits for cache modes */
5555
#define SYS_MM_MEM_CACHE_MASK (BIT(3) - 1)
5656

57+
/**
58+
* @brief Represents an available memory region.
59+
*
60+
* A memory region that can be used by allocators. Driver defined
61+
* attributes can be used to guide the proper usage of each region.
62+
*/
63+
struct sys_mm_drv_region {
64+
void *addr; /**< @brief Address of the memory region */
65+
size_t size; /**< @brief Size of the memory region */
66+
uint32_t attr; /**< @brief Driver defined attributes of the memory region */
67+
};
68+
5769
/**
5870
* @}
5971
*/
@@ -109,6 +121,18 @@ extern "C" {
109121
*/
110122
int sys_mm_drv_map_page(void *virt, uintptr_t phys, uint32_t flags);
111123

124+
/**
125+
* @brief Map one physical page into the virtual address space with region check
126+
*
127+
* This maps one physical page into the virtual address space by calling
128+
* sys_mm_drv_map_page. Refer to sys_mm_drv_map_page for references
129+
*
130+
* Before call it performs a safety check by verifying if the mapped virtual memory page
131+
* fits into a given virtual region
132+
*/
133+
int sys_mm_drv_map_page_safe(const struct sys_mm_drv_region *virtual_region,
134+
void *virt, uintptr_t phys, uint32_t flags);
135+
112136
/**
113137
* @brief Map a region of physical memory into the virtual address space
114138
*
@@ -133,6 +157,19 @@ int sys_mm_drv_map_page(void *virt, uintptr_t phys, uint32_t flags);
133157
int sys_mm_drv_map_region(void *virt, uintptr_t phys,
134158
size_t size, uint32_t flags);
135159

160+
/**
161+
* @brief Map a region of physical memory into the virtual address space with region check
162+
*
163+
* This maps a region of physical memory into the virtual address space by calling
164+
* sys_mm_drv_map_region. Refer to sys_mm_drv_map_region for references
165+
*
166+
* Before call it performs a safety check by verifying if the mapped virtual memory pages
167+
* fit into a given virtual region
168+
*/
169+
int sys_mm_drv_map_region_safe(const struct sys_mm_drv_region *virtual_region,
170+
void *virt, uintptr_t phys, size_t size,
171+
uint32_t flags);
172+
136173
/**
137174
* @brief Map an array of physical memory into the virtual address space
138175
*
@@ -402,18 +439,6 @@ int sys_mm_drv_update_region_flags(void *virt, size_t size, uint32_t flags);
402439
*/
403440
int sys_mm_drv_page_phys_get(void *virt, uintptr_t *phys);
404441

405-
/**
406-
* @brief Represents an available memory region.
407-
*
408-
* A memory region that can be used by allocators. Driver defined
409-
* attributes can be used to guide the proper usage of each region.
410-
*/
411-
struct sys_mm_drv_region {
412-
void *addr; /**< @brief Address of the memory region */
413-
size_t size; /**< @brief Size of the memory region */
414-
uint32_t attr; /**< @brief Driver defined attributes of the memory region */
415-
};
416-
417442
/* TODO is it safe to assume no valid region has size == 0? */
418443
/**
419444
* @brief Iterates over an array of regions returned by #sys_mm_drv_query_memory_regions

0 commit comments

Comments
 (0)