aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/kprobes.c128
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.*/
1043static 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
1059static int __kprobes in_kprobes_functions(unsigned long addr) 1042static 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}
1229EXPORT_SYMBOL_GPL(register_kprobe); 1212EXPORT_SYMBOL_GPL(register_kprobe);
1230 1213
1214/* Check if all probes on the aggrprobe are disabled */
1215static 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 */
1231static 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 }
1263noclean: 1291noclean:
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
1306disarmed:
1307 hlist_del_rcu(&ap->hlist);
1308 return 0;
1277} 1309}
1278 1310
1279static void __kprobes __unregister_kprobe_bottom(struct kprobe *p) 1311static void __kprobes __unregister_kprobe_bottom(struct kprobe *p)
@@ -1606,29 +1638,13 @@ static void __kprobes kill_kprobe(struct kprobe *p)
1606int __kprobes disable_kprobe(struct kprobe *kp) 1638int __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);
1631out:
1632 mutex_unlock(&kprobe_mutex); 1648 mutex_unlock(&kprobe_mutex);
1633 return ret; 1649 return ret;
1634} 1650}