Skip to contentSkip to conversation

m32r: fix rt_sigsuspend()

PATCH New Al Viro 1 participant 5 messages Sep 24, 2010

Subsystems (2)
lore
Share & tools
lore

Al Viro

author
#0 lore raw

PATCH 1/5 m32r: fix rt_sigsuspend()

do_signal() should know about saved_mask for it to work...

---
 arch/m32r/include/asm/signal.h |    1 -
 arch/m32r/include/asm/unistd.h |    1 +
 arch/m32r/kernel/entry.S       |    3 +-
 arch/m32r/kernel/signal.c      |   48 ++++++++++------------------------------
 4 files changed, 14 insertions(+), 39 deletions(-)
arch/m32r/include/asm/signal.h +0 -1
index 9c1acb2..b2eeb0d 100644
@@ -157,7 +157,6 @@ typedef struct sigaltstack {
 #undef __HAVE_ARCH_SIG_BITOPS
 
 struct pt_regs;
-extern int do_signal(struct pt_regs *regs, sigset_t *oldset);
 
 #define ptrace_signal_deliver(regs, cookie)	do { } while (0)
 
arch/m32r/include/asm/unistd.h +1 -0
index 7612577..c705456 100644
@@ -351,6 +351,7 @@
 #define __ARCH_WANT_SYS_OLD_GETRLIMIT /*will be unused*/
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_RT_SIGACTION
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
 
 #define __IGNORE_lchown
 #define __IGNORE_setuid
arch/m32r/kernel/entry.S +1 -2
index 4038698..90149da 100644
@@ -235,8 +235,7 @@ work_resched:
 work_notifysig:				; deal with pending signals and
 					; notify-resume requests
 	mv	r0, sp			; arg1 : struct pt_regs *regs
-	ldi	r1, #0			; arg2 : sigset_t *oldset
-	mv	r2, r9			; arg3 : __u32 thread_info_flags
+	ldi	r1, r9			; arg2 : __u32 thread_info_flags
 	bl	do_notify_resume
 	bra	restore_all
 
arch/m32r/kernel/signal.c +12 -36

95 lines not on this page · raw message

Signature · 1 line
1.5.6.5
author
#1 lore raw

PATCH 2/5 make m32r handle multiple pending signals

---
 arch/m32r/kernel/entry.S  |    4 ++--
 arch/m32r/kernel/signal.c |    6 ++++--
 2 files changed, 6 insertions(+), 4 deletions(-)
arch/m32r/kernel/entry.S +2 -2
index 90149da..225412b 100644
@@ -235,9 +235,9 @@ work_resched:
 work_notifysig:				; deal with pending signals and
 					; notify-resume requests
 	mv	r0, sp			; arg1 : struct pt_regs *regs
-	ldi	r1, r9			; arg2 : __u32 thread_info_flags
+	mv	r1, r9			; arg2 : __u32 thread_info_flags
 	bl	do_notify_resume
-	bra	restore_all
+	bra	resume_userspace
 
 	; perform syscall exit tracing
 	ALIGN
arch/m32r/kernel/signal.c +4 -2
index acd69f7..db15226 100644
@@ -282,6 +282,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
 					regs->bpc -= 2;
 				else
 					regs->bpc -= 4;
+				regs->syscall_nr = -1;
 		}
 	}
 
@@ -353,8 +354,8 @@ static int do_signal(struct pt_regs *regs)
 				regs->bpc -= 2;
 			else
 				regs->bpc -= 4;
-		}
-		if (regs->r0 == -ERESTART_RESTARTBLOCK){
+			regs->syscall_nr = -1;
+		} else if (regs->r0 == -ERESTART_RESTARTBLOCK){
 			regs->r0 = regs->orig_r0;
 			regs->r7 = __NR_restart_syscall;
 			inst = *(unsigned short *)(regs->bpc - 2);
@@ -362,6 +363,7 @@ static int do_signal(struct pt_regs *regs)
 				regs->bpc -= 2;
 			else
 				regs->bpc -= 4;
+			regs->syscall_nr = -1;
 		}
 	}
 	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
Signature · 1 line
1.5.6.5
author
#2 lore raw

PATCH 3/5 m32r: don't block signals if sigframe setup has failed

In reply to Al Viro
---
 arch/m32r/kernel/signal.c |   23 +++++++++++++----------
 1 files changed, 13 insertions(+), 10 deletions(-)
arch/m32r/kernel/signal.c +13 -10
index db15226..a56fcbd 100644
@@ -187,7 +187,7 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
 	return (void __user *)((sp - frame_size) & -8ul);
 }
 
-static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 			   sigset_t *set, struct pt_regs *regs)
 {
 	struct rt_sigframe __user *frame;
@@ -244,17 +244,18 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 		current->comm, current->pid, frame, regs->pc);
 #endif
 
-	return;
+	return 0;
 
 give_sigsegv:
 	force_sigsegv(sig, current);
+	return -EFAULT;
 }
 
 /*
  * OK, we're invoking a handler
  */
 
-static void
+static int
 handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
 	      sigset_t *oldset, struct pt_regs *regs)
 {
@@ -287,7 +288,8 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
 	}
 
 	/* Set up the stack frame */
-	setup_rt_frame(sig, ka, info, oldset, regs);
+	if (setup_rt_frame(sig, ka, info, oldset, regs))
+		return -EFAULT;
 
 	spin_lock_irq(&current->sighand->siglock);
 	sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -295,6 +297,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
 		sigaddset(&current->blocked,sig);
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
+	return 0;
 }
 
 /*
@@ -302,7 +305,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  */
-static int do_signal(struct pt_regs *regs)
+static void do_signal(struct pt_regs *regs)
 {
 	siginfo_t info;
 	int signr;
@@ -317,7 +320,7 @@ static int do_signal(struct pt_regs *regs)
 	 * if so.
 	 */
 	if (!user_mode(regs))
-		return 1;
+		return;
 
 	if (try_to_freeze()) 
 		goto no_signal;
@@ -336,9 +339,10 @@ static int do_signal(struct pt_regs *regs)
 		 */
 
 		/* Whee!  Actually deliver the signal.  */
-		handle_signal(signr, &ka, &info, oldset, regs);
-		clear_thread_flag(TIF_RESTORE_SIGMASK);
-		return 1;
+		if (handle_signal(signr, &ka, &info, oldset, regs) == 0)
+			clear_thread_flag(TIF_RESTORE_SIGMASK);
+
+		return;
 	}
 
  no_signal:
@@ -370,7 +374,6 @@ static int do_signal(struct pt_regs *regs)
 		clear_thread_flag(TIF_RESTORE_SIGMASK);
 		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
 	}
-	return 0;
 }
 
 /*
Signature · 1 line
1.5.6.5
author
#3 lore raw

PATCH 4/5 m32r: hole in shifting pc back

In reply to Al Viro

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

X-Roothole-Covering-Cabal: TINRCC

---
 arch/m32r/kernel/signal.c |   38 +++++++++++++++++---------------------
 1 files changed, 17 insertions(+), 21 deletions(-)
arch/m32r/kernel/signal.c +17 -21
index a56fcbd..7bbe386 100644
@@ -251,6 +251,19 @@ give_sigsegv:
 	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)) {
Signature · 1 line
1.5.6.5
author
#4 lore raw

PATCH 5/5 m32r: fix breakage from "m32r: use generic ptrace_resume code"

In reply to Al Viro
---
 arch/m32r/kernel/ptrace.c |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)
arch/m32r/kernel/ptrace.c +4 -3
index e555091..0021ade 100644
@@ -592,16 +592,17 @@ void user_enable_single_step(struct task_struct *child)
 
 	if (access_process_vm(child, pc&~3, &insn, sizeof(insn), 0)
 	    != sizeof(insn))
-		break;
+		return -EIO;
 
 	compute_next_pc(insn, pc, &next_pc, child);
 	if (next_pc & 0x80000000)
-		break;
+		return -EIO;
 
 	if (embed_debug_trap(child, next_pc))
-		break;
+		return -EIO;
 
 	invalidate_cache();
+	return 0;
 }
 
 void user_disable_single_step(struct task_struct *child)
Signature · 1 line
1.5.6.5