diff options
Diffstat (limited to 'arch/x86/kernel/process.c')
| -rw-r--r-- | arch/x86/kernel/process.c | 21 | 
1 files changed, 20 insertions, 1 deletions
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 72015dba72ab..9f0909142a0a 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -51,6 +51,7 @@  #include <asm/unwind.h>  #include <asm/tdx.h>  #include <asm/mmu_context.h> +#include <asm/shstk.h>  #include "process.h" @@ -122,6 +123,7 @@ void exit_thread(struct task_struct *tsk)  	free_vm86(t); +	shstk_free(tsk);  	fpu__drop(fpu);  } @@ -162,6 +164,7 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)  	struct inactive_task_frame *frame;  	struct fork_frame *fork_frame;  	struct pt_regs *childregs; +	unsigned long new_ssp;  	int ret = 0;  	childregs = task_pt_regs(p); @@ -199,7 +202,16 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)  	frame->flags = X86_EFLAGS_FIXED;  #endif -	fpu_clone(p, clone_flags, args->fn); +	/* +	 * Allocate a new shadow stack for thread if needed. If shadow stack, +	 * is disabled, new_ssp will remain 0, and fpu_clone() will know not to +	 * update it. +	 */ +	new_ssp = shstk_alloc_thread_stack(p, clone_flags, args->stack_size); +	if (IS_ERR_VALUE(new_ssp)) +		return PTR_ERR((void *)new_ssp); + +	fpu_clone(p, clone_flags, args->fn, new_ssp);  	/* Kernel thread ? */  	if (unlikely(p->flags & PF_KTHREAD)) { @@ -245,6 +257,13 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)  	if (!ret && unlikely(test_tsk_thread_flag(current, TIF_IO_BITMAP)))  		io_bitmap_share(p); +	/* +	 * If copy_thread() if failing, don't leak the shadow stack possibly +	 * allocated in shstk_alloc_thread_stack() above. +	 */ +	if (ret) +		shstk_free(p); +  	return ret;  }  |