114 lines
3.6 KiB
Diff
114 lines
3.6 KiB
Diff
From 3d6e48f43340343d97839eadb1ab7b6a3ea98797 Mon Sep 17 00:00:00 2001
|
|
From: Jarod Wilson <jwilson@redhat.com>
|
|
Date: Tue, 9 Sep 2008 12:38:56 +0200
|
|
Subject: S390: CVE-2008-1514: prevent ptrace padding area read/write in 31-bit mode
|
|
|
|
From: Jarod Wilson <jwilson@redhat.com>
|
|
|
|
commit 3d6e48f43340343d97839eadb1ab7b6a3ea98797 upstream
|
|
|
|
When running a 31-bit ptrace, on either an s390 or s390x kernel,
|
|
reads and writes into a padding area in struct user_regs_struct32
|
|
will result in a kernel panic.
|
|
|
|
This is also known as CVE-2008-1514.
|
|
|
|
Test case available here:
|
|
http://sources.redhat.com/cgi-bin/cvsweb.cgi/~checkout~/tests/ptrace-tests/tests/user-area-padding.c?cvsroot=systemtap
|
|
|
|
Steps to reproduce:
|
|
1) wget the above
|
|
2) gcc -o user-area-padding-31bit user-area-padding.c -Wall -ggdb2 -D_GNU_SOURCE -m31
|
|
3) ./user-area-padding-31bit
|
|
<panic>
|
|
|
|
Test status
|
|
-----------
|
|
Without patch, both s390 and s390x kernels panic. With patch, the test case,
|
|
as well as the gdb testsuite, pass without incident, padding area reads
|
|
returning zero, writes ignored.
|
|
|
|
Nb: original version returned -EINVAL on write attempts, which broke the
|
|
gdb test and made the test case slightly unhappy, Jan Kratochvil suggested
|
|
the change to return 0 on write attempts.
|
|
|
|
Signed-off-by: Jarod Wilson <jarod@redhat.com>
|
|
Tested-by: Jan Kratochvil <jan.kratochvil@redhat.com>
|
|
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
|
|
Cc: Moritz Muehlenhoff <jmm@debian.org>
|
|
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
|
|
|
---
|
|
arch/s390/kernel/compat_ptrace.h | 1 +
|
|
arch/s390/kernel/ptrace.c | 28 ++++++++++++++++++++++++++++
|
|
2 files changed, 29 insertions(+)
|
|
|
|
--- a/arch/s390/kernel/compat_ptrace.h
|
|
+++ b/arch/s390/kernel/compat_ptrace.h
|
|
@@ -42,6 +42,7 @@ struct user_regs_struct32
|
|
u32 gprs[NUM_GPRS];
|
|
u32 acrs[NUM_ACRS];
|
|
u32 orig_gpr2;
|
|
+ /* nb: there's a 4-byte hole here */
|
|
s390_fp_regs fp_regs;
|
|
/*
|
|
* These per registers are in here so that gdb can modify them
|
|
--- a/arch/s390/kernel/ptrace.c
|
|
+++ b/arch/s390/kernel/ptrace.c
|
|
@@ -177,6 +177,13 @@ peek_user(struct task_struct *child, add
|
|
*/
|
|
tmp = (addr_t) task_pt_regs(child)->orig_gpr2;
|
|
|
|
+ } else if (addr < (addr_t) &dummy->regs.fp_regs) {
|
|
+ /*
|
|
+ * prevent reads of padding hole between
|
|
+ * orig_gpr2 and fp_regs on s390.
|
|
+ */
|
|
+ tmp = 0;
|
|
+
|
|
} else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) {
|
|
/*
|
|
* floating point regs. are stored in the thread structure
|
|
@@ -268,6 +275,13 @@ poke_user(struct task_struct *child, add
|
|
*/
|
|
task_pt_regs(child)->orig_gpr2 = data;
|
|
|
|
+ } else if (addr < (addr_t) &dummy->regs.fp_regs) {
|
|
+ /*
|
|
+ * prevent writes of padding hole between
|
|
+ * orig_gpr2 and fp_regs on s390.
|
|
+ */
|
|
+ return 0;
|
|
+
|
|
} else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) {
|
|
/*
|
|
* floating point regs. are stored in the thread structure
|
|
@@ -409,6 +423,13 @@ peek_user_emu31(struct task_struct *chil
|
|
*/
|
|
tmp = *(__u32*)((addr_t) &task_pt_regs(child)->orig_gpr2 + 4);
|
|
|
|
+ } else if (addr < (addr_t) &dummy32->regs.fp_regs) {
|
|
+ /*
|
|
+ * prevent reads of padding hole between
|
|
+ * orig_gpr2 and fp_regs on s390.
|
|
+ */
|
|
+ tmp = 0;
|
|
+
|
|
} else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) {
|
|
/*
|
|
* floating point regs. are stored in the thread structure
|
|
@@ -488,6 +509,13 @@ poke_user_emu31(struct task_struct *chil
|
|
*/
|
|
*(__u32*)((addr_t) &task_pt_regs(child)->orig_gpr2 + 4) = tmp;
|
|
|
|
+ } else if (addr < (addr_t) &dummy32->regs.fp_regs) {
|
|
+ /*
|
|
+ * prevent writess of padding hole between
|
|
+ * orig_gpr2 and fp_regs on s390.
|
|
+ */
|
|
+ return 0;
|
|
+
|
|
} else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) {
|
|
/*
|
|
* floating point regs. are stored in the thread structure
|