|
@@ -256,8 +256,20 @@ again:
|
|
|
__xip_unmap(mapping, vmf->pgoff);
|
|
__xip_unmap(mapping, vmf->pgoff);
|
|
|
|
|
|
|
|
found:
|
|
found:
|
|
|
|
|
+ /*
|
|
|
|
|
+ * We must recheck i_size under i_mmap_rwsem to prevent races
|
|
|
|
|
+ * with truncation
|
|
|
|
|
+ */
|
|
|
|
|
+ i_mmap_lock_read(mapping);
|
|
|
|
|
+ size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
|
|
|
|
|
+ PAGE_CACHE_SHIFT;
|
|
|
|
|
+ if (unlikely(vmf->pgoff >= size)) {
|
|
|
|
|
+ i_mmap_unlock_read(mapping);
|
|
|
|
|
+ return VM_FAULT_SIGBUS;
|
|
|
|
|
+ }
|
|
|
err = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address,
|
|
err = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address,
|
|
|
xip_pfn);
|
|
xip_pfn);
|
|
|
|
|
+ i_mmap_unlock_read(mapping);
|
|
|
if (err == -ENOMEM)
|
|
if (err == -ENOMEM)
|
|
|
return VM_FAULT_OOM;
|
|
return VM_FAULT_OOM;
|
|
|
/*
|
|
/*
|
|
@@ -281,16 +293,30 @@ found:
|
|
|
}
|
|
}
|
|
|
if (error != -ENODATA)
|
|
if (error != -ENODATA)
|
|
|
goto out;
|
|
goto out;
|
|
|
|
|
+
|
|
|
|
|
+ /*
|
|
|
|
|
+ * We must recheck i_size under i_mmap_rwsem to prevent races
|
|
|
|
|
+ * with truncation
|
|
|
|
|
+ */
|
|
|
|
|
+ i_mmap_lock_read(mapping);
|
|
|
|
|
+ size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
|
|
|
|
|
+ PAGE_CACHE_SHIFT;
|
|
|
|
|
+ if (unlikely(vmf->pgoff >= size)) {
|
|
|
|
|
+ ret = VM_FAULT_SIGBUS;
|
|
|
|
|
+ goto unlock;
|
|
|
|
|
+ }
|
|
|
/* not shared and writable, use xip_sparse_page() */
|
|
/* not shared and writable, use xip_sparse_page() */
|
|
|
page = xip_sparse_page();
|
|
page = xip_sparse_page();
|
|
|
if (!page)
|
|
if (!page)
|
|
|
- goto out;
|
|
|
|
|
|
|
+ goto unlock;
|
|
|
err = vm_insert_page(vma, (unsigned long)vmf->virtual_address,
|
|
err = vm_insert_page(vma, (unsigned long)vmf->virtual_address,
|
|
|
page);
|
|
page);
|
|
|
if (err == -ENOMEM)
|
|
if (err == -ENOMEM)
|
|
|
- goto out;
|
|
|
|
|
|
|
+ goto unlock;
|
|
|
|
|
|
|
|
ret = VM_FAULT_NOPAGE;
|
|
ret = VM_FAULT_NOPAGE;
|
|
|
|
|
+unlock:
|
|
|
|
|
+ i_mmap_unlock_read(mapping);
|
|
|
out:
|
|
out:
|
|
|
write_seqcount_end(&xip_sparse_seq);
|
|
write_seqcount_end(&xip_sparse_seq);
|
|
|
mutex_unlock(&xip_sparse_mutex);
|
|
mutex_unlock(&xip_sparse_mutex);
|