Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mm: mmap: fix fput in error path v2

Patch "495c10cc1c0c CHROMIUM: dma-buf: restore args..."
adds a workaround for a bug in mmap_region.

As the comment states ->mmap() callback can change
vma->vm_file and so we might call fput() on the wrong file.

Revert the workaround and proper fix this in mmap_region.

v2: drop the extra if in dma_buf_mmap as well

Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Acked-by: Andrew Morton <akpm@linux-foundation.org>
Link: https://patchwork.freedesktop.org/patch/399359/

+4 -18
+3 -17
drivers/dma-buf/dma-buf.c
··· 1166 1166 int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma, 1167 1167 unsigned long pgoff) 1168 1168 { 1169 - struct file *oldfile; 1170 - int ret; 1171 - 1172 1169 if (WARN_ON(!dmabuf || !vma)) 1173 1170 return -EINVAL; 1174 1171 ··· 1183 1186 return -EINVAL; 1184 1187 1185 1188 /* readjust the vma */ 1186 - get_file(dmabuf->file); 1187 - oldfile = vma->vm_file; 1188 - vma->vm_file = dmabuf->file; 1189 + fput(vma->vm_file); 1190 + vma->vm_file = get_file(dmabuf->file); 1189 1191 vma->vm_pgoff = pgoff; 1190 1192 1191 - ret = dmabuf->ops->mmap(dmabuf, vma); 1192 - if (ret) { 1193 - /* restore old parameters on failure */ 1194 - vma->vm_file = oldfile; 1195 - fput(dmabuf->file); 1196 - } else { 1197 - if (oldfile) 1198 - fput(oldfile); 1199 - } 1200 - return ret; 1201 - 1193 + return dmabuf->ops->mmap(dmabuf, vma); 1202 1194 } 1203 1195 EXPORT_SYMBOL_GPL(dma_buf_mmap); 1204 1196
+1 -1
mm/mmap.c
··· 1899 1899 return addr; 1900 1900 1901 1901 unmap_and_free_vma: 1902 + fput(vma->vm_file); 1902 1903 vma->vm_file = NULL; 1903 - fput(file); 1904 1904 1905 1905 /* Undo any partial mapping done by a device driver. */ 1906 1906 unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end);