mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-09-22 09:34:56 +02:00
ftrace: Add global mutex to serialize trace_parser access
commit7720b63bceupstream. In ftrace, the trace_parser structure is allocated and initialized when a trace file is opened, and is subsequently used across write and release handlers to parse user input. The affected handler paths and their specific functions are: - Open paths: ftrace_regex_open(), ftrace_graph_open() - Write paths: ftrace_regex_write(), ftrace_graph_write() - Release paths: ftrace_regex_release(), ftrace_graph_release() If userspace opens a trace file descriptor and shares it across multiple threads, concurrent write calls will race on the parser's internal state, specifically the 'idx', 'cont', and 'buffer' fields, leading to corrupted input or undefined behavior. Fix this by adding a global mutex, parser_lock, to serialize all access to trace_parser across write and release paths, preventing concurrent corruption of parser state. Fixes:e704eff3ff("ftrace: Have set_graph_function handle multiple functions in one write") Fixes:689fd8b65d("tracing: trace parser support for function and graph") Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20260725024721.1983675-1-wutengda@huaweicloud.com Signed-off-by: Tengda Wu <wutengda@huaweicloud.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
95376fe9c1
commit
65bf73bee1
@@ -1072,6 +1072,12 @@ struct ftrace_ops global_ops = {
|
||||
FTRACE_OPS_FL_PID,
|
||||
};
|
||||
|
||||
/*
|
||||
* parser_lock - Protects trace_parser state against concurrent operations.
|
||||
* Held across trace_get_user() and subsequent buffer parsing to prevent races.
|
||||
*/
|
||||
static DEFINE_MUTEX(parser_lock);
|
||||
|
||||
/*
|
||||
* Used by the stack unwinder to know about dynamic ftrace trampolines.
|
||||
*/
|
||||
@@ -5783,6 +5789,8 @@ ftrace_regex_write(struct file *file, const char __user *ubuf,
|
||||
/* iter->hash is a local copy, so we don't need regex_lock */
|
||||
|
||||
parser = &iter->parser;
|
||||
|
||||
guard(mutex)(&parser_lock);
|
||||
read = trace_get_user(parser, ubuf, cnt, ppos);
|
||||
|
||||
if (read >= 0 && trace_parser_loaded(parser) &&
|
||||
@@ -6551,12 +6559,14 @@ int ftrace_regex_release(struct inode *inode, struct file *file)
|
||||
iter = file->private_data;
|
||||
|
||||
parser = &iter->parser;
|
||||
mutex_lock(&parser_lock);
|
||||
if (trace_parser_loaded(parser)) {
|
||||
int enable = !(iter->flags & FTRACE_ITER_NOTRACE);
|
||||
|
||||
ftrace_process_regex(iter, parser->buffer,
|
||||
parser->idx, enable);
|
||||
}
|
||||
mutex_unlock(&parser_lock);
|
||||
|
||||
trace_parser_put(parser);
|
||||
|
||||
@@ -6888,10 +6898,12 @@ ftrace_graph_release(struct inode *inode, struct file *file)
|
||||
|
||||
parser = &fgd->parser;
|
||||
|
||||
mutex_lock(&parser_lock);
|
||||
if (trace_parser_loaded((parser))) {
|
||||
ret = ftrace_graph_set_hash(fgd->new_hash,
|
||||
parser->buffer);
|
||||
}
|
||||
mutex_unlock(&parser_lock);
|
||||
|
||||
trace_parser_put(parser);
|
||||
|
||||
@@ -7004,6 +7016,7 @@ ftrace_graph_write(struct file *file, const char __user *ubuf,
|
||||
|
||||
parser = &fgd->parser;
|
||||
|
||||
guard(mutex)(&parser_lock);
|
||||
read = trace_get_user(parser, ubuf, cnt, ppos);
|
||||
|
||||
if (read >= 0 && trace_parser_loaded(parser) &&
|
||||
|
||||
Reference in New Issue
Block a user