diff options
| -rw-r--r-- | kernel/kprobes.c | 128 |
1 files changed, 72 insertions, 56 deletions
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 8c3aa1452201..ab99caf2b167 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
| @@ -1039,23 +1039,6 @@ static int __kprobes register_aggr_kprobe(struct kprobe *orig_p, | |||
| 1039 | return add_new_kprobe(ap, p); | 1039 | return add_new_kprobe(ap, p); |
| 1040 | } | 1040 | } |
| 1041 | 1041 | ||
| 1042 | /* Try to disable aggr_kprobe, and return 1 if succeeded.*/ | ||
| 1043 | static int __kprobes try_to_disable_aggr_kprobe(struct kprobe *p) | ||
| 1044 | { | ||
| 1045 | struct kprobe *kp; | ||
| 1046 | |||
| 1047 | list_for_each_entry_rcu(kp, &p->list, list) { | ||
| 1048 | if (!kprobe_disabled(kp)) | ||
| 1049 | /* | ||
| 1050 | * There is an active probe on the list. | ||
| 1051 | * We can't disable aggr_kprobe. | ||
| 1052 | */ | ||
| 1053 | return 0; | ||
| 1054 | } | ||
| 1055 | p->flags |= KPROBE_FLAG_DISABLED; | ||
| 1056 | return 1; | ||
| 1057 | } | ||
| 1058 | |||
| 1059 | static int __kprobes in_kprobes_functions(unsigned long addr) | 1042 | static int __kprobes in_kprobes_functions(unsigned long addr) |
| 1060 | { | 1043 | { |
| 1061 | struct kprobe_blackpoint *kb; | 1044 | struct kprobe_blackpoint *kb; |
| @@ -1228,6 +1211,47 @@ fail_with_jump_label: | |||
| 1228 | } | 1211 | } |
| 1229 | EXPORT_SYMBOL_GPL(register_kprobe); | 1212 | EXPORT_SYMBOL_GPL(register_kprobe); |
| 1230 | 1213 | ||
| 1214 | /* Check if all probes on the aggrprobe are disabled */ | ||
| 1215 | static int __kprobes aggr_kprobe_disabled(struct kprobe *ap) | ||
| 1216 | { | ||
| 1217 | struct kprobe *kp; | ||
| 1218 | |||
| 1219 | list_for_each_entry_rcu(kp, &ap->list, list) | ||
| 1220 | if (!kprobe_disabled(kp)) | ||
| 1221 | /* | ||
| 1222 | * There is an active probe on the list. | ||
| 1223 | * We can't disable this ap. | ||
| 1224 | */ | ||
| 1225 | return 0; | ||
| 1226 | |||
| 1227 | return 1; | ||
| 1228 | } | ||
| 1229 | |||
| 1230 | /* Disable one kprobe: Make sure called under kprobe_mutex is locked */ | ||
| 1231 | static struct kprobe *__kprobes __disable_kprobe(struct kprobe *p) | ||
| 1232 | { | ||
| 1233 | struct kprobe *orig_p; | ||
| 1234 | |||
| 1235 | /* Get an original kprobe for return */ | ||
| 1236 | orig_p = __get_valid_kprobe(p); | ||
| 1237 | if (unlikely(orig_p == NULL)) | ||
| 1238 | return NULL; | ||
| 1239 | |||
| 1240 | if (!kprobe_disabled(p)) { | ||
| 1241 | /* Disable probe if it is a child probe */ | ||
| 1242 | if (p != orig_p) | ||
| 1243 | p->flags |= KPROBE_FLAG_DISABLED; | ||
| 1244 | |||
| 1245 | /* Try to disarm and disable this/parent probe */ | ||
| 1246 | if (p == orig_p || aggr_kprobe_disabled(orig_p)) { | ||
| 1247 | disarm_kprobe(orig_p); | ||
| 1248 | orig_p->flags |= KPROBE_FLAG_DISABLED; | ||
| 1249 | } | ||
| 1250 | } | ||
| 1251 | |||
| 1252 | return orig_p; | ||
| 1253 | } | ||
| 1254 | |||
| 1231 | /* | 1255 | /* |
| 1232 | * Unregister a kprobe without a scheduler synchronization. | 1256 | * Unregister a kprobe without a scheduler synchronization. |
| 1233 | */ | 1257 | */ |
| @@ -1235,22 +1259,26 @@ static int __kprobes __unregister_kprobe_top(struct kprobe *p) | |||
| 1235 | { | 1259 | { |
| 1236 | struct kprobe *ap, *list_p; | 1260 | struct kprobe *ap, *list_p; |
| 1237 | 1261 | ||
| 1238 | ap = __get_valid_kprobe(p); | 1262 | /* Disable kprobe. This will disarm it if needed. */ |
| 1263 | ap = __disable_kprobe(p); | ||
| 1239 | if (ap == NULL) | 1264 | if (ap == NULL) |
| 1240 | return -EINVAL; | 1265 | return -EINVAL; |
| 1241 | 1266 | ||
| 1242 | if (ap == p || | 1267 | if (ap == p) |
| 1243 | (kprobe_aggrprobe(ap) && | ||
| 1244 | list_is_singular(&ap->list))) { | ||
| 1245 | /* | 1268 | /* |
| 1246 | * Only probe on the hash list. Disarm only if kprobes are | 1269 | * This probe is an independent(and non-optimized) kprobe |
| 1247 | * enabled and not gone - otherwise, the breakpoint would | 1270 | * (not an aggrprobe). Remove from the hash list. |
| 1248 | * already have been removed. We save on flushing icache. | ||
| 1249 | */ | 1271 | */ |
| 1250 | if (!kprobes_all_disarmed && !kprobe_disabled(ap)) | 1272 | goto disarmed; |
| 1251 | disarm_kprobe(ap); | 1273 | |
| 1252 | hlist_del_rcu(&ap->hlist); | 1274 | /* Following process expects this probe is an aggrprobe */ |
| 1253 | } else { | 1275 | WARN_ON(!kprobe_aggrprobe(ap)); |
| 1276 | |||
| 1277 | if (list_is_singular(&ap->list)) | ||
| 1278 | /* This probe is the last child of aggrprobe */ | ||
| 1279 | goto disarmed; | ||
| 1280 | else { | ||
| 1281 | /* If disabling probe has special handlers, update aggrprobe */ | ||
| 1254 | if (p->break_handler && !kprobe_gone(p)) | 1282 | if (p->break_handler && !kprobe_gone(p)) |
| 1255 | ap->break_handler = NULL; | 1283 | ap->break_handler = NULL; |
| 1256 | if (p->post_handler && !kprobe_gone(p)) { | 1284 | if (p->post_handler && !kprobe_gone(p)) { |
| @@ -1261,19 +1289,23 @@ static int __kprobes __unregister_kprobe_top(struct kprobe *p) | |||
| 1261 | ap->post_handler = NULL; | 1289 | ap->post_handler = NULL; |
| 1262 | } | 1290 | } |
| 1263 | noclean: | 1291 | noclean: |
| 1292 | /* | ||
| 1293 | * Remove from the aggrprobe: this path will do nothing in | ||
| 1294 | * __unregister_kprobe_bottom(). | ||
| 1295 | */ | ||
| 1264 | list_del_rcu(&p->list); | 1296 | list_del_rcu(&p->list); |
| 1265 | if (!kprobe_disabled(ap)) { | 1297 | if (!kprobe_disabled(ap) && !kprobes_all_disarmed) |
| 1266 | try_to_disable_aggr_kprobe(ap); | 1298 | /* |
| 1267 | if (!kprobes_all_disarmed) { | 1299 | * Try to optimize this probe again, because post |
| 1268 | if (kprobe_disabled(ap)) | 1300 | * handler may have been changed. |
| 1269 | disarm_kprobe(ap); | 1301 | */ |
| 1270 | else | 1302 | optimize_kprobe(ap); |
| 1271 | /* Try to optimize this probe again */ | ||
| 1272 | optimize_kprobe(ap); | ||
| 1273 | } | ||
| 1274 | } | ||
| 1275 | } | 1303 | } |
| 1276 | return 0; | 1304 | return 0; |
| 1305 | |||
| 1306 | disarmed: | ||
| 1307 | hlist_del_rcu(&ap->hlist); | ||
| 1308 | return 0; | ||
| 1277 | } | 1309 | } |
| 1278 | 1310 | ||
| 1279 | static void __kprobes __unregister_kprobe_bottom(struct kprobe *p) | 1311 | static void __kprobes __unregister_kprobe_bottom(struct kprobe *p) |
| @@ -1606,29 +1638,13 @@ static void __kprobes kill_kprobe(struct kprobe *p) | |||
| 1606 | int __kprobes disable_kprobe(struct kprobe *kp) | 1638 | int __kprobes disable_kprobe(struct kprobe *kp) |
| 1607 | { | 1639 | { |
| 1608 | int ret = 0; | 1640 | int ret = 0; |
| 1609 | struct kprobe *p; | ||
| 1610 | 1641 | ||
| 1611 | mutex_lock(&kprobe_mutex); | 1642 | mutex_lock(&kprobe_mutex); |
| 1612 | 1643 | ||
| 1613 | /* Check whether specified probe is valid. */ | 1644 | /* Disable this kprobe */ |
| 1614 | p = __get_valid_kprobe(kp); | 1645 | if (__disable_kprobe(kp) == NULL) |
| 1615 | if (unlikely(p == NULL)) { | ||
| 1616 | ret = -EINVAL; | 1646 | ret = -EINVAL; |
| 1617 | goto out; | ||
| 1618 | } | ||
| 1619 | |||
| 1620 | /* If the probe is already disabled (or gone), just return */ | ||
| 1621 | if (kprobe_disabled(kp)) | ||
| 1622 | goto out; | ||
| 1623 | 1647 | ||
| 1624 | kp->flags |= KPROBE_FLAG_DISABLED; | ||
| 1625 | if (p != kp) | ||
| 1626 | /* When kp != p, p is always enabled. */ | ||
| 1627 | try_to_disable_aggr_kprobe(p); | ||
| 1628 | |||
| 1629 | if (!kprobes_all_disarmed && kprobe_disabled(p)) | ||
| 1630 | disarm_kprobe(p); | ||
| 1631 | out: | ||
| 1632 | mutex_unlock(&kprobe_mutex); | 1648 | mutex_unlock(&kprobe_mutex); |
| 1633 | return ret; | 1649 | return ret; |
| 1634 | } | 1650 | } |
