[PATCH v3 6/6] mm/mprotect: use huge_ptep_get() for hugetlb

Dev Jain dev.jain at arm.com
Sun Jul 5 01:47:39 PDT 2026



On 05/07/26 2:03 pm, Andrew Morton wrote:
> On Fri,  3 Jul 2026 11:41:59 +0000 Dev Jain <dev.jain at arm.com> wrote:
> 
>> prot_none_hugetlb_entry() is the hugetlb callback for the early
>> mprotect(PROT_NONE) PFN permission walk on x86.
>>
>> The callback passes the decoded PFN to pfn_modify_allowed(). For a
>> hugetlb callback, the pte pointer refers to a hugetlb entry. On
>> architectures where hugetlb entries need huge_ptep_get(), reading that
>> entry with ptep_get() can make the permission check use the wrong PFN.
>>
>> Use huge_ptep_get() before decoding the hugetlb PFN.
>>
>> Currently there is no path which can trigger a bug: huge_ptep_get() is a
>> simple ptep_get() for x86, and the prot_none walk occurs only for x86.
>>
>> So no need to backport - use the correct helper anyways.
>>
>> ...
>>
>> --- a/mm/mprotect.c
>> +++ b/mm/mprotect.c
>> @@ -699,14 +699,20 @@ static int prot_none_pte_entry(pte_t *pte, unsigned long addr,
>>  		0 : -EACCES;
>>  }
>>  
>> +#ifdef CONFIG_HUGETLB_PAGE
>>  static int prot_none_hugetlb_entry(pte_t *pte, unsigned long hmask,
>>  				   unsigned long addr, unsigned long next,
>>  				   struct mm_walk *walk)
>>  {
>> -	return pfn_modify_allowed(pte_pfn(ptep_get(pte)),
>> -				  *(pgprot_t *)(walk->private)) ?
>> -		0 : -EACCES;
>> +	const pte_t entry = huge_ptep_get(walk->mm, addr, pte);
>> +
>> +	if (pfn_modify_allowed(pte_pfn(entry), *(pgprot_t *)(walk->private)))
>> +		return 0;
>> +	return -EACCESS;
> 
> "EACCES".
> 
>>  }
>> +#else
>> +#define prot_none_hugetlb_entry	NULL
>> +#endif
> 
> Presumably your .config resulted in this change not being tested...

Thanks for folding in the fix!

On arm64, this entire path does not exist. The prot none pagewalk is
only done on x86. Also before sending patches I do an LLM review and
very surprisingly the "language" model did not catch a language issue ...

On the other thing by Sashiko, that looks wrong. There are existing
huge_ptep_get callers not taking the lock. And, there won't be a torn
read because we are using __ptep_get() instead of *ptep.





More information about the linux-arm-kernel mailing list