compat_signal.c 13.5 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_pt_regs_flag(regs, PIF_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;
}

244
COMPAT_SYSCALL_DEFINE0(sigreturn)
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;
}

263
COMPAT_SYSCALL_DEFINE0(rt_sigreturn)
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 324
static int setup_frame32(struct ksignal *ksig, sigset_t *set,
			 struct pt_regs *regs)
L
Linus Torvalds 已提交
325
{
326 327
	int sig = ksig->sig;
	sigframe32 __user *frame = get_sigframe(&ksig->ka, regs, sizeof(sigframe32));
L
Linus Torvalds 已提交
328

329
	if (frame == (void __user *) -1UL)
330
		return -EFAULT;
331

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

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

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

	/* Set up backchain. */
	if (__put_user(regs->gprs[15], (unsigned int __user *) frame))
355
		return -EFAULT;
L
Linus Torvalds 已提交
356 357

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

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

	/* We forgot to include these in the sigcontext.
	   To avoid breaking binary compatibility, they are passed as args. */
M
Martin Schwidefsky 已提交
370 371 372 373 374
	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;
375
		regs->gprs[6] = task_thread_info(current)->last_break;
M
Martin Schwidefsky 已提交
376
	}
L
Linus Torvalds 已提交
377 378

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

384 385
static int setup_rt_frame32(struct ksignal *ksig, sigset_t *set,
			    struct pt_regs *regs)
L
Linus Torvalds 已提交
386 387
{
	int err = 0;
388
	rt_sigframe32 __user *frame = get_sigframe(&ksig->ka, regs, sizeof(rt_sigframe32));
L
Linus Torvalds 已提交
389

390
	if (frame == (void __user *) -1UL)
391
		return -EFAULT;
392

393 394
	if (copy_siginfo_to_user32(&frame->info, &ksig->info))
		return -EFAULT;
L
Linus Torvalds 已提交
395 396

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

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

	/* Set up backchain. */
418
	if (__put_user(regs->gprs[15], (unsigned int __force __user *) frame))
419
		return -EFAULT;
L
Linus Torvalds 已提交
420 421

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

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

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

440 441
void handle_signal32(struct ksignal *ksig, sigset_t *oldset,
		     struct pt_regs *regs)
L
Linus Torvalds 已提交
442
{
443 444
	int ret;

L
Linus Torvalds 已提交
445
	/* Set up the stack frame */
446 447
	if (ksig->ka.sa.sa_flags & SA_SIGINFO)
		ret = setup_rt_frame32(ksig, oldset, regs);
L
Linus Torvalds 已提交
448
	else
449 450 451
		ret = setup_frame32(ksig, oldset, regs);

	signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLE_STEP));
L
Linus Torvalds 已提交
452 453
}