diff options
author | Doug Anderson <dianders@chromium.org> | 2014-04-22 18:14:51 -0400 |
---|---|---|
committer | Kees Cook <keescook@chromium.org> | 2014-10-16 17:38:53 -0400 |
commit | 23a4e4050ba9c98ab67db0980a9fb20e5096d9ea (patch) | |
tree | a5571f323a6f923d5b8d4674112eec798f0bb13b /arch/arm | |
parent | 42d720d1731a9d7035c2812437c35e271ec4dd78 (diff) |
arm: kgdb: Handle read-only text / modules
Handle the case where someone has set the text segment of the kernel
as read-only by using the newly introduced "patch" mechanism.
Signed-off-by: Doug Anderson <dianders@chromium.org>
[kees: switched structure size check to BUILD_BUG_ON (sboyd)]
Signed-off-by: Kees Cook <keescook@chromium.org>
Acked-by: Nicolas Pitre <nico@linaro.org>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/kernel/kgdb.c | 29 |
2 files changed, 30 insertions, 1 deletions
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 38ddd9f83d0e..70b730766330 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile | |||
@@ -67,7 +67,7 @@ test-kprobes-objs += kprobes-test-arm.o | |||
67 | endif | 67 | endif |
68 | obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o | 68 | obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o |
69 | obj-$(CONFIG_ARM_THUMBEE) += thumbee.o | 69 | obj-$(CONFIG_ARM_THUMBEE) += thumbee.o |
70 | obj-$(CONFIG_KGDB) += kgdb.o | 70 | obj-$(CONFIG_KGDB) += kgdb.o patch.o |
71 | obj-$(CONFIG_ARM_UNWIND) += unwind.o | 71 | obj-$(CONFIG_ARM_UNWIND) += unwind.o |
72 | obj-$(CONFIG_HAVE_TCM) += tcm.o | 72 | obj-$(CONFIG_HAVE_TCM) += tcm.o |
73 | obj-$(CONFIG_OF) += devtree.o | 73 | obj-$(CONFIG_OF) += devtree.o |
diff --git a/arch/arm/kernel/kgdb.c b/arch/arm/kernel/kgdb.c index a74b53c1b7df..07db2f8a1b45 100644 --- a/arch/arm/kernel/kgdb.c +++ b/arch/arm/kernel/kgdb.c | |||
@@ -12,8 +12,12 @@ | |||
12 | #include <linux/irq.h> | 12 | #include <linux/irq.h> |
13 | #include <linux/kdebug.h> | 13 | #include <linux/kdebug.h> |
14 | #include <linux/kgdb.h> | 14 | #include <linux/kgdb.h> |
15 | #include <linux/uaccess.h> | ||
16 | |||
15 | #include <asm/traps.h> | 17 | #include <asm/traps.h> |
16 | 18 | ||
19 | #include "patch.h" | ||
20 | |||
17 | struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = | 21 | struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = |
18 | { | 22 | { |
19 | { "r0", 4, offsetof(struct pt_regs, ARM_r0)}, | 23 | { "r0", 4, offsetof(struct pt_regs, ARM_r0)}, |
@@ -244,6 +248,31 @@ void kgdb_arch_exit(void) | |||
244 | unregister_die_notifier(&kgdb_notifier); | 248 | unregister_die_notifier(&kgdb_notifier); |
245 | } | 249 | } |
246 | 250 | ||
251 | int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt) | ||
252 | { | ||
253 | int err; | ||
254 | |||
255 | /* patch_text() only supports int-sized breakpoints */ | ||
256 | BUILD_BUG_ON(sizeof(int) != BREAK_INSTR_SIZE); | ||
257 | |||
258 | err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr, | ||
259 | BREAK_INSTR_SIZE); | ||
260 | if (err) | ||
261 | return err; | ||
262 | |||
263 | patch_text((void *)bpt->bpt_addr, | ||
264 | *(unsigned int *)arch_kgdb_ops.gdb_bpt_instr); | ||
265 | |||
266 | return err; | ||
267 | } | ||
268 | |||
269 | int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt) | ||
270 | { | ||
271 | patch_text((void *)bpt->bpt_addr, *(unsigned int *)bpt->saved_instr); | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
247 | /* | 276 | /* |
248 | * Register our undef instruction hooks with ARM undef core. | 277 | * Register our undef instruction hooks with ARM undef core. |
249 | * We regsiter a hook specifically looking for the KGB break inst | 278 | * We regsiter a hook specifically looking for the KGB break inst |