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 | |
| 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>
| -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 |
