--- /dev/null
+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);
+ }
+
--- /dev/null
+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;