ia32_signal.c 15.8 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>
33
#include <asm/vdso.h>
L
Linus Torvalds 已提交
34 35 36 37 38 39 40 41 42 43 44

#define DEBUG_SIG 0

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

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;
45 46

	if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
L
Linus Torvalds 已提交
47 48 49 50 51 52 53 54 55
		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);
56
	err |= __put_user((short)from->si_code, &to->si_code);
L
Linus Torvalds 已提交
57 58 59

	if (from->si_code < 0) {
		err |= __put_user(from->si_pid, &to->si_pid);
60 61
		err |= __put_user(from->si_uid, &to->si_uid);
		err |= __put_user(ptr_to_compat(from->si_ptr), &to->si_ptr);
L
Linus Torvalds 已提交
62
	} else {
63 64 65 66 67 68
		/*
		 * 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 已提交
69 70 71 72 73 74 75 76 77 78 79 80 81
		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:
82
			err |= __put_user(from->si_fd, &to->si_fd);
L
Linus Torvalds 已提交
83 84
			break;
		case __SI_TIMER >> 16:
85
			err |= __put_user(from->si_overrun, &to->si_overrun);
L
Linus Torvalds 已提交
86
			err |= __put_user(ptr_to_compat(from->si_ptr),
87
					  &to->si_ptr);
L
Linus Torvalds 已提交
88
			break;
89 90
			 /* This is not generated by the kernel as of now.  */
		case __SI_RT >> 16:
L
Linus Torvalds 已提交
91 92 93 94 95 96 97 98 99 100 101 102 103
		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;
104 105

	if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
L
Linus Torvalds 已提交
106 107 108 109 110 111 112 113 114 115 116 117 118 119
		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;
}

120
asmlinkage long sys32_sigsuspend(int history0, int history1, old_sigset_t mask)
L
Linus Torvalds 已提交
121 122 123
{
	mask &= _BLOCKABLE;
	spin_lock_irq(&current->sighand->siglock);
124
	current->saved_sigmask = current->blocked;
L
Linus Torvalds 已提交
125 126 127 128
	siginitset(&current->blocked, mask);
	recalc_sigpending();
	spin_unlock_irq(&current->sighand->siglock);

129 130 131 132
	current->state = TASK_INTERRUPTIBLE;
	schedule();
	set_thread_flag(TIF_RESTORE_SIGMASK);
	return -ERESTARTNOHAND;
L
Linus Torvalds 已提交
133 134
}

135 136 137
asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
				  stack_ia32_t __user *uoss_ptr,
				  struct pt_regs *regs)
L
Linus Torvalds 已提交
138
{
139
	stack_t uss, uoss;
L
Linus Torvalds 已提交
140
	int ret;
141 142 143
	mm_segment_t seg;

	if (uss_ptr) {
L
Linus Torvalds 已提交
144
		u32 ptr;
145 146 147

		memset(&uss, 0, sizeof(stack_t));
		if (!access_ok(VERIFY_READ, uss_ptr, sizeof(stack_ia32_t)) ||
L
Linus Torvalds 已提交
148 149 150 151 152 153
			    __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);
	}
154 155
	seg = get_fs();
	set_fs(KERNEL_DS);
156
	ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->sp);
157
	set_fs(seg);
L
Linus Torvalds 已提交
158
	if (ret >= 0 && uoss_ptr)  {
159
		if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t)) ||
L
Linus Torvalds 已提交
160 161 162 163
		    __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;
164 165
	}
	return ret;
L
Linus Torvalds 已提交
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
}

/*
 * 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];
};

194 195 196
#define COPY(x)		{ 		\
	unsigned int reg;		\
	err |= __get_user(reg, &sc->x);	\
197
	regs->x = reg;			\
L
Linus Torvalds 已提交
198 199 200
}

#define RELOAD_SEG(seg,mask)						\
201
	{ unsigned int cur;						\
L
Linus Torvalds 已提交
202 203
	  unsigned short pre;						\
	  err |= __get_user(pre, &sc->seg);				\
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
	  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",
222
	       sc, sc->err, sc->ip, sc->cs, sc->flags);
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
#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 已提交
240 241 242

	COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
	COPY(dx); COPY(cx); COPY(ip);
243 244 245 246 247 248 249
	/* 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;

250
	err |= __get_user(tmpflags, &sc->flags);
251
	regs->flags = (regs->flags & ~0x40DD5) | (tmpflags & 0x40DD5);
252
	/* disable syscall checks */
253
	regs->orig_ax = -1;
254 255 256 257 258 259

	err |= __get_user(tmp, &sc->fpstate);
	buf = compat_ptr(tmp);
	if (buf) {
		if (!access_ok(VERIFY_READ, buf, sizeof(*buf)))
			goto badframe;
260
		err |= restore_i387_ia32(buf);
261 262
	} else {
		struct task_struct *me = current;
L
Linus Torvalds 已提交
263

264 265 266
		if (used_math()) {
			clear_fpu(me);
			clear_used_math();
L
Linus Torvalds 已提交
267 268 269
		}
	}

270
	err |= __get_user(tmp, &sc->ax);
271 272
	*peax = tmp;

L
Linus Torvalds 已提交
273 274 275 276 277 278 279 280
	return err;

badframe:
	return 1;
}

asmlinkage long sys32_sigreturn(struct pt_regs *regs)
{
281
	struct sigframe __user *frame = (struct sigframe __user *)(regs->sp-8);
L
Linus Torvalds 已提交
282
	sigset_t set;
283
	unsigned int ax;
L
Linus Torvalds 已提交
284 285 286 287 288

	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
		goto badframe;
	if (__get_user(set.sig[0], &frame->sc.oldmask)
	    || (_COMPAT_NSIG_WORDS > 1
289 290
		&& __copy_from_user((((char *) &set.sig) + 4),
				    &frame->extramask,
L
Linus Torvalds 已提交
291 292 293 294 295 296 297 298
				    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);
299

300
	if (ia32_restore_sigcontext(regs, &frame->sc, &ax))
L
Linus Torvalds 已提交
301
		goto badframe;
302
	return ax;
L
Linus Torvalds 已提交
303 304 305 306

badframe:
	signal_fault(regs, frame, "32bit sigreturn");
	return 0;
307
}
L
Linus Torvalds 已提交
308 309 310 311 312

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

316
	frame = (struct rt_sigframe __user *)(regs->sp - 4);
L
Linus Torvalds 已提交
317 318 319 320 321 322 323 324 325 326 327

	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);
328

329
	if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
L
Linus Torvalds 已提交
330 331 332 333 334 335
		goto badframe;

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

336
	return ax;
L
Linus Torvalds 已提交
337 338

badframe:
339
	signal_fault(regs, frame, "32bit rt sigreturn");
L
Linus Torvalds 已提交
340
	return 0;
341
}
L
Linus Torvalds 已提交
342 343 344 345 346

/*
 * Set up a signal frame.
 */

347 348 349
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 已提交
350 351 352 353 354 355 356 357 358 359 360 361 362
{
	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);

363 364 365 366 367 368 369 370
	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 已提交
371 372 373 374
	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);
375 376 377
	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 已提交
378

379
	tmp = save_i387_ia32(fpstate);
L
Linus Torvalds 已提交
380 381
	if (tmp < 0)
		err = -EFAULT;
382
	else {
L
Linus Torvalds 已提交
383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398
		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..
 */
399 400
static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
				 size_t frame_size)
L
Linus Torvalds 已提交
401
{
402
	unsigned long sp;
L
Linus Torvalds 已提交
403 404

	/* Default to using normal stack */
405
	sp = regs->sp;
L
Linus Torvalds 已提交
406 407 408

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

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

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

426
int ia32_setup_frame(int sig, struct k_sigaction *ka,
427
		     compat_sigset_t *set, struct pt_regs *regs)
L
Linus Torvalds 已提交
428 429
{
	struct sigframe __user *frame;
430
	void __user *restorer;
L
Linus Torvalds 已提交
431 432
	int err = 0;

433 434 435 436 437 438 439 440 441 442 443 444 445
	/* 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 已提交
446 447 448 449 450
	frame = get_sigframe(ka, regs, sizeof(*frame));

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

451
	err |= __put_user(sig, &frame->sig);
L
Linus Torvalds 已提交
452 453 454 455 456 457 458 459 460 461 462
	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));
463 464
		if (err)
			goto give_sigsegv;
L
Linus Torvalds 已提交
465 466
	}

467
	if (ka->sa.sa_flags & SA_RESTORER) {
468
		restorer = ka->sa.sa_restorer;
469 470 471 472 473 474 475 476
	} else {
		/* Return stub is in 32bit vsyscall page */
		if (current->binfmt->hasvdso)
			restorer = VDSO32_SYMBOL(current->mm->context.vdso,
						 sigreturn);
		else
			restorer = (void *)&frame->retcode;
	}
477 478 479 480 481 482 483
	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 已提交
484 485 486 487
	if (err)
		goto give_sigsegv;

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

491
	/* Make -mregparm=3 work */
492 493 494
	regs->ax = sig;
	regs->dx = 0;
	regs->cx = 0;
495

496 497
	asm volatile("movl %0,%%ds" :: "r" (__USER32_DS));
	asm volatile("movl %0,%%es" :: "r" (__USER32_DS));
L
Linus Torvalds 已提交
498

499 500
	regs->cs = __USER32_CS;
	regs->ss = __USER32_DS;
L
Linus Torvalds 已提交
501 502

	set_fs(USER_DS);
503
	regs->flags &= ~X86_EFLAGS_TF;
504 505
	if (test_thread_flag(TIF_SINGLESTEP))
		ptrace_notify(SIGTRAP);
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

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

give_sigsegv:
	force_sigsegv(sig, current);
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;
523
	struct exec_domain *ed = current_thread_info()->exec_domain;
524
	void __user *restorer;
L
Linus Torvalds 已提交
525 526
	int err = 0;

527 528 529 530 531 532 533 534 535 536 537 538 539 540
	/* __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 已提交
541 542 543 544 545
	frame = get_sigframe(ka, regs, sizeof(*frame));

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

546 547
	err |= __put_user((ed && ed->signal_invmap && sig < 32
			   ? ed->signal_invmap[sig] : sig), &frame->sig);
L
Linus Torvalds 已提交
548 549 550 551 552 553 554 555 556 557
	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);
558
	err |= __put_user(sas_ss_flags(regs->sp),
L
Linus Torvalds 已提交
559 560 561
			  &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,
562
				     regs, set->sig[0]);
L
Linus Torvalds 已提交
563 564 565 566
	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
	if (err)
		goto give_sigsegv;

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

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

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

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

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

596 597 598 599 600
	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 已提交
601 602

	set_fs(USER_DS);
603
	regs->flags &= ~X86_EFLAGS_TF;
604 605
	if (test_thread_flag(TIF_SINGLESTEP))
		ptrace_notify(SIGTRAP);
L
Linus Torvalds 已提交
606 607

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

612
	return 0;
L
Linus Torvalds 已提交
613 614 615

give_sigsegv:
	force_sigsegv(sig, current);
616
	return -EFAULT;
L
Linus Torvalds 已提交
617
}
反馈
建议
客服 返回
顶部