Skip to content

Commit 4fc4090

Browse files
committed
ftrace: Fix checking of trampoline ftrace_ops in finding trampoline
When modifying code, ftrace has several checks to make sure things are being done correctly. One of them is to make sure any code it modifies is exactly what it expects it to be before it modifies it. In order to do so with the new trampoline logic, it must be able to find out what trampoline a function is hooked to in order to see if the code that hooks to it is what's expected. The logic to find the trampoline from a record (accounting descriptor for a function that is hooked) needs to only look at the "old_hash" of an ops that is being modified. The old_hash is the list of function an ops is hooked to before its update. Since a record would only be pointing to an ops that is being modified if it was already hooked before. Currently, it can pick a modified ops based on its new functions it will be hooked to, and this picks the wrong trampoline and causes the check to fail, disabling ftrace. Signed-off-by: Steven Rostedt <[email protected]> ftrace: squash into ordering of ops for modification
1 parent 8252ecf commit 4fc4090

File tree

1 file changed

+22
-8
lines changed

1 file changed

+22
-8
lines changed

kernel/trace/ftrace.c

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1925,8 +1925,16 @@ ftrace_find_tramp_ops_curr(struct dyn_ftrace *rec)
19251925
* when we are adding another op to the rec or removing the
19261926
* current one. Thus, if the op is being added, we can
19271927
* ignore it because it hasn't attached itself to the rec
1928-
* yet. That means we just need to find the op that has a
1929-
* trampoline and is not beeing added.
1928+
* yet.
1929+
*
1930+
* If an ops is being modified (hooking to different functions)
1931+
* then we don't care about the new functions that are being
1932+
* added, just the old ones (that are probably being removed).
1933+
*
1934+
* If we are adding an ops to a function that already is using
1935+
* a trampoline, it needs to be removed (trampolines are only
1936+
* for single ops connected), then an ops that is not being
1937+
* modified also needs to be checked.
19301938
*/
19311939
do_for_each_ftrace_op(op, ftrace_ops_list) {
19321940

@@ -1940,17 +1948,23 @@ ftrace_find_tramp_ops_curr(struct dyn_ftrace *rec)
19401948
if (op->flags & FTRACE_OPS_FL_ADDING)
19411949
continue;
19421950

1951+
19431952
/*
1944-
* If the ops is not being added and has a trampoline,
1945-
* then it must be the one that we want!
1953+
* If the ops is being modified and is in the old
1954+
* hash, then it is probably being removed from this
1955+
* function.
19461956
*/
1947-
if (hash_contains_ip(ip, op->func_hash))
1948-
return op;
1949-
1950-
/* If the ops is being modified, it may be in the old hash. */
19511957
if ((op->flags & FTRACE_OPS_FL_MODIFYING) &&
19521958
hash_contains_ip(ip, &op->old_hash))
19531959
return op;
1960+
/*
1961+
* If the ops is not being added or modified, and it's
1962+
* in its normal filter hash, then this must be the one
1963+
* we want!
1964+
*/
1965+
if (!(op->flags & FTRACE_OPS_FL_MODIFYING) &&
1966+
hash_contains_ip(ip, op->func_hash))
1967+
return op;
19541968

19551969
} while_for_each_ftrace_op(op);
19561970

0 commit comments

Comments
 (0)