diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2011-05-23 04:24:23 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2011-05-23 04:24:28 -0400 |
commit | 043d07084b5347a26eab0a07aa13a4a929ad9e71 (patch) | |
tree | 13c2a902ccb2ecb779722c8b81ada32d242760c8 /arch/s390/include/asm/pgalloc.h | |
parent | 9bf05098ce34e68a9e15f09ad6cdfea4ed64057a (diff) |
[S390] Remove data execution protection
The noexec support on s390 does not rely on a bit in the page table
entry but utilizes the secondary space mode to distinguish between
memory accesses for instructions vs. data. The noexec code relies
on the assumption that the cpu will always use the secondary space
page table for data accesses while it is running in the secondary
space mode. Up to the z9-109 class machines this has been the case.
Unfortunately this is not true anymore with z10 and later machines.
The load-relative-long instructions lrl, lgrl and lgfrl access the
memory operand using the same addressing-space mode that has been
used to fetch the instruction.
This breaks the noexec mode for all user space binaries compiled
with march=z10 or later. The only option is to remove the current
noexec support.
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/include/asm/pgalloc.h')
-rw-r--r-- | arch/s390/include/asm/pgalloc.h | 28 |
1 files changed, 4 insertions, 24 deletions
diff --git a/arch/s390/include/asm/pgalloc.h b/arch/s390/include/asm/pgalloc.h index 082eb4e50e8b..739ff9ec1395 100644 --- a/arch/s390/include/asm/pgalloc.h +++ b/arch/s390/include/asm/pgalloc.h | |||
@@ -19,14 +19,13 @@ | |||
19 | 19 | ||
20 | #define check_pgt_cache() do {} while (0) | 20 | #define check_pgt_cache() do {} while (0) |
21 | 21 | ||
22 | unsigned long *crst_table_alloc(struct mm_struct *, int); | 22 | unsigned long *crst_table_alloc(struct mm_struct *); |
23 | void crst_table_free(struct mm_struct *, unsigned long *); | 23 | void crst_table_free(struct mm_struct *, unsigned long *); |
24 | void crst_table_free_rcu(struct mm_struct *, unsigned long *); | 24 | void crst_table_free_rcu(struct mm_struct *, unsigned long *); |
25 | 25 | ||
26 | unsigned long *page_table_alloc(struct mm_struct *); | 26 | unsigned long *page_table_alloc(struct mm_struct *); |
27 | void page_table_free(struct mm_struct *, unsigned long *); | 27 | void page_table_free(struct mm_struct *, unsigned long *); |
28 | void page_table_free_rcu(struct mm_struct *, unsigned long *); | 28 | void page_table_free_rcu(struct mm_struct *, unsigned long *); |
29 | void disable_noexec(struct mm_struct *, struct task_struct *); | ||
30 | 29 | ||
31 | static inline void clear_table(unsigned long *s, unsigned long val, size_t n) | 30 | static inline void clear_table(unsigned long *s, unsigned long val, size_t n) |
32 | { | 31 | { |
@@ -50,9 +49,6 @@ static inline void clear_table(unsigned long *s, unsigned long val, size_t n) | |||
50 | static inline void crst_table_init(unsigned long *crst, unsigned long entry) | 49 | static inline void crst_table_init(unsigned long *crst, unsigned long entry) |
51 | { | 50 | { |
52 | clear_table(crst, entry, sizeof(unsigned long)*2048); | 51 | clear_table(crst, entry, sizeof(unsigned long)*2048); |
53 | crst = get_shadow_table(crst); | ||
54 | if (crst) | ||
55 | clear_table(crst, entry, sizeof(unsigned long)*2048); | ||
56 | } | 52 | } |
57 | 53 | ||
58 | #ifndef __s390x__ | 54 | #ifndef __s390x__ |
@@ -90,7 +86,7 @@ void crst_table_downgrade(struct mm_struct *, unsigned long limit); | |||
90 | 86 | ||
91 | static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address) | 87 | static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address) |
92 | { | 88 | { |
93 | unsigned long *table = crst_table_alloc(mm, mm->context.noexec); | 89 | unsigned long *table = crst_table_alloc(mm); |
94 | if (table) | 90 | if (table) |
95 | crst_table_init(table, _REGION3_ENTRY_EMPTY); | 91 | crst_table_init(table, _REGION3_ENTRY_EMPTY); |
96 | return (pud_t *) table; | 92 | return (pud_t *) table; |
@@ -99,7 +95,7 @@ static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address) | |||
99 | 95 | ||
100 | static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr) | 96 | static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr) |
101 | { | 97 | { |
102 | unsigned long *table = crst_table_alloc(mm, mm->context.noexec); | 98 | unsigned long *table = crst_table_alloc(mm); |
103 | if (table) | 99 | if (table) |
104 | crst_table_init(table, _SEGMENT_ENTRY_EMPTY); | 100 | crst_table_init(table, _SEGMENT_ENTRY_EMPTY); |
105 | return (pmd_t *) table; | 101 | return (pmd_t *) table; |
@@ -115,11 +111,6 @@ static inline void pgd_populate_kernel(struct mm_struct *mm, | |||
115 | static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud) | 111 | static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud) |
116 | { | 112 | { |
117 | pgd_populate_kernel(mm, pgd, pud); | 113 | pgd_populate_kernel(mm, pgd, pud); |
118 | if (mm->context.noexec) { | ||
119 | pgd = get_shadow_table(pgd); | ||
120 | pud = get_shadow_table(pud); | ||
121 | pgd_populate_kernel(mm, pgd, pud); | ||
122 | } | ||
123 | } | 114 | } |
124 | 115 | ||
125 | static inline void pud_populate_kernel(struct mm_struct *mm, | 116 | static inline void pud_populate_kernel(struct mm_struct *mm, |
@@ -131,11 +122,6 @@ static inline void pud_populate_kernel(struct mm_struct *mm, | |||
131 | static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) | 122 | static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) |
132 | { | 123 | { |
133 | pud_populate_kernel(mm, pud, pmd); | 124 | pud_populate_kernel(mm, pud, pmd); |
134 | if (mm->context.noexec) { | ||
135 | pud = get_shadow_table(pud); | ||
136 | pmd = get_shadow_table(pmd); | ||
137 | pud_populate_kernel(mm, pud, pmd); | ||
138 | } | ||
139 | } | 125 | } |
140 | 126 | ||
141 | #endif /* __s390x__ */ | 127 | #endif /* __s390x__ */ |
@@ -143,10 +129,8 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) | |||
143 | static inline pgd_t *pgd_alloc(struct mm_struct *mm) | 129 | static inline pgd_t *pgd_alloc(struct mm_struct *mm) |
144 | { | 130 | { |
145 | spin_lock_init(&mm->context.list_lock); | 131 | spin_lock_init(&mm->context.list_lock); |
146 | INIT_LIST_HEAD(&mm->context.crst_list); | ||
147 | INIT_LIST_HEAD(&mm->context.pgtable_list); | 132 | INIT_LIST_HEAD(&mm->context.pgtable_list); |
148 | return (pgd_t *) | 133 | return (pgd_t *) crst_table_alloc(mm); |
149 | crst_table_alloc(mm, user_mode == SECONDARY_SPACE_MODE); | ||
150 | } | 134 | } |
151 | #define pgd_free(mm, pgd) crst_table_free(mm, (unsigned long *) pgd) | 135 | #define pgd_free(mm, pgd) crst_table_free(mm, (unsigned long *) pgd) |
152 | 136 | ||
@@ -160,10 +144,6 @@ static inline void pmd_populate(struct mm_struct *mm, | |||
160 | pmd_t *pmd, pgtable_t pte) | 144 | pmd_t *pmd, pgtable_t pte) |
161 | { | 145 | { |
162 | pmd_populate_kernel(mm, pmd, pte); | 146 | pmd_populate_kernel(mm, pmd, pte); |
163 | if (mm->context.noexec) { | ||
164 | pmd = get_shadow_table(pmd); | ||
165 | pmd_populate_kernel(mm, pmd, pte + PTRS_PER_PTE); | ||
166 | } | ||
167 | } | 147 | } |
168 | 148 | ||
169 | #define pmd_pgtable(pmd) \ | 149 | #define pmd_pgtable(pmd) \ |