compat_signal.c 13.7 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
2
 *    Copyright IBM Corp. 2000, 2006
L
Linus Torvalds 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
 *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
 *               Gerhard Tonn (ton@de.ibm.com)                  
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *
 *  1997-11-28  Modified for POSIX.1b signals by Richard Henderson
 */

#include <linux/compat.h>
#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/tty.h>
#include <linux/personality.h>
#include <linux/binfmts.h>
#include <asm/ucontext.h>
#include <asm/uaccess.h>
#include <asm/lowcore.h>
28
#include <asm/switch_to.h>
L
Linus Torvalds 已提交
29 30
#include "compat_linux.h"
#include "compat_ptrace.h"
31
#include "entry.h"
L
Linus Torvalds 已提交
32 33 34 35 36 37 38

typedef struct 
{
	__u8 callee_used_stack[__SIGNAL_FRAMESIZE32];
	struct sigcontext32 sc;
	_sigregs32 sregs;
	int signo;
39
	__u32 gprs_high[NUM_GPRS];
L
Linus Torvalds 已提交
40 41 42 43 44 45 46 47 48
	__u8 retcode[S390_SYSCALL_SIZE];
} sigframe32;

typedef struct 
{
	__u8 callee_used_stack[__SIGNAL_FRAMESIZE32];
	__u8 retcode[S390_SYSCALL_SIZE];
	compat_siginfo_t info;
	struct ucontext32 uc;
49
	__u32 gprs_high[NUM_GPRS];
L
Linus Torvalds 已提交
50 51
} rt_sigframe32;

A
Al Viro 已提交
52
int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
L
Linus Torvalds 已提交
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
{
	int err;

	/* If you change siginfo_t structure, please be sure
	   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.  
	   This routine must convert siginfo from 64bit to 32bit as well
	   at the same time.  */
	err = __put_user(from->si_signo, &to->si_signo);
	err |= __put_user(from->si_errno, &to->si_errno);
	err |= __put_user((short)from->si_code, &to->si_code);
	if (from->si_code < 0)
		err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
	else {
		switch (from->si_code >> 16) {
		case __SI_RT >> 16: /* This is not generated by the kernel as of now.  */
		case __SI_MESGQ >> 16:
			err |= __put_user(from->si_int, &to->si_int);
			/* fallthrough */
		case __SI_KILL >> 16:
			err |= __put_user(from->si_pid, &to->si_pid);
			err |= __put_user(from->si_uid, &to->si_uid);
			break;
		case __SI_CHLD >> 16:
			err |= __put_user(from->si_pid, &to->si_pid);
			err |= __put_user(from->si_uid, &to->si_uid);
			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);
			break;
		case __SI_FAULT >> 16:
			err |= __put_user((unsigned long) from->si_addr,
					  &to->si_addr);
			break;
		case __SI_POLL >> 16:
			err |= __put_user(from->si_band, &to->si_band);
			err |= __put_user(from->si_fd, &to->si_fd);
			break;
		case __SI_TIMER >> 16:
			err |= __put_user(from->si_tid, &to->si_tid);
			err |= __put_user(from->si_overrun, &to->si_overrun);
			err |= __put_user(from->si_int, &to->si_int);
			break;
		default:
			break;
		}
	}
102
	return err ? -EFAULT : 0;
L
Linus Torvalds 已提交
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
}

int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
{
	int err;
	u32 tmp;

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

	if (to->si_code < 0)
		err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
	else {
		switch (to->si_code >> 16) {
		case __SI_RT >> 16: /* This is not generated by the kernel as of now.  */
		case __SI_MESGQ >> 16:
			err |= __get_user(to->si_int, &from->si_int);
			/* fallthrough */
		case __SI_KILL >> 16:
			err |= __get_user(to->si_pid, &from->si_pid);
			err |= __get_user(to->si_uid, &from->si_uid);
			break;
		case __SI_CHLD >> 16:
			err |= __get_user(to->si_pid, &from->si_pid);
			err |= __get_user(to->si_uid, &from->si_uid);
			err |= __get_user(to->si_utime, &from->si_utime);
			err |= __get_user(to->si_stime, &from->si_stime);
			err |= __get_user(to->si_status, &from->si_status);
			break;
		case __SI_FAULT >> 16:
			err |= __get_user(tmp, &from->si_addr);
135 136
			to->si_addr = (void __force __user *)
				(u64) (tmp & PSW32_ADDR_INSN);
L
Linus Torvalds 已提交
137 138 139 140 141 142 143 144 145 146 147 148 149 150
			break;
		case __SI_POLL >> 16:
			err |= __get_user(to->si_band, &from->si_band);
			err |= __get_user(to->si_fd, &from->si_fd);
			break;
		case __SI_TIMER >> 16:
			err |= __get_user(to->si_tid, &from->si_tid);
			err |= __get_user(to->si_overrun, &from->si_overrun);
			err |= __get_user(to->si_int, &from->si_int);
			break;
		default:
			break;
		}
	}
151
	return err ? -EFAULT : 0;
L
Linus Torvalds 已提交
152 153 154 155
}

static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs)
{
156 157
	_sigregs32 user_sregs;
	int i;
L
Linus Torvalds 已提交
158

159 160
	user_sregs.regs.psw.mask = (__u32)(regs->psw.mask >> 32);
	user_sregs.regs.psw.mask &= PSW32_MASK_USER | PSW32_MASK_RI;
161
	user_sregs.regs.psw.mask |= PSW32_USER_BITS;
162
	user_sregs.regs.psw.addr = (__u32) regs->psw.addr |
163
		(__u32)(regs->psw.mask & PSW_MASK_BA);
L
Linus Torvalds 已提交
164
	for (i = 0; i < NUM_GPRS; i++)
165
		user_sregs.regs.gprs[i] = (__u32) regs->gprs[i];
L
Linus Torvalds 已提交
166
	save_access_regs(current->thread.acrs);
167 168 169 170 171 172 173
	memcpy(&user_sregs.regs.acrs, current->thread.acrs,
	       sizeof(user_sregs.regs.acrs));
	save_fp_ctl(&current->thread.fp_regs.fpc);
	save_fp_regs(current->thread.fp_regs.fprs);
	memcpy(&user_sregs.fpregs, &current->thread.fp_regs,
	       sizeof(user_sregs.fpregs));
	if (__copy_to_user(sregs, &user_sregs, sizeof(_sigregs32)))
174 175
		return -EFAULT;
	return 0;
L
Linus Torvalds 已提交
176 177 178 179
}

static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
{
180 181
	_sigregs32 user_sregs;
	int i;
L
Linus Torvalds 已提交
182 183 184 185

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

186
	if (__copy_from_user(&user_sregs, &sregs->regs, sizeof(user_sregs)))
187
		return -EFAULT;
188

189 190 191
	if (!is_ri_task(current) && (user_sregs.regs.psw.mask & PSW32_MASK_RI))
		return -EINVAL;

192 193 194 195 196
	/* Loading the floating-point-control word can fail. Do that first. */
	if (restore_fp_ctl(&user_sregs.fpregs.fpc))
		return -EINVAL;

	/* Use regs->psw.mask instead of PSW_USER_BITS to preserve PER bit. */
197
	regs->psw.mask = (regs->psw.mask & ~(PSW_MASK_USER | PSW_MASK_RI)) |
198
		(__u64)(user_sregs.regs.psw.mask & PSW32_MASK_USER) << 32 |
199
		(__u64)(user_sregs.regs.psw.mask & PSW32_MASK_RI) << 32 |
200
		(__u64)(user_sregs.regs.psw.addr & PSW32_ADDR_AMODE);
201
	/* Check for invalid user address space control. */
202 203
	if ((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_HOME)
		regs->psw.mask = PSW_ASC_PRIMARY |
204
			(regs->psw.mask & ~PSW_MASK_ASC);
205
	regs->psw.addr = (__u64)(user_sregs.regs.psw.addr & PSW32_ADDR_INSN);
L
Linus Torvalds 已提交
206
	for (i = 0; i < NUM_GPRS; i++)
207 208 209
		regs->gprs[i] = (__u64) user_sregs.regs.gprs[i];
	memcpy(&current->thread.acrs, &user_sregs.regs.acrs,
	       sizeof(current->thread.acrs));
L
Linus Torvalds 已提交
210 211
	restore_access_regs(current->thread.acrs);

212 213
	memcpy(&current->thread.fp_regs, &user_sregs.fpregs,
	       sizeof(current->thread.fp_regs));
L
Linus Torvalds 已提交
214

215
	restore_fp_regs(current->thread.fp_regs.fprs);
216
	clear_thread_flag(TIF_SYSCALL);	/* No longer in a system call */
L
Linus Torvalds 已提交
217 218 219
	return 0;
}

220 221 222 223 224 225 226
static int save_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs)
{
	__u32 gprs_high[NUM_GPRS];
	int i;

	for (i = 0; i < NUM_GPRS; i++)
		gprs_high[i] = regs->gprs[i] >> 32;
227 228 229
	if (__copy_to_user(uregs, &gprs_high, sizeof(gprs_high)))
		return -EFAULT;
	return 0;
230 231 232 233 234
}

static int restore_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs)
{
	__u32 gprs_high[NUM_GPRS];
235
	int i;
236

237 238
	if (__copy_from_user(&gprs_high, uregs, sizeof(gprs_high)))
		return -EFAULT;
239 240 241 242 243
	for (i = 0; i < NUM_GPRS; i++)
		*(__u32 *)&regs->gprs[i] = gprs_high[i];
	return 0;
}

M
Martin Schwidefsky 已提交
244
asmlinkage long sys32_sigreturn(void)
L
Linus Torvalds 已提交
245
{
M
Martin Schwidefsky 已提交
246
	struct pt_regs *regs = task_pt_regs(current);
L
Linus Torvalds 已提交
247 248 249 250 251
	sigframe32 __user *frame = (sigframe32 __user *)regs->gprs[15];
	sigset_t set;

	if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE32))
		goto badframe;
252
	set_current_blocked(&set);
L
Linus Torvalds 已提交
253 254
	if (restore_sigregs32(regs, &frame->sregs))
		goto badframe;
255 256
	if (restore_sigregs_gprs_high(regs, frame->gprs_high))
		goto badframe;
L
Linus Torvalds 已提交
257 258 259 260 261 262
	return regs->gprs[2];
badframe:
	force_sig(SIGSEGV, current);
	return 0;
}

M
Martin Schwidefsky 已提交
263
asmlinkage long sys32_rt_sigreturn(void)
L
Linus Torvalds 已提交
264
{
M
Martin Schwidefsky 已提交
265
	struct pt_regs *regs = task_pt_regs(current);
L
Linus Torvalds 已提交
266 267 268 269 270
	rt_sigframe32 __user *frame = (rt_sigframe32 __user *)regs->gprs[15];
	sigset_t set;

	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
		goto badframe;
271
	set_current_blocked(&set);
L
Linus Torvalds 已提交
272 273
	if (restore_sigregs32(regs, &frame->uc.uc_mcontext))
		goto badframe;
274 275
	if (restore_sigregs_gprs_high(regs, frame->gprs_high))
		goto badframe;
A
Al Viro 已提交
276
	if (compat_restore_altstack(&frame->uc.uc_stack))
L
Linus Torvalds 已提交
277 278 279
		goto badframe; 
	return regs->gprs[2];
badframe:
M
Martin Schwidefsky 已提交
280 281
	force_sig(SIGSEGV, current);
	return 0;
L
Linus Torvalds 已提交
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
}	

/*
 * Set up a signal frame.
 */


/*
 * Determine which stack to use..
 */
static inline void __user *
get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
{
	unsigned long sp;

	/* Default to using normal stack */
	sp = (unsigned long) A(regs->gprs[15]);

300 301 302 303
	/* Overflow on alternate signal stack gives SIGSEGV. */
	if (on_sig_stack(sp) && !on_sig_stack((sp - frame_size) & -8UL))
		return (void __user *) -1UL;

L
Linus Torvalds 已提交
304 305
	/* This is the X/Open sanctioned signal stack switching.  */
	if (ka->sa.sa_flags & SA_ONSTACK) {
306
		if (! sas_ss_flags(sp))
L
Linus Torvalds 已提交
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322
			sp = current->sas_ss_sp + current->sas_ss_size;
	}

	return (void __user *)((sp - frame_size) & -8ul);
}

static inline int map_signal(int sig)
{
	if (current_thread_info()->exec_domain
	    && current_thread_info()->exec_domain->signal_invmap
	    && sig < 32)
		return current_thread_info()->exec_domain->signal_invmap[sig];
        else
		return sig;
}

323
static int setup_frame32(int sig, struct k_sigaction *ka,
L
Linus Torvalds 已提交
324 325 326 327
			sigset_t *set, struct pt_regs * regs)
{
	sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(sigframe32));

328 329 330
	if (frame == (void __user *) -1UL)
		goto give_sigsegv;

L
Linus Torvalds 已提交
331 332 333 334 335
	if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE32))
		goto give_sigsegv;

	if (save_sigregs32(regs, &frame->sregs))
		goto give_sigsegv;
336 337
	if (save_sigregs_gprs_high(regs, frame->gprs_high))
		goto give_sigsegv;
L
Linus Torvalds 已提交
338 339 340 341 342 343
	if (__put_user((unsigned long) &frame->sregs, &frame->sc.sregs))
		goto give_sigsegv;

	/* Set up to return from userspace.  If provided, use a stub
	   already in userspace.  */
	if (ka->sa.sa_flags & SA_RESTORER) {
344
		regs->gprs[14] = (__u64 __force) ka->sa.sa_restorer | PSW32_ADDR_AMODE;
L
Linus Torvalds 已提交
345
	} else {
346
		regs->gprs[14] = (__u64 __force) frame->retcode | PSW32_ADDR_AMODE;
L
Linus Torvalds 已提交
347
		if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
348
			       (u16 __force __user *)(frame->retcode)))
L
Linus Torvalds 已提交
349 350 351 352 353 354 355 356
			goto give_sigsegv;
        }

	/* Set up backchain. */
	if (__put_user(regs->gprs[15], (unsigned int __user *) frame))
		goto give_sigsegv;

	/* Set up registers for signal handler */
357
	regs->gprs[15] = (__force __u64) frame;
358 359
	/* Force 31 bit amode and default user address space control. */
	regs->psw.mask = PSW_MASK_BA |
360
		(PSW_USER_BITS & PSW_MASK_ASC) |
361
		(regs->psw.mask & ~PSW_MASK_ASC);
362
	regs->psw.addr = (__force __u64) ka->sa.sa_handler;
L
Linus Torvalds 已提交
363 364

	regs->gprs[2] = map_signal(sig);
365
	regs->gprs[3] = (__force __u64) &frame->sc;
L
Linus Torvalds 已提交
366 367 368

	/* We forgot to include these in the sigcontext.
	   To avoid breaking binary compatibility, they are passed as args. */
M
Martin Schwidefsky 已提交
369 370 371 372 373
	if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL ||
	    sig == SIGTRAP || sig == SIGFPE) {
		/* set extra registers only for synchronous signals */
		regs->gprs[4] = regs->int_code & 127;
		regs->gprs[5] = regs->int_parm_long;
374
		regs->gprs[6] = task_thread_info(current)->last_break;
M
Martin Schwidefsky 已提交
375
	}
L
Linus Torvalds 已提交
376 377

	/* Place signal number on stack to allow backtrace from handler.  */
378
	if (__put_user(regs->gprs[2], (int __force __user *) &frame->signo))
L
Linus Torvalds 已提交
379
		goto give_sigsegv;
380
	return 0;
L
Linus Torvalds 已提交
381 382 383

give_sigsegv:
	force_sigsegv(sig, current);
384
	return -EFAULT;
L
Linus Torvalds 已提交
385 386
}

387
static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
L
Linus Torvalds 已提交
388 389 390 391 392
			   sigset_t *set, struct pt_regs * regs)
{
	int err = 0;
	rt_sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(rt_sigframe32));

393 394 395
	if (frame == (void __user *) -1UL)
		goto give_sigsegv;

L
Linus Torvalds 已提交
396 397 398 399
	if (copy_siginfo_to_user32(&frame->info, info))
		goto give_sigsegv;

	/* Create the ucontext.  */
400
	err |= __put_user(UC_EXTENDED, &frame->uc.uc_flags);
L
Linus Torvalds 已提交
401
	err |= __put_user(0, &frame->uc.uc_link);
A
Al Viro 已提交
402
	err |= __compat_save_altstack(&frame->uc.uc_stack, regs->gprs[15]);
L
Linus Torvalds 已提交
403
	err |= save_sigregs32(regs, &frame->uc.uc_mcontext);
404
	err |= save_sigregs_gprs_high(regs, frame->gprs_high);
L
Linus Torvalds 已提交
405 406 407 408 409 410 411
	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
	if (err)
		goto give_sigsegv;

	/* Set up to return from userspace.  If provided, use a stub
	   already in userspace.  */
	if (ka->sa.sa_flags & SA_RESTORER) {
412
		regs->gprs[14] = (__u64 __force) ka->sa.sa_restorer | PSW32_ADDR_AMODE;
L
Linus Torvalds 已提交
413
	} else {
414
		regs->gprs[14] = (__u64 __force) frame->retcode | PSW32_ADDR_AMODE;
415 416 417
		if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
			       (u16 __force __user *)(frame->retcode)))
			goto give_sigsegv;
L
Linus Torvalds 已提交
418 419 420
	}

	/* Set up backchain. */
421
	if (__put_user(regs->gprs[15], (unsigned int __force __user *) frame))
L
Linus Torvalds 已提交
422 423 424
		goto give_sigsegv;

	/* Set up registers for signal handler */
425
	regs->gprs[15] = (__force __u64) frame;
426 427
	/* Force 31 bit amode and default user address space control. */
	regs->psw.mask = PSW_MASK_BA |
428
		(PSW_USER_BITS & PSW_MASK_ASC) |
429
		(regs->psw.mask & ~PSW_MASK_ASC);
430
	regs->psw.addr = (__u64 __force) ka->sa.sa_handler;
L
Linus Torvalds 已提交
431 432

	regs->gprs[2] = map_signal(sig);
433 434
	regs->gprs[3] = (__force __u64) &frame->info;
	regs->gprs[4] = (__force __u64) &frame->uc;
435
	regs->gprs[5] = task_thread_info(current)->last_break;
436
	return 0;
L
Linus Torvalds 已提交
437 438 439

give_sigsegv:
	force_sigsegv(sig, current);
440
	return -EFAULT;
L
Linus Torvalds 已提交
441 442 443 444 445 446
}

/*
 * OK, we're invoking a handler
 */	

447
void handle_signal32(unsigned long sig, struct k_sigaction *ka,
448
		    siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
L
Linus Torvalds 已提交
449
{
450 451
	int ret;

L
Linus Torvalds 已提交
452 453
	/* Set up the stack frame */
	if (ka->sa.sa_flags & SA_SIGINFO)
454
		ret = setup_rt_frame32(sig, ka, info, oldset, regs);
L
Linus Torvalds 已提交
455
	else
456
		ret = setup_frame32(sig, ka, oldset, regs);
457
	if (ret)
458
		return;
A
Al Viro 已提交
459
	signal_delivered(sig, info, ka, regs,
460
				 test_thread_flag(TIF_SINGLE_STEP));
L
Linus Torvalds 已提交
461 462
}