Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bb9c861e authored by Al Viro's avatar Al Viro Committed by Linus Torvalds
Browse files

m32r: hole in shifting pc back



It's a userland pointer; worse, an untrustable one since ptrace
has just provided a chance to modify it.

X-Roothole-Covering-Cabal: TINRCC
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent a05c4e1d
Loading
Loading
Loading
Loading
+17 −21
Original line number Diff line number Diff line
@@ -251,6 +251,19 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
	return -EFAULT;
}

static int prev_insn(struct pt_regs *regs)
{
	u16 inst;
	if (get_user(&inst, (u16 __user *)(regs->bpc - 2)))
		return -EFAULT;
	if ((inst & 0xfff0) == 0x10f0)	/* trap ? */
		regs->bpc -= 2;
	else
		regs->bpc -= 4;
	regs->syscall_nr = -1;
	return 0;
}

/*
 * OK, we're invoking a handler
 */
@@ -259,8 +272,6 @@ static int
handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
	      sigset_t *oldset, struct pt_regs *regs)
{
	unsigned short inst;

	/* Are we from a system call? */
	if (regs->syscall_nr >= 0) {
		/* If so, check system call restarting.. */
@@ -278,12 +289,8 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
			/* fallthrough */
			case -ERESTARTNOINTR:
				regs->r0 = regs->orig_r0;
				inst = *(unsigned short *)(regs->bpc - 2);
				if ((inst & 0xfff0) == 0x10f0)	/* trap ? */
					regs->bpc -= 2;
				else
					regs->bpc -= 4;
				regs->syscall_nr = -1;
				if (prev_insn(regs) < 0)
					return -EFAULT;
		}
	}

@@ -310,7 +317,6 @@ static void do_signal(struct pt_regs *regs)
	siginfo_t info;
	int signr;
	struct k_sigaction ka;
	unsigned short inst;
	sigset_t *oldset;

	/*
@@ -353,21 +359,11 @@ static void do_signal(struct pt_regs *regs)
		    regs->r0 == -ERESTARTSYS ||
		    regs->r0 == -ERESTARTNOINTR) {
			regs->r0 = regs->orig_r0;
			inst = *(unsigned short *)(regs->bpc - 2);
			if ((inst & 0xfff0) == 0x10f0)	/* trap ? */
				regs->bpc -= 2;
			else
				regs->bpc -= 4;
			regs->syscall_nr = -1;
			prev_insn(regs);
		} else if (regs->r0 == -ERESTART_RESTARTBLOCK){
			regs->r0 = regs->orig_r0;
			regs->r7 = __NR_restart_syscall;
			inst = *(unsigned short *)(regs->bpc - 2);
			if ((inst & 0xfff0) == 0x10f0)	/* trap ? */
				regs->bpc -= 2;
			else
				regs->bpc -= 4;
			regs->syscall_nr = -1;
			prev_insn(regs);
		}
	}
	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {