--- /dev/null
+From 22839869f21ab3850fbbac9b425ccc4c0023926f Mon Sep 17 00:00:00 2001
+From: Will Deacon <will.deacon@arm.com>
+Date: Wed, 5 Sep 2018 15:34:42 +0100
+Subject: signal: Introduce COMPAT_SIGMINSTKSZ for use in compat_sys_sigaltstack
+
+From: Will Deacon <will.deacon@arm.com>
+
+commit 22839869f21ab3850fbbac9b425ccc4c0023926f upstream.
+
+The sigaltstack(2) system call fails with -ENOMEM if the new alternative
+signal stack is found to be smaller than SIGMINSTKSZ. On architectures
+such as arm64, where the native value for SIGMINSTKSZ is larger than
+the compat value, this can result in an unexpected error being reported
+to a compat task. See, for example:
+
+ https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=904385
+
+This patch fixes the problem by extending do_sigaltstack to take the
+minimum signal stack size as an additional parameter, allowing the
+native and compat system call entry code to pass in their respective
+values. COMPAT_SIGMINSTKSZ is just defined as SIGMINSTKSZ if it has not
+been defined by the architecture.
+
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: Dominik Brodowski <linux@dominikbrodowski.net>
+Cc: "Eric W. Biederman" <ebiederm@xmission.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Al Viro <viro@zeniv.linux.org.uk>
+Cc: Oleg Nesterov <oleg@redhat.com>
+Reported-by: Steve McIntyre <steve.mcintyre@arm.com>
+Tested-by: Steve McIntyre <93sam@debian.org>
+Signed-off-by: Will Deacon <will.deacon@arm.com>
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+[signal: Fix up cherry-pick conflicts for 22839869f21a]
+Signed-off-by: Steve McIntyre <93sam@debian.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/compat.h | 3 +++
+ kernel/signal.c | 17 ++++++++++-------
+ 2 files changed, 13 insertions(+), 7 deletions(-)
+
+--- a/include/linux/compat.h
++++ b/include/linux/compat.h
+@@ -67,6 +67,9 @@ typedef struct compat_sigaltstack {
+ compat_size_t ss_size;
+ } compat_stack_t;
+ #endif
++#ifndef COMPAT_MINSIGSTKSZ
++#define COMPAT_MINSIGSTKSZ MINSIGSTKSZ
++#endif
+
+ #define compat_jiffies_to_clock_t(x) \
+ (((unsigned long)(x) * COMPAT_USER_HZ) / HZ)
+--- a/kernel/signal.c
++++ b/kernel/signal.c
+@@ -3116,7 +3116,8 @@ int do_sigaction(int sig, struct k_sigac
+ }
+
+ static int
+-do_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, unsigned long sp)
++do_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, unsigned long sp,
++ size_t min_ss_size)
+ {
+ stack_t oss;
+ int error;
+@@ -3155,9 +3156,8 @@ do_sigaltstack (const stack_t __user *us
+ ss_size = 0;
+ ss_sp = NULL;
+ } else {
+- error = -ENOMEM;
+- if (ss_size < MINSIGSTKSZ)
+- goto out;
++ if (unlikely(ss_size < min_ss_size))
++ return -ENOMEM;
+ }
+
+ current->sas_ss_sp = (unsigned long) ss_sp;
+@@ -3180,12 +3180,14 @@ out:
+ }
+ SYSCALL_DEFINE2(sigaltstack,const stack_t __user *,uss, stack_t __user *,uoss)
+ {
+- return do_sigaltstack(uss, uoss, current_user_stack_pointer());
++ return do_sigaltstack(uss, uoss, current_user_stack_pointer(),
++ MINSIGSTKSZ);
+ }
+
+ int restore_altstack(const stack_t __user *uss)
+ {
+- int err = do_sigaltstack(uss, NULL, current_user_stack_pointer());
++ int err = do_sigaltstack(uss, NULL, current_user_stack_pointer(),
++ MINSIGSTKSZ);
+ /* squash all but EFAULT for now */
+ return err == -EFAULT ? err : 0;
+ }
+@@ -3226,7 +3228,8 @@ COMPAT_SYSCALL_DEFINE2(sigaltstack,
+ set_fs(KERNEL_DS);
+ ret = do_sigaltstack((stack_t __force __user *) (uss_ptr ? &uss : NULL),
+ (stack_t __force __user *) &uoss,
+- compat_user_stack_pointer());
++ compat_user_stack_pointer(),
++ COMPAT_MINSIGSTKSZ);
+ set_fs(seg);
+ if (ret >= 0 && uoss_ptr) {
+ if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(compat_stack_t)) ||