Skip to content

Commit e1d8f9c

Browse files
committed
Merge tag 'trace-v6.17-rc2-2' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace
Pull tracing fixes from Steven Rostedt: - Fix rtla and latency tooling pkg-config errors If libtraceevent and libtracefs is installed, but their corresponding '.pc' files are not installed, it reports that the libraries are missing and confuses the developer. Instead, report that the pkg-config files are missing and should be installed. - Fix overflow bug of the parser in trace_get_user() trace_get_user() uses the parsing functions to parse the user space strings. If the parser fails due to incorrect processing, it doesn't terminate the buffer with a nul byte. Add a "failed" flag to the parser that gets set when parsing fails and is used to know if the buffer is fine to use or not. - Remove a semicolon that was at an end of a comment line - Fix register_ftrace_graph() to unregister the pm notifier on error The register_ftrace_graph() registers a pm notifier but there's an error path that can exit the function without unregistering it. Since the function returns an error, it will never be unregistered. - Allocate and copy ftrace hash for reader of ftrace filter files When the set_ftrace_filter or set_ftrace_notrace files are open for read, an iterator is created and sets its hash pointer to the associated hash that represents filtering or notrace filtering to it. The issue is that the hash it points to can change while the iteration is happening. All the locking used to access the tracer's hashes are released which means those hashes can change or even be freed. Using the hash pointed to by the iterator can cause UAF bugs or similar. Have the read of these files allocate and copy the corresponding hashes and use that as that will keep them the same while the iterator is open. This also simplifies the code as opening it for write already does an allocate and copy, and now that the read is doing the same, there's no need to check which way it was opened on the release of the file, and the iterator hash can always be freed. - Fix function graph to copy args into temp storage The output of the function graph tracer shows both the entry and the exit of a function. When the exit is right after the entry, it combines the two events into one with the output of "function();", instead of showing: function() { } In order to do this, the iterator descriptor that reads the events includes storage that saves the entry event while it peaks at the next event in the ring buffer. The peek can free the entry event so the iterator must store the information to use it after the peek. With the addition of function graph tracer recording the args, where the args are a dynamic array in the entry event, the temp storage does not save them. This causes the args to be corrupted or even cause a read of unsafe memory. Add space to save the args in the temp storage of the iterator. - Fix race between ftrace_dump and reading trace_pipe ftrace_dump() is used when a crash occurs where the ftrace buffer will be printed to the console. But it can also be triggered by sysrq-z. If a sysrq-z is triggered while a task is reading trace_pipe it can cause a race in the ftrace_dump() where it checks if the buffer has content, then it checks if the next event is available, and then prints the output (regardless if the next event was available or not). Reading trace_pipe at the same time can cause it to not be available, and this triggers a WARN_ON in the print. Move the printing into the check if the next event exists or not * tag 'trace-v6.17-rc2-2' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: ftrace: Also allocate and copy hash for reading of filter files ftrace: Fix potential warning in trace_printk_seq during ftrace_dump fgraph: Copy args in intermediate storage with entry trace/fgraph: Fix the warning caused by missing unregister notifier ring-buffer: Remove redundant semicolons tracing: Limit access to parser->buffer when trace_get_user failed rtla: Check pkg-config install tools/latency-collector: Check pkg-config install
2 parents 52025b8 + bfb336c commit e1d8f9c

File tree

8 files changed

+65
-25
lines changed

8 files changed

+65
-25
lines changed

kernel/trace/fgraph.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1397,6 +1397,7 @@ int register_ftrace_graph(struct fgraph_ops *gops)
13971397
ftrace_graph_active--;
13981398
gops->saved_func = NULL;
13991399
fgraph_lru_release_index(i);
1400+
unregister_pm_notifier(&ftrace_suspend_notifier);
14001401
}
14011402
return ret;
14021403
}

kernel/trace/ftrace.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4661,13 +4661,17 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag,
46614661
} else {
46624662
iter->hash = alloc_and_copy_ftrace_hash(size_bits, hash);
46634663
}
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+
}
46644670

4665-
if (!iter->hash) {
4666-
trace_parser_put(&iter->parser);
4667-
goto out_unlock;
4668-
}
4669-
} else
4670-
iter->hash = hash;
4671+
if (!iter->hash) {
4672+
trace_parser_put(&iter->parser);
4673+
goto out_unlock;
4674+
}
46714675

46724676
ret = 0;
46734677

@@ -6543,9 +6547,6 @@ int ftrace_regex_release(struct inode *inode, struct file *file)
65436547
ftrace_hash_move_and_update_ops(iter->ops, orig_hash,
65446548
iter->hash, filter_hash);
65456549
mutex_unlock(&ftrace_lock);
6546-
} else {
6547-
/* For read only, the hash is the ops hash */
6548-
iter->hash = NULL;
65496550
}
65506551

65516552
mutex_unlock(&iter->ops->func_hash->regex_lock);

kernel/trace/ring_buffer.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7666,7 +7666,7 @@ static __init int test_ringbuffer(void)
76667666
rb_test_started = true;
76677667

76687668
set_current_state(TASK_INTERRUPTIBLE);
7669-
/* Just run for 10 seconds */;
7669+
/* Just run for 10 seconds */
76707670
schedule_timeout(10 * HZ);
76717671

76727672
kthread_stop(rb_hammer);

kernel/trace/trace.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1816,7 +1816,7 @@ int trace_get_user(struct trace_parser *parser, const char __user *ubuf,
18161816

18171817
ret = get_user(ch, ubuf++);
18181818
if (ret)
1819-
return ret;
1819+
goto fail;
18201820

18211821
read++;
18221822
cnt--;
@@ -1830,7 +1830,7 @@ int trace_get_user(struct trace_parser *parser, const char __user *ubuf,
18301830
while (cnt && isspace(ch)) {
18311831
ret = get_user(ch, ubuf++);
18321832
if (ret)
1833-
return ret;
1833+
goto fail;
18341834
read++;
18351835
cnt--;
18361836
}
@@ -1848,12 +1848,14 @@ int trace_get_user(struct trace_parser *parser, const char __user *ubuf,
18481848
while (cnt && !isspace(ch) && ch) {
18491849
if (parser->idx < parser->size - 1)
18501850
parser->buffer[parser->idx++] = ch;
1851-
else
1852-
return -EINVAL;
1851+
else {
1852+
ret = -EINVAL;
1853+
goto fail;
1854+
}
18531855

18541856
ret = get_user(ch, ubuf++);
18551857
if (ret)
1856-
return ret;
1858+
goto fail;
18571859
read++;
18581860
cnt--;
18591861
}
@@ -1868,11 +1870,15 @@ int trace_get_user(struct trace_parser *parser, const char __user *ubuf,
18681870
/* Make sure the parsed string always terminates with '\0'. */
18691871
parser->buffer[parser->idx] = 0;
18701872
} else {
1871-
return -EINVAL;
1873+
ret = -EINVAL;
1874+
goto fail;
18721875
}
18731876

18741877
*ppos += read;
18751878
return read;
1879+
fail:
1880+
trace_parser_fail(parser);
1881+
return ret;
18761882
}
18771883

18781884
/* TODO add a seq_buf_to_buffer() */
@@ -10632,10 +10638,10 @@ static void ftrace_dump_one(struct trace_array *tr, enum ftrace_dump_mode dump_m
1063210638
ret = print_trace_line(&iter);
1063310639
if (ret != TRACE_TYPE_NO_CONSUME)
1063410640
trace_consume(&iter);
10641+
10642+
trace_printk_seq(&iter.seq);
1063510643
}
1063610644
touch_nmi_watchdog();
10637-
10638-
trace_printk_seq(&iter.seq);
1063910645
}
1064010646

1064110647
if (!cnt)

kernel/trace/trace.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1292,14 +1292,15 @@ bool ftrace_event_is_function(struct trace_event_call *call);
12921292
*/
12931293
struct trace_parser {
12941294
bool cont;
1295+
bool fail;
12951296
char *buffer;
12961297
unsigned idx;
12971298
unsigned size;
12981299
};
12991300

13001301
static inline bool trace_parser_loaded(struct trace_parser *parser)
13011302
{
1302-
return (parser->idx != 0);
1303+
return !parser->fail && parser->idx != 0;
13031304
}
13041305

13051306
static inline bool trace_parser_cont(struct trace_parser *parser)
@@ -1313,6 +1314,11 @@ static inline void trace_parser_clear(struct trace_parser *parser)
13131314
parser->idx = 0;
13141315
}
13151316

1317+
static inline void trace_parser_fail(struct trace_parser *parser)
1318+
{
1319+
parser->fail = true;
1320+
}
1321+
13161322
extern int trace_parser_get_init(struct trace_parser *parser, int size);
13171323
extern void trace_parser_put(struct trace_parser *parser);
13181324
extern int trace_get_user(struct trace_parser *parser, const char __user *ubuf,

kernel/trace/trace_functions_graph.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,21 @@ struct fgraph_cpu_data {
2727
unsigned long enter_funcs[FTRACE_RETFUNC_DEPTH];
2828
};
2929

30+
struct fgraph_ent_args {
31+
struct ftrace_graph_ent_entry ent;
32+
/* Force the sizeof of args[] to have FTRACE_REGS_MAX_ARGS entries */
33+
unsigned long args[FTRACE_REGS_MAX_ARGS];
34+
};
35+
3036
struct fgraph_data {
3137
struct fgraph_cpu_data __percpu *cpu_data;
3238

3339
/* Place to preserve last processed entry. */
3440
union {
35-
struct ftrace_graph_ent_entry ent;
41+
struct fgraph_ent_args ent;
42+
/* TODO allow retaddr to have args */
3643
struct fgraph_retaddr_ent_entry rent;
37-
} ent;
44+
};
3845
struct ftrace_graph_ret_entry ret;
3946
int failed;
4047
int cpu;
@@ -627,10 +634,13 @@ get_return_for_leaf(struct trace_iterator *iter,
627634
* Save current and next entries for later reference
628635
* if the output fails.
629636
*/
630-
if (unlikely(curr->ent.type == TRACE_GRAPH_RETADDR_ENT))
631-
data->ent.rent = *(struct fgraph_retaddr_ent_entry *)curr;
632-
else
633-
data->ent.ent = *curr;
637+
if (unlikely(curr->ent.type == TRACE_GRAPH_RETADDR_ENT)) {
638+
data->rent = *(struct fgraph_retaddr_ent_entry *)curr;
639+
} else {
640+
int size = min((int)sizeof(data->ent), (int)iter->ent_size);
641+
642+
memcpy(&data->ent, curr, size);
643+
}
634644
/*
635645
* If the next event is not a return type, then
636646
* we only care about what type it is. Otherwise we can

tools/tracing/latency/Makefile.config

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
# SPDX-License-Identifier: GPL-2.0-only
22

3+
include $(srctree)/tools/scripts/utilities.mak
4+
35
STOP_ERROR :=
46

7+
ifndef ($(NO_LIBTRACEEVENT),1)
8+
ifeq ($(call get-executable,$(PKG_CONFIG)),)
9+
$(error Error: $(PKG_CONFIG) needed by libtraceevent/libtracefs is missing on this system, please install it)
10+
endif
11+
endif
12+
513
define lib_setup
614
$(eval LIB_INCLUDES += $(shell sh -c "$(PKG_CONFIG) --cflags lib$(1)"))
715
$(eval LDFLAGS += $(shell sh -c "$(PKG_CONFIG) --libs-only-L lib$(1)"))

tools/tracing/rtla/Makefile.config

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
# SPDX-License-Identifier: GPL-2.0-only
22

3+
include $(srctree)/tools/scripts/utilities.mak
4+
35
STOP_ERROR :=
46

57
LIBTRACEEVENT_MIN_VERSION = 1.5
68
LIBTRACEFS_MIN_VERSION = 1.6
79

10+
ifndef ($(NO_LIBTRACEEVENT),1)
11+
ifeq ($(call get-executable,$(PKG_CONFIG)),)
12+
$(error Error: $(PKG_CONFIG) needed by libtraceevent/libtracefs is missing on this system, please install it)
13+
endif
14+
endif
15+
816
define lib_setup
917
$(eval LIB_INCLUDES += $(shell sh -c "$(PKG_CONFIG) --cflags lib$(1)"))
1018
$(eval LDFLAGS += $(shell sh -c "$(PKG_CONFIG) --libs-only-L lib$(1)"))

0 commit comments

Comments
 (0)