aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2007-02-05 15:18:41 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2007-02-05 15:18:41 -0500
commit162e006ef59266b9ebf34e3d15ca1f3d9ee956d7 (patch)
treed7f1b61fbe822e71867bd04ee4ee7f3f1cd20842 /arch
parentab14de6c37fae22911ba99f4171613e6d758050b (diff)
[S390] Mark kernel text section read-only.
Set read-only flag in the page table entries for the kernel image text section. This will catch all instruction caused corruptions withing the text section. Instruction replacement via kprobes still works, since it bypasses now dynamic address translation. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/s390/kernel/early.c1
-rw-r--r--arch/s390/kernel/kprobes.c27
-rw-r--r--arch/s390/kernel/vmlinux.lds.S3
-rw-r--r--arch/s390/mm/init.c9
4 files changed, 29 insertions, 11 deletions
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index 40dd47970a33..e518dd53eff5 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -27,7 +27,6 @@
27#define DEFSYS_CMD_SIZE 96 27#define DEFSYS_CMD_SIZE 96
28#define SAVESYS_CMD_SIZE 32 28#define SAVESYS_CMD_SIZE 32
29 29
30extern int _eshared;
31char kernel_nss_name[NSS_NAME_SIZE + 1]; 30char kernel_nss_name[NSS_NAME_SIZE + 1];
32 31
33#ifdef CONFIG_SHARED_KERNEL 32#ifdef CONFIG_SHARED_KERNEL
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index b2e1dc89a8c6..a466bab6677e 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -155,15 +155,34 @@ void __kprobes get_instruction_type(struct arch_specific_insn *ainsn)
155static int __kprobes swap_instruction(void *aref) 155static int __kprobes swap_instruction(void *aref)
156{ 156{
157 struct ins_replace_args *args = aref; 157 struct ins_replace_args *args = aref;
158 u32 *addr;
159 u32 instr;
158 int err = -EFAULT; 160 int err = -EFAULT;
159 161
162 /*
163 * Text segment is read-only, hence we use stura to bypass dynamic
164 * address translation to exchange the instruction. Since stura
165 * always operates on four bytes, but we only want to exchange two
166 * bytes do some calculations to get things right. In addition we
167 * shall not cross any page boundaries (vmalloc area!) when writing
168 * the new instruction.
169 */
170 addr = (u32 *)ALIGN((unsigned long)args->ptr, 4);
171 if ((unsigned long)args->ptr & 2)
172 instr = ((*addr) & 0xffff0000) | args->new;
173 else
174 instr = ((*addr) & 0x0000ffff) | args->new << 16;
175
160 asm volatile( 176 asm volatile(
161 "0: mvc 0(2,%2),0(%3)\n" 177 " lra %1,0(%1)\n"
162 "1: la %0,0\n" 178 "0: stura %2,%1\n"
179 "1: la %0,0\n"
163 "2:\n" 180 "2:\n"
164 EX_TABLE(0b,2b) 181 EX_TABLE(0b,2b)
165 : "+d" (err), "=m" (*args->ptr) 182 : "+d" (err)
166 : "a" (args->ptr), "a" (&args->new), "m" (args->new)); 183 : "a" (addr), "d" (instr)
184 : "memory", "cc");
185
167 return err; 186 return err;
168} 187}
169 188
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 8fedb1f9fc97..a48907392522 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -35,9 +35,10 @@ SECTIONS
35 35
36#ifdef CONFIG_SHARED_KERNEL 36#ifdef CONFIG_SHARED_KERNEL
37 . = ALIGN(1048576); /* VM shared segments are 1MB aligned */ 37 . = ALIGN(1048576); /* VM shared segments are 1MB aligned */
38#endif
38 39
40 . = ALIGN(4096);
39 _eshared = .; /* End of shareable data */ 41 _eshared = .; /* End of shareable data */
40#endif
41 42
42 . = ALIGN(16); /* Exception table */ 43 . = ALIGN(16); /* Exception table */
43 __start___ex_table = .; 44 __start___ex_table = .;
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 162a338a5575..b3e7c45efb63 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -26,7 +26,6 @@
26#include <linux/pfn.h> 26#include <linux/pfn.h>
27#include <linux/poison.h> 27#include <linux/poison.h>
28#include <linux/initrd.h> 28#include <linux/initrd.h>
29
30#include <asm/processor.h> 29#include <asm/processor.h>
31#include <asm/system.h> 30#include <asm/system.h>
32#include <asm/uaccess.h> 31#include <asm/uaccess.h>
@@ -96,8 +95,8 @@ static void __init setup_ro_region(void)
96 pte_t new_pte; 95 pte_t new_pte;
97 unsigned long address, end; 96 unsigned long address, end;
98 97
99 address = ((unsigned long)&__start_rodata) & PAGE_MASK; 98 address = ((unsigned long)&_stext) & PAGE_MASK;
100 end = PFN_ALIGN((unsigned long)&__end_rodata); 99 end = PFN_ALIGN((unsigned long)&_eshared);
101 100
102 for (; address < end; address += PAGE_SIZE) { 101 for (; address < end; address += PAGE_SIZE) {
103 pgd = pgd_offset_k(address); 102 pgd = pgd_offset_k(address);
@@ -173,8 +172,8 @@ void __init mem_init(void)
173 datasize >>10, 172 datasize >>10,
174 initsize >> 10); 173 initsize >> 10);
175 printk("Write protected kernel read-only data: %#lx - %#lx\n", 174 printk("Write protected kernel read-only data: %#lx - %#lx\n",
176 (unsigned long)&__start_rodata, 175 (unsigned long)&_stext,
177 PFN_ALIGN((unsigned long)&__end_rodata) - 1); 176 PFN_ALIGN((unsigned long)&_eshared) - 1);
178} 177}
179 178
180void free_initmem(void) 179void free_initmem(void)