ftrace: Also allocate and copy hash for reading of filter files

Currently the reader of set_ftrace_filter and set_ftrace_notrace just adds
the pointer to the global tracer hash to its iterator. Unlike the writer
that allocates a copy of the hash, the reader keeps the pointer to the
filter hashes. This is problematic because this pointer is static across
function calls that release the locks that can update the global tracer
hashes. This can cause UAF and similar bugs.

Allocate and copy the hash for reading the filter files like it is done
for the writers. This not only fixes UAF bugs, but also makes the code a
bit simpler as it doesn't have to differentiate when to free the
iterator's hash between writers and readers.

Cc: stable@vger.kernel.org
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Nathan Chancellor <nathan@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Link: https://lore.kernel.org/20250822183606.12962cc3@batman.local.home
Fixes: c20489dad156 ("ftrace: Assign iter->hash to filter or notrace hashes on seq read")
Closes: https://lore.kernel.org/all/20250813023044.2121943-1-wutengda@huaweicloud.com/
Closes: https://lore.kernel.org/all/20250822192437.GA458494@ax162/
Reported-by: Tengda Wu <wutengda@huaweicloud.com>
Tested-by: Tengda Wu <wutengda@huaweicloud.com>
Tested-by: Nathan Chancellor <nathan@kernel.org>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>

+10 -9
+10 -9
kernel/trace/ftrace.c
··· 4661 } else { 4662 iter->hash = alloc_and_copy_ftrace_hash(size_bits, hash); 4663 } 4664 4665 - if (!iter->hash) { 4666 - trace_parser_put(&iter->parser); 4667 - goto out_unlock; 4668 - } 4669 - } else 4670 - iter->hash = hash; 4671 4672 ret = 0; 4673 ··· 6547 ftrace_hash_move_and_update_ops(iter->ops, orig_hash, 6548 iter->hash, filter_hash); 6549 mutex_unlock(&ftrace_lock); 6550 - } else { 6551 - /* For read only, the hash is the ops hash */ 6552 - iter->hash = NULL; 6553 } 6554 6555 mutex_unlock(&iter->ops->func_hash->regex_lock);
··· 4661 } else { 4662 iter->hash = alloc_and_copy_ftrace_hash(size_bits, hash); 4663 } 4664 + } else { 4665 + if (hash) 4666 + iter->hash = alloc_and_copy_ftrace_hash(hash->size_bits, hash); 4667 + else 4668 + iter->hash = EMPTY_HASH; 4669 + } 4670 4671 + if (!iter->hash) { 4672 + trace_parser_put(&iter->parser); 4673 + goto out_unlock; 4674 + } 4675 4676 ret = 0; 4677 ··· 6543 ftrace_hash_move_and_update_ops(iter->ops, orig_hash, 6544 iter->hash, filter_hash); 6545 mutex_unlock(&ftrace_lock); 6546 } 6547 6548 mutex_unlock(&iter->ops->func_hash->regex_lock);