path: root/include
diff options
authorHans Verkuil <hans.verkuil@tandberg.com>2010-09-07 06:10:45 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-09-27 22:22:01 -0300
commit2fc11536cf5c0b8eb4eb7e01a2a672a189e9280f (patch)
treef36f0250089dbed08779550f02f78613364bc787 /include
parentc10469c637602c2385e2993d8c730cc44fd47d23 (diff)
V4L/DVB: videobuf-dma-sg: set correct size in last sg element
This fixes a nasty memory corruption bug when using userptr I/O. The function videobuf_pages_to_sg() sets up the scatter-gather list for the DMA transfer to the userspace pages. The first transfer is setup correctly (the size is set to PAGE_SIZE - offset), but all other transfers have size PAGE_SIZE. This is wrong for the last transfer which may be less than PAGE_SIZE. Most, if not all, drivers will program the boards DMA engine correctly, i.e. even though the size in the last sg element is wrong, they will do their own size calculations and make sure the right amount is DMA-ed, and so seemingly prevent memory corruption. However, behind the scenes the dynamic DMA mapping support (in lib/swiotlb.c) may create bounce buffers if the memory pages are not in DMA-able memory. This happens for example on a 64-bit linux with a board that only supports 32-bit DMA. These bounce buffers DO use the information in the sg list to determine the size. So while the DMA engine transfers the correct amount of data, when the data is 'bounced' back too much is copied, causing buffer overwrites. The fix is simple: calculate and set the correct size for the last sg list element. Signed-off-by: Hans Verkuil <hans.verkuil@tandberg.com> Cc: stable@kernel.org Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'include')
1 files changed, 1 insertions, 0 deletions
diff --git a/include/media/videobuf-dma-sg.h b/include/media/videobuf-dma-sg.h
index 97e07f46a0fa..aa4ebb42a565 100644
--- a/include/media/videobuf-dma-sg.h
+++ b/include/media/videobuf-dma-sg.h
@@ -48,6 +48,7 @@ struct videobuf_dmabuf {
/* for userland buffer */
int offset;
+ size_t size;
struct page **pages;
/* for kernel buffers */

Privacy Policy