| From c31669e3589d73574477a855f7be2101dbbb9185 Mon Sep 17 00:00:00 2001 |
| From: "Steven Rostedt (VMware)" <rostedt@goodmis.org> |
| Date: Fri, 11 Oct 2019 17:56:57 -0400 |
| Subject: [PATCH] ftrace: Get a reference counter for the trace_array on filter |
| files |
| |
| commit 9ef16693aff8137faa21d16ffe65bb9832d24d71 upstream. |
| |
| 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> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c |
| index 2373311b4a43..baa54a76c6aa 100644 |
| --- a/kernel/trace/ftrace.c |
| +++ b/kernel/trace/ftrace.c |
| @@ -3540,21 +3540,22 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag, |
| struct ftrace_hash *hash; |
| struct list_head *mod_head; |
| struct trace_array *tr = ops->private; |
| - int ret = 0; |
| + int ret = -ENOMEM; |
| |
| ftrace_ops_init(ops); |
| |
| if (unlikely(ftrace_disabled)) |
| return -ENODEV; |
| |
| + if (tr && trace_array_get(tr) < 0) |
| + return -ENODEV; |
| + |
| iter = kzalloc(sizeof(*iter), GFP_KERNEL); |
| if (!iter) |
| - return -ENOMEM; |
| + goto out; |
| |
| - if (trace_parser_get_init(&iter->parser, FTRACE_BUFF_MAX)) { |
| - kfree(iter); |
| - return -ENOMEM; |
| - } |
| + if (trace_parser_get_init(&iter->parser, FTRACE_BUFF_MAX)) |
| + goto out; |
| |
| iter->ops = ops; |
| iter->flags = flag; |
| @@ -3584,13 +3585,13 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag, |
| |
| if (!iter->hash) { |
| trace_parser_put(&iter->parser); |
| - kfree(iter); |
| - ret = -ENOMEM; |
| goto out_unlock; |
| } |
| } else |
| iter->hash = hash; |
| |
| + ret = 0; |
| + |
| if (file->f_mode & FMODE_READ) { |
| iter->pg = ftrace_pages_start; |
| |
| @@ -3602,7 +3603,6 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag, |
| /* Failed */ |
| free_ftrace_hash(iter->hash); |
| trace_parser_put(&iter->parser); |
| - kfree(iter); |
| } |
| } else |
| file->private_data = iter; |
| @@ -3610,6 +3610,13 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag, |
| out_unlock: |
| mutex_unlock(&ops->func_hash->regex_lock); |
| |
| + out: |
| + if (ret) { |
| + kfree(iter); |
| + if (tr) |
| + trace_array_put(tr); |
| + } |
| + |
| return ret; |
| } |
| |
| @@ -5037,6 +5044,8 @@ int ftrace_regex_release(struct inode *inode, struct file *file) |
| |
| mutex_unlock(&iter->ops->func_hash->regex_lock); |
| free_ftrace_hash(iter->hash); |
| + if (iter->tr) |
| + trace_array_put(iter->tr); |
| kfree(iter); |
| |
| return 0; |
| -- |
| 2.7.4 |
| |