]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 21 Nov 2012 01:36:54 +0000 (17:36 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 21 Nov 2012 01:36:54 +0000 (17:36 -0800)
added patches:
s390-signal-set-correct-address-space-control.patch

queue-3.6/s390-signal-set-correct-address-space-control.patch [new file with mode: 0644]
queue-3.6/series

diff --git a/queue-3.6/s390-signal-set-correct-address-space-control.patch b/queue-3.6/s390-signal-set-correct-address-space-control.patch
new file mode 100644 (file)
index 0000000..c767f4f
--- /dev/null
@@ -0,0 +1,137 @@
+From fa968ee215c0ca91e4a9c3a69ac2405aae6e5d2f Mon Sep 17 00:00:00 2001
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Wed, 7 Nov 2012 10:44:08 +0100
+Subject: s390/signal: set correct address space control
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+commit fa968ee215c0ca91e4a9c3a69ac2405aae6e5d2f upstream.
+
+If user space is running in primary mode it can switch to secondary
+or access register mode, this is used e.g. in the clock_gettime code
+of the vdso. If a signal is delivered to the user space process while
+it has been running in access register mode the signal handler is
+executed in access register mode as well which will result in a crash
+most of the time.
+
+Set the address space control bits in the PSW to the default for the
+execution of the signal handler and make sure that the previous
+address space control is restored on signal return. Take care
+that user space can not switch to the kernel address space by
+modifying the registers in the signal frame.
+
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/s390/include/asm/compat.h   |    2 +-
+ arch/s390/include/asm/ptrace.h   |    4 ++--
+ arch/s390/kernel/compat_signal.c |   14 ++++++++++++--
+ arch/s390/kernel/signal.c        |   14 ++++++++++++--
+ 4 files changed, 27 insertions(+), 7 deletions(-)
+
+--- a/arch/s390/include/asm/compat.h
++++ b/arch/s390/include/asm/compat.h
+@@ -20,7 +20,7 @@
+ #define PSW32_MASK_CC         0x00003000UL
+ #define PSW32_MASK_PM         0x00000f00UL
+-#define PSW32_MASK_USER               0x00003F00UL
++#define PSW32_MASK_USER               0x0000FF00UL
+ #define PSW32_ADDR_AMODE      0x80000000UL
+ #define PSW32_ADDR_INSN               0x7FFFFFFFUL
+--- a/arch/s390/include/asm/ptrace.h
++++ b/arch/s390/include/asm/ptrace.h
+@@ -238,7 +238,7 @@ typedef struct
+ #define PSW_MASK_EA           0x00000000UL
+ #define PSW_MASK_BA           0x00000000UL
+-#define PSW_MASK_USER         0x00003F00UL
++#define PSW_MASK_USER         0x0000FF00UL
+ #define PSW_ADDR_AMODE                0x80000000UL
+ #define PSW_ADDR_INSN         0x7FFFFFFFUL
+@@ -267,7 +267,7 @@ typedef struct
+ #define PSW_MASK_EA           0x0000000100000000UL
+ #define PSW_MASK_BA           0x0000000080000000UL
+-#define PSW_MASK_USER         0x00003F0180000000UL
++#define PSW_MASK_USER         0x0000FF0180000000UL
+ #define PSW_ADDR_AMODE                0x0000000000000000UL
+ #define PSW_ADDR_INSN         0xFFFFFFFFFFFFFFFFUL
+--- a/arch/s390/kernel/compat_signal.c
++++ b/arch/s390/kernel/compat_signal.c
+@@ -309,6 +309,10 @@ static int restore_sigregs32(struct pt_r
+       regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
+               (__u64)(regs32.psw.mask & PSW32_MASK_USER) << 32 |
+               (__u64)(regs32.psw.addr & PSW32_ADDR_AMODE);
++      /* Check for invalid user address space control. */
++      if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC))
++              regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) |
++                      (regs->psw.mask & ~PSW_MASK_ASC);
+       regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN);
+       for (i = 0; i < NUM_GPRS; i++)
+               regs->gprs[i] = (__u64) regs32.gprs[i];
+@@ -481,7 +485,10 @@ static int setup_frame32(int sig, struct
+       /* Set up registers for signal handler */
+       regs->gprs[15] = (__force __u64) frame;
+-      regs->psw.mask |= PSW_MASK_BA;          /* force amode 31 */
++      /* Force 31 bit amode and default user address space control. */
++      regs->psw.mask = PSW_MASK_BA |
++              (psw_user_bits & PSW_MASK_ASC) |
++              (regs->psw.mask & ~PSW_MASK_ASC);
+       regs->psw.addr = (__force __u64) ka->sa.sa_handler;
+       regs->gprs[2] = map_signal(sig);
+@@ -549,7 +556,10 @@ static int setup_rt_frame32(int sig, str
+       /* Set up registers for signal handler */
+       regs->gprs[15] = (__force __u64) frame;
+-      regs->psw.mask |= PSW_MASK_BA;          /* force amode 31 */
++      /* Force 31 bit amode and default user address space control. */
++      regs->psw.mask = PSW_MASK_BA |
++              (psw_user_bits & PSW_MASK_ASC) |
++              (regs->psw.mask & ~PSW_MASK_ASC);
+       regs->psw.addr = (__u64) ka->sa.sa_handler;
+       regs->gprs[2] = map_signal(sig);
+--- a/arch/s390/kernel/signal.c
++++ b/arch/s390/kernel/signal.c
+@@ -136,6 +136,10 @@ static int restore_sigregs(struct pt_reg
+       /* Use regs->psw.mask instead of psw_user_bits to preserve PER bit. */
+       regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
+               (user_sregs.regs.psw.mask & PSW_MASK_USER);
++      /* Check for invalid user address space control. */
++      if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC))
++              regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) |
++                      (regs->psw.mask & ~PSW_MASK_ASC);
+       /* Check for invalid amode */
+       if (regs->psw.mask & PSW_MASK_EA)
+               regs->psw.mask |= PSW_MASK_BA;
+@@ -273,7 +277,10 @@ static int setup_frame(int sig, struct k
+       /* Set up registers for signal handler */
+       regs->gprs[15] = (unsigned long) frame;
+-      regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA;    /* 64 bit amode */
++      /* Force default amode and default user address space control. */
++      regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
++              (psw_user_bits & PSW_MASK_ASC) |
++              (regs->psw.mask & ~PSW_MASK_ASC);
+       regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
+       regs->gprs[2] = map_signal(sig);
+@@ -346,7 +353,10 @@ static int setup_rt_frame(int sig, struc
+       /* Set up registers for signal handler */
+       regs->gprs[15] = (unsigned long) frame;
+-      regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA;    /* 64 bit amode */
++      /* Force default amode and default user address space control. */
++      regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
++              (psw_user_bits & PSW_MASK_ASC) |
++              (regs->psw.mask & ~PSW_MASK_ASC);
+       regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
+       regs->gprs[2] = map_signal(sig);
index 7ce7e13bee29efb10e760e65f55d1703b39cf9a7..d3bd7feb83f3adc01ba284b4676f8ff39c7edc15 100644 (file)
@@ -49,3 +49,4 @@ r8169-allow-multicast-packets-on-sub-8168f-chipset.patch
 netfilter-nf_nat-don-t-check-for-port-change-on-icmp-tuples.patch
 netfilter-xt_tee-don-t-use-destination-address-found-in-header.patch
 netfilter-nf_conntrack-fix-rt_gateway-checks-for-h.323-helper.patch
+s390-signal-set-correct-address-space-control.patch