From: Jordan Niethe <hidden> Date: 2021-05-06 02:39:07
Adding more Strict RWX support on powerpc, in particular Strict Module RWX.
Thanks for all of the feedback everyone.
It is now rebased on linux-next + powerpc/64s/radix: Enable huge vmalloc mappings
(https://lore.kernel.org/linuxppc-dev/20210503091755.613393-1-npiggin@gmail.com/)
For reference the previous revision is available here:
https://lore.kernel.org/linuxppc-dev/20210429031602.2606654-1-jniethe5@gmail.com/
The changes in v12 for each patch:
Christophe Leroy (2):
powerpc/mm: implement set_memory_attr()
powerpc/32: use set_memory_attr()
Jordan Niethe (3):
powerpc/lib/code-patching: Set up Strict RWX patching earlier
powerpc/bpf: Remove bpf_jit_free()
powerpc/bpf: Write protect JIT code
Russell Currey (3):
powerpc/mm: Implement set_memory() routines
v12: - change_page_attr() back to taking an action value
- disallow operating on huge pages
powerpc/kprobes: Mark newly allocated probes as ROX
v12: - Switch from __vmalloc_node_range() to module_alloc()
powerpc: Set ARCH_HAS_STRICT_MODULE_RWX
Some patches were dropped from this revision:
powerpc: Always define MODULES_{VADDR,END}
- Can use what Nick did with "Enable huge vmalloc mappings"
arch/powerpc/Kconfig | 2 +
arch/powerpc/include/asm/set_memory.h | 34 +++++++
arch/powerpc/kernel/kprobes.c | 17 ++++
arch/powerpc/kernel/module.c | 4 +-
arch/powerpc/lib/code-patching.c | 12 +--
arch/powerpc/mm/Makefile | 2 +-
arch/powerpc/mm/pageattr.c | 133 ++++++++++++++++++++++++++
arch/powerpc/mm/pgtable_32.c | 60 ++----------
arch/powerpc/net/bpf_jit_comp.c | 13 +--
9 files changed, 205 insertions(+), 72 deletions(-)
create mode 100644 arch/powerpc/include/asm/set_memory.h
create mode 100644 arch/powerpc/mm/pageattr.c
--
2.25.1
From: Jordan Niethe <hidden> Date: 2021-05-06 02:39:33
From: Russell Currey <redacted>
The set_memory_{ro/rw/nx/x}() functions are required for
STRICT_MODULE_RWX, and are generally useful primitives to have. This
implementation is designed to be generic across powerpc's many MMUs.
It's possible that this could be optimised to be faster for specific
MMUs.
This implementation does not handle cases where the caller is attempting
to change the mapping of the page it is executing from, or if another
CPU is concurrently using the page being altered. These cases likely
shouldn't happen, but a more complex implementation with MMU-specific code
could safely handle them.
On hash, the linear mapping is not kept in the linux pagetable, so this
will not change the protection if used on that range. Currently these
functions are not used on the linear map so just WARN for now.
apply_to_existing_page_range() does not work on huge pages so for now
disallow changing the protection of huge pages.
Reviewed-by: Daniel Axtens <redacted>
Signed-off-by: Russell Currey <redacted>
Signed-off-by: Christophe Leroy <redacted>
[jpn: - Allow set memory functions to be used without Strict RWX
- Hash: Disallow certain regions
- Have change_page_attr() take function pointers to manipulate ptes
- Radix: Add ptesync after set_pte_at()]
Signed-off-by: Jordan Niethe <redacted>
---
v10: WARN if trying to change the hash linear map
v11: - Update copywrite dates
- Allow set memory functions to be used without Strict RWX
- Hash: Disallow certain regions and add comment explaining why
- Have change_page_attr() take function pointers to manipulate ptes
- Clarify change_page_attr()'s comment
- Radix: Add ptesync after set_pte_at()
v12: - change_page_attr() back to taking an action value
- disallow operating on huge pages
---
arch/powerpc/Kconfig | 1 +
arch/powerpc/include/asm/set_memory.h | 32 +++++++++
arch/powerpc/mm/Makefile | 2 +-
arch/powerpc/mm/pageattr.c | 100 ++++++++++++++++++++++++++
4 files changed, 134 insertions(+), 1 deletion(-)
create mode 100644 arch/powerpc/include/asm/set_memory.h
create mode 100644 arch/powerpc/mm/pageattr.c
@@ -0,0 +1,100 @@+// SPDX-License-Identifier: GPL-2.0++/*+*MMU-genericset_memoryimplementationforpowerpc+*+*Copyright2019-2021,IBMCorporation.+*/++#include<linux/mm.h>+#include<linux/vmalloc.h>+#include<linux/set_memory.h>++#include<asm/mmu.h>+#include<asm/page.h>+#include<asm/pgtable.h>+++/*+*Updatestheattributesofapageinthreesteps:+*+*1.invalidatethepagetableentry+*2.flushtheTLB+*3.installthenewentrywiththeupdatedattributes+*+*Invalidatingtheptemeanstherearesituationswherethiswillnotwork+*whenintheoryitshould.+*Forexample:+*-removingwritefrompagewhilstitisbeingexecuted+*-settingapageread-onlywhilstitisbeingreadbyanotherCPU+*+*/+staticintchange_page_attr(pte_t*ptep,unsignedlongaddr,void*data)+{+longaction=(long)data;+pte_tpte;++spin_lock(&init_mm.page_table_lock);++/* invalidate the PTE so it's safe to modify */+pte=ptep_get_and_clear(&init_mm,addr,ptep);+flush_tlb_kernel_range(addr,addr+PAGE_SIZE);++/* modify the PTE bits as desired, then apply */+switch(action){+caseSET_MEMORY_RO:+pte=pte_wrprotect(pte);+break;+caseSET_MEMORY_RW:+pte=pte_mkwrite(pte_mkdirty(pte));+break;+caseSET_MEMORY_NX:+pte=pte_exprotect(pte);+break;+caseSET_MEMORY_X:+pte=pte_mkexec(pte);+break;+default:+WARN_ON_ONCE(1);+break;+}++set_pte_at(&init_mm,addr,ptep,pte);++/* See ptesync comment in radix__set_pte_at() */+if(radix_enabled())+asmvolatile("ptesync":::"memory");+spin_unlock(&init_mm.page_table_lock);++return0;+}++intchange_memory_attr(unsignedlongaddr,intnumpages,longaction)+{+unsignedlongstart=ALIGN_DOWN(addr,PAGE_SIZE);+unsignedlongsize=numpages*PAGE_SIZE;++if(!numpages)+return0;++if(WARN_ON_ONCE(is_vm_area_hugepages((void*)addr)))+return-EINVAL;++#ifdef CONFIG_PPC_BOOK3S_64+/*+*Onhash,thelinearmappingisnotintheLinuxpagetableso+*apply_to_existing_page_range()willhavenoeffect.Ifinthefuture+*theset_memory_*functionsareusedonthelinearmapthiswillneed+*tobeupdated.+*/+if(!radix_enabled()){+intregion=get_region_id(addr);++if(WARN_ON_ONCE(region!=VMALLOC_REGION_ID&®ion!=IO_REGION_ID))+return-EINVAL;+}+#endif++returnapply_to_existing_page_range(&init_mm,start,size,+change_page_attr,(void*)action);+}
From: Jordan Niethe <hidden> Date: 2021-05-06 02:39:57
setup_text_poke_area() is a late init call so it runs before
mark_rodata_ro() and after the init calls. This lets all the init code
patching simply write to their locations. In the future, kprobes is
going to allocate its instruction pages RO which means they will need
setup_text__poke_area() to have been already called for their code
patching. However, init_kprobes() (which allocates and patches some
instruction pages) is an early init call so it happens before
setup_text__poke_area().
start_kernel() calls poking_init() before any of the init calls. On
powerpc, poking_init() is currently a nop. setup_text_poke_area() relies
on kernel virtual memory, cpu hotplug and per_cpu_areas being setup.
setup_per_cpu_areas(), boot_cpu_hotplug_init() and mm_init() are called
before poking_init().
Turn setup_text_poke_area() into poking_init().
Reviewed-by: Russell Currey <redacted>
Signed-off-by: Jordan Niethe <redacted>
---
v9: New to series
---
arch/powerpc/lib/code-patching.c | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
@@ -70,14 +70,11 @@ static int text_area_cpu_down(unsigned int cpu)}/*-*Runasalateinitcall.Thisallowsalltheboottimepatchingtobedone-*simplybypatchingthecode,andthenwe'recalledherepriorto-*mark_rodata_ro(),whichhappensafterallinitcallsarerun.Although-*BUG_ON()isrude,inthiscaseitshouldonlyhappenifENOMEM,andwejudge-*itasbeingpreferabletoakernelthatwillcrashlaterwhensomeonetries-*tousepatch_instruction().+*AlthoughBUG_ON()isrude,inthiscaseitshouldonlyhappenifENOMEM,and+*wejudgeitasbeingpreferabletoakernelthatwillcrashlaterwhen+*someonetriestousepatch_instruction().*/-staticint__initsetup_text_poke_area(void)+int__initpoking_init(void){BUG_ON(!cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,"powerpc/text_poke:online",text_area_cpu_up,
@@ -85,7 +82,6 @@ static int __init setup_text_poke_area(void)return0;}-late_initcall(setup_text_poke_area);/**Thiscanbecalledforkerneltextoramodule.
From: Jordan Niethe <hidden> Date: 2021-05-06 02:40:33
From: Russell Currey <redacted>
Add the arch specific insn page allocator for powerpc. This allocates
ROX pages if STRICT_KERNEL_RWX is enabled. These pages are only written
to with patch_instruction() which is able to write RO pages.
Reviewed-by: Daniel Axtens <redacted>
Signed-off-by: Russell Currey <redacted>
Signed-off-by: Christophe Leroy <redacted>
[jpn: Reword commit message, switch to __vmalloc_node_range()]
Signed-off-by: Jordan Niethe <redacted>
---
v9: - vmalloc_exec() no longer exists
- Set the page to RW before freeing it
v10: - use __vmalloc_node_range()
v11: - Neaten up
v12: - Switch from __vmalloc_node_range() to module_alloc()
---
arch/powerpc/kernel/kprobes.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
From: Jordan Niethe <hidden> Date: 2021-05-06 02:40:57
Commit 74451e66d516 ("bpf: make jited programs visible in traces") added
a default bpf_jit_free() implementation. Powerpc did not use the default
bpf_jit_free() as powerpc did not set the images read-only. The default
bpf_jit_free() called bpf_jit_binary_unlock_ro() is why it could not be
used for powerpc.
Commit d53d2f78cead ("bpf: Use vmalloc special flag") moved keeping
track of read-only memory to vmalloc. This included removing
bpf_jit_binary_unlock_ro(). Therefore there is no reason powerpc needs
its own bpf_jit_free(). Remove it.
Signed-off-by: Jordan Niethe <redacted>
---
v11: New to series
---
arch/powerpc/net/bpf_jit_comp.c | 12 ------------
1 file changed, 12 deletions(-)
From: Jordan Niethe <hidden> Date: 2021-05-06 02:41:27
Add the necessary call to bpf_jit_binary_lock_ro() to remove write and
add exec permissions to the JIT image after it has finished being
written.
Without CONFIG_STRICT_MODULE_RWX the image will be writable and
executable until the call to bpf_jit_binary_lock_ro().
Signed-off-by: Jordan Niethe <redacted>
---
v10: New to series
v11: Remove CONFIG_STRICT_MODULE_RWX conditional
---
arch/powerpc/net/bpf_jit_comp.c | 1 +
1 file changed, 1 insertion(+)
From: Jordan Niethe <hidden> Date: 2021-05-06 02:41:53
From: Russell Currey <redacted>
To enable strict module RWX on powerpc, set:
CONFIG_STRICT_MODULE_RWX=y
You should also have CONFIG_STRICT_KERNEL_RWX=y set to have any real
security benefit.
ARCH_HAS_STRICT_MODULE_RWX is set to require ARCH_HAS_STRICT_KERNEL_RWX.
This is due to a quirk in arch/Kconfig and arch/powerpc/Kconfig that
makes STRICT_MODULE_RWX *on by default* in configurations where
STRICT_KERNEL_RWX is *unavailable*.
Since this doesn't make much sense, and module RWX without kernel RWX
doesn't make much sense, having the same dependencies as kernel RWX
works around this problem.
With STRICT_MODULE_RWX, now make module_alloc() allocate pages with
KERNEL_PAGE protection rather than KERNEL_PAGE_EXEC.
Book32s/32 processors with a hash mmu (i.e. 604 core) can not set memory
protection on a page by page basis so do not enable.
Signed-off-by: Russell Currey <redacted>
[jpn: - predicate on !PPC_BOOK3S_604
- make module_alloc() use PAGE_KERNEL protection]
Signed-off-by: Jordan Niethe <redacted>
---
v10: - Predicate on !PPC_BOOK3S_604
- Make module_alloc() use PAGE_KERNEL protection
v11: - Neaten up
---
arch/powerpc/Kconfig | 1 +
arch/powerpc/kernel/module.c | 4 +++-
2 files changed, 4 insertions(+), 1 deletion(-)
From: Jordan Niethe <hidden> Date: 2021-05-06 02:42:20
From: Christophe Leroy <redacted>
In addition to the set_memory_xx() functions which allows to change
the memory attributes of not (yet) used memory regions, implement a
set_memory_attr() function to:
- set the final memory protection after init on currently used
kernel regions.
- enable/disable kernel memory regions in the scope of DEBUG_PAGEALLOC.
Unlike the set_memory_xx() which can act in three step as the regions
are unused, this function must modify 'on the fly' as the kernel is
executing from them. At the moment only PPC32 will use it and changing
page attributes on the fly is not an issue.
Signed-off-by: Christophe Leroy <redacted>
Reported-by: kbuild test robot <redacted>
[ruscur: cast "data" to unsigned long instead of int]
Signed-off-by: Russell Currey <redacted>
Signed-off-by: Jordan Niethe <redacted>
---
arch/powerpc/include/asm/set_memory.h | 2 ++
arch/powerpc/mm/pageattr.c | 33 +++++++++++++++++++++++++++
2 files changed, 35 insertions(+)
@@ -29,4 +29,6 @@ static inline int set_memory_x(unsigned long addr, int numpages)returnchange_memory_attr(addr,numpages,SET_MEMORY_X);}+intset_memory_attr(unsignedlongaddr,intnumpages,pgprot_tprot);+#endif
@@ -98,3 +98,36 @@ int change_memory_attr(unsigned long addr, int numpages, long action)returnapply_to_existing_page_range(&init_mm,start,size,change_page_attr,(void*)action);}++/*+*Settheattributesofapage:+*+*ThisfunctionisusedbyPPC32attheendofinittosetfinalkernelmemory+*protection.Itincludeschangingthemapingofthepageitisexecutingfrom+*anddatapagesitisusing.+*/+staticintset_page_attr(pte_t*ptep,unsignedlongaddr,void*data)+{+pgprot_tprot=__pgprot((unsignedlong)data);++spin_lock(&init_mm.page_table_lock);++set_pte_at(&init_mm,addr,ptep,pte_modify(*ptep,prot));+flush_tlb_kernel_range(addr,addr+PAGE_SIZE);++spin_unlock(&init_mm.page_table_lock);++return0;+}++intset_memory_attr(unsignedlongaddr,intnumpages,pgprot_tprot)+{+unsignedlongstart=ALIGN_DOWN(addr,PAGE_SIZE);+unsignedlongsz=numpages*PAGE_SIZE;++if(numpages<=0)+return0;++returnapply_to_existing_page_range(&init_mm,start,sz,set_page_attr,+(void*)pgprot_val(prot));+}
From: Jordan Niethe <hidden> Date: 2021-05-06 02:42:51
From: Christophe Leroy <redacted>
Use set_memory_attr() instead of the PPC32 specific change_page_attr()
change_page_attr() was checking that the address was not mapped by
blocks and was handling highmem, but that's unneeded because the
affected pages can't be in highmem and block mapping verification
is already done by the callers.
Signed-off-by: Christophe Leroy <redacted>
[ruscur: rebase on powerpc/merge with Christophe's new patches]
Signed-off-by: Russell Currey <redacted>
Signed-off-by: Jordan Niethe <redacted>
---
arch/powerpc/mm/pgtable_32.c | 60 ++++++------------------------------
1 file changed, 10 insertions(+), 50 deletions(-)
@@ -198,20 +155,18 @@ void mark_rodata_ro(void)return;}-page=virt_to_page(_stext);numpages=PFN_UP((unsignedlong)_etext)-PFN_DOWN((unsignedlong)_stext);-change_page_attr(page,numpages,PAGE_KERNEL_ROX);+set_memory_attr((unsignedlong)_stext,numpages,PAGE_KERNEL_ROX);/**mark.rodataasreadonly.Use__init_beginratherthan__end_rodata*tocoverNOTESandEXCEPTION_TABLE.*/-page=virt_to_page(__start_rodata);numpages=PFN_UP((unsignedlong)__init_begin)-PFN_DOWN((unsignedlong)__start_rodata);-change_page_attr(page,numpages,PAGE_KERNEL_RO);+set_memory_attr((unsignedlong)__start_rodata,numpages,PAGE_KERNEL_RO);// mark_initmem_nx() should have already run by nowptdump_check_wx();
From: Russell Currey <redacted>
Add the arch specific insn page allocator for powerpc. This allocates
ROX pages if STRICT_KERNEL_RWX is enabled. These pages are only written
to with patch_instruction() which is able to write RO pages.
Reviewed-by: Daniel Axtens <redacted>
Signed-off-by: Russell Currey <redacted>
Signed-off-by: Christophe Leroy <redacted>
[jpn: Reword commit message, switch to __vmalloc_node_range()]
Signed-off-by: Jordan Niethe <redacted>
---
v9: - vmalloc_exec() no longer exists
- Set the page to RW before freeing it
v10: - use __vmalloc_node_range()
v11: - Neaten up
v12: - Switch from __vmalloc_node_range() to module_alloc()
---
arch/powerpc/kernel/kprobes.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
I'm not sure this test is OK, because strict kernel/module rwx can be disabled at boottime.
There is a global variable 'rodata_enabled' to reflect that.
We have a helper in powerpc asm/mmu.h called strict_kernel_rwx_enabled() to check it.
+ set_memory_ro((unsigned long)page, 1);
+ set_memory_x((unsigned long)page, 1);
+ }
+ return page;
+}
+
int arch_prepare_kprobe(struct kprobe *p)
{
int ret = 0;
From: Russell Currey <redacted>
To enable strict module RWX on powerpc, set:
CONFIG_STRICT_MODULE_RWX=y
You should also have CONFIG_STRICT_KERNEL_RWX=y set to have any real
security benefit.
ARCH_HAS_STRICT_MODULE_RWX is set to require ARCH_HAS_STRICT_KERNEL_RWX.
This is due to a quirk in arch/Kconfig and arch/powerpc/Kconfig that
makes STRICT_MODULE_RWX *on by default* in configurations where
STRICT_KERNEL_RWX is *unavailable*.
Since this doesn't make much sense, and module RWX without kernel RWX
doesn't make much sense, having the same dependencies as kernel RWX
works around this problem.
With STRICT_MODULE_RWX, now make module_alloc() allocate pages with
KERNEL_PAGE protection rather than KERNEL_PAGE_EXEC.
Book32s/32 processors with a hash mmu (i.e. 604 core) can not set memory
protection on a page by page basis so do not enable.
Signed-off-by: Russell Currey <redacted>
[jpn: - predicate on !PPC_BOOK3S_604
- make module_alloc() use PAGE_KERNEL protection]
Signed-off-by: Jordan Niethe <redacted>
---
v10: - Predicate on !PPC_BOOK3S_604
- Make module_alloc() use PAGE_KERNEL protection
v11: - Neaten up
---
arch/powerpc/Kconfig | 1 +
arch/powerpc/kernel/module.c | 4 +++-
2 files changed, 4 insertions(+), 1 deletion(-)
@@ -92,12 +92,14 @@ int module_finalize(const Elf_Ehdr *hdr,static__always_inlinevoid*__module_alloc(unsignedlongsize,unsignedlongstart,unsignedlongend){+pgprot_tprot=IS_ENABLED(CONFIG_STRICT_MODULE_RWX)?PAGE_KERNEL:+PAGE_KERNEL_EXEC;
I'm not sure this test is OK, because strict kernel/module rwx can be disabled at boottime.
There is a global variable 'rodata_enabled' to reflect that.
We have a helper in powerpc asm/mmu.h called strict_kernel_rwx_enabled() to check it.
/*
* Don't do huge page allocations for modules yet until more testing
* is done. STRICT_MODULE_RWX may require extra work to support this
* too.
*/
- return __vmalloc_node_range(size, 1, start, end, GFP_KERNEL, PAGE_KERNEL_EXEC,
+ return __vmalloc_node_range(size, 1, start, end, GFP_KERNEL, prot,
VM_FLUSH_RESET_PERMS | VM_NO_HUGE_VMAP,
NUMA_NO_NODE, __builtin_return_address(0));
}
setup_text_poke_area() is a late init call so it runs before
mark_rodata_ro() and after the init calls. This lets all the init code
patching simply write to their locations. In the future, kprobes is
going to allocate its instruction pages RO which means they will need
setup_text__poke_area() to have been already called for their code
patching. However, init_kprobes() (which allocates and patches some
instruction pages) is an early init call so it happens before
setup_text__poke_area().
start_kernel() calls poking_init() before any of the init calls. On
powerpc, poking_init() is currently a nop. setup_text_poke_area() relies
on kernel virtual memory, cpu hotplug and per_cpu_areas being setup.
setup_per_cpu_areas(), boot_cpu_hotplug_init() and mm_init() are called
before poking_init().
Turn setup_text_poke_area() into poking_init().
Reviewed-by: Russell Currey <redacted>
Signed-off-by: Jordan Niethe <redacted>
Reviewed-by: Christophe Leroy <redacted>
quoted hunk
---
v9: New to series
---
arch/powerpc/lib/code-patching.c | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
@@ -70,14 +70,11 @@ static int text_area_cpu_down(unsigned int cpu)}/*-*Runasalateinitcall.Thisallowsalltheboottimepatchingtobedone-*simplybypatchingthecode,andthenwe'recalledherepriorto-*mark_rodata_ro(),whichhappensafterallinitcallsarerun.Although-*BUG_ON()isrude,inthiscaseitshouldonlyhappenifENOMEM,andwejudge-*itasbeingpreferabletoakernelthatwillcrashlaterwhensomeonetries-*tousepatch_instruction().+*AlthoughBUG_ON()isrude,inthiscaseitshouldonlyhappenifENOMEM,and+*wejudgeitasbeingpreferabletoakernelthatwillcrashlaterwhen+*someonetriestousepatch_instruction().*/-staticint__initsetup_text_poke_area(void)+int__initpoking_init(void){BUG_ON(!cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,"powerpc/text_poke:online",text_area_cpu_up,
@@ -85,7 +82,6 @@ static int __init setup_text_poke_area(void)return0;}-late_initcall(setup_text_poke_area);/**Thiscanbecalledforkerneltextoramodule.
Commit 74451e66d516 ("bpf: make jited programs visible in traces") added
a default bpf_jit_free() implementation. Powerpc did not use the default
bpf_jit_free() as powerpc did not set the images read-only. The default
bpf_jit_free() called bpf_jit_binary_unlock_ro() is why it could not be
used for powerpc.
Commit d53d2f78cead ("bpf: Use vmalloc special flag") moved keeping
track of read-only memory to vmalloc. This included removing
bpf_jit_binary_unlock_ro(). Therefore there is no reason powerpc needs
its own bpf_jit_free(). Remove it.
Signed-off-by: Jordan Niethe <redacted>
Reviewed-by: Christophe Leroy <redacted>
quoted hunk
---
v11: New to series
---
arch/powerpc/net/bpf_jit_comp.c | 12 ------------
1 file changed, 12 deletions(-)
Add the necessary call to bpf_jit_binary_lock_ro() to remove write and
add exec permissions to the JIT image after it has finished being
written.
Without CONFIG_STRICT_MODULE_RWX the image will be writable and
executable until the call to bpf_jit_binary_lock_ro().
Signed-off-by: Jordan Niethe <redacted>
Reviewed-by: Christophe Leroy <redacted>
quoted hunk
---
v10: New to series
v11: Remove CONFIG_STRICT_MODULE_RWX conditional
---
arch/powerpc/net/bpf_jit_comp.c | 1 +
1 file changed, 1 insertion(+)
From: Jordan Niethe <hidden> Date: 2021-05-10 00:52:59
On Fri, May 7, 2021 at 3:35 PM Christophe Leroy
[off-list ref] wrote:
Le 06/05/2021 à 04:34, Jordan Niethe a écrit :
quoted
From: Russell Currey <redacted>
To enable strict module RWX on powerpc, set:
CONFIG_STRICT_MODULE_RWX=y
You should also have CONFIG_STRICT_KERNEL_RWX=y set to have any real
security benefit.
ARCH_HAS_STRICT_MODULE_RWX is set to require ARCH_HAS_STRICT_KERNEL_RWX.
This is due to a quirk in arch/Kconfig and arch/powerpc/Kconfig that
makes STRICT_MODULE_RWX *on by default* in configurations where
STRICT_KERNEL_RWX is *unavailable*.
Since this doesn't make much sense, and module RWX without kernel RWX
doesn't make much sense, having the same dependencies as kernel RWX
works around this problem.
With STRICT_MODULE_RWX, now make module_alloc() allocate pages with
KERNEL_PAGE protection rather than KERNEL_PAGE_EXEC.
Book32s/32 processors with a hash mmu (i.e. 604 core) can not set memory
protection on a page by page basis so do not enable.
Signed-off-by: Russell Currey <redacted>
[jpn: - predicate on !PPC_BOOK3S_604
- make module_alloc() use PAGE_KERNEL protection]
Signed-off-by: Jordan Niethe <redacted>
---
v10: - Predicate on !PPC_BOOK3S_604
- Make module_alloc() use PAGE_KERNEL protection
v11: - Neaten up
---
arch/powerpc/Kconfig | 1 +
arch/powerpc/kernel/module.c | 4 +++-
2 files changed, 4 insertions(+), 1 deletion(-)
@@ -92,12 +92,14 @@ int module_finalize(const Elf_Ehdr *hdr,static__always_inlinevoid*__module_alloc(unsignedlongsize,unsignedlongstart,unsignedlongend){+pgprot_tprot=IS_ENABLED(CONFIG_STRICT_MODULE_RWX)?PAGE_KERNEL:+PAGE_KERNEL_EXEC;
I'm not sure this test is OK, because strict kernel/module rwx can be disabled at boottime.
There is a global variable 'rodata_enabled' to reflect that.
We have a helper in powerpc asm/mmu.h called strict_kernel_rwx_enabled() to check it.
Thanks, I will change to that.
quoted
/*
* Don't do huge page allocations for modules yet until more testing
* is done. STRICT_MODULE_RWX may require extra work to support this
* too.
*/
- return __vmalloc_node_range(size, 1, start, end, GFP_KERNEL, PAGE_KERNEL_EXEC,
+ return __vmalloc_node_range(size, 1, start, end, GFP_KERNEL, prot,
VM_FLUSH_RESET_PERMS | VM_NO_HUGE_VMAP,
NUMA_NO_NODE, __builtin_return_address(0));
}