lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Sun, 31 Jan 2021 16:14:37 +0800
From:   Jinyang He <hejinyang@...ngson.cn>
To:     Thomas Bogendoerfer <tsbogend@...ha.franken.de>,
        Steven Rostedt <rostedt@...dmis.org>,
        Ingo Molnar <mingo@...hat.com>
Cc:     Wu Zhangjin <wuzhangjin@...il.com>, linux-mips@...r.kernel.org,
        linux-kernel@...r.kernel.org, Huacai Chen <chenhuacai@...nel.org>,
        Jiaxun Yang <jiaxun.yang@...goat.com>,
        Tiezhu Yang <yangtiezhu@...ngson.cn>
Subject: [PATCH 2/3] MIPS: ftrace: Combine ftrace_modify_code* into one function

Behavior of ftrace_modify_code_2r() is similar to ftrace_modify_code_2(),
just the order of modification changed. Add a new struct ftrace_insn
to combine ftrace_modify_code with above two functions. The function is
same with the original ftrace_modify_code when ftrace_insn.code[1]
is DONT_SET.

Signed-off-by: Jinyang He <hejinyang@...ngson.cn>
---
 arch/mips/include/asm/ftrace.h |   3 +
 arch/mips/kernel/ftrace.c      | 157 +++++++++++++++++------------------------
 2 files changed, 68 insertions(+), 92 deletions(-)

diff --git a/arch/mips/include/asm/ftrace.h b/arch/mips/include/asm/ftrace.h
index b463f2a..636c640 100644
--- a/arch/mips/include/asm/ftrace.h
+++ b/arch/mips/include/asm/ftrace.h
@@ -84,6 +84,9 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 struct dyn_arch_ftrace {
 };
 
+struct ftrace_insn {
+	unsigned int code[2];
+};
 #endif /*  CONFIG_DYNAMIC_FTRACE */
 #endif /* __ASSEMBLY__ */
 #endif /* CONFIG_FUNCTION_TRACER */
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c
index f57e68f..fd6d1da 100644
--- a/arch/mips/kernel/ftrace.c
+++ b/arch/mips/kernel/ftrace.c
@@ -44,89 +44,70 @@ void arch_ftrace_update_code(int command)
 #define INSN_NOP 0x00000000	/* nop */
 #define INSN_JAL(addr)	\
 	((unsigned int)(JAL | (((addr) >> 2) & ADDR_MASK)))
+#define INSN_B_1F (0x10000000 | MCOUNT_OFFSET_INSNS)
+
+#define DONT_SET 0xffffffff
+
+static struct ftrace_insn jal_ftrace_caller __read_mostly;
+static struct ftrace_insn la_mcount __read_mostly;
+static struct ftrace_insn nop_kernel __read_mostly;
+static struct ftrace_insn nop_module __read_mostly;
 
-static unsigned int insn_jal_ftrace_caller __read_mostly;
-static unsigned int insn_la_mcount[2] __read_mostly;
-static unsigned int insn_j_ftrace_graph_caller __maybe_unused __read_mostly;
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+static struct ftrace_insn j_ftrace_graph_caller __read_mostly;
+#endif
 
 static inline void ftrace_dyn_arch_init_insns(void)
 {
 	u32 *buf;
-	unsigned int v1;
+	unsigned int v1 = 3;
 
 	/* la v1, _mcount */
-	v1 = 3;
-	buf = (u32 *)&insn_la_mcount[0];
+	buf = (u32 *)&la_mcount;
 	UASM_i_LA(&buf, v1, MCOUNT_ADDR);
+#ifdef CONFIG_64BIT
+	la_mcount.code[1] = DONT_SET;
+#endif
 
 	/* jal (ftrace_caller + 8), jump over the first two instruction */
-	buf = (u32 *)&insn_jal_ftrace_caller;
+	buf = (u32 *)&jal_ftrace_caller;
 	uasm_i_jal(&buf, (FTRACE_ADDR + 8) & JUMP_RANGE_MASK);
+	jal_ftrace_caller.code[1] = DONT_SET;
+
+	nop_kernel.code[0] = INSN_NOP;
+	nop_module.code[0] = INSN_B_1F;
+
+#ifdef CONFIG_64BIT
+	nop_kernel.code[1] = DONT_SET;
+	nop_module.code[1] = DONT_SET;
+#else
+	nop_kernel.code[1] = INSN_NOP;
+	nop_module.code[1] = INSN_NOP;
+#endif
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 	/* j ftrace_graph_caller */
-	buf = (u32 *)&insn_j_ftrace_graph_caller;
+	buf = (u32 *)&j_ftrace_graph_caller;
 	uasm_i_j(&buf, (unsigned long)ftrace_graph_caller & JUMP_RANGE_MASK);
+	j_ftrace_graph_caller.code[1] = DONT_SET;
 #endif
 }
 
-static int ftrace_modify_code(unsigned long ip, unsigned int new_code)
-{
-	int faulted;
-	mm_segment_t old_fs;
-
-	/* *(unsigned int *)ip = new_code; */
-	safe_store_code(new_code, ip, faulted);
-
-	if (unlikely(faulted))
-		return -EFAULT;
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	flush_icache_range(ip, ip + 8);
-	set_fs(old_fs);
-
-	return 0;
-}
-
-#ifndef CONFIG_64BIT
-static int ftrace_modify_code_2(unsigned long ip, unsigned int new_code1,
-				unsigned int new_code2)
-{
-	int faulted;
-	mm_segment_t old_fs;
-
-	safe_store_code(new_code1, ip, faulted);
-	if (unlikely(faulted))
-		return -EFAULT;
-
-	ip += 4;
-	safe_store_code(new_code2, ip, faulted);
-	if (unlikely(faulted))
-		return -EFAULT;
-
-	ip -= 4;
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	flush_icache_range(ip, ip + 8);
-	set_fs(old_fs);
-
-	return 0;
-}
-
-static int ftrace_modify_code_2r(unsigned long ip, unsigned int new_code1,
-				 unsigned int new_code2)
+static int ftrace_modify_code(unsigned long ip, struct ftrace_insn insns)
 {
 	int faulted;
 	mm_segment_t old_fs;
 
-	ip += 4;
-	safe_store_code(new_code2, ip, faulted);
-	if (unlikely(faulted))
-		return -EFAULT;
+	if (insns.code[1] != DONT_SET) {
+		ip += 4;
+		safe_store_code(insns.code[1], ip, faulted);
+		if (unlikely(faulted))
+			return -EFAULT;
+		ip -= 4;
+	}
 
-	ip -= 4;
-	safe_store_code(new_code1, ip, faulted);
+	/* *(unsigned int *)ip = insns.code[0]; */
+	safe_store_code(insns.code[0], ip, faulted);
 	if (unlikely(faulted))
 		return -EFAULT;
 
@@ -137,7 +118,6 @@ static int ftrace_modify_code_2r(unsigned long ip, unsigned int new_code1,
 
 	return 0;
 }
-#endif
 
 /*
  * The details about the calling site of mcount on MIPS
@@ -169,66 +149,55 @@ static int ftrace_modify_code_2r(unsigned long ip, unsigned int new_code1,
  *				    1: offset = 4 instructions
  */
 
-#define INSN_B_1F (0x10000000 | MCOUNT_OFFSET_INSNS)
-
 int ftrace_make_nop(struct module *mod,
 		    struct dyn_ftrace *rec, unsigned long addr)
 {
-	unsigned int new;
+	struct ftrace_insn insns;
 	unsigned long ip = rec->ip;
 
 	/*
 	 * If ip is in kernel space, no long call, otherwise, long call is
 	 * needed.
 	 */
-	new = core_kernel_text(ip) ? INSN_NOP : INSN_B_1F;
-#ifdef CONFIG_64BIT
-	return ftrace_modify_code(ip, new);
-#else
-	/*
-	 * On 32 bit MIPS platforms, gcc adds a stack adjust
-	 * instruction in the delay slot after the branch to
-	 * mcount and expects mcount to restore the sp on return.
-	 * This is based on a legacy API and does nothing but
-	 * waste instructions so it's being removed at runtime.
-	 */
-	return ftrace_modify_code_2(ip, new, INSN_NOP);
-#endif
+	insns = core_kernel_text(ip) ? nop_kernel : nop_module;
+
+	return ftrace_modify_code(ip, insns);
 }
 
 int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
 {
-	unsigned int new;
+	struct ftrace_insn insns;
 	unsigned long ip = rec->ip;
 
-	new = core_kernel_text(ip) ? insn_jal_ftrace_caller : insn_la_mcount[0];
+	insns = core_kernel_text(ip) ? jal_ftrace_caller : la_mcount;
 
-#ifdef CONFIG_64BIT
-	return ftrace_modify_code(ip, new);
-#else
-	return ftrace_modify_code_2r(ip, new, core_kernel_text(ip) ?
-						INSN_NOP : insn_la_mcount[1]);
-#endif
+	return ftrace_modify_code(ip, insns);
 }
 
 #define FTRACE_CALL_IP ((unsigned long)(&ftrace_call))
 
 int ftrace_update_ftrace_func(ftrace_func_t func)
 {
-	unsigned int new;
+	struct ftrace_insn insns;
 
-	new = INSN_JAL((unsigned long)func);
+	insns.code[0] = INSN_JAL((unsigned long)func);
+	insns.code[1] = DONT_SET;
 
-	return ftrace_modify_code(FTRACE_CALL_IP, new);
+	return ftrace_modify_code(FTRACE_CALL_IP, insns);
 }
 
 int __init ftrace_dyn_arch_init(void)
 {
+	struct ftrace_insn insns;
+
+	insns.code[0] = INSN_NOP;
+	insns.code[1] = DONT_SET;
+
 	/* Encode the instructions when booting */
 	ftrace_dyn_arch_init_insns();
 
 	/* Remove "b ftrace_stub" to ensure ftrace_caller() is executed */
-	ftrace_modify_code(MCOUNT_ADDR, INSN_NOP);
+	ftrace_modify_code(MCOUNT_ADDR, insns);
 
 	return 0;
 }
@@ -243,13 +212,17 @@ extern void ftrace_graph_call(void);
 
 int ftrace_enable_ftrace_graph_caller(void)
 {
-	return ftrace_modify_code(FTRACE_GRAPH_CALL_IP,
-			insn_j_ftrace_graph_caller);
+	return ftrace_modify_code(FTRACE_GRAPH_CALL_IP, j_ftrace_graph_caller);
 }
 
 int ftrace_disable_ftrace_graph_caller(void)
 {
-	return ftrace_modify_code(FTRACE_GRAPH_CALL_IP, INSN_NOP);
+	struct ftrace_insn insns;
+
+	insns.code[0] = INSN_NOP;
+	insns.code[1] = DONT_SET;
+
+	return ftrace_modify_code(FTRACE_GRAPH_CALL_IP, insns);
 }
 
 #endif	/* CONFIG_DYNAMIC_FTRACE */
-- 
2.1.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ