mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-16 22:10:24 +00:00
dma-api: Teach the "DMA-from-stack" check about vmapped stacks
If we're using CONFIG_VMAP_STACK=y and we manage to point an sg entry at the stack, then either the sg page will be in highmem or sg_virt() will return the direct-map alias. In neither case will the existing check_for_stack() implementation realize that it's a stack page. Fix it by explicitly checking for stack pages. This has no effect by itself. It's broken out for ease of review. Signed-off-by: Andy Lutomirski <luto@kernel.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/448460622731312298bf19dcbacb1606e75de7a9.1470907718.git.luto@kernel.org [ Minor edits. ] Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
parent
ba14a194a4
commit
b4a0f533e5
@ -22,6 +22,7 @@
|
||||
#include <linux/stacktrace.h>
|
||||
#include <linux/dma-debug.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/export.h>
|
||||
@ -1164,11 +1165,32 @@ static void check_unmap(struct dma_debug_entry *ref)
|
||||
put_hash_bucket(bucket, &flags);
|
||||
}
|
||||
|
||||
static void check_for_stack(struct device *dev, void *addr)
|
||||
static void check_for_stack(struct device *dev,
|
||||
struct page *page, size_t offset)
|
||||
{
|
||||
if (object_is_on_stack(addr))
|
||||
err_printk(dev, NULL, "DMA-API: device driver maps memory from "
|
||||
"stack [addr=%p]\n", addr);
|
||||
void *addr;
|
||||
struct vm_struct *stack_vm_area = task_stack_vm_area(current);
|
||||
|
||||
if (!stack_vm_area) {
|
||||
/* Stack is direct-mapped. */
|
||||
if (PageHighMem(page))
|
||||
return;
|
||||
addr = page_address(page) + offset;
|
||||
if (object_is_on_stack(addr))
|
||||
err_printk(dev, NULL, "DMA-API: device driver maps memory from stack [addr=%p]\n", addr);
|
||||
} else {
|
||||
/* Stack is vmalloced. */
|
||||
int i;
|
||||
|
||||
for (i = 0; i < stack_vm_area->nr_pages; i++) {
|
||||
if (page != stack_vm_area->pages[i])
|
||||
continue;
|
||||
|
||||
addr = (u8 *)current->stack + i * PAGE_SIZE + offset;
|
||||
err_printk(dev, NULL, "DMA-API: device driver maps memory from stack [probable addr=%p]\n", addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool overlap(void *addr, unsigned long len, void *start, void *end)
|
||||
@ -1291,10 +1313,11 @@ void debug_dma_map_page(struct device *dev, struct page *page, size_t offset,
|
||||
if (map_single)
|
||||
entry->type = dma_debug_single;
|
||||
|
||||
check_for_stack(dev, page, offset);
|
||||
|
||||
if (!PageHighMem(page)) {
|
||||
void *addr = page_address(page) + offset;
|
||||
|
||||
check_for_stack(dev, addr);
|
||||
check_for_illegal_area(dev, addr, size);
|
||||
}
|
||||
|
||||
@ -1386,8 +1409,9 @@ void debug_dma_map_sg(struct device *dev, struct scatterlist *sg,
|
||||
entry->sg_call_ents = nents;
|
||||
entry->sg_mapped_ents = mapped_ents;
|
||||
|
||||
check_for_stack(dev, sg_page(s), s->offset);
|
||||
|
||||
if (!PageHighMem(sg_page(s))) {
|
||||
check_for_stack(dev, sg_virt(s));
|
||||
check_for_illegal_area(dev, sg_virt(s), sg_dma_len(s));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user