aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>2010-12-03 04:53:57 -0500
committerIngo Molnar <mingo@elte.hu>2010-12-06 11:59:29 -0500
commit6f0f1dd71953d4243c11e490dd49ef24ebaf6c0b (patch)
tree84a77def76610b59a2abfed87f548ab42b64da84
parent6d8e40a85ef72a0514ebd00748eb18cab432b200 (diff)
kprobes: Cleanup disabling and unregistering path
Merge disabling kprobe to unregistering kprobe function and add comments for disabing/unregistring process. Current unregistering code disables(disarms) kprobes after checking target kprobe status. This patch changes it to disabling kprobe first after that it changing the kprobe's state. This allows to share probe disabling code between disable_kprobe() and unregister_kprobe(). Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Cc: Rusty Russell <rusty@rustcorp.com.au> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com> Cc: Jason Baron <jbaron@redhat.com> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Cc: 2nddept-manager@sdl.hitachi.co.jp LKML-Reference: <20101203095356.2961.30152.stgit@ltc236.sdl.hitachi.co.jp> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-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}