diff --git a/mm/ashmem.c b/mm/ashmem.c index bc977ee9fc9..e4aab56f10f 100644 --- a/mm/ashmem.c +++ b/mm/ashmem.c @@ -673,10 +673,28 @@ static int ashmem_cache_op(struct ashmem_area *asma, void (*cache_func)(unsigned long vstart, unsigned long length, unsigned long pstart)) { + int ret = 0; + struct vm_area_struct *vma; #ifdef CONFIG_OUTER_CACHE unsigned long vaddr; #endif - mutex_lock(&ashmem_mutex); + if (!asma->vm_start) + return -EINVAL; + + down_read(¤t->mm->mmap_sem); + vma = find_vma(current->mm, asma->vm_start); + if (!vma) { + ret = -EINVAL; + goto done; + } + if (vma->vm_file != asma->file) { + ret = -EINVAL; + goto done; + } + if ((asma->vm_start + asma->size) > (vma->vm_start + vma->vm_end)) { + ret = -EINVAL; + goto done; + } #ifndef CONFIG_OUTER_CACHE cache_func(asma->vm_start, asma->size, 0); #else @@ -689,8 +707,11 @@ static int ashmem_cache_op(struct ashmem_area *asma, cache_func(vaddr, PAGE_SIZE, physaddr); } #endif - mutex_unlock(&ashmem_mutex); - return 0; +done: + up_read(¤t->mm->mmap_sem); + if (ret) + asma->vm_start = 0; + return ret; } static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)