All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alexandre Chartre <alexandre.chartre@oracle.com>
To: x86@kernel.org
Cc: linux-kernel@vger.kernel.org, jpoimboe@redhat.com,
	peterz@infradead.org, jthierry@redhat.com, tglx@linutronix.de,
	alexandre.chartre@oracle.com
Subject: [PATCH V3 5/9] objtool: Add return address unwind hints
Date: Tue, 14 Apr 2020 12:36:14 +0200	[thread overview]
Message-ID: <20200414103618.12657-6-alexandre.chartre@oracle.com> (raw)
In-Reply-To: <20200414103618.12657-1-alexandre.chartre@oracle.com>

Add the UNWIND_HINT_RADDR_DELETE and UNWIND_HINT_RADDR_ALTER unwind
hint macros to flag instructions which remove or modify return
addresses.

Signed-off-by: Alexandre Chartre <alexandre.chartre@oracle.com>
---
 arch/x86/include/asm/orc_types.h       |  2 +
 arch/x86/include/asm/unwind_hints.h    | 23 +++++++++
 tools/arch/x86/include/asm/orc_types.h |  2 +
 tools/objtool/check.c                  | 67 ++++++++++++++++++++++++++
 4 files changed, 94 insertions(+)

diff --git a/arch/x86/include/asm/orc_types.h b/arch/x86/include/asm/orc_types.h
index 6e060907c163..5c1141175d51 100644
--- a/arch/x86/include/asm/orc_types.h
+++ b/arch/x86/include/asm/orc_types.h
@@ -60,6 +60,8 @@
 #define ORC_TYPE_REGS_IRET		2
 #define UNWIND_HINT_TYPE_SAVE		3
 #define UNWIND_HINT_TYPE_RESTORE	4
+#define UNWIND_HINT_TYPE_RADDR_ALTER	6
+#define UNWIND_HINT_TYPE_RADDR_DELETE	7
 
 #ifndef __ASSEMBLY__
 /*
diff --git a/arch/x86/include/asm/unwind_hints.h b/arch/x86/include/asm/unwind_hints.h
index f5e2eb12cb71..5211d2c5b7a2 100644
--- a/arch/x86/include/asm/unwind_hints.h
+++ b/arch/x86/include/asm/unwind_hints.h
@@ -94,6 +94,23 @@
 	UNWIND_HINT type=UNWIND_HINT_TYPE_RESTORE
 .endm
 
+/*
+ * RADDR_DELETE: Used on instructions (other than ret instruction)
+ * which remove a return address from the stack. count is the number
+ * of return address which are removed.
+ */
+.macro UNWIND_HINT_RADDR_DELETE count=1
+	UNWIND_HINT type=UNWIND_HINT_TYPE_RADDR_DELETE sp_offset=\count
+.endm
+
+/*
+ * RADDR_ALTER: Used on instructions which change a return address on
+ * the stack. count is the number of return address which are changed.
+ */
+.macro UNWIND_HINT_RADDR_ALTER count=1
+	UNWIND_HINT type=UNWIND_HINT_TYPE_RADDR_ALTER sp_offset=\count
+.endm
+
 #else /* !__ASSEMBLY__ */
 
 #define UNWIND_HINT(sp_reg, sp_offset, type, end)		\
@@ -112,6 +129,12 @@
 
 #define UNWIND_HINT_RESTORE UNWIND_HINT(0, 0, UNWIND_HINT_TYPE_RESTORE, 0)
 
+#define UNWIND_HINT_RADDR_ALTER(count)	\
+	UNWIND_HINT(0, count, UNWIND_HINT_TYPE_RADDR_ALTER, 0)
+
+#define UNWIND_HINT_RADDR_DELETE(count)	\
+	UNWIND_HINT(0, count, UNWIND_HINT_TYPE_RADDR_DELETE, 0)
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_X86_UNWIND_HINTS_H */
diff --git a/tools/arch/x86/include/asm/orc_types.h b/tools/arch/x86/include/asm/orc_types.h
index 6e060907c163..5c1141175d51 100644
--- a/tools/arch/x86/include/asm/orc_types.h
+++ b/tools/arch/x86/include/asm/orc_types.h
@@ -60,6 +60,8 @@
 #define ORC_TYPE_REGS_IRET		2
 #define UNWIND_HINT_TYPE_SAVE		3
 #define UNWIND_HINT_TYPE_RESTORE	4
+#define UNWIND_HINT_TYPE_RADDR_ALTER	6
+#define UNWIND_HINT_TYPE_RADDR_DELETE	7
 
 #ifndef __ASSEMBLY__
 /*
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 8b1df659cd68..0574ce8e232d 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -66,6 +66,28 @@ static bool raddr_pop(struct instruction **insn)
 	return true;
 }
 
+static bool raddr_delete(int count)
+{
+	if (raddr_count < count)
+		return false;
+
+	raddr_count -= count;
+	return true;
+}
+
+static bool raddr_alter(int count)
+{
+	int i;
+
+	if (raddr_count < count)
+		false;
+
+	for (i = 0; i < count; i++)
+		raddr_list[raddr_count - 1 - i] = RADDR_ALTERED;
+
+	return true;
+}
+
 static int validate_branch(struct objtool_file *file, struct symbol *func,
 			   struct instruction *from,
 			   struct instruction *first, struct insn_state state);
@@ -1314,6 +1336,14 @@ static int read_unwind_hints(struct objtool_file *file)
 			insn->restore = true;
 			insn->hint = true;
 			continue;
+
+		} else if (hint->type == UNWIND_HINT_TYPE_RADDR_DELETE) {
+			insn->raddr_delete = hint->sp_offset;
+			continue;
+
+		} else if (hint->type == UNWIND_HINT_TYPE_RADDR_ALTER) {
+			insn->raddr_alter = hint->sp_offset;
+			continue;
 		}
 
 		insn->hint = true;
@@ -1526,6 +1556,13 @@ static bool has_modified_stack_frame(struct insn_state *state)
 	    state->drap)
 		return true;
 
+	/*
+	 * If the stack was altered then don't check registers because
+	 * a callee-saved registers might have been pushed on the stack.
+	 */
+	if (state->stack_altered)
+		return false;
+
 	for (i = 0; i < CFI_NUM_REGS; i++)
 		if (state->regs[i].base != initial_func_cfi.regs[i].base ||
 		    state->regs[i].offset != initial_func_cfi.regs[i].offset)
@@ -2103,6 +2140,15 @@ static int validate_return_address(struct objtool_file *file,
 		if (!raddr_insn)
 			break;
 
+		/*
+		 * If this is a dynamic branch then we expect this
+		 * branch to return or not, depending on the defined
+		 * list of RA we have, so just continue the processing
+		 * of the RA list.
+		 */
+		if (raddr_insn == RADDR_ALTERED)
+			continue;
+
 		/*
 		 * If we are branching to a defined address then
 		 * just do an unconditional jump there.
@@ -2287,6 +2333,27 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
 				return 0;
 		}
 
+		if (insn->raddr_delete) {
+			/* delete return address */
+			if (!raddr_delete(insn->raddr_delete)) {
+				WARN_FUNC("fail to delete %d return address",
+					  insn->sec, insn->offset,
+					  insn->raddr_delete);
+				return 1;
+			}
+			state.stack_altered = true;
+
+		} else if (insn->raddr_alter) {
+			/* alter return address */
+			if (!raddr_alter(insn->raddr_alter)) {
+				WARN_FUNC("fail to alter %d return address",
+					  insn->sec, insn->offset,
+					  insn->raddr_alter);
+				return 1;
+			}
+			state.stack_altered = true;
+		}
+
 		switch (insn->type) {
 
 		case INSN_RETURN:
-- 
2.18.2


  parent reply	other threads:[~2020-04-14 10:35 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-14 10:36 [PATCH V3 0/9] objtool changes to check retpoline code Alexandre Chartre
2020-04-14 10:36 ` [PATCH V3 1/9] objtool: is_fentry_call() crashes if call has no destination Alexandre Chartre
2020-05-01 18:22   ` [tip: objtool/core] " tip-bot2 for Alexandre Chartre
2020-04-14 10:36 ` [PATCH V3 2/9] objtool: Allow branches within the same alternative Alexandre Chartre
2020-04-14 10:36 ` [PATCH V3 3/9] objtool: Add support for intra-function calls Alexandre Chartre
2020-04-14 12:07   ` Julien Thierry
2020-04-16 12:12   ` Miroslav Benes
2020-05-01 18:22   ` [tip: objtool/core] " tip-bot2 for Alexandre Chartre
2020-04-14 10:36 ` [PATCH V3 4/9] objtool: Handle return instruction with intra-function call Alexandre Chartre
2020-04-14 13:44   ` Julien Thierry
2020-04-14 10:36 ` Alexandre Chartre [this message]
2020-04-14 16:16   ` [PATCH V3 5/9] objtool: Add return address unwind hints Peter Zijlstra
2020-04-14 16:40     ` Alexandre Chartre
2020-04-14 17:56       ` Peter Zijlstra
2020-04-14 18:31         ` Alexandre Chartre
2020-04-14 18:42           ` Peter Zijlstra
2020-04-14 19:27             ` Alexandre Chartre
2020-04-14 19:48               ` Peter Zijlstra
2020-04-14 10:36 ` [PATCH V3 6/9] objtool: Report inconsistent stack changes in alternative Alexandre Chartre
2020-04-14 15:35   ` Julien Thierry
2020-04-14 22:41   ` kbuild test robot
2020-04-14 22:41     ` kbuild test robot
2020-04-14 23:09   ` kbuild test robot
2020-04-14 23:09     ` kbuild test robot
2020-04-16 14:18   ` Peter Zijlstra
2020-04-16 14:43     ` Alexandre Chartre
2020-04-14 10:36 ` [PATCH V3 7/9] x86/speculation: Change __FILL_RETURN_BUFFER to work with objtool Alexandre Chartre
2020-04-14 10:36 ` [PATCH V3 8/9] x86/speculation: Add return address unwind hints to retpoline and RSB stuffing Alexandre Chartre
2020-04-14 10:36 ` [PATCH V3 9/9] x86/speculation: Annotate intra-function calls Alexandre Chartre

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200414103618.12657-6-alexandre.chartre@oracle.com \
    --to=alexandre.chartre@oracle.com \
    --cc=jpoimboe@redhat.com \
    --cc=jthierry@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=peterz@infradead.org \
    --cc=tglx@linutronix.de \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.