linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/3] objtool: Extend CFA updating/checking
@ 2020-10-14  7:37 Julien Thierry
  2020-10-14  7:38 ` [PATCH v3 1/3] objtool: check: Fully validate the stack frame Julien Thierry
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Julien Thierry @ 2020-10-14  7:37 UTC (permalink / raw)
  To: linux-kernel
  Cc: jpoimboe, peterz, mbenes, raphael.gault, benh, Julien Thierry

Hi,

The following patches are the result of limitation found on the CFA
management code when trying to validate arm64 frames. I tried to keep
things simple and not contradict current CFA management logic nor
introduce too many corner cases.

Changes since V2[1]:
- Simplify cfa offset checking for BP and return address

[1] https://lkml.org/lkml/2020/9/28/354

Thanks,

Julien

Julien Thierry (3):
  objtool: check: Fully validate the stack frame
  objtool: check: Support addition to set CFA base
  objtool: check: Make SP memory operation match PUSH/POP semantics

 tools/objtool/check.c | 46 +++++++++++++++++++++++++++++++++++++++----
 1 file changed, 42 insertions(+), 4 deletions(-)

--
2.25.4


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v3 1/3] objtool: check: Fully validate the stack frame
  2020-10-14  7:37 [PATCH v3 0/3] objtool: Extend CFA updating/checking Julien Thierry
@ 2020-10-14  7:38 ` Julien Thierry
  2020-10-14  7:38 ` [PATCH v3 2/3] objtool: check: Support addition to set CFA base Julien Thierry
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Julien Thierry @ 2020-10-14  7:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: jpoimboe, peterz, mbenes, raphael.gault, benh, Julien Thierry

A valid stack frame should contain both the return address and the
previous frame pointer value.

On x86, the return value is placed on the stack by the calling
instructions. On other architectures, the callee need to explicitly
save the return address on the stack.

Add the necessary checks to verify a function properly sets up all the
elements of the stack frame.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
---
 tools/objtool/check.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index f50ffa243c72..87f10e726a75 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1671,12 +1671,20 @@ static bool has_modified_stack_frame(struct instruction *insn, struct insn_state
 	return false;
 }
 
+static bool check_reg_frame_pos(const struct cfi_reg *reg,
+				int expected_offset)
+{
+	return reg->base == CFI_CFA &&
+	       reg->offset == expected_offset;
+}
+
 static bool has_valid_stack_frame(struct insn_state *state)
 {
 	struct cfi_state *cfi = &state->cfi;
 
-	if (cfi->cfa.base == CFI_BP && cfi->regs[CFI_BP].base == CFI_CFA &&
-	    cfi->regs[CFI_BP].offset == -16)
+	if (cfi->cfa.base == CFI_BP &&
+	    check_reg_frame_pos(&cfi->regs[CFI_BP], -cfi->cfa.offset) &&
+	    check_reg_frame_pos(&cfi->regs[CFI_RA], -cfi->cfa.offset + 8))
 		return true;
 
 	if (cfi->drap && cfi->regs[CFI_BP].base == CFI_BP)
@@ -1805,8 +1813,7 @@ static int update_cfi_state(struct instruction *insn, struct cfi_state *cfi,
 		case OP_SRC_REG:
 			if (op->src.reg == CFI_SP && op->dest.reg == CFI_BP &&
 			    cfa->base == CFI_SP &&
-			    regs[CFI_BP].base == CFI_CFA &&
-			    regs[CFI_BP].offset == -cfa->offset) {
+			    check_reg_frame_pos(&regs[CFI_BP], -cfa->offset)) {
 
 				/* mov %rsp, %rbp */
 				cfa->base = op->dest.reg;
-- 
2.25.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v3 2/3] objtool: check: Support addition to set CFA base
  2020-10-14  7:37 [PATCH v3 0/3] objtool: Extend CFA updating/checking Julien Thierry
  2020-10-14  7:38 ` [PATCH v3 1/3] objtool: check: Fully validate the stack frame Julien Thierry
@ 2020-10-14  7:38 ` Julien Thierry
  2020-10-14  7:38 ` [PATCH v3 3/3] objtool: check: Make SP memory operation match PUSH/POP semantics Julien Thierry
  2020-10-14 12:30 ` [PATCH v3 0/3] objtool: Extend CFA updating/checking Peter Zijlstra
  3 siblings, 0 replies; 5+ messages in thread
From: Julien Thierry @ 2020-10-14  7:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: jpoimboe, peterz, mbenes, raphael.gault, benh, Julien Thierry

On arm64, the compiler can set the frame pointer either
with a move operation or with and add operation like:

    add (SP + constant), BP

For a simple move operation, the CFA base is changed from SP to BP.
Handle also changing the CFA base when the frame pointer is set with
an addition instruction.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
---
 tools/objtool/check.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 87f10e726a75..815aeb770930 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1898,6 +1898,17 @@ static int update_cfi_state(struct instruction *insn, struct cfi_state *cfi,
 				break;
 			}
 
+			if (!cfi->drap && op->src.reg == CFI_SP &&
+			    op->dest.reg == CFI_BP && cfa->base == CFI_SP &&
+			    check_reg_frame_pos(&regs[CFI_BP], -cfa->offset + op->src.offset)) {
+
+				/* lea disp(%rsp), %rbp */
+				cfa->base = CFI_BP;
+				cfa->offset -= op->src.offset;
+				cfi->bp_scratch = false;
+				break;
+			}
+
 			if (op->src.reg == CFI_SP && cfa->base == CFI_SP) {
 
 				/* drap: lea disp(%rsp), %drap */
-- 
2.25.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v3 3/3] objtool: check: Make SP memory operation match PUSH/POP semantics
  2020-10-14  7:37 [PATCH v3 0/3] objtool: Extend CFA updating/checking Julien Thierry
  2020-10-14  7:38 ` [PATCH v3 1/3] objtool: check: Fully validate the stack frame Julien Thierry
  2020-10-14  7:38 ` [PATCH v3 2/3] objtool: check: Support addition to set CFA base Julien Thierry
@ 2020-10-14  7:38 ` Julien Thierry
  2020-10-14 12:30 ` [PATCH v3 0/3] objtool: Extend CFA updating/checking Peter Zijlstra
  3 siblings, 0 replies; 5+ messages in thread
From: Julien Thierry @ 2020-10-14  7:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: jpoimboe, peterz, mbenes, raphael.gault, benh, Julien Thierry

Architectures without PUSH/POP instructions will always access the stack
though memory operations (SRC/DEST_INDIRECT). Make those operations have
the same effect on the CFA as PUSH/POP, with no stack pointer
modification.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
---
 tools/objtool/check.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 815aeb770930..32ee9902ade2 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -2003,6 +2003,14 @@ static int update_cfi_state(struct instruction *insn, struct cfi_state *cfi,
 			break;
 
 		case OP_SRC_REG_INDIRECT:
+			if (!cfi->drap && op->dest.reg == cfa->base &&
+			    op->dest.reg == CFI_BP) {
+
+				/* mov disp(%rsp), %rbp */
+				cfa->base = CFI_SP;
+				cfa->offset = cfi->stack_size;
+			}
+
 			if (cfi->drap && op->src.reg == CFI_BP &&
 			    op->src.offset == cfi->drap_offset) {
 
@@ -2024,6 +2032,12 @@ static int update_cfi_state(struct instruction *insn, struct cfi_state *cfi,
 				/* mov disp(%rbp), %reg */
 				/* mov disp(%rsp), %reg */
 				restore_reg(cfi, op->dest.reg);
+
+			} else if (op->src.reg == CFI_SP &&
+				   op->src.offset == regs[op->dest.reg].offset + cfi->stack_size) {
+
+				/* mov disp(%rsp), %reg */
+				restore_reg(cfi, op->dest.reg);
 			}
 
 			break;
@@ -2101,6 +2115,12 @@ static int update_cfi_state(struct instruction *insn, struct cfi_state *cfi,
 			/* mov reg, disp(%rsp) */
 			save_reg(cfi, op->src.reg, CFI_CFA,
 				 op->dest.offset - cfi->cfa.offset);
+
+		} else if (op->dest.reg == CFI_SP) {
+
+			/* mov reg, disp(%rsp) */
+			save_reg(cfi, op->src.reg, CFI_CFA,
+				 op->dest.offset - cfi->stack_size);
 		}
 
 		break;
-- 
2.25.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v3 0/3] objtool: Extend CFA updating/checking
  2020-10-14  7:37 [PATCH v3 0/3] objtool: Extend CFA updating/checking Julien Thierry
                   ` (2 preceding siblings ...)
  2020-10-14  7:38 ` [PATCH v3 3/3] objtool: check: Make SP memory operation match PUSH/POP semantics Julien Thierry
@ 2020-10-14 12:30 ` Peter Zijlstra
  3 siblings, 0 replies; 5+ messages in thread
From: Peter Zijlstra @ 2020-10-14 12:30 UTC (permalink / raw)
  To: Julien Thierry; +Cc: linux-kernel, jpoimboe, mbenes, raphael.gault, benh

On Wed, Oct 14, 2020 at 08:37:59AM +0100, Julien Thierry wrote:
> Julien Thierry (3):
>   objtool: check: Fully validate the stack frame
>   objtool: check: Support addition to set CFA base
>   objtool: check: Make SP memory operation match PUSH/POP semantics

Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-10-14 12:30 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-14  7:37 [PATCH v3 0/3] objtool: Extend CFA updating/checking Julien Thierry
2020-10-14  7:38 ` [PATCH v3 1/3] objtool: check: Fully validate the stack frame Julien Thierry
2020-10-14  7:38 ` [PATCH v3 2/3] objtool: check: Support addition to set CFA base Julien Thierry
2020-10-14  7:38 ` [PATCH v3 3/3] objtool: check: Make SP memory operation match PUSH/POP semantics Julien Thierry
2020-10-14 12:30 ` [PATCH v3 0/3] objtool: Extend CFA updating/checking Peter Zijlstra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).