diff options
-rw-r--r-- | kernel/kprobes.c | 93 |
1 files changed, 46 insertions, 47 deletions
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 9737a76e106f..8c3aa1452201 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
@@ -357,10 +357,10 @@ static inline int kprobe_aggrprobe(struct kprobe *p) | |||
357 | /* | 357 | /* |
358 | * Keep all fields in the kprobe consistent | 358 | * Keep all fields in the kprobe consistent |
359 | */ | 359 | */ |
360 | static inline void copy_kprobe(struct kprobe *old_p, struct kprobe *p) | 360 | static inline void copy_kprobe(struct kprobe *ap, struct kprobe *p) |
361 | { | 361 | { |
362 | memcpy(&p->opcode, &old_p->opcode, sizeof(kprobe_opcode_t)); | 362 | memcpy(&p->opcode, &ap->opcode, sizeof(kprobe_opcode_t)); |
363 | memcpy(&p->ainsn, &old_p->ainsn, sizeof(struct arch_specific_insn)); | 363 | memcpy(&p->ainsn, &ap->ainsn, sizeof(struct arch_specific_insn)); |
364 | } | 364 | } |
365 | 365 | ||
366 | #ifdef CONFIG_OPTPROBES | 366 | #ifdef CONFIG_OPTPROBES |
@@ -671,12 +671,12 @@ int proc_kprobes_optimization_handler(struct ctl_table *table, int write, | |||
671 | 671 | ||
672 | static void __kprobes __arm_kprobe(struct kprobe *p) | 672 | static void __kprobes __arm_kprobe(struct kprobe *p) |
673 | { | 673 | { |
674 | struct kprobe *old_p; | 674 | struct kprobe *_p; |
675 | 675 | ||
676 | /* Check collision with other optimized kprobes */ | 676 | /* Check collision with other optimized kprobes */ |
677 | old_p = get_optimized_kprobe((unsigned long)p->addr); | 677 | _p = get_optimized_kprobe((unsigned long)p->addr); |
678 | if (unlikely(old_p)) | 678 | if (unlikely(_p)) |
679 | unoptimize_kprobe(old_p); /* Fallback to unoptimized kprobe */ | 679 | unoptimize_kprobe(_p); /* Fallback to unoptimized kprobe */ |
680 | 680 | ||
681 | arch_arm_kprobe(p); | 681 | arch_arm_kprobe(p); |
682 | optimize_kprobe(p); /* Try to optimize (add kprobe to a list) */ | 682 | optimize_kprobe(p); /* Try to optimize (add kprobe to a list) */ |
@@ -684,15 +684,15 @@ static void __kprobes __arm_kprobe(struct kprobe *p) | |||
684 | 684 | ||
685 | static void __kprobes __disarm_kprobe(struct kprobe *p) | 685 | static void __kprobes __disarm_kprobe(struct kprobe *p) |
686 | { | 686 | { |
687 | struct kprobe *old_p; | 687 | struct kprobe *_p; |
688 | 688 | ||
689 | unoptimize_kprobe(p); /* Try to unoptimize */ | 689 | unoptimize_kprobe(p); /* Try to unoptimize */ |
690 | arch_disarm_kprobe(p); | 690 | arch_disarm_kprobe(p); |
691 | 691 | ||
692 | /* If another kprobe was blocked, optimize it. */ | 692 | /* If another kprobe was blocked, optimize it. */ |
693 | old_p = get_optimized_kprobe((unsigned long)p->addr); | 693 | _p = get_optimized_kprobe((unsigned long)p->addr); |
694 | if (unlikely(old_p)) | 694 | if (unlikely(_p)) |
695 | optimize_kprobe(old_p); | 695 | optimize_kprobe(_p); |
696 | } | 696 | } |
697 | 697 | ||
698 | #else /* !CONFIG_OPTPROBES */ | 698 | #else /* !CONFIG_OPTPROBES */ |
@@ -993,18 +993,18 @@ static void __kprobes init_aggr_kprobe(struct kprobe *ap, struct kprobe *p) | |||
993 | * This is the second or subsequent kprobe at the address - handle | 993 | * This is the second or subsequent kprobe at the address - handle |
994 | * the intricacies | 994 | * the intricacies |
995 | */ | 995 | */ |
996 | static int __kprobes register_aggr_kprobe(struct kprobe *old_p, | 996 | static int __kprobes register_aggr_kprobe(struct kprobe *orig_p, |
997 | struct kprobe *p) | 997 | struct kprobe *p) |
998 | { | 998 | { |
999 | int ret = 0; | 999 | int ret = 0; |
1000 | struct kprobe *ap = old_p; | 1000 | struct kprobe *ap = orig_p; |
1001 | 1001 | ||
1002 | if (!kprobe_aggrprobe(old_p)) { | 1002 | if (!kprobe_aggrprobe(orig_p)) { |
1003 | /* If old_p is not an aggr_kprobe, create new aggr_kprobe. */ | 1003 | /* If orig_p is not an aggr_kprobe, create new aggr_kprobe. */ |
1004 | ap = alloc_aggr_kprobe(old_p); | 1004 | ap = alloc_aggr_kprobe(orig_p); |
1005 | if (!ap) | 1005 | if (!ap) |
1006 | return -ENOMEM; | 1006 | return -ENOMEM; |
1007 | init_aggr_kprobe(ap, old_p); | 1007 | init_aggr_kprobe(ap, orig_p); |
1008 | } | 1008 | } |
1009 | 1009 | ||
1010 | if (kprobe_gone(ap)) { | 1010 | if (kprobe_gone(ap)) { |
@@ -1098,34 +1098,33 @@ static kprobe_opcode_t __kprobes *kprobe_addr(struct kprobe *p) | |||
1098 | /* Check passed kprobe is valid and return kprobe in kprobe_table. */ | 1098 | /* Check passed kprobe is valid and return kprobe in kprobe_table. */ |
1099 | static struct kprobe * __kprobes __get_valid_kprobe(struct kprobe *p) | 1099 | static struct kprobe * __kprobes __get_valid_kprobe(struct kprobe *p) |
1100 | { | 1100 | { |
1101 | struct kprobe *old_p, *list_p; | 1101 | struct kprobe *ap, *list_p; |
1102 | 1102 | ||
1103 | old_p = get_kprobe(p->addr); | 1103 | ap = get_kprobe(p->addr); |
1104 | if (unlikely(!old_p)) | 1104 | if (unlikely(!ap)) |
1105 | return NULL; | 1105 | return NULL; |
1106 | 1106 | ||
1107 | if (p != old_p) { | 1107 | if (p != ap) { |
1108 | list_for_each_entry_rcu(list_p, &old_p->list, list) | 1108 | list_for_each_entry_rcu(list_p, &ap->list, list) |
1109 | if (list_p == p) | 1109 | if (list_p == p) |
1110 | /* kprobe p is a valid probe */ | 1110 | /* kprobe p is a valid probe */ |
1111 | goto valid; | 1111 | goto valid; |
1112 | return NULL; | 1112 | return NULL; |
1113 | } | 1113 | } |
1114 | valid: | 1114 | valid: |
1115 | return old_p; | 1115 | return ap; |
1116 | } | 1116 | } |
1117 | 1117 | ||
1118 | /* Return error if the kprobe is being re-registered */ | 1118 | /* Return error if the kprobe is being re-registered */ |
1119 | static inline int check_kprobe_rereg(struct kprobe *p) | 1119 | static inline int check_kprobe_rereg(struct kprobe *p) |
1120 | { | 1120 | { |
1121 | int ret = 0; | 1121 | int ret = 0; |
1122 | struct kprobe *old_p; | ||
1123 | 1122 | ||
1124 | mutex_lock(&kprobe_mutex); | 1123 | mutex_lock(&kprobe_mutex); |
1125 | old_p = __get_valid_kprobe(p); | 1124 | if (__get_valid_kprobe(p)) |
1126 | if (old_p) | ||
1127 | ret = -EINVAL; | 1125 | ret = -EINVAL; |
1128 | mutex_unlock(&kprobe_mutex); | 1126 | mutex_unlock(&kprobe_mutex); |
1127 | |||
1129 | return ret; | 1128 | return ret; |
1130 | } | 1129 | } |
1131 | 1130 | ||
@@ -1234,43 +1233,43 @@ EXPORT_SYMBOL_GPL(register_kprobe); | |||
1234 | */ | 1233 | */ |
1235 | static int __kprobes __unregister_kprobe_top(struct kprobe *p) | 1234 | static int __kprobes __unregister_kprobe_top(struct kprobe *p) |
1236 | { | 1235 | { |
1237 | struct kprobe *old_p, *list_p; | 1236 | struct kprobe *ap, *list_p; |
1238 | 1237 | ||
1239 | old_p = __get_valid_kprobe(p); | 1238 | ap = __get_valid_kprobe(p); |
1240 | if (old_p == NULL) | 1239 | if (ap == NULL) |
1241 | return -EINVAL; | 1240 | return -EINVAL; |
1242 | 1241 | ||
1243 | if (old_p == p || | 1242 | if (ap == p || |
1244 | (kprobe_aggrprobe(old_p) && | 1243 | (kprobe_aggrprobe(ap) && |
1245 | list_is_singular(&old_p->list))) { | 1244 | list_is_singular(&ap->list))) { |
1246 | /* | 1245 | /* |
1247 | * Only probe on the hash list. Disarm only if kprobes are | 1246 | * Only probe on the hash list. Disarm only if kprobes are |
1248 | * enabled and not gone - otherwise, the breakpoint would | 1247 | * enabled and not gone - otherwise, the breakpoint would |
1249 | * already have been removed. We save on flushing icache. | 1248 | * already have been removed. We save on flushing icache. |
1250 | */ | 1249 | */ |
1251 | if (!kprobes_all_disarmed && !kprobe_disabled(old_p)) | 1250 | if (!kprobes_all_disarmed && !kprobe_disabled(ap)) |
1252 | disarm_kprobe(old_p); | 1251 | disarm_kprobe(ap); |
1253 | hlist_del_rcu(&old_p->hlist); | 1252 | hlist_del_rcu(&ap->hlist); |
1254 | } else { | 1253 | } else { |
1255 | if (p->break_handler && !kprobe_gone(p)) | 1254 | if (p->break_handler && !kprobe_gone(p)) |
1256 | old_p->break_handler = NULL; | 1255 | ap->break_handler = NULL; |
1257 | if (p->post_handler && !kprobe_gone(p)) { | 1256 | if (p->post_handler && !kprobe_gone(p)) { |
1258 | list_for_each_entry_rcu(list_p, &old_p->list, list) { | 1257 | list_for_each_entry_rcu(list_p, &ap->list, list) { |
1259 | if ((list_p != p) && (list_p->post_handler)) | 1258 | if ((list_p != p) && (list_p->post_handler)) |
1260 | goto noclean; | 1259 | goto noclean; |
1261 | } | 1260 | } |
1262 | old_p->post_handler = NULL; | 1261 | ap->post_handler = NULL; |
1263 | } | 1262 | } |
1264 | noclean: | 1263 | noclean: |
1265 | list_del_rcu(&p->list); | 1264 | list_del_rcu(&p->list); |
1266 | if (!kprobe_disabled(old_p)) { | 1265 | if (!kprobe_disabled(ap)) { |
1267 | try_to_disable_aggr_kprobe(old_p); | 1266 | try_to_disable_aggr_kprobe(ap); |
1268 | if (!kprobes_all_disarmed) { | 1267 | if (!kprobes_all_disarmed) { |
1269 | if (kprobe_disabled(old_p)) | 1268 | if (kprobe_disabled(ap)) |
1270 | disarm_kprobe(old_p); | 1269 | disarm_kprobe(ap); |
1271 | else | 1270 | else |
1272 | /* Try to optimize this probe again */ | 1271 | /* Try to optimize this probe again */ |
1273 | optimize_kprobe(old_p); | 1272 | optimize_kprobe(ap); |
1274 | } | 1273 | } |
1275 | } | 1274 | } |
1276 | } | 1275 | } |
@@ -1279,16 +1278,16 @@ noclean: | |||
1279 | 1278 | ||
1280 | static void __kprobes __unregister_kprobe_bottom(struct kprobe *p) | 1279 | static void __kprobes __unregister_kprobe_bottom(struct kprobe *p) |
1281 | { | 1280 | { |
1282 | struct kprobe *old_p; | 1281 | struct kprobe *ap; |
1283 | 1282 | ||
1284 | if (list_empty(&p->list)) | 1283 | if (list_empty(&p->list)) |
1285 | arch_remove_kprobe(p); | 1284 | arch_remove_kprobe(p); |
1286 | else if (list_is_singular(&p->list)) { | 1285 | else if (list_is_singular(&p->list)) { |
1287 | /* "p" is the last child of an aggr_kprobe */ | 1286 | /* "p" is the last child of an aggr_kprobe */ |
1288 | old_p = list_entry(p->list.next, struct kprobe, list); | 1287 | ap = list_entry(p->list.next, struct kprobe, list); |
1289 | list_del(&p->list); | 1288 | list_del(&p->list); |
1290 | arch_remove_kprobe(old_p); | 1289 | arch_remove_kprobe(ap); |
1291 | free_aggr_kprobe(old_p); | 1290 | free_aggr_kprobe(ap); |
1292 | } | 1291 | } |
1293 | } | 1292 | } |
1294 | 1293 | ||