Skip to content

Commit fcf8dda

Browse files
Dev Jainwilldeacon
authored andcommitted
arm64: pageattr: Explicitly bail out when changing permissions for vmalloc_huge mappings
arm64 uses apply_to_page_range to change permissions for kernel vmalloc mappings, which does not support changing permissions for block mappings. This function will change permissions until it encounters a block mapping, and will bail out with a warning. Since there are no reports of this triggering, it implies that there are currently no cases of code doing a vmalloc_huge() followed by partial permission change. But this is a footgun waiting to go off, so let's detect it early and avoid the possibility of permissions in an intermediate state. So, explicitly disallow changing permissions for VM_ALLOW_HUGE_VMAP mappings. Reviewed-by: Ryan Roberts <[email protected]> Reviewed-by: Mike Rapoport (Microsoft) <[email protected]> Signed-off-by: Dev Jain <[email protected]> Acked-by: David Hildenbrand <[email protected]> Reviewed-by: Gavin Shan <[email protected]> Reviewed-by: Anshuman Khandual <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent f101c56 commit fcf8dda

File tree

1 file changed

+3
-3
lines changed

1 file changed

+3
-3
lines changed

arch/arm64/mm/pageattr.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,16 +96,16 @@ static int change_memory_common(unsigned long addr, int numpages,
9696
* we are operating on does not result in such splitting.
9797
*
9898
* Let's restrict ourselves to mappings created by vmalloc (or vmap).
99-
* Those are guaranteed to consist entirely of page mappings, and
100-
* splitting is never needed.
99+
* Disallow VM_ALLOW_HUGE_VMAP mappings to guarantee that only page
100+
* mappings are updated and splitting is never needed.
101101
*
102102
* So check whether the [addr, addr + size) interval is entirely
103103
* covered by precisely one VM area that has the VM_ALLOC flag set.
104104
*/
105105
area = find_vm_area((void *)addr);
106106
if (!area ||
107107
end > (unsigned long)kasan_reset_tag(area->addr) + area->size ||
108-
!(area->flags & VM_ALLOC))
108+
((area->flags & (VM_ALLOC | VM_ALLOW_HUGE_VMAP)) != VM_ALLOC))
109109
return -EINVAL;
110110

111111
if (!numpages)

0 commit comments

Comments
 (0)