diff options
Diffstat (limited to 'arch/x86/kernel/signal.c')
| -rw-r--r-- | arch/x86/kernel/signal.c | 403 | 
1 files changed, 187 insertions, 216 deletions
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 8a29573851a3..83b74fb38c8f 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -42,29 +42,9 @@  #endif /* CONFIG_X86_64 */  #include <asm/syscall.h> -#include <asm/syscalls.h> -  #include <asm/sigframe.h>  #include <asm/signal.h> -#define COPY(x)			do {			\ -	get_user_ex(regs->x, &sc->x);			\ -} while (0) - -#define GET_SEG(seg)		({			\ -	unsigned short tmp;				\ -	get_user_ex(tmp, &sc->seg);			\ -	tmp;						\ -}) - -#define COPY_SEG(seg)		do {			\ -	regs->seg = GET_SEG(seg);			\ -} while (0) - -#define COPY_SEG_CPL3(seg)	do {			\ -	regs->seg = GET_SEG(seg) | 3;			\ -} while (0) -  #ifdef CONFIG_X86_64  /*   * If regs->ss will cause an IRET fault, change it.  Otherwise leave it @@ -92,53 +72,58 @@ static void force_valid_ss(struct pt_regs *regs)  	    ar != (AR_DPL3 | AR_S | AR_P | AR_TYPE_RWDATA_EXPDOWN))  		regs->ss = __USER_DS;  } +# define CONTEXT_COPY_SIZE	offsetof(struct sigcontext, reserved1) +#else +# define CONTEXT_COPY_SIZE	sizeof(struct sigcontext)  #endif  static int restore_sigcontext(struct pt_regs *regs, -			      struct sigcontext __user *sc, +			      struct sigcontext __user *usc,  			      unsigned long uc_flags)  { -	unsigned long buf_val; -	void __user *buf; -	unsigned int tmpflags; -	unsigned int err = 0; +	struct sigcontext sc;  	/* Always make any pending restarted system calls return -EINTR */  	current->restart_block.fn = do_no_restart_syscall; -	get_user_try { +	if (copy_from_user(&sc, usc, CONTEXT_COPY_SIZE)) +		return -EFAULT;  #ifdef CONFIG_X86_32 -		set_user_gs(regs, GET_SEG(gs)); -		COPY_SEG(fs); -		COPY_SEG(es); -		COPY_SEG(ds); +	set_user_gs(regs, sc.gs); +	regs->fs = sc.fs; +	regs->es = sc.es; +	regs->ds = sc.ds;  #endif /* CONFIG_X86_32 */ -		COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); -		COPY(dx); COPY(cx); COPY(ip); COPY(ax); +	regs->bx = sc.bx; +	regs->cx = sc.cx; +	regs->dx = sc.dx; +	regs->si = sc.si; +	regs->di = sc.di; +	regs->bp = sc.bp; +	regs->ax = sc.ax; +	regs->sp = sc.sp; +	regs->ip = sc.ip;  #ifdef CONFIG_X86_64 -		COPY(r8); -		COPY(r9); -		COPY(r10); -		COPY(r11); -		COPY(r12); -		COPY(r13); -		COPY(r14); -		COPY(r15); +	regs->r8 = sc.r8; +	regs->r9 = sc.r9; +	regs->r10 = sc.r10; +	regs->r11 = sc.r11; +	regs->r12 = sc.r12; +	regs->r13 = sc.r13; +	regs->r14 = sc.r14; +	regs->r15 = sc.r15;  #endif /* CONFIG_X86_64 */ -		COPY_SEG_CPL3(cs); -		COPY_SEG_CPL3(ss); - -		get_user_ex(tmpflags, &sc->flags); -		regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); -		regs->orig_ax = -1;		/* disable syscall checks */ +	/* Get CS/SS and force CPL3 */ +	regs->cs = sc.cs | 0x03; +	regs->ss = sc.ss | 0x03; -		get_user_ex(buf_val, &sc->fpstate); -		buf = (void __user *)buf_val; -	} get_user_catch(err); +	regs->flags = (regs->flags & ~FIX_EFLAGS) | (sc.flags & FIX_EFLAGS); +	/* disable syscall checks */ +	regs->orig_ax = -1;  #ifdef CONFIG_X86_64  	/* @@ -149,70 +134,78 @@ static int restore_sigcontext(struct pt_regs *regs,  		force_valid_ss(regs);  #endif -	err |= fpu__restore_sig(buf, IS_ENABLED(CONFIG_X86_32)); - -	return err; +	return fpu__restore_sig((void __user *)sc.fpstate, +			       IS_ENABLED(CONFIG_X86_32));  } -int setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate, +static __always_inline int +__unsafe_setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,  		     struct pt_regs *regs, unsigned long mask)  { -	int err = 0; - -	put_user_try { -  #ifdef CONFIG_X86_32 -		put_user_ex(get_user_gs(regs), (unsigned int __user *)&sc->gs); -		put_user_ex(regs->fs, (unsigned int __user *)&sc->fs); -		put_user_ex(regs->es, (unsigned int __user *)&sc->es); -		put_user_ex(regs->ds, (unsigned int __user *)&sc->ds); +	unsafe_put_user(get_user_gs(regs), +				  (unsigned int __user *)&sc->gs, Efault); +	unsafe_put_user(regs->fs, (unsigned int __user *)&sc->fs, Efault); +	unsafe_put_user(regs->es, (unsigned int __user *)&sc->es, Efault); +	unsafe_put_user(regs->ds, (unsigned int __user *)&sc->ds, Efault);  #endif /* CONFIG_X86_32 */ -		put_user_ex(regs->di, &sc->di); -		put_user_ex(regs->si, &sc->si); -		put_user_ex(regs->bp, &sc->bp); -		put_user_ex(regs->sp, &sc->sp); -		put_user_ex(regs->bx, &sc->bx); -		put_user_ex(regs->dx, &sc->dx); -		put_user_ex(regs->cx, &sc->cx); -		put_user_ex(regs->ax, &sc->ax); +	unsafe_put_user(regs->di, &sc->di, Efault); +	unsafe_put_user(regs->si, &sc->si, Efault); +	unsafe_put_user(regs->bp, &sc->bp, Efault); +	unsafe_put_user(regs->sp, &sc->sp, Efault); +	unsafe_put_user(regs->bx, &sc->bx, Efault); +	unsafe_put_user(regs->dx, &sc->dx, Efault); +	unsafe_put_user(regs->cx, &sc->cx, Efault); +	unsafe_put_user(regs->ax, &sc->ax, Efault);  #ifdef CONFIG_X86_64 -		put_user_ex(regs->r8, &sc->r8); -		put_user_ex(regs->r9, &sc->r9); -		put_user_ex(regs->r10, &sc->r10); -		put_user_ex(regs->r11, &sc->r11); -		put_user_ex(regs->r12, &sc->r12); -		put_user_ex(regs->r13, &sc->r13); -		put_user_ex(regs->r14, &sc->r14); -		put_user_ex(regs->r15, &sc->r15); +	unsafe_put_user(regs->r8, &sc->r8, Efault); +	unsafe_put_user(regs->r9, &sc->r9, Efault); +	unsafe_put_user(regs->r10, &sc->r10, Efault); +	unsafe_put_user(regs->r11, &sc->r11, Efault); +	unsafe_put_user(regs->r12, &sc->r12, Efault); +	unsafe_put_user(regs->r13, &sc->r13, Efault); +	unsafe_put_user(regs->r14, &sc->r14, Efault); +	unsafe_put_user(regs->r15, &sc->r15, Efault);  #endif /* CONFIG_X86_64 */ -		put_user_ex(current->thread.trap_nr, &sc->trapno); -		put_user_ex(current->thread.error_code, &sc->err); -		put_user_ex(regs->ip, &sc->ip); +	unsafe_put_user(current->thread.trap_nr, &sc->trapno, Efault); +	unsafe_put_user(current->thread.error_code, &sc->err, Efault); +	unsafe_put_user(regs->ip, &sc->ip, Efault);  #ifdef CONFIG_X86_32 -		put_user_ex(regs->cs, (unsigned int __user *)&sc->cs); -		put_user_ex(regs->flags, &sc->flags); -		put_user_ex(regs->sp, &sc->sp_at_signal); -		put_user_ex(regs->ss, (unsigned int __user *)&sc->ss); +	unsafe_put_user(regs->cs, (unsigned int __user *)&sc->cs, Efault); +	unsafe_put_user(regs->flags, &sc->flags, Efault); +	unsafe_put_user(regs->sp, &sc->sp_at_signal, Efault); +	unsafe_put_user(regs->ss, (unsigned int __user *)&sc->ss, Efault);  #else /* !CONFIG_X86_32 */ -		put_user_ex(regs->flags, &sc->flags); -		put_user_ex(regs->cs, &sc->cs); -		put_user_ex(0, &sc->gs); -		put_user_ex(0, &sc->fs); -		put_user_ex(regs->ss, &sc->ss); +	unsafe_put_user(regs->flags, &sc->flags, Efault); +	unsafe_put_user(regs->cs, &sc->cs, Efault); +	unsafe_put_user(0, &sc->gs, Efault); +	unsafe_put_user(0, &sc->fs, Efault); +	unsafe_put_user(regs->ss, &sc->ss, Efault);  #endif /* CONFIG_X86_32 */ -		put_user_ex(fpstate, (unsigned long __user *)&sc->fpstate); - -		/* non-iBCS2 extensions.. */ -		put_user_ex(mask, &sc->oldmask); -		put_user_ex(current->thread.cr2, &sc->cr2); -	} put_user_catch(err); +	unsafe_put_user(fpstate, (unsigned long __user *)&sc->fpstate, Efault); -	return err; +	/* non-iBCS2 extensions.. */ +	unsafe_put_user(mask, &sc->oldmask, Efault); +	unsafe_put_user(current->thread.cr2, &sc->cr2, Efault); +	return 0; +Efault: +	return -EFAULT;  } +#define unsafe_put_sigcontext(sc, fp, regs, set, label)			\ +do {									\ +	if (__unsafe_setup_sigcontext(sc, fp, regs, set->sig[0]))	\ +		goto label;						\ +} while(0); + +#define unsafe_put_sigmask(set, frame, label) \ +	unsafe_put_user(*(__u64 *)(set), \ +			(__u64 __user *)&(frame)->uc.uc_sigmask, \ +			label) +  /*   * Set up a signal frame.   */ @@ -312,26 +305,16 @@ __setup_frame(int sig, struct ksignal *ksig, sigset_t *set,  {  	struct sigframe __user *frame;  	void __user *restorer; -	int err = 0; -	void __user *fpstate = NULL; - -	frame = get_sigframe(&ksig->ka, regs, sizeof(*frame), &fpstate); - -	if (!access_ok(frame, sizeof(*frame))) -		return -EFAULT; +	void __user *fp = NULL; -	if (__put_user(sig, &frame->sig)) -		return -EFAULT; +	frame = get_sigframe(&ksig->ka, regs, sizeof(*frame), &fp); -	if (setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0])) +	if (!user_access_begin(frame, sizeof(*frame)))  		return -EFAULT; -	if (_NSIG_WORDS > 1) { -		if (__copy_to_user(&frame->extramask, &set->sig[1], -				   sizeof(frame->extramask))) -			return -EFAULT; -	} - +	unsafe_put_user(sig, &frame->sig, Efault); +	unsafe_put_sigcontext(&frame->sc, fp, regs, set, Efault); +	unsafe_put_user(set->sig[1], &frame->extramask[0], Efault);  	if (current->mm->context.vdso)  		restorer = current->mm->context.vdso +  			vdso_image_32.sym___kernel_sigreturn; @@ -341,7 +324,7 @@ __setup_frame(int sig, struct ksignal *ksig, sigset_t *set,  		restorer = ksig->ka.sa.sa_restorer;  	/* Set up to return from userspace.  */ -	err |= __put_user(restorer, &frame->pretcode); +	unsafe_put_user(restorer, &frame->pretcode, Efault);  	/*  	 * This is popl %eax ; movl $__NR_sigreturn, %eax ; int $0x80 @@ -350,10 +333,8 @@ __setup_frame(int sig, struct ksignal *ksig, sigset_t *set,  	 * reasons and because gdb uses it as a signature to notice  	 * signal handler stack frames.  	 */ -	err |= __put_user(*((u64 *)&retcode), (u64 *)frame->retcode); - -	if (err) -		return -EFAULT; +	unsafe_put_user(*((u64 *)&retcode), (u64 *)frame->retcode, Efault); +	user_access_end();  	/* Set up registers for signal handler */  	regs->sp = (unsigned long)frame; @@ -368,6 +349,10 @@ __setup_frame(int sig, struct ksignal *ksig, sigset_t *set,  	regs->cs = __USER_CS;  	return 0; + +Efault: +	user_access_end(); +	return -EFAULT;  }  static int __setup_rt_frame(int sig, struct ksignal *ksig, @@ -375,50 +360,45 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig,  {  	struct rt_sigframe __user *frame;  	void __user *restorer; -	int err = 0; -	void __user *fpstate = NULL; +	void __user *fp = NULL; -	frame = get_sigframe(&ksig->ka, regs, sizeof(*frame), &fpstate); +	frame = get_sigframe(&ksig->ka, regs, sizeof(*frame), &fp); -	if (!access_ok(frame, sizeof(*frame))) +	if (!user_access_begin(frame, sizeof(*frame)))  		return -EFAULT; -	put_user_try { -		put_user_ex(sig, &frame->sig); -		put_user_ex(&frame->info, &frame->pinfo); -		put_user_ex(&frame->uc, &frame->puc); +	unsafe_put_user(sig, &frame->sig, Efault); +	unsafe_put_user(&frame->info, &frame->pinfo, Efault); +	unsafe_put_user(&frame->uc, &frame->puc, Efault); -		/* Create the ucontext.  */ -		if (static_cpu_has(X86_FEATURE_XSAVE)) -			put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags); -		else -			put_user_ex(0, &frame->uc.uc_flags); -		put_user_ex(0, &frame->uc.uc_link); -		save_altstack_ex(&frame->uc.uc_stack, regs->sp); +	/* Create the ucontext.  */ +	if (static_cpu_has(X86_FEATURE_XSAVE)) +		unsafe_put_user(UC_FP_XSTATE, &frame->uc.uc_flags, Efault); +	else +		unsafe_put_user(0, &frame->uc.uc_flags, Efault); +	unsafe_put_user(0, &frame->uc.uc_link, Efault); +	unsafe_save_altstack(&frame->uc.uc_stack, regs->sp, Efault); -		/* Set up to return from userspace.  */ -		restorer = current->mm->context.vdso + -			vdso_image_32.sym___kernel_rt_sigreturn; -		if (ksig->ka.sa.sa_flags & SA_RESTORER) -			restorer = ksig->ka.sa.sa_restorer; -		put_user_ex(restorer, &frame->pretcode); +	/* Set up to return from userspace.  */ +	restorer = current->mm->context.vdso + +		vdso_image_32.sym___kernel_rt_sigreturn; +	if (ksig->ka.sa.sa_flags & SA_RESTORER) +		restorer = ksig->ka.sa.sa_restorer; +	unsafe_put_user(restorer, &frame->pretcode, Efault); -		/* -		 * This is movl $__NR_rt_sigreturn, %ax ; int $0x80 -		 * -		 * WE DO NOT USE IT ANY MORE! It's only left here for historical -		 * reasons and because gdb uses it as a signature to notice -		 * signal handler stack frames. -		 */ -		put_user_ex(*((u64 *)&rt_retcode), (u64 *)frame->retcode); -	} put_user_catch(err); +	/* +	 * This is movl $__NR_rt_sigreturn, %ax ; int $0x80 +	 * +	 * WE DO NOT USE IT ANY MORE! It's only left here for historical +	 * reasons and because gdb uses it as a signature to notice +	 * signal handler stack frames. +	 */ +	unsafe_put_user(*((u64 *)&rt_retcode), (u64 *)frame->retcode, Efault); +	unsafe_put_sigcontext(&frame->uc.uc_mcontext, fp, regs, set, Efault); +	unsafe_put_sigmask(set, frame, Efault); +	user_access_end(); -	err |= copy_siginfo_to_user(&frame->info, &ksig->info); -	err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate, -				regs, set->sig[0]); -	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); - -	if (err) +	if (copy_siginfo_to_user(&frame->info, &ksig->info))  		return -EFAULT;  	/* Set up registers for signal handler */ @@ -434,6 +414,9 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig,  	regs->cs = __USER_CS;  	return 0; +Efault: +	user_access_end(); +	return -EFAULT;  }  #else /* !CONFIG_X86_32 */  static unsigned long frame_uc_flags(struct pt_regs *regs) @@ -457,43 +440,34 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig,  	struct rt_sigframe __user *frame;  	void __user *fp = NULL;  	unsigned long uc_flags; -	int err = 0; + +	/* x86-64 should always use SA_RESTORER. */ +	if (!(ksig->ka.sa.sa_flags & SA_RESTORER)) +		return -EFAULT;  	frame = get_sigframe(&ksig->ka, regs, sizeof(struct rt_sigframe), &fp); +	uc_flags = frame_uc_flags(regs); -	if (!access_ok(frame, sizeof(*frame))) +	if (!user_access_begin(frame, sizeof(*frame)))  		return -EFAULT; +	/* Create the ucontext.  */ +	unsafe_put_user(uc_flags, &frame->uc.uc_flags, Efault); +	unsafe_put_user(0, &frame->uc.uc_link, Efault); +	unsafe_save_altstack(&frame->uc.uc_stack, regs->sp, Efault); + +	/* Set up to return from userspace.  If provided, use a stub +	   already in userspace.  */ +	unsafe_put_user(ksig->ka.sa.sa_restorer, &frame->pretcode, Efault); +	unsafe_put_sigcontext(&frame->uc.uc_mcontext, fp, regs, set, Efault); +	unsafe_put_sigmask(set, frame, Efault); +	user_access_end(); +  	if (ksig->ka.sa.sa_flags & SA_SIGINFO) {  		if (copy_siginfo_to_user(&frame->info, &ksig->info))  			return -EFAULT;  	} -	uc_flags = frame_uc_flags(regs); - -	put_user_try { -		/* Create the ucontext.  */ -		put_user_ex(uc_flags, &frame->uc.uc_flags); -		put_user_ex(0, &frame->uc.uc_link); -		save_altstack_ex(&frame->uc.uc_stack, regs->sp); - -		/* Set up to return from userspace.  If provided, use a stub -		   already in userspace.  */ -		/* x86-64 should always use SA_RESTORER. */ -		if (ksig->ka.sa.sa_flags & SA_RESTORER) { -			put_user_ex(ksig->ka.sa.sa_restorer, &frame->pretcode); -		} else { -			/* could use a vstub here */ -			err |= -EFAULT; -		} -	} put_user_catch(err); - -	err |= setup_sigcontext(&frame->uc.uc_mcontext, fp, regs, set->sig[0]); -	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); - -	if (err) -		return -EFAULT; -  	/* Set up registers for signal handler */  	regs->di = sig;  	/* In case the signal handler was declared without prototypes */ @@ -530,6 +504,10 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig,  		force_valid_ss(regs);  	return 0; + +Efault: +	user_access_end(); +	return -EFAULT;  }  #endif /* CONFIG_X86_32 */ @@ -541,44 +519,33 @@ static int x32_setup_rt_frame(struct ksignal *ksig,  	struct rt_sigframe_x32 __user *frame;  	unsigned long uc_flags;  	void __user *restorer; -	int err = 0; -	void __user *fpstate = NULL; - -	frame = get_sigframe(&ksig->ka, regs, sizeof(*frame), &fpstate); +	void __user *fp = NULL; -	if (!access_ok(frame, sizeof(*frame))) +	if (!(ksig->ka.sa.sa_flags & SA_RESTORER))  		return -EFAULT; -	if (ksig->ka.sa.sa_flags & SA_SIGINFO) { -		if (__copy_siginfo_to_user32(&frame->info, &ksig->info, true)) -			return -EFAULT; -	} +	frame = get_sigframe(&ksig->ka, regs, sizeof(*frame), &fp);  	uc_flags = frame_uc_flags(regs); -	put_user_try { -		/* Create the ucontext.  */ -		put_user_ex(uc_flags, &frame->uc.uc_flags); -		put_user_ex(0, &frame->uc.uc_link); -		compat_save_altstack_ex(&frame->uc.uc_stack, regs->sp); -		put_user_ex(0, &frame->uc.uc__pad0); - -		if (ksig->ka.sa.sa_flags & SA_RESTORER) { -			restorer = ksig->ka.sa.sa_restorer; -		} else { -			/* could use a vstub here */ -			restorer = NULL; -			err |= -EFAULT; -		} -		put_user_ex(restorer, (unsigned long __user *)&frame->pretcode); -	} put_user_catch(err); +	if (!user_access_begin(frame, sizeof(*frame))) +		return -EFAULT; -	err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate, -				regs, set->sig[0]); -	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); +	/* Create the ucontext.  */ +	unsafe_put_user(uc_flags, &frame->uc.uc_flags, Efault); +	unsafe_put_user(0, &frame->uc.uc_link, Efault); +	unsafe_compat_save_altstack(&frame->uc.uc_stack, regs->sp, Efault); +	unsafe_put_user(0, &frame->uc.uc__pad0, Efault); +	restorer = ksig->ka.sa.sa_restorer; +	unsafe_put_user(restorer, (unsigned long __user *)&frame->pretcode, Efault); +	unsafe_put_sigcontext(&frame->uc.uc_mcontext, fp, regs, set, Efault); +	unsafe_put_sigmask(set, frame, Efault); +	user_access_end(); -	if (err) -		return -EFAULT; +	if (ksig->ka.sa.sa_flags & SA_SIGINFO) { +		if (__copy_siginfo_to_user32(&frame->info, &ksig->info, true)) +			return -EFAULT; +	}  	/* Set up registers for signal handler */  	regs->sp = (unsigned long) frame; @@ -597,6 +564,11 @@ static int x32_setup_rt_frame(struct ksignal *ksig,  #endif	/* CONFIG_X86_X32_ABI */  	return 0; +#ifdef CONFIG_X86_X32_ABI +Efault: +	user_access_end(); +	return -EFAULT; +#endif  }  /* @@ -613,9 +585,8 @@ SYSCALL_DEFINE0(sigreturn)  	if (!access_ok(frame, sizeof(*frame)))  		goto badframe; -	if (__get_user(set.sig[0], &frame->sc.oldmask) || (_NSIG_WORDS > 1 -		&& __copy_from_user(&set.sig[1], &frame->extramask, -				    sizeof(frame->extramask)))) +	if (__get_user(set.sig[0], &frame->sc.oldmask) || +	    __get_user(set.sig[1], &frame->extramask[0]))  		goto badframe;  	set_current_blocked(&set); @@ -645,7 +616,7 @@ SYSCALL_DEFINE0(rt_sigreturn)  	frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long));  	if (!access_ok(frame, sizeof(*frame)))  		goto badframe; -	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) +	if (__get_user(*(__u64 *)&set, (__u64 __user *)&frame->uc.uc_sigmask))  		goto badframe;  	if (__get_user(uc_flags, &frame->uc.uc_flags))  		goto badframe; @@ -859,7 +830,7 @@ void signal_fault(struct pt_regs *regs, void __user *frame, char *where)  }  #ifdef CONFIG_X86_X32_ABI -asmlinkage long sys32_x32_rt_sigreturn(void) +COMPAT_SYSCALL_DEFINE0(x32_rt_sigreturn)  {  	struct pt_regs *regs = current_pt_regs();  	struct rt_sigframe_x32 __user *frame; @@ -870,7 +841,7 @@ asmlinkage long sys32_x32_rt_sigreturn(void)  	if (!access_ok(frame, sizeof(*frame)))  		goto badframe; -	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) +	if (__get_user(set.sig[0], (__u64 __user *)&frame->uc.uc_sigmask))  		goto badframe;  	if (__get_user(uc_flags, &frame->uc.uc_flags))  		goto badframe;  |