diff options
| -rw-r--r-- | arch/arm/kernel/kprobes.c | 2 | ||||
| -rw-r--r-- | arch/arm/kernel/kprobes.h | 1 | ||||
| -rw-r--r-- | arch/arm/kernel/probes-arm.c | 4 | ||||
| -rw-r--r-- | arch/arm/kernel/probes-arm.h | 2 | ||||
| -rw-r--r-- | arch/arm/kernel/probes-thumb.c | 8 | ||||
| -rw-r--r-- | arch/arm/kernel/probes-thumb.h | 4 | ||||
| -rw-r--r-- | arch/arm/kernel/probes.c | 18 | ||||
| -rw-r--r-- | arch/arm/kernel/probes.h | 2 |
8 files changed, 25 insertions, 16 deletions
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c index 468d4a980c6c..8795f9f819d5 100644 --- a/arch/arm/kernel/kprobes.c +++ b/arch/arm/kernel/kprobes.c | |||
| @@ -89,7 +89,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) | |||
| 89 | p->opcode = insn; | 89 | p->opcode = insn; |
| 90 | p->ainsn.insn = tmp_insn; | 90 | p->ainsn.insn = tmp_insn; |
| 91 | 91 | ||
| 92 | switch ((*decode_insn)(insn, &p->ainsn, actions)) { | 92 | switch ((*decode_insn)(insn, &p->ainsn, true, actions)) { |
| 93 | case INSN_REJECTED: /* not supported */ | 93 | case INSN_REJECTED: /* not supported */ |
| 94 | return -EINVAL; | 94 | return -EINVAL; |
| 95 | 95 | ||
diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h index eee8089b1b93..d0a24b73bcfa 100644 --- a/arch/arm/kernel/kprobes.h +++ b/arch/arm/kernel/kprobes.h | |||
| @@ -35,6 +35,7 @@ kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi, | |||
| 35 | 35 | ||
| 36 | typedef enum probes_insn (kprobe_decode_insn_t)(probes_opcode_t, | 36 | typedef enum probes_insn (kprobe_decode_insn_t)(probes_opcode_t, |
| 37 | struct arch_specific_insn *, | 37 | struct arch_specific_insn *, |
| 38 | bool, | ||
| 38 | const union decode_action *); | 39 | const union decode_action *); |
| 39 | 40 | ||
| 40 | #ifdef CONFIG_THUMB2_KERNEL | 41 | #ifdef CONFIG_THUMB2_KERNEL |
diff --git a/arch/arm/kernel/probes-arm.c b/arch/arm/kernel/probes-arm.c index 738e5fc58928..8e7fde876521 100644 --- a/arch/arm/kernel/probes-arm.c +++ b/arch/arm/kernel/probes-arm.c | |||
| @@ -725,10 +725,10 @@ static void __kprobes arm_singlestep(probes_opcode_t insn, | |||
| 725 | */ | 725 | */ |
| 726 | enum probes_insn __kprobes | 726 | enum probes_insn __kprobes |
| 727 | arm_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, | 727 | arm_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, |
| 728 | const union decode_action *actions) | 728 | bool emulate, const union decode_action *actions) |
| 729 | { | 729 | { |
| 730 | asi->insn_singlestep = arm_singlestep; | 730 | asi->insn_singlestep = arm_singlestep; |
| 731 | asi->insn_check_cc = probes_condition_checks[insn>>28]; | 731 | asi->insn_check_cc = probes_condition_checks[insn>>28]; |
| 732 | return probes_decode_insn(insn, asi, probes_decode_arm_table, false, | 732 | return probes_decode_insn(insn, asi, probes_decode_arm_table, false, |
| 733 | actions); | 733 | emulate, actions); |
| 734 | } | 734 | } |
diff --git a/arch/arm/kernel/probes-arm.h b/arch/arm/kernel/probes-arm.h index 7a5cce497a9b..ea614dc5aaa3 100644 --- a/arch/arm/kernel/probes-arm.h +++ b/arch/arm/kernel/probes-arm.h | |||
| @@ -67,7 +67,7 @@ void __kprobes simulate_mov_ipsp(probes_opcode_t opcode, | |||
| 67 | extern const union decode_item probes_decode_arm_table[]; | 67 | extern const union decode_item probes_decode_arm_table[]; |
| 68 | 68 | ||
| 69 | enum probes_insn arm_probes_decode_insn(probes_opcode_t, | 69 | enum probes_insn arm_probes_decode_insn(probes_opcode_t, |
| 70 | struct arch_specific_insn *, | 70 | struct arch_specific_insn *, bool emulate, |
| 71 | const union decode_action *actions); | 71 | const union decode_action *actions); |
| 72 | 72 | ||
| 73 | #endif | 73 | #endif |
diff --git a/arch/arm/kernel/probes-thumb.c b/arch/arm/kernel/probes-thumb.c index eab440f6b2d4..23e2cbdb37cb 100644 --- a/arch/arm/kernel/probes-thumb.c +++ b/arch/arm/kernel/probes-thumb.c | |||
| @@ -863,20 +863,20 @@ static void __kprobes thumb32_singlestep(probes_opcode_t opcode, | |||
| 863 | 863 | ||
| 864 | enum probes_insn __kprobes | 864 | enum probes_insn __kprobes |
| 865 | thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, | 865 | thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, |
| 866 | const union decode_action *actions) | 866 | bool emulate, const union decode_action *actions) |
| 867 | { | 867 | { |
| 868 | asi->insn_singlestep = thumb16_singlestep; | 868 | asi->insn_singlestep = thumb16_singlestep; |
| 869 | asi->insn_check_cc = thumb_check_cc; | 869 | asi->insn_check_cc = thumb_check_cc; |
| 870 | return probes_decode_insn(insn, asi, probes_decode_thumb16_table, true, | 870 | return probes_decode_insn(insn, asi, probes_decode_thumb16_table, true, |
| 871 | actions); | 871 | emulate, actions); |
| 872 | } | 872 | } |
| 873 | 873 | ||
| 874 | enum probes_insn __kprobes | 874 | enum probes_insn __kprobes |
| 875 | thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, | 875 | thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, |
| 876 | const union decode_action *actions) | 876 | bool emulate, const union decode_action *actions) |
| 877 | { | 877 | { |
| 878 | asi->insn_singlestep = thumb32_singlestep; | 878 | asi->insn_singlestep = thumb32_singlestep; |
| 879 | asi->insn_check_cc = thumb_check_cc; | 879 | asi->insn_check_cc = thumb_check_cc; |
| 880 | return probes_decode_insn(insn, asi, probes_decode_thumb32_table, true, | 880 | return probes_decode_insn(insn, asi, probes_decode_thumb32_table, true, |
| 881 | actions); | 881 | emulate, actions); |
| 882 | } | 882 | } |
diff --git a/arch/arm/kernel/probes-thumb.h b/arch/arm/kernel/probes-thumb.h index d6f67c1df7af..65e4250e9b78 100644 --- a/arch/arm/kernel/probes-thumb.h +++ b/arch/arm/kernel/probes-thumb.h | |||
| @@ -89,9 +89,9 @@ extern const union decode_item probes_decode_thumb16_table[]; | |||
| 89 | 89 | ||
| 90 | enum probes_insn __kprobes | 90 | enum probes_insn __kprobes |
| 91 | thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, | 91 | thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, |
| 92 | const union decode_action *actions); | 92 | bool emulate, const union decode_action *actions); |
| 93 | enum probes_insn __kprobes | 93 | enum probes_insn __kprobes |
| 94 | thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, | 94 | thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, |
| 95 | const union decode_action *actions); | 95 | bool emulate, const union decode_action *actions); |
| 96 | 96 | ||
| 97 | #endif | 97 | #endif |
diff --git a/arch/arm/kernel/probes.c b/arch/arm/kernel/probes.c index b6d9b855273c..f9dff12cf85c 100644 --- a/arch/arm/kernel/probes.c +++ b/arch/arm/kernel/probes.c | |||
| @@ -257,7 +257,7 @@ set_emulated_insn(probes_opcode_t insn, struct arch_specific_insn *asi, | |||
| 257 | * non-zero value, the corresponding nibble in pinsn is validated and modified | 257 | * non-zero value, the corresponding nibble in pinsn is validated and modified |
| 258 | * according to the type. | 258 | * according to the type. |
| 259 | */ | 259 | */ |
| 260 | static bool __kprobes decode_regs(probes_opcode_t *pinsn, u32 regs) | 260 | static bool __kprobes decode_regs(probes_opcode_t *pinsn, u32 regs, bool modify) |
| 261 | { | 261 | { |
| 262 | probes_opcode_t insn = *pinsn; | 262 | probes_opcode_t insn = *pinsn; |
| 263 | probes_opcode_t mask = 0xf; /* Start at least significant nibble */ | 263 | probes_opcode_t mask = 0xf; /* Start at least significant nibble */ |
| @@ -323,7 +323,9 @@ static bool __kprobes decode_regs(probes_opcode_t *pinsn, u32 regs) | |||
| 323 | insn |= new_bits & mask; | 323 | insn |= new_bits & mask; |
| 324 | } | 324 | } |
| 325 | 325 | ||
| 326 | *pinsn = insn; | 326 | if (modify) |
| 327 | *pinsn = insn; | ||
| 328 | |||
| 327 | return true; | 329 | return true; |
| 328 | 330 | ||
| 329 | reject: | 331 | reject: |
| @@ -385,13 +387,14 @@ static const int decode_struct_sizes[NUM_DECODE_TYPES] = { | |||
| 385 | int __kprobes | 387 | int __kprobes |
| 386 | probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, | 388 | probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, |
| 387 | const union decode_item *table, bool thumb, | 389 | const union decode_item *table, bool thumb, |
| 388 | const union decode_action *actions) | 390 | bool emulate, const union decode_action *actions) |
| 389 | { | 391 | { |
| 390 | const struct decode_header *h = (struct decode_header *)table; | 392 | const struct decode_header *h = (struct decode_header *)table; |
| 391 | const struct decode_header *next; | 393 | const struct decode_header *next; |
| 392 | bool matched = false; | 394 | bool matched = false; |
| 393 | 395 | ||
| 394 | insn = prepare_emulated_insn(insn, asi, thumb); | 396 | if (emulate) |
| 397 | insn = prepare_emulated_insn(insn, asi, thumb); | ||
| 395 | 398 | ||
| 396 | for (;; h = next) { | 399 | for (;; h = next) { |
| 397 | enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK; | 400 | enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK; |
| @@ -406,7 +409,7 @@ probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, | |||
| 406 | if (!matched && (insn & h->mask.bits) != h->value.bits) | 409 | if (!matched && (insn & h->mask.bits) != h->value.bits) |
| 407 | continue; | 410 | continue; |
| 408 | 411 | ||
| 409 | if (!decode_regs(&insn, regs)) | 412 | if (!decode_regs(&insn, regs, emulate)) |
| 410 | return INSN_REJECTED; | 413 | return INSN_REJECTED; |
| 411 | 414 | ||
| 412 | switch (type) { | 415 | switch (type) { |
| @@ -430,6 +433,11 @@ probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, | |||
| 430 | 433 | ||
| 431 | case DECODE_TYPE_EMULATE: { | 434 | case DECODE_TYPE_EMULATE: { |
| 432 | struct decode_emulate *d = (struct decode_emulate *)h; | 435 | struct decode_emulate *d = (struct decode_emulate *)h; |
| 436 | |||
| 437 | if (!emulate) | ||
| 438 | return actions[d->handler.action].decoder(insn, | ||
| 439 | asi, h); | ||
| 440 | |||
| 433 | asi->insn_handler = actions[d->handler.action].handler; | 441 | asi->insn_handler = actions[d->handler.action].handler; |
| 434 | set_emulated_insn(insn, asi, thumb); | 442 | set_emulated_insn(insn, asi, thumb); |
| 435 | return INSN_GOOD; | 443 | return INSN_GOOD; |
diff --git a/arch/arm/kernel/probes.h b/arch/arm/kernel/probes.h index 0c72e544175d..33cc30c50cf5 100644 --- a/arch/arm/kernel/probes.h +++ b/arch/arm/kernel/probes.h | |||
| @@ -401,7 +401,7 @@ probes_insn_handler_t probes_emulate_none; | |||
| 401 | 401 | ||
| 402 | int __kprobes | 402 | int __kprobes |
| 403 | probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, | 403 | probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, |
| 404 | const union decode_item *table, bool thumb, | 404 | const union decode_item *table, bool thumb, bool emulate, |
| 405 | const union decode_action *actions); | 405 | const union decode_action *actions); |
| 406 | 406 | ||
| 407 | #endif | 407 | #endif |
