Skip to content

Commit a069a22

Browse files
mhiramatrostedt
authored andcommitted
tracing: fgraph: Fix to add new fgraph_ops to array after ftrace_startup_subops()
Since the register_ftrace_graph() assigns a new fgraph_ops to fgraph_array before registring it by ftrace_startup_subops(), the new fgraph_ops can be used in function_graph_enter(). In most cases, it is still OK because those fgraph_ops's hashtable is already initialized by ftrace_set_filter*() etc. But if a user registers a new fgraph_ops which does not initialize the hash list, ftrace_ops_test() in function_graph_enter() causes a NULL pointer dereference BUG because fgraph_ops->ops.func_hash is NULL. This can be reproduced by the below commands because function profiler's fgraph_ops does not initialize the hash list; # cd /sys/kernel/tracing # echo function_graph > current_tracer # echo 1 > function_profile_enabled To fix this problem, add a new fgraph_ops to fgraph_array after ftrace_startup_subops(). Thus, until the new fgraph_ops is initialized, we will see fgraph_stub on the corresponding fgraph_array entry. Cc: Alexei Starovoitov <[email protected]> Cc: Florent Revest <[email protected]> Cc: Martin KaFai Lau <[email protected]> Cc: bpf <[email protected]> Cc: Sven Schnelle <[email protected]> Cc: Alexei Starovoitov <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Arnaldo Carvalho de Melo <[email protected]> Cc: Daniel Borkmann <[email protected]> Cc: Alan Maguire <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Guo Ren <[email protected]> Link: https://lore.kernel.org/172398528350.293426.8347220120333730248.stgit@devnote2 Fixes: c132be2 ("function_graph: Have the instances use their own ftrace_ops for filtering") Signed-off-by: Masami Hiramatsu (Google) <[email protected]> Signed-off-by: Steven Rostedt (Google) <[email protected]>
1 parent 47ac09b commit a069a22

File tree

1 file changed

+18
-13
lines changed

1 file changed

+18
-13
lines changed

kernel/trace/fgraph.c

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,18 +1206,24 @@ static void init_task_vars(int idx)
12061206
read_unlock(&tasklist_lock);
12071207
}
12081208

1209-
static void ftrace_graph_enable_direct(bool enable_branch)
1209+
static void ftrace_graph_enable_direct(bool enable_branch, struct fgraph_ops *gops)
12101210
{
12111211
trace_func_graph_ent_t func = NULL;
12121212
trace_func_graph_ret_t retfunc = NULL;
12131213
int i;
12141214

1215-
for_each_set_bit(i, &fgraph_array_bitmask,
1216-
sizeof(fgraph_array_bitmask) * BITS_PER_BYTE) {
1217-
func = fgraph_array[i]->entryfunc;
1218-
retfunc = fgraph_array[i]->retfunc;
1219-
fgraph_direct_gops = fgraph_array[i];
1220-
}
1215+
if (gops) {
1216+
func = gops->entryfunc;
1217+
retfunc = gops->retfunc;
1218+
fgraph_direct_gops = gops;
1219+
} else {
1220+
for_each_set_bit(i, &fgraph_array_bitmask,
1221+
sizeof(fgraph_array_bitmask) * BITS_PER_BYTE) {
1222+
func = fgraph_array[i]->entryfunc;
1223+
retfunc = fgraph_array[i]->retfunc;
1224+
fgraph_direct_gops = fgraph_array[i];
1225+
}
1226+
}
12211227
if (WARN_ON_ONCE(!func))
12221228
return;
12231229

@@ -1256,8 +1262,6 @@ int register_ftrace_graph(struct fgraph_ops *gops)
12561262
ret = -ENOSPC;
12571263
goto out;
12581264
}
1259-
1260-
fgraph_array[i] = gops;
12611265
gops->idx = i;
12621266

12631267
ftrace_graph_active++;
@@ -1266,7 +1270,7 @@ int register_ftrace_graph(struct fgraph_ops *gops)
12661270
ftrace_graph_disable_direct(true);
12671271

12681272
if (ftrace_graph_active == 1) {
1269-
ftrace_graph_enable_direct(false);
1273+
ftrace_graph_enable_direct(false, gops);
12701274
register_pm_notifier(&ftrace_suspend_notifier);
12711275
ret = start_graph_tracing();
12721276
if (ret)
@@ -1281,14 +1285,15 @@ int register_ftrace_graph(struct fgraph_ops *gops)
12811285
} else {
12821286
init_task_vars(gops->idx);
12831287
}
1284-
12851288
/* Always save the function, and reset at unregistering */
12861289
gops->saved_func = gops->entryfunc;
12871290

12881291
ret = ftrace_startup_subops(&graph_ops, &gops->ops, command);
1292+
if (!ret)
1293+
fgraph_array[i] = gops;
1294+
12891295
error:
12901296
if (ret) {
1291-
fgraph_array[i] = &fgraph_stub;
12921297
ftrace_graph_active--;
12931298
gops->saved_func = NULL;
12941299
fgraph_lru_release_index(i);
@@ -1324,7 +1329,7 @@ void unregister_ftrace_graph(struct fgraph_ops *gops)
13241329
ftrace_shutdown_subops(&graph_ops, &gops->ops, command);
13251330

13261331
if (ftrace_graph_active == 1)
1327-
ftrace_graph_enable_direct(true);
1332+
ftrace_graph_enable_direct(true, NULL);
13281333
else if (!ftrace_graph_active)
13291334
ftrace_graph_disable_direct(false);
13301335

0 commit comments

Comments
 (0)