diff options
author | Andrew Morton <akpm@linux-foundation.org> | 2009-01-06 17:43:08 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-06 18:59:30 -0500 |
commit | 0bef3c2dc7d0c8238330785c8f4504761b0e370b (patch) | |
tree | f43e7c7e49f5e67823e7e077c821e8f8d2571e48 /kernel | |
parent | 8375d4909aee4c18798f373ecf24a79f040f75fc (diff) |
dma_alloc_from_coherent(): fix fallback to generic memory
If bitmap_find_free_region() fails and DMA_MEMORY_EXCLUSIVE is not set,
the function will fail to write anything to *ret and will return 1. This will cause dma_alloc_coherent() to return an uninitialised value,
crashing the kernel, perhaps via DMA to a random address.
Fix that by changing it to return zero in this case, so the caller will
proceed to allocate the memory from the generic memory allocator.
Cc: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>
Cc: Dmitry Baryshkov <dbaryshkov@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/dma-coherent.c | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/kernel/dma-coherent.c b/kernel/dma-coherent.c index f013a0c2e111..4bdcea822b45 100644 --- a/kernel/dma-coherent.c +++ b/kernel/dma-coherent.c | |||
@@ -116,11 +116,25 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size, | |||
116 | int page = bitmap_find_free_region(mem->bitmap, mem->size, | 116 | int page = bitmap_find_free_region(mem->bitmap, mem->size, |
117 | order); | 117 | order); |
118 | if (page >= 0) { | 118 | if (page >= 0) { |
119 | /* | ||
120 | * Memory was found in the per-device arena. | ||
121 | */ | ||
119 | *dma_handle = mem->device_base + (page << PAGE_SHIFT); | 122 | *dma_handle = mem->device_base + (page << PAGE_SHIFT); |
120 | *ret = mem->virt_base + (page << PAGE_SHIFT); | 123 | *ret = mem->virt_base + (page << PAGE_SHIFT); |
121 | memset(*ret, 0, size); | 124 | memset(*ret, 0, size); |
122 | } else if (mem->flags & DMA_MEMORY_EXCLUSIVE) | 125 | } else if (mem->flags & DMA_MEMORY_EXCLUSIVE) { |
126 | /* | ||
127 | * The per-device arena is exhausted and we are not | ||
128 | * permitted to fall back to generic memory. | ||
129 | */ | ||
123 | *ret = NULL; | 130 | *ret = NULL; |
131 | } else { | ||
132 | /* | ||
133 | * The per-device arena is exhausted and we are | ||
134 | * permitted to fall back to generic memory. | ||
135 | */ | ||
136 | return 0; | ||
137 | } | ||
124 | } | 138 | } |
125 | return (mem != NULL); | 139 | return (mem != NULL); |
126 | } | 140 | } |