Skip to content

Commit 1713b63

Browse files
olsajirimhiramat
authored andcommitted
x86/shstk: Make return uprobe work with shadow stack
Currently the application with enabled shadow stack will crash if it sets up return uprobe. The reason is the uretprobe kernel code changes the user space task's stack, but does not update shadow stack accordingly. Adding new functions to update values on shadow stack and using them in uprobe code to keep shadow stack in sync with uretprobe changes to user stack. Link: https://lore.kernel.org/all/[email protected]/ Acked-by: Andrii Nakryiko <[email protected]> Acked-by: Rick Edgecombe <[email protected]> Reviewed-by: Oleg Nesterov <[email protected]> Fixes: 488af8e ("x86/shstk: Wire in shadow stack interface") Signed-off-by: Jiri Olsa <[email protected]> Signed-off-by: Masami Hiramatsu (Google) <[email protected]>
1 parent 1b3c86e commit 1713b63

File tree

3 files changed

+19
-1
lines changed

3 files changed

+19
-1
lines changed

arch/x86/include/asm/shstk.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ unsigned long shstk_alloc_thread_stack(struct task_struct *p, unsigned long clon
2121
void shstk_free(struct task_struct *p);
2222
int setup_signal_shadow_stack(struct ksignal *ksig);
2323
int restore_signal_shadow_stack(void);
24+
int shstk_update_last_frame(unsigned long val);
2425
#else
2526
static inline long shstk_prctl(struct task_struct *task, int option,
2627
unsigned long arg2) { return -EINVAL; }
@@ -31,6 +32,7 @@ static inline unsigned long shstk_alloc_thread_stack(struct task_struct *p,
3132
static inline void shstk_free(struct task_struct *p) {}
3233
static inline int setup_signal_shadow_stack(struct ksignal *ksig) { return 0; }
3334
static inline int restore_signal_shadow_stack(void) { return 0; }
35+
static inline int shstk_update_last_frame(unsigned long val) { return 0; }
3436
#endif /* CONFIG_X86_USER_SHADOW_STACK */
3537

3638
#endif /* __ASSEMBLY__ */

arch/x86/kernel/shstk.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,3 +577,14 @@ long shstk_prctl(struct task_struct *task, int option, unsigned long arg2)
577577
return wrss_control(true);
578578
return -EINVAL;
579579
}
580+
581+
int shstk_update_last_frame(unsigned long val)
582+
{
583+
unsigned long ssp;
584+
585+
if (!features_enabled(ARCH_SHSTK_SHSTK))
586+
return 0;
587+
588+
ssp = get_user_shstk_addr();
589+
return write_user_shstk_64((u64 __user *)ssp, (u64)val);
590+
}

arch/x86/kernel/uprobes.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1076,8 +1076,13 @@ arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs
10761076
return orig_ret_vaddr;
10771077

10781078
nleft = copy_to_user((void __user *)regs->sp, &trampoline_vaddr, rasize);
1079-
if (likely(!nleft))
1079+
if (likely(!nleft)) {
1080+
if (shstk_update_last_frame(trampoline_vaddr)) {
1081+
force_sig(SIGSEGV);
1082+
return -1;
1083+
}
10801084
return orig_ret_vaddr;
1085+
}
10811086

10821087
if (nleft != rasize) {
10831088
pr_err("return address clobbered: pid=%d, %%sp=%#lx, %%ip=%#lx\n",

0 commit comments

Comments
 (0)