aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt (VMware) <rostedt@goodmis.org>2018-07-10 03:22:40 -0400
committerRussell King <rmk+kernel@armlinux.org.uk>2018-07-11 17:57:57 -0400
commitb4c7e2bd2eb4764afe3af9409ff3b1b87116fa30 (patch)
tree1a448c113d6bd23feeea5c04f0a53ea86a0afd7f
parentcea394772d3c41d04cb71a032f6ed878392bd134 (diff)
ARM: 8780/1: ftrace: Only set kernel memory back to read-only after boot
Dynamic ftrace requires modifying the code segments that are usually set to read-only. To do this, a per arch function is called both before and after the ftrace modifications are performed. The "before" function will set kernel code text to read-write to allow for ftrace to make the modifications, and the "after" function will set the kernel code text back to "read-only" to keep the kernel code text protected. The issue happens when dynamic ftrace is tested at boot up. The test is done before the kernel code text has been set to read-only. But the "before" and "after" calls are still performed. The "after" call will change the kernel code text to read-only prematurely, and other boot code that expects this code to be read-write will fail. The solution is to add a variable that is set when the kernel code text is expected to be converted to read-only, and make the ftrace "before" and "after" calls do nothing if that variable is not yet set. This is similar to the x86 solution from commit 162396309745 ("ftrace, x86: make kernel text writable only for conversions"). Link: http://lkml.kernel.org/r/20180620212906.24b7b66e@vmware.local.home Reported-by: Stefan Agner <stefan@agner.ch> Tested-by: Stefan Agner <stefan@agner.ch> Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
-rw-r--r--arch/arm/mm/init.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index c186474422f3..0cc8e04295a4 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -736,20 +736,29 @@ static int __mark_rodata_ro(void *unused)
736 return 0; 736 return 0;
737} 737}
738 738
739static int kernel_set_to_readonly __read_mostly;
740
739void mark_rodata_ro(void) 741void mark_rodata_ro(void)
740{ 742{
743 kernel_set_to_readonly = 1;
741 stop_machine(__mark_rodata_ro, NULL, NULL); 744 stop_machine(__mark_rodata_ro, NULL, NULL);
742 debug_checkwx(); 745 debug_checkwx();
743} 746}
744 747
745void set_kernel_text_rw(void) 748void set_kernel_text_rw(void)
746{ 749{
750 if (!kernel_set_to_readonly)
751 return;
752
747 set_section_perms(ro_perms, ARRAY_SIZE(ro_perms), false, 753 set_section_perms(ro_perms, ARRAY_SIZE(ro_perms), false,
748 current->active_mm); 754 current->active_mm);
749} 755}
750 756
751void set_kernel_text_ro(void) 757void set_kernel_text_ro(void)
752{ 758{
759 if (!kernel_set_to_readonly)
760 return;
761
753 set_section_perms(ro_perms, ARRAY_SIZE(ro_perms), true, 762 set_section_perms(ro_perms, ARRAY_SIZE(ro_perms), true,
754 current->active_mm); 763 current->active_mm);
755} 764}