[RHEL7,COMMIT] ms/jump_label: Explicitly disable jump labels in __init code

Submitted by Konstantin Khorenko on April 3, 2018, 1:06 p.m.

Details

Message ID 201804031306.w33D67AA023841@finist_ce7.work
State New
Series "ms/jump_label: Explicitly disable jump labels in __init code"
Headers show

Commit Message

Konstantin Khorenko April 3, 2018, 1:06 p.m.
The commit is pushed to "branch-rh7-3.10.0-693.21.1.vz7.46.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-693.21.1.vz7.46.3
------>
commit eabde991ddb71f7312dccd28ae867a41284a62f1
Author: Josh Poimboeuf <jpoimboe@redhat.com>
Date:   Tue Feb 20 11:37:51 2018 -0600

    ms/jump_label: Explicitly disable jump labels in __init code
    
    After initmem has been freed, any jump labels in __init code are
    prevented from being written to by the kernel_text_address() check in
    __jump_label_update().  However, this check is quite broad.  If
    kernel_text_address() were to return false for any other reason, the
    jump label write would fail silently with no warning.
    
    For jump labels in module init code, entry->code is set to zero to
    indicate that the entry is disabled.  Do the same thing for core kernel
    init code.  This makes the behavior more consistent, and will also make
    it more straightforward to detect non-init jump label write failures in
    the next patch.
    
    Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
    Acked-by: Peter Zijlstra <peterz@infradead.org>
    Cc: Borislav Petkov <bp@suse.de>
    Cc: Jason Baron <jbaron@akamai.com>
    Cc: Linus Torvalds <torvalds@linux-foundation.org>
    Cc: Steven Rostedt <rostedt@goodmis.org>
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Link: http://lkml.kernel.org/r/c52825c73f3a174e8398b6898284ec20d4deb126.1519051220.git.jpoimboe@redhat.com
    Signed-off-by: Ingo Molnar <mingo@kernel.org>
    
    (cherry picked from commit 33352244706369ea6736781ae41fe41692eb69bb)
    
    https://jira.sw.ru/browse/PSBM-83162
    Signed-off-by: Konstantin Khorenko <khorenko@virtuozzo.com>
---
 include/linux/jump_label.h |  3 +++
 init/main.c                |  2 ++
 kernel/jump_label.c        | 16 ++++++++++++++++
 3 files changed, 21 insertions(+)

Patch hide | download patch | download mbox

diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index e96be7245717..ae22ca61d467 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -111,6 +111,7 @@  extern struct jump_entry __start___jump_table[];
 extern struct jump_entry __stop___jump_table[];
 
 extern void jump_label_init(void);
+extern void jump_label_invalidate_init(void);
 extern void jump_label_lock(void);
 extern void jump_label_unlock(void);
 extern void arch_jump_label_transform(struct jump_entry *entry,
@@ -138,6 +139,8 @@  static __always_inline void jump_label_init(void)
 	static_key_initialized = true;
 }
 
+static inline void jump_label_invalidate_init(void) {}
+
 static __always_inline bool static_key_false(struct static_key *key)
 {
 	if (unlikely(atomic_read(&key->enabled)) > 0)
diff --git a/init/main.c b/init/main.c
index 08711b084144..f88365106339 100644
--- a/init/main.c
+++ b/init/main.c
@@ -78,6 +78,7 @@ 
 #include <linux/context_tracking.h>
 #include <linux/list.h>
 #include <linux/io.h>
+#include <linux/jump_label.h>
 #include <linux/ve.h>
 
 #include <bc/beancounter.h>
@@ -910,6 +911,7 @@  static int __ref kernel_init(void *unused)
 	kernel_init_freeable();
 	/* need to finish all async __init code before freeing the memory */
 	async_synchronize_full();
+	jump_label_invalidate_init();
 	free_initmem();
 	mark_rodata_ro();
 	system_state = SYSTEM_RUNNING;
diff --git a/kernel/jump_label.c b/kernel/jump_label.c
index 59b260c856c1..2a46c6c395d9 100644
--- a/kernel/jump_label.c
+++ b/kernel/jump_label.c
@@ -14,6 +14,7 @@ 
 #include <linux/err.h>
 #include <linux/static_key.h>
 #include <linux/jump_label_ratelimit.h>
+#include <asm/sections.h>
 
 #ifdef HAVE_JUMP_LABEL
 
@@ -232,6 +233,20 @@  void __init jump_label_init(void)
 	jump_label_unlock();
 }
 
+/* Disable any jump label entries in __init code */
+void __init jump_label_invalidate_init(void)
+{
+	struct jump_entry *iter_start = __start___jump_table;
+	struct jump_entry *iter_stop = __stop___jump_table;
+	struct jump_entry *iter;
+
+	for (iter = iter_start; iter < iter_stop; iter++) {
+		if (iter->code >= (unsigned long)_sinittext &&
+		    iter->code < (unsigned long)_einittext)
+			iter->code = 0;
+	}
+}
+
 #ifdef CONFIG_MODULES
 
 struct static_key_mod {
@@ -369,6 +384,7 @@  static void jump_label_del_module(struct module *mod)
 	}
 }
 
+/* Disable any jump label entries in module init code */
 static void jump_label_invalidate_module_init(struct module *mod)
 {
 	struct jump_entry *iter_start = mod->jump_entries;