arm64: pageattr: Explicitly bail out when changing permissions for vmalloc_huge mappings
PATCH v2 1/1 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.
---v1->v2:
- Improve changelog, keep mention of page mappings in comment
arch/arm64/mm/pageattr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
arch/arm64/mm/pageattr.c +3 -3
@@ -96,8 +96,8 @@ static int change_memory_common(unsigned long addr, int numpages,* we are operating on does not result in such splitting. * * Let's restrict ourselves to mappings created by vmalloc (or vmap). -* Those are guaranteed to consist entirely of page mappings, and -* splitting is never needed. +* Disallow VM_ALLOW_HUGE_VMAP mappings to guarantee that only page +* mappings are updated and splitting is never needed. * * So check whether the [addr, addr + size) interval is entirely * covered by precisely one VM area that has the VM_ALLOC flag set.
@@ -105,7 +105,7 @@ static int change_memory_common(unsigned long addr, int numpages, area =find_vm_area ((void *)addr);if (!area || end > (unsigned long )kasan_reset_tag (area->addr) + area->size || - !(area->flags &VM_ALLOC )) + ((area->flags & (VM_ALLOC |VM_ALLOW_HUGE_VMAP )) !=VM_ALLOC ))return -EINVAL ;if (!numpages)
Signature · 1 line
2.30.2
Quoted 36 lines · Dev Jain
arm64 uses
apply_to_page_rangeto 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 avmalloc_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 forVM_ALLOW_HUGE_VMAPmappings.Reviewed-by Ryan Roberts <[email protected]>Reviewed-by Mike Rapoport (Microsoft) <[email protected]>Signed-off-by Dev Jain <[email protected]>---
v1->v2:
- Improve changelog, keep mention of page mappings in commentarch/arm64/mm/pageattr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)arch/arm64/mm/pageattr.c +2
-2@@ -96,8 +96,8 @@ static int change_memory_common(unsigned long addr, int numpages,* we are operating on does not result in such splitting. * * Let's restrict ourselves to mappings created by vmalloc (or vmap). -* Those are guaranteed to consist entirely of page mappings, and -* splitting is never needed. +* Disallow VM_ALLOW_HUGE_VMAP mappings to guarantee that only page +* mappings are updated and splitting is never needed. * * So check whether the [addr, addr + size) interval is entirely * covered by precisely one VM area that has the VM_ALLOC flag set.
arch/arm64/mm/pageattr.c static int change_memory_common(unsigned long addr, int numpages, · line 111
Quoted 8 lines
arch/arm64/mm/pageattr.c +1
-1@@ -105,7 +105,7 @@ static int change_memory_common(unsigned long addr, int numpages, area =find_vm_area ((void *)addr);if (!area || end > (unsigned long )kasan_reset_tag (area->addr) + area->size || - !(area->flags &VM_ALLOC )) + ((area->flags & (VM_ALLOC |VM_ALLOW_HUGE_VMAP )) !=VM_ALLOC ))return -EINVAL ;if (!numpages)
LGTM
Quoted 13 lines · Dev Jain
arm64 uses
apply_to_page_rangeto 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 avmalloc_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 forVM_ALLOW_HUGE_VMAPmappings.Reviewed-by Ryan Roberts <[email protected]>Reviewed-by Mike Rapoport (Microsoft) <[email protected]>Signed-off-by Dev Jain <[email protected]>
Quoted 7 lines
---
v1->v2:
- Improve changelog, keep mention of page mappings in commentarch/arm64/mm/pageattr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
Quoted 36 lines · Dev Jain
arm64 uses
apply_to_page_rangeto 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 avmalloc_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 forVM_ALLOW_HUGE_VMAPmappings.Reviewed-by Ryan Roberts <[email protected]>Reviewed-by Mike Rapoport (Microsoft) <[email protected]>Signed-off-by Dev Jain <[email protected]>---
v1->v2:
- Improve changelog, keep mention of page mappings in commentarch/arm64/mm/pageattr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)arch/arm64/mm/pageattr.c +2
-2@@ -96,8 +96,8 @@ static int change_memory_common(unsigned long addr, int numpages,* we are operating on does not result in such splitting. * * Let's restrict ourselves to mappings created by vmalloc (or vmap). -* Those are guaranteed to consist entirely of page mappings, and -* splitting is never needed. +* Disallow VM_ALLOW_HUGE_VMAP mappings to guarantee that only page +* mappings are updated and splitting is never needed. * * So check whether the [addr, addr + size) interval is entirely * covered by precisely one VM area that has the VM_ALLOC flag set.
arch/arm64/mm/pageattr.c static int change_memory_common(unsigned long addr, int numpages, · line 111
Quoted 8 lines
arch/arm64/mm/pageattr.c +1
-1@@ -105,7 +105,7 @@ static int change_memory_common(unsigned long addr, int numpages, area =find_vm_area ((void *)addr);if (!area || end > (unsigned long )kasan_reset_tag (area->addr) + area->size || - !(area->flags &VM_ALLOC )) + ((area->flags & (VM_ALLOC |VM_ALLOW_HUGE_VMAP )) !=VM_ALLOC ))return -EINVAL ;if (!numpages)
Makes sense to me. Whenever required, we can improve the checks (or even try supporting splitting).
Signature · 3 lines
Cheers, David / dhildenb
Quoted 41 lines · David Hildenbrand
Quoted 40 lines · Dev Jain
arm64 uses
apply_to_page_rangeto 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 avmalloc_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 forVM_ALLOW_HUGE_VMAPmappings.Reviewed-by Ryan Roberts <[email protected]>Reviewed-by Mike Rapoport (Microsoft) <[email protected]>Signed-off-by Dev Jain <[email protected]>---
v1->v2:
- Improve changelog, keep mention of page mappings in comment
arch/arm64/mm/pageattr.c| 6 +++---1 file changed, 3 insertions(+), 3 deletions(-)arch/arm64/mm/pageattr.c +2
-2@@ -96,8 +96,8 @@ static int change_memory_common(unsigned long addr, int numpages, * we are operating on does not result in such splitting. * * Let's restrict ourselves to mappings created by vmalloc (or vmap). - * Those are guaranteed to consist entirely of page mappings, and - * splitting is never needed. + * Disallow VM_ALLOW_HUGE_VMAP mappings to guarantee that only page + * mappings are updated and splitting is never needed. * * So check whether the [addr, addr + size) interval is entirely* covered by precisely one VM area that has the
VM_ALLOCflag set.arch/arm64/mm/pageattr.c +0
-0@@ -105,7 +105,7 @@ static int change_memory_common(unsigned long addr, int numpages, area = find_vm_area((void *)addr);if (!area ||
Quoted 8 lines
Quoted 5 lines
end > (unsigned long)kasan_reset_tag(area->addr) +
area->size|| - !(area->flags &VM_ALLOC))
+ ((area->flags& (VM_ALLOC|VM_ALLOW_HUGE_VMAP)) !=VM_ALLOC)) return-EINVAL;
if (!numpages)Makes sense to me. Whenever required, we can improve the checks (or even try supporting splitting).
Yes that's the plan; I'd like to get to the point where we can do huge vmalloc mappings by default on systems that support BBML2, then split mappings when needed.
Quoted 3 lines
Gentle Ping
Quoted 44 lines · Dev Jain
arm64 uses
apply_to_page_rangeto 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 avmalloc_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 forVM_ALLOW_HUGE_VMAPmappings.Reviewed-by Ryan Roberts <[email protected]>Reviewed-by Mike Rapoport (Microsoft) <[email protected]>Signed-off-by Dev Jain <[email protected]>---
v1->v2:
- Improve changelog, keep mention of page mappings in commentarch/arm64/mm/pageattr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)arch/arm64/mm/pageattr.c +3
-3@@ -96,8 +96,8 @@ static int change_memory_common(unsigned long addr, int numpages,* we are operating on does not result in such splitting. * * Let's restrict ourselves to mappings created by vmalloc (or vmap). -* Those are guaranteed to consist entirely of page mappings, and -* splitting is never needed. +* Disallow VM_ALLOW_HUGE_VMAP mappings to guarantee that only page +* mappings are updated and splitting is never needed. * * So check whether the [addr, addr + size) interval is entirely * covered by precisely one VM area that has the VM_ALLOC flag set. @@ -105,7 +105,7 @@ static int change_memory_common(unsigned long addr, int numpages, area =find_vm_area ((void *)addr);if (!area || end > (unsigned long )kasan_reset_tag (area->addr) + area->size || - !(area->flags &VM_ALLOC )) + ((area->flags & (VM_ALLOC |VM_ALLOW_HUGE_VMAP )) !=VM_ALLOC ))return -EINVAL ;if (!numpages)
Quoted 11 lines · Dev Jain
arm64 uses
apply_to_page_rangeto 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 avmalloc_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 forVM_ALLOW_HUGE_VMAPmappings.[...]
Applied to arm64 (for-next/mm), thanks!
[1/1] arm64: pageattr: Explicitly bail out when changing permissions for vmalloc_huge mappings
https://git.kernel.org/arm64/c/fcf8dda8cc48
Cheers,
Signature · 5 lines
Will https://fixes.arm64.dev https://next.arm64.dev https://will.arm64.dev