mirror of
https://github.com/hardkernel/linux.git
synced 2026-03-26 12:30:23 +09:00
ANDROID: dma-buf: Don't change vm_ops if vm_file changes
When CONFIG_DMABUF_SYSFS_STATS=y, dma_buf_do_mmap() will call a dma-bufs mmap() callback before overriding the open() and close() callbacks for the dma-buf's vm_operations_stuct, such that dma_buf_vma_open() and dma_buf_vma_close() are used instead. Each of the two aforementioend callbacks assumes that the vma->vm_file pointer they use points to a dma-buf file. However, it is possible that during the invocation of the dma-buf's mmap() callback, that the vma->vm_file pointer changes to store something other than a dma-buf file (it is permissible to do this so long as certain conditions are met, see the callsite of call_mmap in mm/mmap.c as of commita2e00b4b5d("FROMGIT: mm/slub: add taint after the errors are printed"). This means that when dma_buf_vma_open() and dma_buf_vma_close() run, that their accesses to vma->vm_file will cease to be semantically valid. Accordingly, only override the open() and close() vm_operations_struct callbacks if a dma-buf's mmap() callback preserves the vma->vm_file across the mmap() callback. Bug: 191742286 Fixes:9132fbe545("ANDROID: dmabuf: Add mmap_count to struct dmabuf") Signed-off-by: Chris Goldsworthy <quic_cgoldswo@quicinc.com> Change-Id: I4f80ade7f0bc85e2cb9219478550dcb6bbb29f3e
This commit is contained in:
@@ -173,12 +173,17 @@ static void dma_buf_vma_close(struct vm_area_struct *vma)
|
||||
|
||||
static int dma_buf_do_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
|
||||
{
|
||||
/* call this first because the exporter might override vma->vm_ops */
|
||||
int ret = dmabuf->ops->mmap(dmabuf, vma);
|
||||
int ret;
|
||||
struct file *orig_vm_file = vma->vm_file;
|
||||
|
||||
/* call this first because the exporter might override vma->vm_ops */
|
||||
ret = dmabuf->ops->mmap(dmabuf, vma);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (orig_vm_file != vma->vm_file)
|
||||
return 0;
|
||||
|
||||
/* save the exporter provided vm_ops */
|
||||
dmabuf->exp_vm_ops = vma->vm_ops;
|
||||
dmabuf->vm_ops = *(dmabuf->exp_vm_ops);
|
||||
|
||||
Reference in New Issue
Block a user