diff options
author | Steven Rostedt (VMware) <rostedt@goodmis.org> | 2019-10-11 17:56:57 -0400 |
---|---|---|
committer | Steven Rostedt (VMware) <rostedt@goodmis.org> | 2019-10-12 20:40:21 -0400 |
commit | 9ef16693aff8137faa21d16ffe65bb9832d24d71 (patch) | |
tree | 7e23890397b42a49853612a91c2edb9f48f489f2 /kernel/trace/ftrace.c | |
parent | 3ed270b129a45c7c502c819a4286b464a52dac61 (diff) |
ftrace: Get a reference counter for the trace_array on filter files
The ftrace set_ftrace_filter and set_ftrace_notrace files are specific for
an instance now. They need to take a reference to the instance otherwise
there could be a race between accessing the files and deleting the instance.
It wasn't until the :mod: caching where these file operations started
referencing the trace_array directly.
Cc: stable@vger.kernel.org
Fixes: 673feb9d76ab3 ("ftrace: Add :mod: caching infrastructure to trace_array")
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace/ftrace.c')
-rw-r--r-- | kernel/trace/ftrace.c | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 62a50bf399d6..32c2eb167de0 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
@@ -3540,21 +3540,22 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag, | |||
3540 | struct ftrace_hash *hash; | 3540 | struct ftrace_hash *hash; |
3541 | struct list_head *mod_head; | 3541 | struct list_head *mod_head; |
3542 | struct trace_array *tr = ops->private; | 3542 | struct trace_array *tr = ops->private; |
3543 | int ret = 0; | 3543 | int ret = -ENOMEM; |
3544 | 3544 | ||
3545 | ftrace_ops_init(ops); | 3545 | ftrace_ops_init(ops); |
3546 | 3546 | ||
3547 | if (unlikely(ftrace_disabled)) | 3547 | if (unlikely(ftrace_disabled)) |
3548 | return -ENODEV; | 3548 | return -ENODEV; |
3549 | 3549 | ||
3550 | if (tr && trace_array_get(tr) < 0) | ||
3551 | return -ENODEV; | ||
3552 | |||
3550 | iter = kzalloc(sizeof(*iter), GFP_KERNEL); | 3553 | iter = kzalloc(sizeof(*iter), GFP_KERNEL); |
3551 | if (!iter) | 3554 | if (!iter) |
3552 | return -ENOMEM; | 3555 | goto out; |
3553 | 3556 | ||
3554 | if (trace_parser_get_init(&iter->parser, FTRACE_BUFF_MAX)) { | 3557 | if (trace_parser_get_init(&iter->parser, FTRACE_BUFF_MAX)) |
3555 | kfree(iter); | 3558 | goto out; |
3556 | return -ENOMEM; | ||
3557 | } | ||
3558 | 3559 | ||
3559 | iter->ops = ops; | 3560 | iter->ops = ops; |
3560 | iter->flags = flag; | 3561 | iter->flags = flag; |
@@ -3584,13 +3585,13 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag, | |||
3584 | 3585 | ||
3585 | if (!iter->hash) { | 3586 | if (!iter->hash) { |
3586 | trace_parser_put(&iter->parser); | 3587 | trace_parser_put(&iter->parser); |
3587 | kfree(iter); | ||
3588 | ret = -ENOMEM; | ||
3589 | goto out_unlock; | 3588 | goto out_unlock; |
3590 | } | 3589 | } |
3591 | } else | 3590 | } else |
3592 | iter->hash = hash; | 3591 | iter->hash = hash; |
3593 | 3592 | ||
3593 | ret = 0; | ||
3594 | |||
3594 | if (file->f_mode & FMODE_READ) { | 3595 | if (file->f_mode & FMODE_READ) { |
3595 | iter->pg = ftrace_pages_start; | 3596 | iter->pg = ftrace_pages_start; |
3596 | 3597 | ||
@@ -3602,7 +3603,6 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag, | |||
3602 | /* Failed */ | 3603 | /* Failed */ |
3603 | free_ftrace_hash(iter->hash); | 3604 | free_ftrace_hash(iter->hash); |
3604 | trace_parser_put(&iter->parser); | 3605 | trace_parser_put(&iter->parser); |
3605 | kfree(iter); | ||
3606 | } | 3606 | } |
3607 | } else | 3607 | } else |
3608 | file->private_data = iter; | 3608 | file->private_data = iter; |
@@ -3610,6 +3610,13 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag, | |||
3610 | out_unlock: | 3610 | out_unlock: |
3611 | mutex_unlock(&ops->func_hash->regex_lock); | 3611 | mutex_unlock(&ops->func_hash->regex_lock); |
3612 | 3612 | ||
3613 | out: | ||
3614 | if (ret) { | ||
3615 | kfree(iter); | ||
3616 | if (tr) | ||
3617 | trace_array_put(tr); | ||
3618 | } | ||
3619 | |||
3613 | return ret; | 3620 | return ret; |
3614 | } | 3621 | } |
3615 | 3622 | ||
@@ -5037,6 +5044,8 @@ int ftrace_regex_release(struct inode *inode, struct file *file) | |||
5037 | 5044 | ||
5038 | mutex_unlock(&iter->ops->func_hash->regex_lock); | 5045 | mutex_unlock(&iter->ops->func_hash->regex_lock); |
5039 | free_ftrace_hash(iter->hash); | 5046 | free_ftrace_hash(iter->hash); |
5047 | if (iter->tr) | ||
5048 | trace_array_put(iter->tr); | ||
5040 | kfree(iter); | 5049 | kfree(iter); |
5041 | 5050 | ||
5042 | return 0; | 5051 | return 0; |