aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/kprobes.c
diff options
context:
space:
mode:
authorMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>2012-06-05 06:28:20 -0400
committerSteven Rostedt <rostedt@goodmis.org>2012-07-31 10:29:56 -0400
commitf7fa6ef0ded995aad68650a877198f70e44b7621 (patch)
treec4f211caf1b11d437cc078df8a0917ad205cb3cf /kernel/kprobes.c
parent72ef3794c5cd5f5f0e6355c24a529224c449cd14 (diff)
kprobes: cleanup to separate probe-able check
Separate probe-able address checking code from register_kprobe(). Link: http://lkml.kernel.org/r/20120605102820.27845.90133.stgit@localhost.localdomain Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@redhat.com> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com> Cc: "Frank Ch. Eigler" <fche@redhat.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/kprobes.c')
-rw-r--r--kernel/kprobes.c82
1 files changed, 45 insertions, 37 deletions
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 7a8a1222c7b1..6137fe32b4b8 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1313,67 +1313,80 @@ static inline int check_kprobe_rereg(struct kprobe *p)
1313 return ret; 1313 return ret;
1314} 1314}
1315 1315
1316int __kprobes register_kprobe(struct kprobe *p) 1316static __kprobes int check_kprobe_address_safe(struct kprobe *p,
1317 struct module **probed_mod)
1317{ 1318{
1318 int ret = 0; 1319 int ret = 0;
1319 struct kprobe *old_p;
1320 struct module *probed_mod;
1321 kprobe_opcode_t *addr;
1322
1323 addr = kprobe_addr(p);
1324 if (IS_ERR(addr))
1325 return PTR_ERR(addr);
1326 p->addr = addr;
1327
1328 ret = check_kprobe_rereg(p);
1329 if (ret)
1330 return ret;
1331 1320
1332 jump_label_lock(); 1321 jump_label_lock();
1333 preempt_disable(); 1322 preempt_disable();
1323
1324 /* Ensure it is not in reserved area nor out of text */
1334 if (!kernel_text_address((unsigned long) p->addr) || 1325 if (!kernel_text_address((unsigned long) p->addr) ||
1335 in_kprobes_functions((unsigned long) p->addr) || 1326 in_kprobes_functions((unsigned long) p->addr) ||
1336 ftrace_text_reserved(p->addr, p->addr) || 1327 ftrace_text_reserved(p->addr, p->addr) ||
1337 jump_label_text_reserved(p->addr, p->addr)) { 1328 jump_label_text_reserved(p->addr, p->addr)) {
1338 ret = -EINVAL; 1329 ret = -EINVAL;
1339 goto cannot_probe; 1330 goto out;
1340 } 1331 }
1341 1332
1342 /* User can pass only KPROBE_FLAG_DISABLED to register_kprobe */ 1333 /* Check if are we probing a module */
1343 p->flags &= KPROBE_FLAG_DISABLED; 1334 *probed_mod = __module_text_address((unsigned long) p->addr);
1344 1335 if (*probed_mod) {
1345 /*
1346 * Check if are we probing a module.
1347 */
1348 probed_mod = __module_text_address((unsigned long) p->addr);
1349 if (probed_mod) {
1350 /* Return -ENOENT if fail. */
1351 ret = -ENOENT;
1352 /* 1336 /*
1353 * We must hold a refcount of the probed module while updating 1337 * We must hold a refcount of the probed module while updating
1354 * its code to prohibit unexpected unloading. 1338 * its code to prohibit unexpected unloading.
1355 */ 1339 */
1356 if (unlikely(!try_module_get(probed_mod))) 1340 if (unlikely(!try_module_get(*probed_mod))) {
1357 goto cannot_probe; 1341 ret = -ENOENT;
1342 goto out;
1343 }
1358 1344
1359 /* 1345 /*
1360 * If the module freed .init.text, we couldn't insert 1346 * If the module freed .init.text, we couldn't insert
1361 * kprobes in there. 1347 * kprobes in there.
1362 */ 1348 */
1363 if (within_module_init((unsigned long)p->addr, probed_mod) && 1349 if (within_module_init((unsigned long)p->addr, *probed_mod) &&
1364 probed_mod->state != MODULE_STATE_COMING) { 1350 (*probed_mod)->state != MODULE_STATE_COMING) {
1365 module_put(probed_mod); 1351 module_put(*probed_mod);
1366 goto cannot_probe; 1352 *probed_mod = NULL;
1353 ret = -ENOENT;
1367 } 1354 }
1368 /* ret will be updated by following code */
1369 } 1355 }
1356out:
1370 preempt_enable(); 1357 preempt_enable();
1371 jump_label_unlock(); 1358 jump_label_unlock();
1372 1359
1360 return ret;
1361}
1362
1363int __kprobes register_kprobe(struct kprobe *p)
1364{
1365 int ret;
1366 struct kprobe *old_p;
1367 struct module *probed_mod;
1368 kprobe_opcode_t *addr;
1369
1370 /* Adjust probe address from symbol */
1371 addr = kprobe_addr(p);
1372 if (IS_ERR(addr))
1373 return PTR_ERR(addr);
1374 p->addr = addr;
1375
1376 ret = check_kprobe_rereg(p);
1377 if (ret)
1378 return ret;
1379
1380 /* User can pass only KPROBE_FLAG_DISABLED to register_kprobe */
1381 p->flags &= KPROBE_FLAG_DISABLED;
1373 p->nmissed = 0; 1382 p->nmissed = 0;
1374 INIT_LIST_HEAD(&p->list); 1383 INIT_LIST_HEAD(&p->list);
1375 mutex_lock(&kprobe_mutex);
1376 1384
1385 ret = check_kprobe_address_safe(p, &probed_mod);
1386 if (ret)
1387 return ret;
1388
1389 mutex_lock(&kprobe_mutex);
1377 jump_label_lock(); /* needed to call jump_label_text_reserved() */ 1390 jump_label_lock(); /* needed to call jump_label_text_reserved() */
1378 1391
1379 get_online_cpus(); /* For avoiding text_mutex deadlock. */ 1392 get_online_cpus(); /* For avoiding text_mutex deadlock. */
@@ -1410,11 +1423,6 @@ out:
1410 module_put(probed_mod); 1423 module_put(probed_mod);
1411 1424
1412 return ret; 1425 return ret;
1413
1414cannot_probe:
1415 preempt_enable();
1416 jump_label_unlock();
1417 return ret;
1418} 1426}
1419EXPORT_SYMBOL_GPL(register_kprobe); 1427EXPORT_SYMBOL_GPL(register_kprobe);
1420 1428