Message ID | 20200108185634.1163-6-mark.rutland@arm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | arm64: entry deasmification and cleanup | expand |
On 01/09/2020 12:26 AM, Mark Rutland wrote: > In some cases, we want to call a function from C code, using an > alternative stack. Add a helper that we can use in such cases. > > Signed-off-by: Mark Rutland <mark.rutland@arm.com> > Cc: Catalin Marinas <catalin.marinas@arm.com> > Cc: James Morse <james.morse@arm.com> > Cc: Will Deacon <will@kernel.org> > --- > arch/arm64/include/asm/exception.h | 2 ++ > arch/arm64/kernel/entry.S | 21 +++++++++++++++++++++ > 2 files changed, 23 insertions(+) > > diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h > index b87c6e276ab1..a49038fa4faf 100644 > --- a/arch/arm64/include/asm/exception.h > +++ b/arch/arm64/include/asm/exception.h > @@ -31,6 +31,8 @@ static inline u32 disr_to_esr(u64 disr) > return esr; > } > > +asmlinkage void call_on_stack(struct pt_regs *, void (*)(struct pt_regs *), > + unsigned long); > asmlinkage void enter_from_user_mode(void); > void do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs); > void do_sp_pc_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs); > diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S > index 53ce1877a4aa..184313c773ea 100644 > --- a/arch/arm64/kernel/entry.S > +++ b/arch/arm64/kernel/entry.S > @@ -901,6 +901,27 @@ ENTRY(ret_from_fork) > ENDPROC(ret_from_fork) > NOKPROBE(ret_from_fork) > > +/* > + * x0 = argument to function A small nit. Though the definition here itself does not limit the argument type, it might worth to mention that to be struct pt_regs per the previous declaration. > + * x1 = function to call > + * x2 = new stack pointer > + */ > +ENTRY(call_on_stack) > + /* Create a frame record to save our LR and SP (implicit in FP) */ > + stp x29, x30, [sp, #-16]! > + mov x29, sp > + > + /* Move to the new stack and call the function there */ > + mov sp, x2 > + blr x1 > + > + /* Restore SP from the FP, FP and LR from the record, and return */ > + mov sp, x29 > + ldp x29, x30, [sp], #16 > + ret > +ENDPROC(call_on_stack) > +NOKPROBE(call_on_stack) > + > #ifdef CONFIG_ARM_SDE_INTERFACE > > #include <asm/sdei.h> > Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
On 1/8/20 1:56 PM, Mark Rutland wrote: > In some cases, we want to call a function from C code, using an > alternative stack. Add a helper that we can use in such cases. > > Signed-off-by: Mark Rutland <mark.rutland@arm.com> > Cc: Catalin Marinas <catalin.marinas@arm.com> > Cc: James Morse <james.morse@arm.com> > Cc: Will Deacon <will@kernel.org> > --- > arch/arm64/include/asm/exception.h | 2 ++ > arch/arm64/kernel/entry.S | 21 +++++++++++++++++++++ > 2 files changed, 23 insertions(+) > > diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h > index b87c6e276ab1..a49038fa4faf 100644 > --- a/arch/arm64/include/asm/exception.h > +++ b/arch/arm64/include/asm/exception.h > @@ -31,6 +31,8 @@ static inline u32 disr_to_esr(u64 disr) > return esr; > } > > +asmlinkage void call_on_stack(struct pt_regs *, void (*)(struct pt_regs *), > + unsigned long); > asmlinkage void enter_from_user_mode(void); > void do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs); > void do_sp_pc_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs); > diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S > index 53ce1877a4aa..184313c773ea 100644 > --- a/arch/arm64/kernel/entry.S > +++ b/arch/arm64/kernel/entry.S > @@ -901,6 +901,27 @@ ENTRY(ret_from_fork) > ENDPROC(ret_from_fork) > NOKPROBE(ret_from_fork) > > +/* > + * x0 = argument to function > + * x1 = function to call > + * x2 = new stack pointer > + */ > +ENTRY(call_on_stack) > + /* Create a frame record to save our LR and SP (implicit in FP) */ > + stp x29, x30, [sp, #-16]! > + mov x29, sp > + > + /* Move to the new stack and call the function there */ > + mov sp, x2 > + blr x1 > + > + /* Restore SP from the FP, FP and LR from the record, and return */ > + mov sp, x29 > + ldp x29, x30, [sp], #16 > + ret > +ENDPROC(call_on_stack) > +NOKPROBE(call_on_stack) > + > #ifdef CONFIG_ARM_SDE_INTERFACE > > #include <asm/sdei.h> > I'm a little worried this makes a very tempting gadget for attackers to use. Maybe future security features will make this less vulnerable? Thanks, Laura
On Thu, Jan 09, 2020 at 09:30:13AM -0500, Laura Abbott wrote: > On 1/8/20 1:56 PM, Mark Rutland wrote: > > In some cases, we want to call a function from C code, using an > > alternative stack. Add a helper that we can use in such cases. > > > > Signed-off-by: Mark Rutland <mark.rutland@arm.com> > > Cc: Catalin Marinas <catalin.marinas@arm.com> > > Cc: James Morse <james.morse@arm.com> > > Cc: Will Deacon <will@kernel.org> > > --- > > arch/arm64/include/asm/exception.h | 2 ++ > > arch/arm64/kernel/entry.S | 21 +++++++++++++++++++++ > > 2 files changed, 23 insertions(+) > > > > diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h > > index b87c6e276ab1..a49038fa4faf 100644 > > --- a/arch/arm64/include/asm/exception.h > > +++ b/arch/arm64/include/asm/exception.h > > @@ -31,6 +31,8 @@ static inline u32 disr_to_esr(u64 disr) > > return esr; > > } > > +asmlinkage void call_on_stack(struct pt_regs *, void (*)(struct pt_regs *), > > + unsigned long); > > asmlinkage void enter_from_user_mode(void); > > void do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs); > > void do_sp_pc_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs); > > diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S > > index 53ce1877a4aa..184313c773ea 100644 > > --- a/arch/arm64/kernel/entry.S > > +++ b/arch/arm64/kernel/entry.S > > @@ -901,6 +901,27 @@ ENTRY(ret_from_fork) > > ENDPROC(ret_from_fork) > > NOKPROBE(ret_from_fork) > > +/* > > + * x0 = argument to function > > + * x1 = function to call > > + * x2 = new stack pointer > > + */ > > +ENTRY(call_on_stack) > > + /* Create a frame record to save our LR and SP (implicit in FP) */ > > + stp x29, x30, [sp, #-16]! > > + mov x29, sp > > + > > + /* Move to the new stack and call the function there */ > > + mov sp, x2 > > + blr x1 > > + > > + /* Restore SP from the FP, FP and LR from the record, and return */ > > + mov sp, x29 > > + ldp x29, x30, [sp], #16 > > + ret > > +ENDPROC(call_on_stack) > > +NOKPROBE(call_on_stack) > > + > > #ifdef CONFIG_ARM_SDE_INTERFACE > > #include <asm/sdei.h> > > > > I'm a little worried this makes a very tempting gadget for > attackers to use. Maybe future security features will > make this less vulnerable? With BTI we'll have to add a target identifier to the start of the function, but that's about it. As a gadget, I think it's similar to the existing cpu_switch_to(). If we could protect assembly functions with CFI somehow that'd be great for both. Thanks, Mark.
On Thu, Jan 09, 2020 at 01:30:02PM +0530, Anshuman Khandual wrote: > > > On 01/09/2020 12:26 AM, Mark Rutland wrote: > > In some cases, we want to call a function from C code, using an > > alternative stack. Add a helper that we can use in such cases. > > > > Signed-off-by: Mark Rutland <mark.rutland@arm.com> > > Cc: Catalin Marinas <catalin.marinas@arm.com> > > Cc: James Morse <james.morse@arm.com> > > Cc: Will Deacon <will@kernel.org> > > --- > > arch/arm64/include/asm/exception.h | 2 ++ > > arch/arm64/kernel/entry.S | 21 +++++++++++++++++++++ > > 2 files changed, 23 insertions(+) > > > > diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h > > index b87c6e276ab1..a49038fa4faf 100644 > > --- a/arch/arm64/include/asm/exception.h > > +++ b/arch/arm64/include/asm/exception.h > > @@ -31,6 +31,8 @@ static inline u32 disr_to_esr(u64 disr) > > return esr; > > } > > > > +asmlinkage void call_on_stack(struct pt_regs *, void (*)(struct pt_regs *), > > + unsigned long); > > asmlinkage void enter_from_user_mode(void); > > void do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs); > > void do_sp_pc_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs); > > diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S > > index 53ce1877a4aa..184313c773ea 100644 > > --- a/arch/arm64/kernel/entry.S > > +++ b/arch/arm64/kernel/entry.S > > @@ -901,6 +901,27 @@ ENTRY(ret_from_fork) > > ENDPROC(ret_from_fork) > > NOKPROBE(ret_from_fork) > > > > +/* > > + * x0 = argument to function > > A small nit. Though the definition here itself does not limit the > argument type, it might worth to mention that to be struct pt_regs > per the previous declaration. > True. To make this clearer, I've given the C prototype instead, as we do for the SMCCC wrappers: /* * void call_on_stack(struct pt_regs *regs, * void (*func)(struct pt_regs *), * unsigned long new_sp) * * Calls func(regs) using new_sp as the initial stack pointer. */ > > +ENTRY(call_on_stack) > > + /* Create a frame record to save our LR and SP (implicit in FP) */ > > + stp x29, x30, [sp, #-16]! > > + mov x29, sp > > + > > + /* Move to the new stack and call the function there */ > > + mov sp, x2 > > + blr x1 > > + > > + /* Restore SP from the FP, FP and LR from the record, and return */ > > + mov sp, x29 > > + ldp x29, x30, [sp], #16 > > + ret > > +ENDPROC(call_on_stack) > > +NOKPROBE(call_on_stack) > > + > > #ifdef CONFIG_ARM_SDE_INTERFACE > > > > #include <asm/sdei.h> > > > > Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com> Thanks! Mark.
diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h index b87c6e276ab1..a49038fa4faf 100644 --- a/arch/arm64/include/asm/exception.h +++ b/arch/arm64/include/asm/exception.h @@ -31,6 +31,8 @@ static inline u32 disr_to_esr(u64 disr) return esr; } +asmlinkage void call_on_stack(struct pt_regs *, void (*)(struct pt_regs *), + unsigned long); asmlinkage void enter_from_user_mode(void); void do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs); void do_sp_pc_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs); diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 53ce1877a4aa..184313c773ea 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -901,6 +901,27 @@ ENTRY(ret_from_fork) ENDPROC(ret_from_fork) NOKPROBE(ret_from_fork) +/* + * x0 = argument to function + * x1 = function to call + * x2 = new stack pointer + */ +ENTRY(call_on_stack) + /* Create a frame record to save our LR and SP (implicit in FP) */ + stp x29, x30, [sp, #-16]! + mov x29, sp + + /* Move to the new stack and call the function there */ + mov sp, x2 + blr x1 + + /* Restore SP from the FP, FP and LR from the record, and return */ + mov sp, x29 + ldp x29, x30, [sp], #16 + ret +ENDPROC(call_on_stack) +NOKPROBE(call_on_stack) + #ifdef CONFIG_ARM_SDE_INTERFACE #include <asm/sdei.h>
In some cases, we want to call a function from C code, using an alternative stack. Add a helper that we can use in such cases. Signed-off-by: Mark Rutland <mark.rutland@arm.com> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: James Morse <james.morse@arm.com> Cc: Will Deacon <will@kernel.org> --- arch/arm64/include/asm/exception.h | 2 ++ arch/arm64/kernel/entry.S | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+)