mirror of
https://github.com/opnsense/src.git
synced 2026-06-05 06:42:56 -04:00
linuxkpi: Handle direct-mapped addresses in linux_free_kmem()
See the analysis in PR 271333. It is possible for driver code to allocate a page, store its address as returned by page_address(), then call free_page() on that address. On most systems that'll result in the LinuxKPI calling kmem_free() with a direct-mapped address, which is not legal. Fix the problem by making linux_free_kmem() check the address to see whether it's direct-mapped or not, and handling it appropriately. PR: 271333, 274515 Reviewed by: hselasky, bz Tested by: trasz MFC after: 1 week Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D40028
This commit is contained in:
parent
56279238b0
commit
6223d0b67a
1 changed files with 19 additions and 3 deletions
|
|
@ -145,6 +145,14 @@ linux_alloc_pages(gfp_t flags, unsigned int order)
|
|||
return (page);
|
||||
}
|
||||
|
||||
static void
|
||||
_linux_free_kmem(vm_offset_t addr, unsigned int order)
|
||||
{
|
||||
size_t size = ((size_t)PAGE_SIZE) << order;
|
||||
|
||||
kmem_free((void *)addr, size);
|
||||
}
|
||||
|
||||
void
|
||||
linux_free_pages(struct page *page, unsigned int order)
|
||||
{
|
||||
|
|
@ -163,7 +171,7 @@ linux_free_pages(struct page *page, unsigned int order)
|
|||
|
||||
vaddr = (vm_offset_t)page_address(page);
|
||||
|
||||
linux_free_kmem(vaddr, order);
|
||||
_linux_free_kmem(vaddr, order);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -185,9 +193,17 @@ linux_alloc_kmem(gfp_t flags, unsigned int order)
|
|||
void
|
||||
linux_free_kmem(vm_offset_t addr, unsigned int order)
|
||||
{
|
||||
size_t size = ((size_t)PAGE_SIZE) << order;
|
||||
KASSERT((addr & PAGE_MASK) == 0,
|
||||
("%s: addr %p is not page aligned", __func__, (void *)addr));
|
||||
|
||||
kmem_free((void *)addr, size);
|
||||
if (addr >= VM_MIN_KERNEL_ADDRESS && addr < VM_MAX_KERNEL_ADDRESS) {
|
||||
_linux_free_kmem(addr, order);
|
||||
} else {
|
||||
vm_page_t page;
|
||||
|
||||
page = PHYS_TO_VM_PAGE(DMAP_TO_PHYS(addr));
|
||||
linux_free_pages(page, order);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
|||
Loading…
Reference in a new issue