diff options
| -rw-r--r-- | kernel/trace/trace_uprobe.c | 35 |
1 files changed, 14 insertions, 21 deletions
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c index 34fd0e0ec51d..ac892878dbe6 100644 --- a/kernel/trace/trace_uprobe.c +++ b/kernel/trace/trace_uprobe.c | |||
| @@ -55,6 +55,7 @@ struct trace_uprobe { | |||
| 55 | struct list_head list; | 55 | struct list_head list; |
| 56 | struct trace_uprobe_filter filter; | 56 | struct trace_uprobe_filter filter; |
| 57 | struct uprobe_consumer consumer; | 57 | struct uprobe_consumer consumer; |
| 58 | struct path path; | ||
| 58 | struct inode *inode; | 59 | struct inode *inode; |
| 59 | char *filename; | 60 | char *filename; |
| 60 | unsigned long offset; | 61 | unsigned long offset; |
| @@ -289,7 +290,7 @@ static void free_trace_uprobe(struct trace_uprobe *tu) | |||
| 289 | for (i = 0; i < tu->tp.nr_args; i++) | 290 | for (i = 0; i < tu->tp.nr_args; i++) |
| 290 | traceprobe_free_probe_arg(&tu->tp.args[i]); | 291 | traceprobe_free_probe_arg(&tu->tp.args[i]); |
| 291 | 292 | ||
| 292 | iput(tu->inode); | 293 | path_put(&tu->path); |
| 293 | kfree(tu->tp.call.class->system); | 294 | kfree(tu->tp.call.class->system); |
| 294 | kfree(tu->tp.call.name); | 295 | kfree(tu->tp.call.name); |
| 295 | kfree(tu->filename); | 296 | kfree(tu->filename); |
| @@ -363,7 +364,6 @@ end: | |||
| 363 | static int create_trace_uprobe(int argc, char **argv) | 364 | static int create_trace_uprobe(int argc, char **argv) |
| 364 | { | 365 | { |
| 365 | struct trace_uprobe *tu; | 366 | struct trace_uprobe *tu; |
| 366 | struct inode *inode; | ||
| 367 | char *arg, *event, *group, *filename; | 367 | char *arg, *event, *group, *filename; |
| 368 | char buf[MAX_EVENT_NAME_LEN]; | 368 | char buf[MAX_EVENT_NAME_LEN]; |
| 369 | struct path path; | 369 | struct path path; |
| @@ -371,7 +371,6 @@ static int create_trace_uprobe(int argc, char **argv) | |||
| 371 | bool is_delete, is_return; | 371 | bool is_delete, is_return; |
| 372 | int i, ret; | 372 | int i, ret; |
| 373 | 373 | ||
| 374 | inode = NULL; | ||
| 375 | ret = 0; | 374 | ret = 0; |
| 376 | is_delete = false; | 375 | is_delete = false; |
| 377 | is_return = false; | 376 | is_return = false; |
| @@ -437,21 +436,16 @@ static int create_trace_uprobe(int argc, char **argv) | |||
| 437 | } | 436 | } |
| 438 | /* Find the last occurrence, in case the path contains ':' too. */ | 437 | /* Find the last occurrence, in case the path contains ':' too. */ |
| 439 | arg = strrchr(argv[1], ':'); | 438 | arg = strrchr(argv[1], ':'); |
| 440 | if (!arg) { | 439 | if (!arg) |
| 441 | ret = -EINVAL; | 440 | return -EINVAL; |
| 442 | goto fail_address_parse; | ||
| 443 | } | ||
| 444 | 441 | ||
| 445 | *arg++ = '\0'; | 442 | *arg++ = '\0'; |
| 446 | filename = argv[1]; | 443 | filename = argv[1]; |
| 447 | ret = kern_path(filename, LOOKUP_FOLLOW, &path); | 444 | ret = kern_path(filename, LOOKUP_FOLLOW, &path); |
| 448 | if (ret) | 445 | if (ret) |
| 449 | goto fail_address_parse; | 446 | return ret; |
| 450 | |||
| 451 | inode = igrab(d_real_inode(path.dentry)); | ||
| 452 | path_put(&path); | ||
| 453 | 447 | ||
| 454 | if (!inode || !S_ISREG(inode->i_mode)) { | 448 | if (!d_is_reg(path.dentry)) { |
| 455 | ret = -EINVAL; | 449 | ret = -EINVAL; |
| 456 | goto fail_address_parse; | 450 | goto fail_address_parse; |
| 457 | } | 451 | } |
| @@ -490,7 +484,7 @@ static int create_trace_uprobe(int argc, char **argv) | |||
| 490 | goto fail_address_parse; | 484 | goto fail_address_parse; |
| 491 | } | 485 | } |
| 492 | tu->offset = offset; | 486 | tu->offset = offset; |
| 493 | tu->inode = inode; | 487 | tu->path = path; |
| 494 | tu->filename = kstrdup(filename, GFP_KERNEL); | 488 | tu->filename = kstrdup(filename, GFP_KERNEL); |
| 495 | 489 | ||
| 496 | if (!tu->filename) { | 490 | if (!tu->filename) { |
| @@ -558,7 +552,7 @@ error: | |||
| 558 | return ret; | 552 | return ret; |
| 559 | 553 | ||
| 560 | fail_address_parse: | 554 | fail_address_parse: |
| 561 | iput(inode); | 555 | path_put(&path); |
| 562 | 556 | ||
| 563 | pr_info("Failed to parse address or file.\n"); | 557 | pr_info("Failed to parse address or file.\n"); |
| 564 | 558 | ||
| @@ -922,6 +916,7 @@ probe_event_enable(struct trace_uprobe *tu, struct trace_event_file *file, | |||
| 922 | goto err_flags; | 916 | goto err_flags; |
| 923 | 917 | ||
| 924 | tu->consumer.filter = filter; | 918 | tu->consumer.filter = filter; |
| 919 | tu->inode = d_real_inode(tu->path.dentry); | ||
| 925 | ret = uprobe_register(tu->inode, tu->offset, &tu->consumer); | 920 | ret = uprobe_register(tu->inode, tu->offset, &tu->consumer); |
| 926 | if (ret) | 921 | if (ret) |
| 927 | goto err_buffer; | 922 | goto err_buffer; |
| @@ -967,6 +962,7 @@ probe_event_disable(struct trace_uprobe *tu, struct trace_event_file *file) | |||
| 967 | WARN_ON(!uprobe_filter_is_empty(&tu->filter)); | 962 | WARN_ON(!uprobe_filter_is_empty(&tu->filter)); |
| 968 | 963 | ||
| 969 | uprobe_unregister(tu->inode, tu->offset, &tu->consumer); | 964 | uprobe_unregister(tu->inode, tu->offset, &tu->consumer); |
| 965 | tu->inode = NULL; | ||
| 970 | tu->tp.flags &= file ? ~TP_FLAG_TRACE : ~TP_FLAG_PROFILE; | 966 | tu->tp.flags &= file ? ~TP_FLAG_TRACE : ~TP_FLAG_PROFILE; |
| 971 | 967 | ||
| 972 | uprobe_buffer_disable(); | 968 | uprobe_buffer_disable(); |
| @@ -1337,7 +1333,6 @@ struct trace_event_call * | |||
| 1337 | create_local_trace_uprobe(char *name, unsigned long offs, bool is_return) | 1333 | create_local_trace_uprobe(char *name, unsigned long offs, bool is_return) |
| 1338 | { | 1334 | { |
| 1339 | struct trace_uprobe *tu; | 1335 | struct trace_uprobe *tu; |
| 1340 | struct inode *inode; | ||
| 1341 | struct path path; | 1336 | struct path path; |
| 1342 | int ret; | 1337 | int ret; |
| 1343 | 1338 | ||
| @@ -1345,11 +1340,8 @@ create_local_trace_uprobe(char *name, unsigned long offs, bool is_return) | |||
| 1345 | if (ret) | 1340 | if (ret) |
| 1346 | return ERR_PTR(ret); | 1341 | return ERR_PTR(ret); |
| 1347 | 1342 | ||
| 1348 | inode = igrab(d_inode(path.dentry)); | 1343 | if (!d_is_reg(path.dentry)) { |
| 1349 | path_put(&path); | 1344 | path_put(&path); |
| 1350 | |||
| 1351 | if (!inode || !S_ISREG(inode->i_mode)) { | ||
| 1352 | iput(inode); | ||
| 1353 | return ERR_PTR(-EINVAL); | 1345 | return ERR_PTR(-EINVAL); |
| 1354 | } | 1346 | } |
| 1355 | 1347 | ||
| @@ -1364,11 +1356,12 @@ create_local_trace_uprobe(char *name, unsigned long offs, bool is_return) | |||
| 1364 | if (IS_ERR(tu)) { | 1356 | if (IS_ERR(tu)) { |
| 1365 | pr_info("Failed to allocate trace_uprobe.(%d)\n", | 1357 | pr_info("Failed to allocate trace_uprobe.(%d)\n", |
| 1366 | (int)PTR_ERR(tu)); | 1358 | (int)PTR_ERR(tu)); |
| 1359 | path_put(&path); | ||
| 1367 | return ERR_CAST(tu); | 1360 | return ERR_CAST(tu); |
| 1368 | } | 1361 | } |
| 1369 | 1362 | ||
| 1370 | tu->offset = offs; | 1363 | tu->offset = offs; |
| 1371 | tu->inode = inode; | 1364 | tu->path = path; |
| 1372 | tu->filename = kstrdup(name, GFP_KERNEL); | 1365 | tu->filename = kstrdup(name, GFP_KERNEL); |
| 1373 | init_trace_event_call(tu, &tu->tp.call); | 1366 | init_trace_event_call(tu, &tu->tp.call); |
| 1374 | 1367 | ||
