Skip to content

Commit 594d281

Browse files
committed
Merge tag 'trace-v6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace
Pull tracing updates from Steven Rostedt: - Remove unused ftrace_direct_funcs variables - Fix a possible NULL pointer dereference race in eventfs - Update do_div() usage in trace event benchmark test - Speedup direct function registration with asynchronous RCU callback. The synchronization was done in the registration code and this caused delays when registering direct callbacks. Move the freeing to a call_rcu() that will prevent delaying of the registering. - Replace simple_strtoul() usage with kstrtoul() * tag 'trace-v6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: eventfs: Fix a possible null pointer dereference in eventfs_find_events() ftrace: Fix possible use-after-free issue in ftrace_location() ftrace: Remove unused global 'ftrace_direct_func_count' ftrace: Remove unused list 'ftrace_direct_funcs' tracing: Improve benchmark test performance by using do_div() ftrace: Use asynchronous grace period for register_ftrace_direct() ftrace: Replaces simple_strtoul in ftrace
2 parents 70a6632 + d4e9a96 commit 594d281

File tree

5 files changed

+39
-52
lines changed

5 files changed

+39
-52
lines changed

fs/tracefs/event_inode.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -345,10 +345,9 @@ static struct eventfs_inode *eventfs_find_events(struct dentry *dentry)
345345
* If the ei is being freed, the ownership of the children
346346
* doesn't matter.
347347
*/
348-
if (ei->is_freed) {
349-
ei = NULL;
350-
break;
351-
}
348+
if (ei->is_freed)
349+
return NULL;
350+
352351
// Walk upwards until you find the events inode
353352
} while (!ei->is_events);
354353

include/linux/ftrace.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ static inline void early_trace_init(void) { }
8383

8484
struct module;
8585
struct ftrace_hash;
86-
struct ftrace_direct_func;
8786

8887
#if defined(CONFIG_FUNCTION_TRACER) && defined(CONFIG_MODULES) && \
8988
defined(CONFIG_DYNAMIC_FTRACE)
@@ -414,7 +413,6 @@ struct ftrace_func_entry {
414413
};
415414

416415
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
417-
extern int ftrace_direct_func_count;
418416
unsigned long ftrace_find_rec_direct(unsigned long ip);
419417
int register_ftrace_direct(struct ftrace_ops *ops, unsigned long addr);
420418
int unregister_ftrace_direct(struct ftrace_ops *ops, unsigned long addr,
@@ -426,7 +424,6 @@ void ftrace_stub_direct_tramp(void);
426424

427425
#else
428426
struct ftrace_ops;
429-
# define ftrace_direct_func_count 0
430427
static inline unsigned long ftrace_find_rec_direct(unsigned long ip)
431428
{
432429
return 0;

kernel/trace/fgraph.c

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -125,17 +125,6 @@ int function_graph_enter(unsigned long ret, unsigned long func,
125125
{
126126
struct ftrace_graph_ent trace;
127127

128-
#ifndef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS
129-
/*
130-
* Skip graph tracing if the return location is served by direct trampoline,
131-
* since call sequence and return addresses are unpredictable anyway.
132-
* Ex: BPF trampoline may call original function and may skip frame
133-
* depending on type of BPF programs attached.
134-
*/
135-
if (ftrace_direct_func_count &&
136-
ftrace_find_rec_direct(ret - MCOUNT_INSN_SIZE))
137-
return -EBUSY;
138-
#endif
139128
trace.func = func;
140129
trace.depth = ++current->curr_ret_depth;
141130

kernel/trace/ftrace.c

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1595,12 +1595,15 @@ static struct dyn_ftrace *lookup_rec(unsigned long start, unsigned long end)
15951595
unsigned long ftrace_location_range(unsigned long start, unsigned long end)
15961596
{
15971597
struct dyn_ftrace *rec;
1598+
unsigned long ip = 0;
15981599

1600+
rcu_read_lock();
15991601
rec = lookup_rec(start, end);
16001602
if (rec)
1601-
return rec->ip;
1603+
ip = rec->ip;
1604+
rcu_read_unlock();
16021605

1603-
return 0;
1606+
return ip;
16041607
}
16051608

16061609
/**
@@ -1614,25 +1617,22 @@ unsigned long ftrace_location_range(unsigned long start, unsigned long end)
16141617
*/
16151618
unsigned long ftrace_location(unsigned long ip)
16161619
{
1617-
struct dyn_ftrace *rec;
1620+
unsigned long loc;
16181621
unsigned long offset;
16191622
unsigned long size;
16201623

1621-
rec = lookup_rec(ip, ip);
1622-
if (!rec) {
1624+
loc = ftrace_location_range(ip, ip);
1625+
if (!loc) {
16231626
if (!kallsyms_lookup_size_offset(ip, &size, &offset))
16241627
goto out;
16251628

16261629
/* map sym+0 to __fentry__ */
16271630
if (!offset)
1628-
rec = lookup_rec(ip, ip + size - 1);
1631+
loc = ftrace_location_range(ip, ip + size - 1);
16291632
}
16301633

1631-
if (rec)
1632-
return rec->ip;
1633-
16341634
out:
1635-
return 0;
1635+
return loc;
16361636
}
16371637

16381638
/**
@@ -2538,7 +2538,6 @@ ftrace_find_unique_ops(struct dyn_ftrace *rec)
25382538
/* Protected by rcu_tasks for reading, and direct_mutex for writing */
25392539
static struct ftrace_hash __rcu *direct_functions = EMPTY_HASH;
25402540
static DEFINE_MUTEX(direct_mutex);
2541-
int ftrace_direct_func_count;
25422541

25432542
/*
25442543
* Search the direct_functions hash to see if the given instruction pointer
@@ -4201,12 +4200,12 @@ static int
42014200
add_rec_by_index(struct ftrace_hash *hash, struct ftrace_glob *func_g,
42024201
int clear_filter)
42034202
{
4204-
long index = simple_strtoul(func_g->search, NULL, 0);
4203+
long index;
42054204
struct ftrace_page *pg;
42064205
struct dyn_ftrace *rec;
42074206

42084207
/* The index starts at 1 */
4209-
if (--index < 0)
4208+
if (kstrtoul(func_g->search, 0, &index) || --index < 0)
42104209
return 0;
42114210

42124211
do_for_each_ftrace_rec(pg, rec) {
@@ -5317,14 +5316,6 @@ ftrace_set_addr(struct ftrace_ops *ops, unsigned long *ips, unsigned int cnt,
53175316

53185317
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
53195318

5320-
struct ftrace_direct_func {
5321-
struct list_head next;
5322-
unsigned long addr;
5323-
int count;
5324-
};
5325-
5326-
static LIST_HEAD(ftrace_direct_funcs);
5327-
53285319
static int register_ftrace_function_nolock(struct ftrace_ops *ops);
53295320

53305321
/*
@@ -5365,6 +5356,13 @@ static void remove_direct_functions_hash(struct ftrace_hash *hash, unsigned long
53655356
}
53665357
}
53675358

5359+
static void register_ftrace_direct_cb(struct rcu_head *rhp)
5360+
{
5361+
struct ftrace_hash *fhp = container_of(rhp, struct ftrace_hash, rcu);
5362+
5363+
free_ftrace_hash(fhp);
5364+
}
5365+
53685366
/**
53695367
* register_ftrace_direct - Call a custom trampoline directly
53705368
* for multiple functions registered in @ops
@@ -5463,10 +5461,8 @@ int register_ftrace_direct(struct ftrace_ops *ops, unsigned long addr)
54635461
out_unlock:
54645462
mutex_unlock(&direct_mutex);
54655463

5466-
if (free_hash && free_hash != EMPTY_HASH) {
5467-
synchronize_rcu_tasks();
5468-
free_ftrace_hash(free_hash);
5469-
}
5464+
if (free_hash && free_hash != EMPTY_HASH)
5465+
call_rcu_tasks(&free_hash->rcu, register_ftrace_direct_cb);
54705466

54715467
if (new_hash)
54725468
free_ftrace_hash(new_hash);
@@ -5816,9 +5812,8 @@ __setup("ftrace_graph_notrace=", set_graph_notrace_function);
58165812

58175813
static int __init set_graph_max_depth_function(char *str)
58185814
{
5819-
if (!str)
5815+
if (!str || kstrtouint(str, 0, &fgraph_max_depth))
58205816
return 0;
5821-
fgraph_max_depth = simple_strtoul(str, NULL, 0);
58225817
return 1;
58235818
}
58245819
__setup("ftrace_graph_max_depth=", set_graph_max_depth_function);
@@ -6595,6 +6590,8 @@ static int ftrace_process_locs(struct module *mod,
65956590
/* We should have used all pages unless we skipped some */
65966591
if (pg_unuse) {
65976592
WARN_ON(!skipped);
6593+
/* Need to synchronize with ftrace_location_range() */
6594+
synchronize_rcu();
65986595
ftrace_free_pages(pg_unuse);
65996596
}
66006597
return ret;
@@ -6808,6 +6805,9 @@ void ftrace_release_mod(struct module *mod)
68086805
out_unlock:
68096806
mutex_unlock(&ftrace_lock);
68106807

6808+
/* Need to synchronize with ftrace_location_range() */
6809+
if (tmp_page)
6810+
synchronize_rcu();
68116811
for (pg = tmp_page; pg; pg = tmp_page) {
68126812

68136813
/* Needs to be called outside of ftrace_lock */
@@ -7141,6 +7141,7 @@ void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr)
71417141
unsigned long start = (unsigned long)(start_ptr);
71427142
unsigned long end = (unsigned long)(end_ptr);
71437143
struct ftrace_page **last_pg = &ftrace_pages_start;
7144+
struct ftrace_page *tmp_page = NULL;
71447145
struct ftrace_page *pg;
71457146
struct dyn_ftrace *rec;
71467147
struct dyn_ftrace key;
@@ -7182,12 +7183,8 @@ void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr)
71827183
ftrace_update_tot_cnt--;
71837184
if (!pg->index) {
71847185
*last_pg = pg->next;
7185-
if (pg->records) {
7186-
free_pages((unsigned long)pg->records, pg->order);
7187-
ftrace_number_of_pages -= 1 << pg->order;
7188-
}
7189-
ftrace_number_of_groups--;
7190-
kfree(pg);
7186+
pg->next = tmp_page;
7187+
tmp_page = pg;
71917188
pg = container_of(last_pg, struct ftrace_page, next);
71927189
if (!(*last_pg))
71937190
ftrace_pages = pg;
@@ -7204,6 +7201,11 @@ void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr)
72047201
clear_func_from_hashes(func);
72057202
kfree(func);
72067203
}
7204+
/* Need to synchronize with ftrace_location_range() */
7205+
if (tmp_page) {
7206+
synchronize_rcu();
7207+
ftrace_free_pages(tmp_page);
7208+
}
72077209
}
72087210

72097211
void __init ftrace_free_init_mem(void)

kernel/trace/trace_benchmark.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ static void trace_do_benchmark(void)
104104
stddev = 0;
105105

106106
delta = bm_total;
107-
delta = div64_u64(delta, bm_cnt);
107+
do_div(delta, (u32)bm_cnt);
108108
avg = delta;
109109

110110
if (stddev > 0) {

0 commit comments

Comments
 (0)