ia32_signal.c 15.6 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*
 *  linux/arch/x86_64/ia32/ia32_signal.c
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *
 *  1997-11-28  Modified for POSIX.1b signals by Richard Henderson
 *  2000-06-20  Pentium III FXSR, SSE support by Gareth Hughes
 *  2000-12-*   x86-64 compatibility mode signal handling by Andi Kleen
 */

#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/errno.h>
#include <linux/wait.h>
#include <linux/ptrace.h>
#include <linux/unistd.h>
#include <linux/stddef.h>
#include <linux/personality.h>
#include <linux/compat.h>
23
#include <linux/binfmts.h>
L
Linus Torvalds 已提交
24 25 26 27 28 29 30 31 32
#include <asm/ucontext.h>
#include <asm/uaccess.h>
#include <asm/i387.h>
#include <asm/ia32.h>
#include <asm/ptrace.h>
#include <asm/ia32_unistd.h>
#include <asm/user32.h>
#include <asm/sigcontext32.h>
#include <asm/proto.h>
R
Roland McGrath 已提交
33
#include <asm/vdso.h>
L
Linus Torvalds 已提交
34 35 36 37 38

#define DEBUG_SIG 0

#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))

39 40 41 42 43
#define FIX_EFLAGS	(X86_EFLAGS_AC | X86_EFLAGS_OF | \
			 X86_EFLAGS_DF | X86_EFLAGS_TF | X86_EFLAGS_SF | \
			 X86_EFLAGS_ZF | X86_EFLAGS_AF | X86_EFLAGS_PF | \
			 X86_EFLAGS_CF)

L
Linus Torvalds 已提交
44 45 46 47 48 49
asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
void signal_fault(struct pt_regs *regs, void __user *frame, char *where);

int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
{
	int err;
50 51

	if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
L
Linus Torvalds 已提交
52 53 54 55 56 57 58 59 60
		return -EFAULT;

	/* If you change siginfo_t structure, please make sure that
	   this code is fixed accordingly.
	   It should never copy any pad contained in the structure
	   to avoid security leaks, but must copy the generic
	   3 ints plus the relevant union member.  */
	err = __put_user(from->si_signo, &to->si_signo);
	err |= __put_user(from->si_errno, &to->si_errno);
61
	err |= __put_user((short)from->si_code, &to->si_code);
L
Linus Torvalds 已提交
62 63 64

	if (from->si_code < 0) {
		err |= __put_user(from->si_pid, &to->si_pid);
65 66
		err |= __put_user(from->si_uid, &to->si_uid);
		err |= __put_user(ptr_to_compat(from->si_ptr), &to->si_ptr);
L
Linus Torvalds 已提交
67
	} else {
68 69 70 71 72 73
		/*
		 * First 32bits of unions are always present:
		 * si_pid === si_band === si_tid === si_addr(LS half)
		 */
		err |= __put_user(from->_sifields._pad[0],
				  &to->_sifields._pad[0]);
L
Linus Torvalds 已提交
74 75 76 77 78 79 80 81 82 83 84 85 86
		switch (from->si_code >> 16) {
		case __SI_FAULT >> 16:
			break;
		case __SI_CHLD >> 16:
			err |= __put_user(from->si_utime, &to->si_utime);
			err |= __put_user(from->si_stime, &to->si_stime);
			err |= __put_user(from->si_status, &to->si_status);
			/* FALL THROUGH */
		default:
		case __SI_KILL >> 16:
			err |= __put_user(from->si_uid, &to->si_uid);
			break;
		case __SI_POLL >> 16:
87
			err |= __put_user(from->si_fd, &to->si_fd);
L
Linus Torvalds 已提交
88 89
			break;
		case __SI_TIMER >> 16:
90
			err |= __put_user(from->si_overrun, &to->si_overrun);
L
Linus Torvalds 已提交
91
			err |= __put_user(ptr_to_compat(from->si_ptr),
92
					  &to->si_ptr);
L
Linus Torvalds 已提交
93
			break;
94 95
			 /* This is not generated by the kernel as of now.  */
		case __SI_RT >> 16:
L
Linus Torvalds 已提交
96 97 98 99 100 101 102 103 104 105 106 107 108
		case __SI_MESGQ >> 16:
			err |= __put_user(from->si_uid, &to->si_uid);
			err |= __put_user(from->si_int, &to->si_int);
			break;
		}
	}
	return err;
}

int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
{
	int err;
	u32 ptr32;
109 110

	if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
L
Linus Torvalds 已提交
111 112 113 114 115 116 117 118 119 120 121 122 123 124
		return -EFAULT;

	err = __get_user(to->si_signo, &from->si_signo);
	err |= __get_user(to->si_errno, &from->si_errno);
	err |= __get_user(to->si_code, &from->si_code);

	err |= __get_user(to->si_pid, &from->si_pid);
	err |= __get_user(to->si_uid, &from->si_uid);
	err |= __get_user(ptr32, &from->si_ptr);
	to->si_ptr = compat_ptr(ptr32);

	return err;
}

125
asmlinkage long sys32_sigsuspend(int history0, int history1, old_sigset_t mask)
L
Linus Torvalds 已提交
126 127 128
{
	mask &= _BLOCKABLE;
	spin_lock_irq(&current->sighand->siglock);
A
Andi Kleen 已提交
129
	current->saved_sigmask = current->blocked;
L
Linus Torvalds 已提交
130 131 132 133
	siginitset(&current->blocked, mask);
	recalc_sigpending();
	spin_unlock_irq(&current->sighand->siglock);

A
Andi Kleen 已提交
134 135
	current->state = TASK_INTERRUPTIBLE;
	schedule();
R
Roland McGrath 已提交
136
	set_restore_sigmask();
A
Andi Kleen 已提交
137
	return -ERESTARTNOHAND;
L
Linus Torvalds 已提交
138 139
}

140 141 142
asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
				  stack_ia32_t __user *uoss_ptr,
				  struct pt_regs *regs)
L
Linus Torvalds 已提交
143
{
144
	stack_t uss, uoss;
L
Linus Torvalds 已提交
145
	int ret;
146 147 148
	mm_segment_t seg;

	if (uss_ptr) {
L
Linus Torvalds 已提交
149
		u32 ptr;
150 151 152

		memset(&uss, 0, sizeof(stack_t));
		if (!access_ok(VERIFY_READ, uss_ptr, sizeof(stack_ia32_t)) ||
L
Linus Torvalds 已提交
153 154 155 156 157 158
			    __get_user(ptr, &uss_ptr->ss_sp) ||
			    __get_user(uss.ss_flags, &uss_ptr->ss_flags) ||
			    __get_user(uss.ss_size, &uss_ptr->ss_size))
			return -EFAULT;
		uss.ss_sp = compat_ptr(ptr);
	}
159 160
	seg = get_fs();
	set_fs(KERNEL_DS);
161
	ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->sp);
162
	set_fs(seg);
L
Linus Torvalds 已提交
163
	if (ret >= 0 && uoss_ptr)  {
164
		if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t)) ||
L
Linus Torvalds 已提交
165 166 167 168
		    __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) ||
		    __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) ||
		    __put_user(uoss.ss_size, &uoss_ptr->ss_size))
			ret = -EFAULT;
169 170
	}
	return ret;
L
Linus Torvalds 已提交
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
}

/*
 * Do a signal return; undo the signal stack.
 */

struct sigframe
{
	u32 pretcode;
	int sig;
	struct sigcontext_ia32 sc;
	struct _fpstate_ia32 fpstate;
	unsigned int extramask[_COMPAT_NSIG_WORDS-1];
	char retcode[8];
};

struct rt_sigframe
{
	u32 pretcode;
	int sig;
	u32 pinfo;
	u32 puc;
	compat_siginfo_t info;
	struct ucontext_ia32 uc;
	struct _fpstate_ia32 fpstate;
	char retcode[8];
};

199 200 201
#define COPY(x)		{ 		\
	unsigned int reg;		\
	err |= __get_user(reg, &sc->x);	\
202
	regs->x = reg;			\
L
Linus Torvalds 已提交
203 204 205
}

#define RELOAD_SEG(seg,mask)						\
206
	{ unsigned int cur;						\
L
Linus Torvalds 已提交
207 208
	  unsigned short pre;						\
	  err |= __get_user(pre, &sc->seg);				\
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
	  asm volatile("movl %%" #seg ",%0" : "=r" (cur));		\
	  pre |= mask;							\
	  if (pre != cur) loadsegment(seg, pre); }

static int ia32_restore_sigcontext(struct pt_regs *regs,
				   struct sigcontext_ia32 __user *sc,
				   unsigned int *peax)
{
	unsigned int tmpflags, gs, oldgs, err = 0;
	struct _fpstate_ia32 __user *buf;
	u32 tmp;

	/* Always make any pending restarted system calls return -EINTR */
	current_thread_info()->restart_block.fn = do_no_restart_syscall;

#if DEBUG_SIG
	printk(KERN_DEBUG "SIG restore_sigcontext: "
	       "sc=%p err(%x) eip(%x) cs(%x) flg(%x)\n",
227
	       sc, sc->err, sc->ip, sc->cs, sc->flags);
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
#endif

	/*
	 * Reload fs and gs if they have changed in the signal
	 * handler.  This does not handle long fs/gs base changes in
	 * the handler, but does not clobber them at least in the
	 * normal case.
	 */
	err |= __get_user(gs, &sc->gs);
	gs |= 3;
	asm("movl %%gs,%0" : "=r" (oldgs));
	if (gs != oldgs)
		load_gs_index(gs);

	RELOAD_SEG(fs, 3);
	RELOAD_SEG(ds, 3);
	RELOAD_SEG(es, 3);
L
Linus Torvalds 已提交
245 246 247

	COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
	COPY(dx); COPY(cx); COPY(ip);
248 249 250 251 252 253 254
	/* Don't touch extended registers */

	err |= __get_user(regs->cs, &sc->cs);
	regs->cs |= 3;
	err |= __get_user(regs->ss, &sc->ss);
	regs->ss |= 3;

255
	err |= __get_user(tmpflags, &sc->flags);
256
	regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
257
	/* disable syscall checks */
258
	regs->orig_ax = -1;
259 260 261 262 263 264

	err |= __get_user(tmp, &sc->fpstate);
	buf = compat_ptr(tmp);
	if (buf) {
		if (!access_ok(VERIFY_READ, buf, sizeof(*buf)))
			goto badframe;
R
Roland McGrath 已提交
265
		err |= restore_i387_ia32(buf);
266 267
	} else {
		struct task_struct *me = current;
L
Linus Torvalds 已提交
268

269 270 271
		if (used_math()) {
			clear_fpu(me);
			clear_used_math();
L
Linus Torvalds 已提交
272 273 274
		}
	}

275
	err |= __get_user(tmp, &sc->ax);
276 277
	*peax = tmp;

L
Linus Torvalds 已提交
278 279 280 281 282 283 284 285
	return err;

badframe:
	return 1;
}

asmlinkage long sys32_sigreturn(struct pt_regs *regs)
{
286
	struct sigframe __user *frame = (struct sigframe __user *)(regs->sp-8);
L
Linus Torvalds 已提交
287
	sigset_t set;
288
	unsigned int ax;
L
Linus Torvalds 已提交
289 290 291 292 293

	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
		goto badframe;
	if (__get_user(set.sig[0], &frame->sc.oldmask)
	    || (_COMPAT_NSIG_WORDS > 1
294 295
		&& __copy_from_user((((char *) &set.sig) + 4),
				    &frame->extramask,
L
Linus Torvalds 已提交
296 297 298 299 300 301 302 303
				    sizeof(frame->extramask))))
		goto badframe;

	sigdelsetmask(&set, ~_BLOCKABLE);
	spin_lock_irq(&current->sighand->siglock);
	current->blocked = set;
	recalc_sigpending();
	spin_unlock_irq(&current->sighand->siglock);
304

305
	if (ia32_restore_sigcontext(regs, &frame->sc, &ax))
L
Linus Torvalds 已提交
306
		goto badframe;
307
	return ax;
L
Linus Torvalds 已提交
308 309 310 311

badframe:
	signal_fault(regs, frame, "32bit sigreturn");
	return 0;
312
}
L
Linus Torvalds 已提交
313 314 315 316 317

asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
{
	struct rt_sigframe __user *frame;
	sigset_t set;
318
	unsigned int ax;
L
Linus Torvalds 已提交
319 320
	struct pt_regs tregs;

321
	frame = (struct rt_sigframe __user *)(regs->sp - 4);
L
Linus Torvalds 已提交
322 323 324 325 326 327 328 329 330 331 332

	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
		goto badframe;
	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
		goto badframe;

	sigdelsetmask(&set, ~_BLOCKABLE);
	spin_lock_irq(&current->sighand->siglock);
	current->blocked = set;
	recalc_sigpending();
	spin_unlock_irq(&current->sighand->siglock);
333

334
	if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
L
Linus Torvalds 已提交
335 336 337 338 339 340
		goto badframe;

	tregs = *regs;
	if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, &tregs) == -EFAULT)
		goto badframe;

341
	return ax;
L
Linus Torvalds 已提交
342 343

badframe:
344
	signal_fault(regs, frame, "32bit rt sigreturn");
L
Linus Torvalds 已提交
345
	return 0;
346
}
L
Linus Torvalds 已提交
347 348 349 350 351

/*
 * Set up a signal frame.
 */

352 353 354
static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,
				 struct _fpstate_ia32 __user *fpstate,
				 struct pt_regs *regs, unsigned int mask)
L
Linus Torvalds 已提交
355 356 357 358 359 360 361 362 363 364 365 366 367
{
	int tmp, err = 0;

	tmp = 0;
	__asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp));
	err |= __put_user(tmp, (unsigned int __user *)&sc->gs);
	__asm__("movl %%fs,%0" : "=r"(tmp): "0"(tmp));
	err |= __put_user(tmp, (unsigned int __user *)&sc->fs);
	__asm__("movl %%ds,%0" : "=r"(tmp): "0"(tmp));
	err |= __put_user(tmp, (unsigned int __user *)&sc->ds);
	__asm__("movl %%es,%0" : "=r"(tmp): "0"(tmp));
	err |= __put_user(tmp, (unsigned int __user *)&sc->es);

368 369 370 371 372 373 374 375
	err |= __put_user((u32)regs->di, &sc->di);
	err |= __put_user((u32)regs->si, &sc->si);
	err |= __put_user((u32)regs->bp, &sc->bp);
	err |= __put_user((u32)regs->sp, &sc->sp);
	err |= __put_user((u32)regs->bx, &sc->bx);
	err |= __put_user((u32)regs->dx, &sc->dx);
	err |= __put_user((u32)regs->cx, &sc->cx);
	err |= __put_user((u32)regs->ax, &sc->ax);
L
Linus Torvalds 已提交
376 377 378 379
	err |= __put_user((u32)regs->cs, &sc->cs);
	err |= __put_user((u32)regs->ss, &sc->ss);
	err |= __put_user(current->thread.trap_no, &sc->trapno);
	err |= __put_user(current->thread.error_code, &sc->err);
380 381 382
	err |= __put_user((u32)regs->ip, &sc->ip);
	err |= __put_user((u32)regs->flags, &sc->flags);
	err |= __put_user((u32)regs->sp, &sc->sp_at_signal);
L
Linus Torvalds 已提交
383

R
Roland McGrath 已提交
384
	tmp = save_i387_ia32(fpstate);
L
Linus Torvalds 已提交
385 386
	if (tmp < 0)
		err = -EFAULT;
387
	else {
L
Linus Torvalds 已提交
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403
		clear_used_math();
		stts();
		err |= __put_user(ptr_to_compat(tmp ? fpstate : NULL),
					&sc->fpstate);
	}

	/* non-iBCS2 extensions.. */
	err |= __put_user(mask, &sc->oldmask);
	err |= __put_user(current->thread.cr2, &sc->cr2);

	return err;
}

/*
 * Determine which stack to use..
 */
404 405
static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
				 size_t frame_size)
L
Linus Torvalds 已提交
406
{
407
	unsigned long sp;
L
Linus Torvalds 已提交
408 409

	/* Default to using normal stack */
410
	sp = regs->sp;
L
Linus Torvalds 已提交
411 412 413

	/* This is the X/Open sanctioned signal stack switching.  */
	if (ka->sa.sa_flags & SA_ONSTACK) {
414 415
		if (sas_ss_flags(sp) == 0)
			sp = current->sas_ss_sp + current->sas_ss_size;
L
Linus Torvalds 已提交
416 417 418 419 420
	}

	/* This is the legacy signal stack switching. */
	else if ((regs->ss & 0xffff) != __USER_DS &&
		!(ka->sa.sa_flags & SA_RESTORER) &&
421
		 ka->sa.sa_restorer)
422
		sp = (unsigned long) ka->sa.sa_restorer;
L
Linus Torvalds 已提交
423

424
	sp -= frame_size;
425 426
	/* Align the stack pointer according to the i386 ABI,
	 * i.e. so that on function entry ((sp + 4) & 15) == 0. */
427 428
	sp = ((sp + 4) & -16ul) - 4;
	return (void __user *) sp;
L
Linus Torvalds 已提交
429 430
}

431
int ia32_setup_frame(int sig, struct k_sigaction *ka,
432
		     compat_sigset_t *set, struct pt_regs *regs)
L
Linus Torvalds 已提交
433 434
{
	struct sigframe __user *frame;
435
	void __user *restorer;
L
Linus Torvalds 已提交
436 437
	int err = 0;

438 439 440 441 442 443 444 445 446 447 448 449 450
	/* copy_to_user optimizes that into a single 8 byte store */
	static const struct {
		u16 poplmovl;
		u32 val;
		u16 int80;
		u16 pad;
	} __attribute__((packed)) code = {
		0xb858,		 /* popl %eax ; movl $...,%eax */
		__NR_ia32_sigreturn,
		0x80cd,		/* int $0x80 */
		0,
	};

L
Linus Torvalds 已提交
451 452 453 454 455
	frame = get_sigframe(ka, regs, sizeof(*frame));

	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
		goto give_sigsegv;

456
	err |= __put_user(sig, &frame->sig);
L
Linus Torvalds 已提交
457 458 459 460 461 462 463 464 465 466 467
	if (err)
		goto give_sigsegv;

	err |= ia32_setup_sigcontext(&frame->sc, &frame->fpstate, regs,
					set->sig[0]);
	if (err)
		goto give_sigsegv;

	if (_COMPAT_NSIG_WORDS > 1) {
		err |= __copy_to_user(frame->extramask, &set->sig[1],
				      sizeof(frame->extramask));
468 469
		if (err)
			goto give_sigsegv;
L
Linus Torvalds 已提交
470 471
	}

R
Roland McGrath 已提交
472
	if (ka->sa.sa_flags & SA_RESTORER) {
473
		restorer = ka->sa.sa_restorer;
R
Roland McGrath 已提交
474 475
	} else {
		/* Return stub is in 32bit vsyscall page */
476
		if (current->mm->context.vdso)
R
Roland McGrath 已提交
477 478 479
			restorer = VDSO32_SYMBOL(current->mm->context.vdso,
						 sigreturn);
		else
J
Jan Engelhardt 已提交
480
			restorer = &frame->retcode;
R
Roland McGrath 已提交
481
	}
482 483 484 485 486 487 488
	err |= __put_user(ptr_to_compat(restorer), &frame->pretcode);

	/*
	 * These are actually not used anymore, but left because some
	 * gdb versions depend on them as a marker.
	 */
	err |= __copy_to_user(frame->retcode, &code, 8);
L
Linus Torvalds 已提交
489 490 491 492
	if (err)
		goto give_sigsegv;

	/* Set up registers for signal handler */
493 494
	regs->sp = (unsigned long) frame;
	regs->ip = (unsigned long) ka->sa.sa_handler;
L
Linus Torvalds 已提交
495

496
	/* Make -mregparm=3 work */
497 498 499
	regs->ax = sig;
	regs->dx = 0;
	regs->cx = 0;
500

501 502
	asm volatile("movl %0,%%ds" :: "r" (__USER32_DS));
	asm volatile("movl %0,%%es" :: "r" (__USER32_DS));
L
Linus Torvalds 已提交
503

504 505
	regs->cs = __USER32_CS;
	regs->ss = __USER32_DS;
L
Linus Torvalds 已提交
506 507

#if DEBUG_SIG
508
	printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
509
	       current->comm, current->pid, frame, regs->ip, frame->pretcode);
L
Linus Torvalds 已提交
510 511
#endif

A
Andi Kleen 已提交
512
	return 0;
L
Linus Torvalds 已提交
513 514 515

give_sigsegv:
	force_sigsegv(sig, current);
A
Andi Kleen 已提交
516
	return -EFAULT;
L
Linus Torvalds 已提交
517 518
}

519
int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
520
			compat_sigset_t *set, struct pt_regs *regs)
L
Linus Torvalds 已提交
521 522
{
	struct rt_sigframe __user *frame;
R
Roland McGrath 已提交
523
	void __user *restorer;
L
Linus Torvalds 已提交
524 525
	int err = 0;

526 527 528 529 530 531 532 533 534 535 536 537 538 539
	/* __copy_to_user optimizes that into a single 8 byte store */
	static const struct {
		u8 movl;
		u32 val;
		u16 int80;
		u16 pad;
		u8  pad2;
	} __attribute__((packed)) code = {
		0xb8,
		__NR_ia32_rt_sigreturn,
		0x80cd,
		0,
	};

L
Linus Torvalds 已提交
540 541 542 543 544
	frame = get_sigframe(ka, regs, sizeof(*frame));

	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
		goto give_sigsegv;

545
	err |= __put_user(sig, &frame->sig);
L
Linus Torvalds 已提交
546 547 548 549 550 551 552 553 554 555
	err |= __put_user(ptr_to_compat(&frame->info), &frame->pinfo);
	err |= __put_user(ptr_to_compat(&frame->uc), &frame->puc);
	err |= copy_siginfo_to_user32(&frame->info, info);
	if (err)
		goto give_sigsegv;

	/* Create the ucontext.  */
	err |= __put_user(0, &frame->uc.uc_flags);
	err |= __put_user(0, &frame->uc.uc_link);
	err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
556
	err |= __put_user(sas_ss_flags(regs->sp),
L
Linus Torvalds 已提交
557 558 559
			  &frame->uc.uc_stack.ss_flags);
	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
	err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate,
560
				     regs, set->sig[0]);
L
Linus Torvalds 已提交
561 562 563 564
	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
	if (err)
		goto give_sigsegv;

565 566
	if (ka->sa.sa_flags & SA_RESTORER)
		restorer = ka->sa.sa_restorer;
R
Roland McGrath 已提交
567 568 569
	else
		restorer = VDSO32_SYMBOL(current->mm->context.vdso,
					 rt_sigreturn);
570
	err |= __put_user(ptr_to_compat(restorer), &frame->pretcode);
L
Linus Torvalds 已提交
571

572 573 574 575 576
	/*
	 * Not actually used anymore, but left because some gdb
	 * versions need it.
	 */
	err |= __copy_to_user(frame->retcode, &code, 8);
L
Linus Torvalds 已提交
577 578 579 580
	if (err)
		goto give_sigsegv;

	/* Set up registers for signal handler */
581 582
	regs->sp = (unsigned long) frame;
	regs->ip = (unsigned long) ka->sa.sa_handler;
L
Linus Torvalds 已提交
583

584
	/* Make -mregparm=3 work */
585 586 587
	regs->ax = sig;
	regs->dx = (unsigned long) &frame->info;
	regs->cx = (unsigned long) &frame->uc;
588

589
	/* Make -mregparm=3 work */
590 591 592
	regs->ax = sig;
	regs->dx = (unsigned long) &frame->info;
	regs->cx = (unsigned long) &frame->uc;
593

594 595 596 597 598
	asm volatile("movl %0,%%ds" :: "r" (__USER32_DS));
	asm volatile("movl %0,%%es" :: "r" (__USER32_DS));

	regs->cs = __USER32_CS;
	regs->ss = __USER32_DS;
L
Linus Torvalds 已提交
599 600

#if DEBUG_SIG
601
	printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
602
	       current->comm, current->pid, frame, regs->ip, frame->pretcode);
L
Linus Torvalds 已提交
603 604
#endif

A
Andi Kleen 已提交
605
	return 0;
L
Linus Torvalds 已提交
606 607 608

give_sigsegv:
	force_sigsegv(sig, current);
A
Andi Kleen 已提交
609
	return -EFAULT;
L
Linus Torvalds 已提交
610
}