diff options
Diffstat (limited to 'drivers/dax/dax.c')
| -rw-r--r-- | drivers/dax/dax.c | 33 | 
1 files changed, 30 insertions, 3 deletions
diff --git a/drivers/dax/dax.c b/drivers/dax/dax.c index 8d9829ff2a78..80c6db279ae1 100644 --- a/drivers/dax/dax.c +++ b/drivers/dax/dax.c @@ -427,6 +427,7 @@ static int __dax_dev_pte_fault(struct dax_dev *dax_dev, struct vm_fault *vmf)  	int rc = VM_FAULT_SIGBUS;  	phys_addr_t phys;  	pfn_t pfn; +	unsigned int fault_size = PAGE_SIZE;  	if (check_vma(dax_dev, vmf->vma, __func__))  		return VM_FAULT_SIGBUS; @@ -437,9 +438,12 @@ static int __dax_dev_pte_fault(struct dax_dev *dax_dev, struct vm_fault *vmf)  		return VM_FAULT_SIGBUS;  	} +	if (fault_size != dax_region->align) +		return VM_FAULT_SIGBUS; +  	phys = pgoff_to_phys(dax_dev, vmf->pgoff, PAGE_SIZE);  	if (phys == -1) { -		dev_dbg(dev, "%s: phys_to_pgoff(%#lx) failed\n", __func__, +		dev_dbg(dev, "%s: pgoff_to_phys(%#lx) failed\n", __func__,  				vmf->pgoff);  		return VM_FAULT_SIGBUS;  	} @@ -464,6 +468,7 @@ static int __dax_dev_pmd_fault(struct dax_dev *dax_dev, struct vm_fault *vmf)  	phys_addr_t phys;  	pgoff_t pgoff;  	pfn_t pfn; +	unsigned int fault_size = PMD_SIZE;  	if (check_vma(dax_dev, vmf->vma, __func__))  		return VM_FAULT_SIGBUS; @@ -480,10 +485,20 @@ static int __dax_dev_pmd_fault(struct dax_dev *dax_dev, struct vm_fault *vmf)  		return VM_FAULT_SIGBUS;  	} +	if (fault_size < dax_region->align) +		return VM_FAULT_SIGBUS; +	else if (fault_size > dax_region->align) +		return VM_FAULT_FALLBACK; + +	/* if we are outside of the VMA */ +	if (pmd_addr < vmf->vma->vm_start || +			(pmd_addr + PMD_SIZE) > vmf->vma->vm_end) +		return VM_FAULT_SIGBUS; +  	pgoff = linear_page_index(vmf->vma, pmd_addr);  	phys = pgoff_to_phys(dax_dev, pgoff, PMD_SIZE);  	if (phys == -1) { -		dev_dbg(dev, "%s: phys_to_pgoff(%#lx) failed\n", __func__, +		dev_dbg(dev, "%s: pgoff_to_phys(%#lx) failed\n", __func__,  				pgoff);  		return VM_FAULT_SIGBUS;  	} @@ -503,6 +518,8 @@ static int __dax_dev_pud_fault(struct dax_dev *dax_dev, struct vm_fault *vmf)  	phys_addr_t phys;  	pgoff_t pgoff;  	pfn_t pfn; +	unsigned int fault_size = PUD_SIZE; +  	if (check_vma(dax_dev, vmf->vma, __func__))  		return VM_FAULT_SIGBUS; @@ -519,10 +536,20 @@ static int __dax_dev_pud_fault(struct dax_dev *dax_dev, struct vm_fault *vmf)  		return VM_FAULT_SIGBUS;  	} +	if (fault_size < dax_region->align) +		return VM_FAULT_SIGBUS; +	else if (fault_size > dax_region->align) +		return VM_FAULT_FALLBACK; + +	/* if we are outside of the VMA */ +	if (pud_addr < vmf->vma->vm_start || +			(pud_addr + PUD_SIZE) > vmf->vma->vm_end) +		return VM_FAULT_SIGBUS; +  	pgoff = linear_page_index(vmf->vma, pud_addr);  	phys = pgoff_to_phys(dax_dev, pgoff, PUD_SIZE);  	if (phys == -1) { -		dev_dbg(dev, "%s: phys_to_pgoff(%#lx) failed\n", __func__, +		dev_dbg(dev, "%s: pgoff_to_phys(%#lx) failed\n", __func__,  				pgoff);  		return VM_FAULT_SIGBUS;  	}  | 
