signal_32.c 16.8 KB
Newer Older
1
/*  linux/arch/sparc/kernel/signal.c
L
Linus Torvalds 已提交
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
 *  Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
 *  Copyright (C) 1997 Eddie C. Dost   (ecd@skynet.be)
 */

#include <linux/sched.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/mm.h>
#include <linux/tty.h>
#include <linux/smp.h>
#include <linux/binfmts.h>	/* do_coredum */
#include <linux/bitops.h>
21
#include <linux/tracehook.h>
L
Linus Torvalds 已提交
22 23 24 25 26 27

#include <asm/uaccess.h>
#include <asm/ptrace.h>
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
#include <asm/cacheflush.h>	/* flush_sig_insns */
28
#include <asm/switch_to.h>
L
Linus Torvalds 已提交
29

30 31
#include "sigutil.h"

L
Linus Torvalds 已提交
32 33 34 35 36 37
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))

extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
		   void *fpqueue, unsigned long *fpqdepth);
extern void fpload(unsigned long *fpregs, unsigned long *fsr);

38
struct signal_frame {
L
Linus Torvalds 已提交
39
	struct sparc_stackf	ss;
40
	__siginfo32_t		info;
L
Linus Torvalds 已提交
41 42 43 44
	__siginfo_fpu_t __user	*fpu_save;
	unsigned long		insns[2] __attribute__ ((aligned (8)));
	unsigned int		extramask[_NSIG_WORDS - 1];
	unsigned int		extra_size; /* Should be 0 */
45 46
	__siginfo_rwin_t __user	*rwin_save;
} __attribute__((aligned(8)));
L
Linus Torvalds 已提交
47 48 49 50 51 52 53 54 55 56

struct rt_signal_frame {
	struct sparc_stackf	ss;
	siginfo_t		info;
	struct pt_regs		regs;
	sigset_t		mask;
	__siginfo_fpu_t __user	*fpu_save;
	unsigned int		insns[2];
	stack_t			stack;
	unsigned int		extra_size; /* Should be 0 */
57 58
	__siginfo_rwin_t __user	*rwin_save;
} __attribute__((aligned(8)));
L
Linus Torvalds 已提交
59 60

/* Align macros */
61
#define SF_ALIGNEDSZ  (((sizeof(struct signal_frame) + 7) & (~7)))
L
Linus Torvalds 已提交
62 63
#define RT_ALIGNEDSZ  (((sizeof(struct rt_signal_frame) + 7) & (~7)))

64
static int _sigpause_common(old_sigset_t set)
L
Linus Torvalds 已提交
65
{
M
Matt Fleming 已提交
66 67
	sigset_t blocked;
	siginitset(&blocked, set);
A
Al Viro 已提交
68
	return sigsuspend(&blocked);
L
Linus Torvalds 已提交
69 70
}

71
asmlinkage int sys_sigsuspend(old_sigset_t set)
L
Linus Torvalds 已提交
72
{
73
	return _sigpause_common(set);
L
Linus Torvalds 已提交
74 75
}

76
asmlinkage void do_sigreturn(struct pt_regs *regs)
L
Linus Torvalds 已提交
77
{
78
	struct signal_frame __user *sf;
L
Linus Torvalds 已提交
79 80 81
	unsigned long up_psr, pc, npc;
	sigset_t set;
	__siginfo_fpu_t __user *fpu_save;
82
	__siginfo_rwin_t __user *rwin_save;
L
Linus Torvalds 已提交
83 84
	int err;

85 86 87 88 89 90
	/* Always make any pending restarted system calls return -EINTR */
	current_thread_info()->restart_block.fn = do_no_restart_syscall;

	synchronize_user_stack();

	sf = (struct signal_frame __user *) regs->u_regs[UREG_FP];
L
Linus Torvalds 已提交
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112

	/* 1. Make sure we are not getting garbage from the user */
	if (!access_ok(VERIFY_READ, sf, sizeof(*sf)))
		goto segv_and_exit;

	if (((unsigned long) sf) & 3)
		goto segv_and_exit;

	err = __get_user(pc,  &sf->info.si_regs.pc);
	err |= __get_user(npc, &sf->info.si_regs.npc);

	if ((pc | npc) & 3)
		goto segv_and_exit;

	/* 2. Restore the state */
	up_psr = regs->psr;
	err |= __copy_from_user(regs, &sf->info.si_regs, sizeof(struct pt_regs));

	/* User can only change condition codes and FPU enabling in %psr. */
	regs->psr = (up_psr & ~(PSR_ICC | PSR_EF))
		  | (regs->psr & (PSR_ICC | PSR_EF));

113 114 115
	/* Prevent syscall restart.  */
	pt_regs_clear_syscall(regs);

L
Linus Torvalds 已提交
116 117 118
	err |= __get_user(fpu_save, &sf->fpu_save);
	if (fpu_save)
		err |= restore_fpu_state(regs, fpu_save);
119 120 121
	err |= __get_user(rwin_save, &sf->rwin_save);
	if (rwin_save)
		err |= restore_rwin_state(rwin_save);
L
Linus Torvalds 已提交
122 123 124 125 126 127 128 129 130 131 132 133

	/* This is pretty much atomic, no amount locking would prevent
	 * the races which exist anyways.
	 */
	err |= __get_user(set.sig[0], &sf->info.si_mask);
	err |= __copy_from_user(&set.sig[1], &sf->extramask,
			        (_NSIG_WORDS-1) * sizeof(unsigned int));
			   
	if (err)
		goto segv_and_exit;

	sigdelsetmask(&set, ~_BLOCKABLE);
M
Matt Fleming 已提交
134
	set_current_blocked(&set);
L
Linus Torvalds 已提交
135 136 137 138 139 140 141 142 143 144 145
	return;

segv_and_exit:
	force_sig(SIGSEGV, current);
}

asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
{
	struct rt_signal_frame __user *sf;
	unsigned int psr, pc, npc;
	__siginfo_fpu_t __user *fpu_save;
146
	__siginfo_rwin_t __user *rwin_save;
L
Linus Torvalds 已提交
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
	mm_segment_t old_fs;
	sigset_t set;
	stack_t st;
	int err;

	synchronize_user_stack();
	sf = (struct rt_signal_frame __user *) regs->u_regs[UREG_FP];
	if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) ||
	    (((unsigned long) sf) & 0x03))
		goto segv;

	err = __get_user(pc, &sf->regs.pc);
	err |= __get_user(npc, &sf->regs.npc);
	err |= ((pc | npc) & 0x03);

	err |= __get_user(regs->y, &sf->regs.y);
	err |= __get_user(psr, &sf->regs.psr);

	err |= __copy_from_user(&regs->u_regs[UREG_G1],
				&sf->regs.u_regs[UREG_G1], 15 * sizeof(u32));

	regs->psr = (regs->psr & ~PSR_ICC) | (psr & PSR_ICC);

170 171 172
	/* Prevent syscall restart.  */
	pt_regs_clear_syscall(regs);

L
Linus Torvalds 已提交
173
	err |= __get_user(fpu_save, &sf->fpu_save);
174
	if (!err && fpu_save)
L
Linus Torvalds 已提交
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
		err |= restore_fpu_state(regs, fpu_save);
	err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t));
	
	err |= __copy_from_user(&st, &sf->stack, sizeof(stack_t));
	
	if (err)
		goto segv;
		
	regs->pc = pc;
	regs->npc = npc;
	
	/* It is more difficult to avoid calling this function than to
	 * call it and ignore errors.
	 */
	old_fs = get_fs();
	set_fs(KERNEL_DS);
	do_sigaltstack((const stack_t __user *) &st, NULL, (unsigned long)sf);
	set_fs(old_fs);

194 195 196 197 198 199
	err |= __get_user(rwin_save, &sf->rwin_save);
	if (!err && rwin_save) {
		if (restore_rwin_state(rwin_save))
			goto segv;
	}

L
Linus Torvalds 已提交
200
	sigdelsetmask(&set, ~_BLOCKABLE);
M
Matt Fleming 已提交
201
	set_current_blocked(&set);
L
Linus Torvalds 已提交
202 203 204 205 206 207 208 209
	return;
segv:
	force_sig(SIGSEGV, current);
}

/* Checks if the fp is valid */
static inline int invalid_frame_pointer(void __user *fp, int fplen)
{
210
	if ((((unsigned long) fp) & 7) || !__access_ok((unsigned long)fp, fplen))
L
Linus Torvalds 已提交
211
		return 1;
212

L
Linus Torvalds 已提交
213 214 215 216 217
	return 0;
}

static inline void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, unsigned long framesize)
{
218
	unsigned long sp = regs->u_regs[UREG_FP];
L
Linus Torvalds 已提交
219

220 221 222 223 224 225
	/*
	 * If we are on the alternate signal stack and would overflow it, don't.
	 * Return an always-bogus address instead so we will die with SIGSEGV.
	 */
	if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize)))
		return (void __user *) -1L;
L
Linus Torvalds 已提交
226 227 228

	/* This is the X/Open sanctioned signal stack switching.  */
	if (sa->sa_flags & SA_ONSTACK) {
229
		if (sas_ss_flags(sp) == 0)
L
Linus Torvalds 已提交
230 231
			sp = current->sas_ss_sp + current->sas_ss_size;
	}
232

233 234
	sp -= framesize;

235 236 237 238 239 240
	/* Always align the stack frame.  This handles two cases.  First,
	 * sigaltstack need not be mindful of platform specific stack
	 * alignment.  Second, if we took this signal because the stack
	 * is not aligned properly, we'd like to take the signal cleanly
	 * and report that.
	 */
241
	sp &= ~15UL;
242

243
	return (void __user *) sp;
L
Linus Torvalds 已提交
244 245
}

246 247
static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
		       int signo, sigset_t *oldset)
L
Linus Torvalds 已提交
248
{
249
	struct signal_frame __user *sf;
250 251
	int sigframe_size, err, wsaved;
	void __user *tail;
L
Linus Torvalds 已提交
252 253 254 255

	/* 1. Make sure everything is clean */
	synchronize_user_stack();

256 257 258 259 260 261 262
	wsaved = current_thread_info()->w_saved;

	sigframe_size = sizeof(*sf);
	if (used_math())
		sigframe_size += sizeof(__siginfo_fpu_t);
	if (wsaved)
		sigframe_size += sizeof(__siginfo_rwin_t);
L
Linus Torvalds 已提交
263

264
	sf = (struct signal_frame __user *)
L
Linus Torvalds 已提交
265 266 267 268 269
		get_sigframe(&ka->sa, regs, sigframe_size);

	if (invalid_frame_pointer(sf, sigframe_size))
		goto sigill_and_return;

270
	tail = sf + 1;
L
Linus Torvalds 已提交
271 272 273 274 275 276 277

	/* 2. Save the current process state */
	err = __copy_to_user(&sf->info.si_regs, regs, sizeof(struct pt_regs));
	
	err |= __put_user(0, &sf->extra_size);

	if (used_math()) {
278 279 280 281
		__siginfo_fpu_t __user *fp = tail;
		tail += sizeof(*fp);
		err |= save_fpu_state(regs, fp);
		err |= __put_user(fp, &sf->fpu_save);
L
Linus Torvalds 已提交
282 283 284
	} else {
		err |= __put_user(0, &sf->fpu_save);
	}
285 286 287 288 289 290 291 292
	if (wsaved) {
		__siginfo_rwin_t __user *rwp = tail;
		tail += sizeof(*rwp);
		err |= save_rwin_state(wsaved, rwp);
		err |= __put_user(rwp, &sf->rwin_save);
	} else {
		err |= __put_user(0, &sf->rwin_save);
	}
L
Linus Torvalds 已提交
293 294 295 296

	err |= __put_user(oldset->sig[0], &sf->info.si_mask);
	err |= __copy_to_user(sf->extramask, &oldset->sig[1],
			      (_NSIG_WORDS - 1) * sizeof(unsigned int));
297 298 299 300 301 302 303 304 305
	if (!wsaved) {
		err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP],
				      sizeof(struct reg_window32));
	} else {
		struct reg_window32 *rp;

		rp = &current_thread_info()->reg_window[wsaved - 1];
		err |= __copy_to_user(sf, rp, sizeof(struct reg_window32));
	}
L
Linus Torvalds 已提交
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
	if (err)
		goto sigsegv;
	
	/* 3. signal handler back-trampoline and parameters */
	regs->u_regs[UREG_FP] = (unsigned long) sf;
	regs->u_regs[UREG_I0] = signo;
	regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
	regs->u_regs[UREG_I2] = (unsigned long) &sf->info;

	/* 4. signal handler */
	regs->pc = (unsigned long) ka->sa.sa_handler;
	regs->npc = (regs->pc + 4);

	/* 5. return to kernel instructions */
	if (ka->ka_restorer)
		regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;
	else {
		regs->u_regs[UREG_I7] = (unsigned long)(&(sf->insns[0]) - 2);

		/* mov __NR_sigreturn, %g1 */
		err |= __put_user(0x821020d8, &sf->insns[0]);

		/* t 0x10 */
		err |= __put_user(0x91d02010, &sf->insns[1]);
		if (err)
			goto sigsegv;

		/* Flush instruction space. */
		flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
	}
336
	return 0;
L
Linus Torvalds 已提交
337 338 339

sigill_and_return:
	do_exit(SIGILL);
340 341
	return -EINVAL;

L
Linus Torvalds 已提交
342 343
sigsegv:
	force_sigsegv(signo, current);
344
	return -EFAULT;
L
Linus Torvalds 已提交
345 346
}

347 348
static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
			  int signo, sigset_t *oldset, siginfo_t *info)
L
Linus Torvalds 已提交
349 350
{
	struct rt_signal_frame __user *sf;
351 352
	int sigframe_size, wsaved;
	void __user *tail;
L
Linus Torvalds 已提交
353 354 355 356
	unsigned int psr;
	int err;

	synchronize_user_stack();
357 358 359 360 361 362
	wsaved = current_thread_info()->w_saved;
	sigframe_size = sizeof(*sf);
	if (used_math())
		sigframe_size += sizeof(__siginfo_fpu_t);
	if (wsaved)
		sigframe_size += sizeof(__siginfo_rwin_t);
L
Linus Torvalds 已提交
363 364 365 366 367
	sf = (struct rt_signal_frame __user *)
		get_sigframe(&ka->sa, regs, sigframe_size);
	if (invalid_frame_pointer(sf, sigframe_size))
		goto sigill;

368
	tail = sf + 1;
L
Linus Torvalds 已提交
369 370 371 372 373 374 375 376 377 378 379
	err  = __put_user(regs->pc, &sf->regs.pc);
	err |= __put_user(regs->npc, &sf->regs.npc);
	err |= __put_user(regs->y, &sf->regs.y);
	psr = regs->psr;
	if (used_math())
		psr |= PSR_EF;
	err |= __put_user(psr, &sf->regs.psr);
	err |= __copy_to_user(&sf->regs.u_regs, regs->u_regs, sizeof(regs->u_regs));
	err |= __put_user(0, &sf->extra_size);

	if (psr & PSR_EF) {
380 381 382 383
		__siginfo_fpu_t *fp = tail;
		tail += sizeof(*fp);
		err |= save_fpu_state(regs, fp);
		err |= __put_user(fp, &sf->fpu_save);
L
Linus Torvalds 已提交
384 385 386
	} else {
		err |= __put_user(0, &sf->fpu_save);
	}
387 388 389 390 391 392 393 394
	if (wsaved) {
		__siginfo_rwin_t *rwp = tail;
		tail += sizeof(*rwp);
		err |= save_rwin_state(wsaved, rwp);
		err |= __put_user(rwp, &sf->rwin_save);
	} else {
		err |= __put_user(0, &sf->rwin_save);
	}
L
Linus Torvalds 已提交
395 396 397 398 399 400 401
	err |= __copy_to_user(&sf->mask, &oldset->sig[0], sizeof(sigset_t));
	
	/* Setup sigaltstack */
	err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp);
	err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags);
	err |= __put_user(current->sas_ss_size, &sf->stack.ss_size);
	
402 403 404 405 406 407 408 409 410
	if (!wsaved) {
		err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP],
				      sizeof(struct reg_window32));
	} else {
		struct reg_window32 *rp;

		rp = &current_thread_info()->reg_window[wsaved - 1];
		err |= __copy_to_user(sf, rp, sizeof(struct reg_window32));
	}
L
Linus Torvalds 已提交
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440

	err |= copy_siginfo_to_user(&sf->info, info);

	if (err)
		goto sigsegv;

	regs->u_regs[UREG_FP] = (unsigned long) sf;
	regs->u_regs[UREG_I0] = signo;
	regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
	regs->u_regs[UREG_I2] = (unsigned long) &sf->regs;

	regs->pc = (unsigned long) ka->sa.sa_handler;
	regs->npc = (regs->pc + 4);

	if (ka->ka_restorer)
		regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;
	else {
		regs->u_regs[UREG_I7] = (unsigned long)(&(sf->insns[0]) - 2);

		/* mov __NR_sigreturn, %g1 */
		err |= __put_user(0x821020d8, &sf->insns[0]);

		/* t 0x10 */
		err |= __put_user(0x91d02010, &sf->insns[1]);
		if (err)
			goto sigsegv;

		/* Flush instruction space. */
		flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
	}
441
	return 0;
L
Linus Torvalds 已提交
442 443 444

sigill:
	do_exit(SIGILL);
445 446
	return -EINVAL;

L
Linus Torvalds 已提交
447 448
sigsegv:
	force_sigsegv(signo, current);
449
	return -EFAULT;
L
Linus Torvalds 已提交
450 451
}

452
static inline int
L
Linus Torvalds 已提交
453
handle_signal(unsigned long signr, struct k_sigaction *ka,
454
	      siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
L
Linus Torvalds 已提交
455
{
456 457
	int err;

458
	if (ka->sa.sa_flags & SA_SIGINFO)
459
		err = setup_rt_frame(ka, regs, signr, oldset, info);
460
	else
461 462 463 464
		err = setup_frame(ka, regs, signr, oldset);

	if (err)
		return err;
465

M
Matt Fleming 已提交
466
	block_sigmask(ka, signr);
467 468 469
	tracehook_signal_handler(signr, info, ka, regs, 0);

	return 0;
L
Linus Torvalds 已提交
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496
}

static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
				   struct sigaction *sa)
{
	switch(regs->u_regs[UREG_I0]) {
	case ERESTART_RESTARTBLOCK:
	case ERESTARTNOHAND:
	no_system_call_restart:
		regs->u_regs[UREG_I0] = EINTR;
		regs->psr |= PSR_C;
		break;
	case ERESTARTSYS:
		if (!(sa->sa_flags & SA_RESTART))
			goto no_system_call_restart;
		/* fallthrough */
	case ERESTARTNOINTR:
		regs->u_regs[UREG_I0] = orig_i0;
		regs->pc -= 4;
		regs->npc -= 4;
	}
}

/* Note that 'init' is a special process: it doesn't get signals it doesn't
 * want to handle. Thus you cannot kill init even with a SIGKILL even by
 * mistake.
 */
497
static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
L
Linus Torvalds 已提交
498 499
{
	struct k_sigaction ka;
500
	int restart_syscall;
501
	sigset_t *oldset;
502 503
	siginfo_t info;
	int signr;
L
Linus Torvalds 已提交
504

505 506 507 508
	/* It's a lot of work and synchronization to add a new ptrace
	 * register for GDB to save and restore in order to get
	 * orig_i0 correct for syscall restarts when debugging.
	 *
509 510 511 512 513 514 515 516 517 518 519 520 521
	 * Although it should be the case that most of the global
	 * registers are volatile across a system call, glibc already
	 * depends upon that fact that we preserve them.  So we can't
	 * just use any global register to save away the orig_i0 value.
	 *
	 * In particular %g2, %g3, %g4, and %g5 are all assumed to be
	 * preserved across a system call trap by various pieces of
	 * code in glibc.
	 *
	 * %g7 is used as the "thread register".   %g6 is not used in
	 * any fixed manner.  %g6 is used as a scratch register and
	 * a compiler temporary, but it's value is never used across
	 * a system call.  Therefore %g6 is usable for orig_i0 storage.
522
	 */
523
	if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C))
524
		regs->u_regs[UREG_G6] = orig_i0;
L
Linus Torvalds 已提交
525

526 527 528
	if (test_thread_flag(TIF_RESTORE_SIGMASK))
		oldset = &current->saved_sigmask;
	else
L
Linus Torvalds 已提交
529 530
		oldset = &current->blocked;

531 532 533 534 535 536
	signr = get_signal_to_deliver(&info, &ka, regs, NULL);

	/* If the debugger messes with the program counter, it clears
	 * the software "in syscall" bit, directing us to not perform
	 * a syscall restart.
	 */
537 538 539
	restart_syscall = 0;
	if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C)) {
		restart_syscall = 1;
540
		orig_i0 = regs->u_regs[UREG_G6];
541 542
	}

543

L
Linus Torvalds 已提交
544
	if (signr > 0) {
545 546
		if (restart_syscall)
			syscall_restart(orig_i0, regs, &ka.sa);
547 548 549 550 551 552 553 554 555
		if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
			/* a signal was successfully delivered; the saved
			 * sigmask will have been stored in the signal frame,
			 * and will be restored by sigreturn, so we can simply
			 * clear the TIF_RESTORE_SIGMASK flag.
			 */
			if (test_thread_flag(TIF_RESTORE_SIGMASK))
				clear_thread_flag(TIF_RESTORE_SIGMASK);
		}
556
		return;
L
Linus Torvalds 已提交
557
	}
558
	if (restart_syscall &&
L
Linus Torvalds 已提交
559 560 561 562
	    (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
	     regs->u_regs[UREG_I0] == ERESTARTSYS ||
	     regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
		/* replay the system call when we are done */
563
		regs->u_regs[UREG_I0] = orig_i0;
L
Linus Torvalds 已提交
564 565
		regs->pc -= 4;
		regs->npc -= 4;
566
		pt_regs_clear_syscall(regs);
L
Linus Torvalds 已提交
567
	}
568
	if (restart_syscall &&
L
Linus Torvalds 已提交
569 570 571 572
	    regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
		regs->u_regs[UREG_G1] = __NR_restart_syscall;
		regs->pc -= 4;
		regs->npc -= 4;
573
		pt_regs_clear_syscall(regs);
L
Linus Torvalds 已提交
574
	}
575 576 577 578 579 580

	/* if there's no signal to deliver, we just put the saved sigmask
	 * back
	 */
	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
		clear_thread_flag(TIF_RESTORE_SIGMASK);
581
		set_current_blocked(&current->saved_sigmask);
582
	}
L
Linus Torvalds 已提交
583 584
}

585 586 587 588 589 590 591 592
void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0,
		      unsigned long thread_info_flags)
{
	if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
		do_signal(regs, orig_i0);
	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
		clear_thread_flag(TIF_NOTIFY_RESUME);
		tracehook_notify_resume(regs);
593 594
		if (current->replacement_session_keyring)
			key_replace_session_keyring();
595 596 597
	}
}

L
Linus Torvalds 已提交
598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633
asmlinkage int
do_sys_sigstack(struct sigstack __user *ssptr, struct sigstack __user *ossptr,
		unsigned long sp)
{
	int ret = -EFAULT;

	/* First see if old state is wanted. */
	if (ossptr) {
		if (put_user(current->sas_ss_sp + current->sas_ss_size,
			     &ossptr->the_stack) ||
		    __put_user(on_sig_stack(sp), &ossptr->cur_status))
			goto out;
	}

	/* Now see if we want to update the new state. */
	if (ssptr) {
		char *ss_sp;

		if (get_user(ss_sp, &ssptr->the_stack))
			goto out;
		/* If the current stack was set with sigaltstack, don't
		   swap stacks while we are on it.  */
		ret = -EPERM;
		if (current->sas_ss_sp && on_sig_stack(sp))
			goto out;

		/* Since we don't know the extent of the stack, and we don't
		   track onstack-ness, but rather calculate it, we must
		   presume a size.  Ho hum this interface is lossy.  */
		current->sas_ss_sp = (unsigned long)ss_sp - SIGSTKSZ;
		current->sas_ss_size = SIGSTKSZ;
	}
	ret = 0;
out:
	return ret;
}