mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 10:00:17 +00:00
sparc64: Use arch_validate_flags() to validate ADI flag
[ Upstream commit147d8622f2] When userspace calls mprotect() to enable ADI on an address range, do_mprotect_pkey() calls arch_validate_prot() to validate new protection flags. arch_validate_prot() for sparc looks at the first VMA associated with address range to verify if ADI can indeed be enabled on this address range. This has two issues - (1) Address range might cover multiple VMAs while arch_validate_prot() looks at only the first VMA, (2) arch_validate_prot() peeks at VMA without holding mmap lock which can result in race condition. arch_validate_flags() from commitc462ac288f("mm: Introduce arch_validate_flags()") allows for VMA flags to be validated for all VMAs that cover the address range given by user while holding mmap lock. This patch updates sparc code to move the VMA check from arch_validate_prot() to arch_validate_flags() to fix above two issues. Suggested-by: Jann Horn <jannh@google.com> Suggested-by: Christoph Hellwig <hch@infradead.org> Suggested-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Khalid Aziz <khalid.aziz@oracle.com> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
99ed6ae4d0
commit
f27af42b1f
@@ -57,20 +57,26 @@ static inline int sparc_validate_prot(unsigned long prot, unsigned long addr)
|
|||||||
{
|
{
|
||||||
if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM | PROT_ADI))
|
if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM | PROT_ADI))
|
||||||
return 0;
|
return 0;
|
||||||
if (prot & PROT_ADI) {
|
return 1;
|
||||||
if (!adi_capable())
|
}
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (addr) {
|
#define arch_validate_flags(vm_flags) arch_validate_flags(vm_flags)
|
||||||
struct vm_area_struct *vma;
|
/* arch_validate_flags() - Ensure combination of flags is valid for a
|
||||||
|
* VMA.
|
||||||
vma = find_vma(current->mm, addr);
|
|
||||||
if (vma) {
|
|
||||||
/* ADI can not be enabled on PFN
|
|
||||||
* mapped pages
|
|
||||||
*/
|
*/
|
||||||
if (vma->vm_flags & (VM_PFNMAP | VM_MIXEDMAP))
|
static inline bool arch_validate_flags(unsigned long vm_flags)
|
||||||
return 0;
|
{
|
||||||
|
/* If ADI is being enabled on this VMA, check for ADI
|
||||||
|
* capability on the platform and ensure VMA is suitable
|
||||||
|
* for ADI
|
||||||
|
*/
|
||||||
|
if (vm_flags & VM_SPARC_ADI) {
|
||||||
|
if (!adi_capable())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* ADI can not be enabled on PFN mapped pages */
|
||||||
|
if (vm_flags & (VM_PFNMAP | VM_MIXEDMAP))
|
||||||
|
return false;
|
||||||
|
|
||||||
/* Mergeable pages can become unmergeable
|
/* Mergeable pages can become unmergeable
|
||||||
* if ADI is enabled on them even if they
|
* if ADI is enabled on them even if they
|
||||||
@@ -80,12 +86,10 @@ static inline int sparc_validate_prot(unsigned long prot, unsigned long addr)
|
|||||||
* tags on them. Disallow ADI on mergeable
|
* tags on them. Disallow ADI on mergeable
|
||||||
* pages.
|
* pages.
|
||||||
*/
|
*/
|
||||||
if (vma->vm_flags & VM_MERGEABLE)
|
if (vm_flags & VM_MERGEABLE)
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
return true;
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_SPARC64 */
|
#endif /* CONFIG_SPARC64 */
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user