]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.25/patches.arch/s390-08-09-switch-amode-off.patch
Revert "Move xen patchset to new version's subdir."
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.arch / s390-08-09-switch-amode-off.patch
CommitLineData
00e5a55c
BS
1From: Gerald Schaefer <geraldsc@de.ibm.com>
2Subject: kernel: Fix user copy functions (pagetable walk) with KERNEL_DS.
3References: bnc#466462
4
5Symptom: Kernel OOPS / system hang on user program core dump on pre z9
6 hardware.
7Problem: Passing incorrect addresses to user copy functions is not handled
8 correctly when address spaces are switched and KERNEL_DS is set.
9Solution: Verify addresses by handling KERNEL_DS case in the same way as
10 USER_DS (pagetable walk). Also disable switch_amode by default
11 because pagetable walk has negative performance impact.
12
13Acked-by: John Jolly <jjolly@suse.de>
14---
15 arch/s390/kernel/setup.c | 4 ----
16 arch/s390/lib/uaccess_pt.c | 32 +++++++-------------------------
17 arch/s390/mm/pgtable.c | 4 ++++
18 3 files changed, 11 insertions(+), 29 deletions(-)
19
20Index: linux-sles11/arch/s390/kernel/setup.c
21===================================================================
22--- linux-sles11.orig/arch/s390/kernel/setup.c
23+++ linux-sles11/arch/s390/kernel/setup.c
24@@ -285,11 +285,7 @@ static int __init early_parse_mem(char *
25 early_param("mem", early_parse_mem);
26
27 #ifdef CONFIG_S390_SWITCH_AMODE
28-#ifdef CONFIG_PGSTE
29-unsigned int switch_amode = 1;
30-#else
31 unsigned int switch_amode = 0;
32-#endif
33 EXPORT_SYMBOL_GPL(switch_amode);
34
35 static int set_amode_and_uaccess(unsigned long user_amode,
36Index: linux-sles11/arch/s390/mm/pgtable.c
37===================================================================
38--- linux-sles11.orig/arch/s390/mm/pgtable.c
39+++ linux-sles11/arch/s390/mm/pgtable.c
40@@ -256,6 +256,10 @@ int s390_enable_sie(void)
41 struct task_struct *tsk = current;
42 struct mm_struct *mm, *old_mm;
43
44+ /* Do we have switched amode? If no, we cannot do sie */
45+ if (!switch_amode)
46+ return -EINVAL;
47+
48 /* Do we have pgstes? if yes, we are done */
49 if (tsk->mm->context.pgstes)
50 return 0;
51Index: linux-sles11/arch/s390/lib/uaccess_pt.c
52===================================================================
53--- linux-sles11.orig/arch/s390/lib/uaccess_pt.c
54+++ linux-sles11/arch/s390/lib/uaccess_pt.c
55@@ -43,8 +43,9 @@ static int __handle_fault(struct mm_stru
56 int ret = -EFAULT;
57 int fault;
58
59- if (in_atomic())
60+ if (in_atomic() || segment_eq(get_fs(), KERNEL_DS))
61 return ret;
62+
63 down_read(&mm->mmap_sem);
64 vma = find_vma(mm, address);
65 if (unlikely(!vma))
66@@ -109,6 +110,8 @@ static size_t __user_copy_pt(unsigned lo
67 pte_t *pte;
68 void *from, *to;
69
70+ if (segment_eq(get_fs(), KERNEL_DS))
71+ mm = &init_mm;
72 done = 0;
73 retry:
74 spin_lock(&mm->page_table_lock);
75@@ -182,10 +185,6 @@ size_t copy_from_user_pt(size_t n, const
76 {
77 size_t rc;
78
79- if (segment_eq(get_fs(), KERNEL_DS)) {
80- memcpy(to, (void __kernel __force *) from, n);
81- return 0;
82- }
83 rc = __user_copy_pt((unsigned long) from, to, n, 0);
84 if (unlikely(rc))
85 memset(to + n - rc, 0, rc);
86@@ -194,10 +193,6 @@ size_t copy_from_user_pt(size_t n, const
87
88 size_t copy_to_user_pt(size_t n, void __user *to, const void *from)
89 {
90- if (segment_eq(get_fs(), KERNEL_DS)) {
91- memcpy((void __kernel __force *) to, from, n);
92- return 0;
93- }
94 return __user_copy_pt((unsigned long) to, (void *) from, n, 1);
95 }
96
97@@ -205,10 +200,6 @@ static size_t clear_user_pt(size_t n, vo
98 {
99 long done, size, ret;
100
101- if (segment_eq(get_fs(), KERNEL_DS)) {
102- memset((void __kernel __force *) to, 0, n);
103- return 0;
104- }
105 done = 0;
106 do {
107 if (n - done > PAGE_SIZE)
108@@ -234,7 +225,7 @@ static size_t strnlen_user_pt(size_t cou
109 size_t len_str;
110
111 if (segment_eq(get_fs(), KERNEL_DS))
112- return strnlen((const char __kernel __force *) src, count) + 1;
113+ mm = &init_mm;
114 done = 0;
115 retry:
116 spin_lock(&mm->page_table_lock);
117@@ -276,13 +267,6 @@ static size_t strncpy_from_user_pt(size_
118 return -EFAULT;
119 if (n > count)
120 n = count;
121- if (segment_eq(get_fs(), KERNEL_DS)) {
122- memcpy(dst, (const char __kernel __force *) src, n);
123- if (dst[n-1] == '\0')
124- return n-1;
125- else
126- return n;
127- }
128 if (__user_copy_pt((unsigned long) src, dst, n, 0))
129 return -EFAULT;
130 if (dst[n-1] == '\0')
131@@ -302,10 +286,8 @@ static size_t copy_in_user_pt(size_t n,
132 pte_t *pte_from, *pte_to;
133 int write_user;
134
135- if (segment_eq(get_fs(), KERNEL_DS)) {
136- memcpy((void __force *) to, (void __force *) from, n);
137- return 0;
138- }
139+ if (segment_eq(get_fs(), KERNEL_DS))
140+ mm = &init_mm;
141 done = 0;
142 retry:
143 spin_lock(&mm->page_table_lock);