aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/include/asm/uaccess.h1
-rw-r--r--arch/s390/kernel/ftrace.c12
-rw-r--r--arch/s390/kernel/jump_label.c2
-rw-r--r--arch/s390/kernel/kprobes.c2
-rw-r--r--arch/s390/mm/maccess.c29
5 files changed, 28 insertions, 18 deletions
diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h
index cd4c68e0398d..d64a7a62164f 100644
--- a/arch/s390/include/asm/uaccess.h
+++ b/arch/s390/include/asm/uaccess.h
@@ -372,5 +372,6 @@ static inline unsigned long __must_check clear_user(void __user *to, unsigned lo
372} 372}
373 373
374int copy_to_user_real(void __user *dest, void *src, unsigned long count); 374int copy_to_user_real(void __user *dest, void *src, unsigned long count);
375void s390_kernel_write(void *dst, const void *src, size_t size);
375 376
376#endif /* __S390_UACCESS_H */ 377#endif /* __S390_UACCESS_H */
diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c
index 6c79f1b44fe7..e0eaf11134b4 100644
--- a/arch/s390/kernel/ftrace.c
+++ b/arch/s390/kernel/ftrace.c
@@ -130,8 +130,7 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
130 /* Verify that the to be replaced code matches what we expect. */ 130 /* Verify that the to be replaced code matches what we expect. */
131 if (memcmp(&orig, &old, sizeof(old))) 131 if (memcmp(&orig, &old, sizeof(old)))
132 return -EINVAL; 132 return -EINVAL;
133 if (probe_kernel_write((void *) rec->ip, &new, sizeof(new))) 133 s390_kernel_write((void *) rec->ip, &new, sizeof(new));
134 return -EPERM;
135 return 0; 134 return 0;
136} 135}
137 136
@@ -159,8 +158,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
159 /* Verify that the to be replaced code matches what we expect. */ 158 /* Verify that the to be replaced code matches what we expect. */
160 if (memcmp(&orig, &old, sizeof(old))) 159 if (memcmp(&orig, &old, sizeof(old)))
161 return -EINVAL; 160 return -EINVAL;
162 if (probe_kernel_write((void *) rec->ip, &new, sizeof(new))) 161 s390_kernel_write((void *) rec->ip, &new, sizeof(new));
163 return -EPERM;
164 return 0; 162 return 0;
165} 163}
166 164
@@ -231,14 +229,16 @@ int ftrace_enable_ftrace_graph_caller(void)
231{ 229{
232 u8 op = 0x04; /* set mask field to zero */ 230 u8 op = 0x04; /* set mask field to zero */
233 231
234 return probe_kernel_write(__va(ftrace_graph_caller)+1, &op, sizeof(op)); 232 s390_kernel_write(__va(ftrace_graph_caller)+1, &op, sizeof(op));
233 return 0;
235} 234}
236 235
237int ftrace_disable_ftrace_graph_caller(void) 236int ftrace_disable_ftrace_graph_caller(void)
238{ 237{
239 u8 op = 0xf4; /* set mask field to all ones */ 238 u8 op = 0xf4; /* set mask field to all ones */
240 239
241 return probe_kernel_write(__va(ftrace_graph_caller)+1, &op, sizeof(op)); 240 s390_kernel_write(__va(ftrace_graph_caller)+1, &op, sizeof(op));
241 return 0;
242} 242}
243 243
244#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 244#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/s390/kernel/jump_label.c b/arch/s390/kernel/jump_label.c
index 830066f936c8..a90299600483 100644
--- a/arch/s390/kernel/jump_label.c
+++ b/arch/s390/kernel/jump_label.c
@@ -78,7 +78,7 @@ static void __jump_label_transform(struct jump_entry *entry,
78 if (memcmp((void *)entry->code, &old, sizeof(old))) 78 if (memcmp((void *)entry->code, &old, sizeof(old)))
79 jump_label_bug(entry, &old, &new); 79 jump_label_bug(entry, &old, &new);
80 } 80 }
81 probe_kernel_write((void *)entry->code, &new, sizeof(new)); 81 s390_kernel_write((void *)entry->code, &new, sizeof(new));
82} 82}
83 83
84static int __sm_arch_jump_label_transform(void *data) 84static int __sm_arch_jump_label_transform(void *data)
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index f516edc1fbe3..389db56a2208 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -178,7 +178,7 @@ static int swap_instruction(void *data)
178 } 178 }
179skip_ftrace: 179skip_ftrace:
180 kcb->kprobe_status = KPROBE_SWAP_INST; 180 kcb->kprobe_status = KPROBE_SWAP_INST;
181 probe_kernel_write(p->addr, &new_insn, len); 181 s390_kernel_write(p->addr, &new_insn, len);
182 kcb->kprobe_status = status; 182 kcb->kprobe_status = status;
183 return 0; 183 return 0;
184} 184}
diff --git a/arch/s390/mm/maccess.c b/arch/s390/mm/maccess.c
index 2eb34bdfc613..fb737e9e0683 100644
--- a/arch/s390/mm/maccess.c
+++ b/arch/s390/mm/maccess.c
@@ -16,13 +16,7 @@
16#include <asm/ctl_reg.h> 16#include <asm/ctl_reg.h>
17#include <asm/io.h> 17#include <asm/io.h>
18 18
19/* 19static notrace long s390_kernel_write_odd(void *dst, const void *src, size_t size)
20 * This function writes to kernel memory bypassing DAT and possible
21 * write protection. It copies one to four bytes from src to dst
22 * using the stura instruction.
23 * Returns the number of bytes copied or -EFAULT.
24 */
25static long probe_kernel_write_odd(void *dst, const void *src, size_t size)
26{ 20{
27 unsigned long count, aligned; 21 unsigned long count, aligned;
28 int offset, mask; 22 int offset, mask;
@@ -48,19 +42,34 @@ static long probe_kernel_write_odd(void *dst, const void *src, size_t size)
48 return rc ? rc : count; 42 return rc ? rc : count;
49} 43}
50 44
51long probe_kernel_write(void *dst, const void *src, size_t size) 45/*
46 * s390_kernel_write - write to kernel memory bypassing DAT
47 * @dst: destination address
48 * @src: source address
49 * @size: number of bytes to copy
50 *
51 * This function writes to kernel memory bypassing DAT and possible page table
52 * write protection. It writes to the destination using the sturg instruction.
53 * Therefore we have a read-modify-write sequence: the function reads four
54 * bytes from destination at a four byte boundary, modifies the bytes
55 * requested and writes the result back in a loop.
56 *
57 * Note: this means that this function may not be called concurrently on
58 * several cpus with overlapping words, since this may potentially
59 * cause data corruption.
60 */
61void notrace s390_kernel_write(void *dst, const void *src, size_t size)
52{ 62{
53 long copied = 0; 63 long copied = 0;
54 64
55 while (size) { 65 while (size) {
56 copied = probe_kernel_write_odd(dst, src, size); 66 copied = s390_kernel_write_odd(dst, src, size);
57 if (copied < 0) 67 if (copied < 0)
58 break; 68 break;
59 dst += copied; 69 dst += copied;
60 src += copied; 70 src += copied;
61 size -= copied; 71 size -= copied;
62 } 72 }
63 return copied < 0 ? -EFAULT : 0;
64} 73}
65 74
66static int __memcpy_real(void *dest, void *src, size_t count) 75static int __memcpy_real(void *dest, void *src, size_t count)