]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.7-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 27 Dec 2012 22:58:59 +0000 (14:58 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 27 Dec 2012 22:58:59 +0000 (14:58 -0800)
added patches:
arm64-make-dirty-ptes-read-only.patch
arm64-signal-push-the-unwinding-prologue-on-the-signal-stack.patch

queue-3.7/arm64-make-dirty-ptes-read-only.patch [new file with mode: 0644]
queue-3.7/arm64-signal-push-the-unwinding-prologue-on-the-signal-stack.patch [new file with mode: 0644]
queue-3.7/series

diff --git a/queue-3.7/arm64-make-dirty-ptes-read-only.patch b/queue-3.7/arm64-make-dirty-ptes-read-only.patch
new file mode 100644 (file)
index 0000000..c6334af
--- /dev/null
@@ -0,0 +1,31 @@
+From 33eaa58f854770dc9c98411a356c98e3a53edfda Mon Sep 17 00:00:00 2001
+From: Catalin Marinas <catalin.marinas@arm.com>
+Date: Wed, 28 Nov 2012 17:06:05 +0000
+Subject: arm64: Make !dirty ptes read-only
+
+From: Catalin Marinas <catalin.marinas@arm.com>
+
+commit 33eaa58f854770dc9c98411a356c98e3a53edfda upstream.
+
+The AArch64 Linux port relies on the mm code to wrprotect clean ptes.
+This however is not the case with newly created ptes and
+PAGE_SHARED(_EXEC) is writable but !dirty.
+
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm64/include/asm/pgtable.h |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/arch/arm64/include/asm/pgtable.h
++++ b/arch/arm64/include/asm/pgtable.h
+@@ -159,6 +159,8 @@ static inline void set_pte_at(struct mm_
+ {
+       if (pte_present_exec_user(pte))
+               __sync_icache_dcache(pte, addr);
++      if (!pte_dirty(pte))
++              pte = pte_wrprotect(pte);
+       set_pte(ptep, pte);
+ }
diff --git a/queue-3.7/arm64-signal-push-the-unwinding-prologue-on-the-signal-stack.patch b/queue-3.7/arm64-signal-push-the-unwinding-prologue-on-the-signal-stack.patch
new file mode 100644 (file)
index 0000000..b472cd4
--- /dev/null
@@ -0,0 +1,120 @@
+From 304ef4e8367244b547734143c792a2ab764831e8 Mon Sep 17 00:00:00 2001
+From: Will Deacon <will.deacon@arm.com>
+Date: Fri, 23 Nov 2012 12:34:13 +0000
+Subject: arm64: signal: push the unwinding prologue on the signal stack
+
+From: Will Deacon <will.deacon@arm.com>
+
+commit 304ef4e8367244b547734143c792a2ab764831e8 upstream.
+
+To allow debuggers to unwind through signal frames, we create a fake
+stack unwinding prologue containing the link register and frame pointer
+of the interrupted context. The signal frame is then offset by 16 bytes
+to make room for the two saved registers which are pushed onto the frame
+of the *interrupted* context, rather than placed directly above the
+signal stack.
+
+This doesn't work when an alternative signal stack is set up for a SEGV
+handler, which is raised in response to RLIMIT_STACK being reached. In
+this case, we try to push the unwinding prologue onto the full stack and
+subsequently take a fault which we fail to resolve, causing setup_return
+to return -EFAULT and handle_signal to force_sigsegv on the current task.
+
+This patch fixes the problem by including the unwinding prologue as part
+of the rt_sigframe definition, which is populated during setup_sigframe,
+ensuring that it always ends up on the signal stack.
+
+Signed-off-by: Will Deacon <will.deacon@arm.com>
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm64/kernel/signal.c |   37 ++++++++++++++++---------------------
+ 1 file changed, 16 insertions(+), 21 deletions(-)
+
+--- a/arch/arm64/kernel/signal.c
++++ b/arch/arm64/kernel/signal.c
+@@ -41,6 +41,8 @@
+ struct rt_sigframe {
+       struct siginfo info;
+       struct ucontext uc;
++      u64 fp;
++      u64 lr;
+ };
+ static int preserve_fpsimd_context(struct fpsimd_context __user *ctx)
+@@ -175,6 +177,10 @@ static int setup_sigframe(struct rt_sigf
+       struct aux_context __user *aux =
+               (struct aux_context __user *)sf->uc.uc_mcontext.__reserved;
++      /* set up the stack frame for unwinding */
++      __put_user_error(regs->regs[29], &sf->fp, err);
++      __put_user_error(regs->regs[30], &sf->lr, err);
++
+       for (i = 0; i < 31; i++)
+               __put_user_error(regs->regs[i], &sf->uc.uc_mcontext.regs[i],
+                                err);
+@@ -210,9 +216,6 @@ static void __user *get_sigframe(struct
+       if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
+               sp = sp_top = current->sas_ss_sp + current->sas_ss_size;
+-      /* room for stack frame (FP, LR) */
+-      sp -= 16;
+-
+       sp = (sp - framesize) & ~15;
+       frame = (void __user *)sp;
+@@ -225,20 +228,14 @@ static void __user *get_sigframe(struct
+       return frame;
+ }
+-static int setup_return(struct pt_regs *regs, struct k_sigaction *ka,
+-                      void __user *frame, int usig)
++static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
++                       void __user *frame, int usig)
+ {
+-      int err = 0;
+       __sigrestore_t sigtramp;
+-      unsigned long __user *sp = (unsigned long __user *)regs->sp;
+-
+-      /* set up the stack frame */
+-      __put_user_error(regs->regs[29], sp - 2, err);
+-      __put_user_error(regs->regs[30], sp - 1, err);
+       regs->regs[0] = usig;
+-      regs->regs[29] = regs->sp - 16;
+       regs->sp = (unsigned long)frame;
++      regs->regs[29] = regs->sp + offsetof(struct rt_sigframe, fp);
+       regs->pc = (unsigned long)ka->sa.sa_handler;
+       if (ka->sa.sa_flags & SA_RESTORER)
+@@ -247,8 +244,6 @@ static int setup_return(struct pt_regs *
+               sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp);
+       regs->regs[30] = (unsigned long)sigtramp;
+-
+-      return err;
+ }
+ static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
+@@ -272,13 +267,13 @@ static int setup_rt_frame(int usig, stru
+       err |= __copy_to_user(&frame->uc.uc_stack, &stack, sizeof(stack));
+       err |= setup_sigframe(frame, regs, set);
+-      if (err == 0)
+-              err = setup_return(regs, ka, frame, usig);
+-
+-      if (err == 0 && ka->sa.sa_flags & SA_SIGINFO) {
+-              err |= copy_siginfo_to_user(&frame->info, info);
+-              regs->regs[1] = (unsigned long)&frame->info;
+-              regs->regs[2] = (unsigned long)&frame->uc;
++      if (err == 0) {
++              setup_return(regs, ka, frame, usig);
++              if (ka->sa.sa_flags & SA_SIGINFO) {
++                      err |= copy_siginfo_to_user(&frame->info, info);
++                      regs->regs[1] = (unsigned long)&frame->info;
++                      regs->regs[2] = (unsigned long)&frame->uc;
++              }
+       }
+       return err;
index f9f86dd3ab1fc5f915f25f6758a90f5c0c205c01..dfc8af7f7be0db527d347cfa44d844d198f9cd91 100644 (file)
@@ -6,3 +6,5 @@ b43-fix-tx-path-skb-leaks.patch
 pnpacpi-fix-incorrect-test_alpha-test.patch
 sgi-xp-handle-non-fatal-traps.patch
 exec-do-not-leave-bprm-interp-on-stack.patch
+arm64-make-dirty-ptes-read-only.patch
+arm64-signal-push-the-unwinding-prologue-on-the-signal-stack.patch