6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Keita Morisaki keyz@google.com
[ Upstream commit 765399553714e934a219d698953d435f4f99caa7 ]
The devres ftrace event logs the name of the devres node, which is often a function name (e.g., "devm_work_drop") stringified by macros like devm_add_action. Currently, ftrace stores this name as a string literal address, which can become invalid when the module containing the string is unloaded. This results in page faults when ftrace tries to access the name.
This behavior is problematic because the devres ftrace event is designed to trace resource management throughout a device driver's lifecycle, including during module unload. The event should be available even after the module is unloaded to properly diagnose resource issues.
Fix the issue by copying the devres node name into the ftrace ring buffer using __assign_str(), instead of storing just the address. This ensures that ftrace can always access the name, even if the module is unloaded.
This change increases the memory usage for each of the ftrace entry by 12-16 bytes assuming the average devres node name is 20 bytes long, depending on the size of const char *.
Note that this change does not affect anything unless all of following conditions are met. - CONFIG_DEBUG_DEVRES is enabled - ftrace tracing is enabled - The devres event is enabled in ftrace tracing
Fixes: 09705dcb63d2 ("devres: Enable trace events") Reviewed-by: Andy Shevchenko andriy.shevchenko@linux.intel.com Signed-off-by: Keita Morisaki keyz@google.com Link: https://lore.kernel.org/r/20240928125005.714781-1-keyz@google.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/base/trace.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/base/trace.h b/drivers/base/trace.h index e52b6eae060dd..3b83b13a57ff1 100644 --- a/drivers/base/trace.h +++ b/drivers/base/trace.h @@ -24,18 +24,18 @@ DECLARE_EVENT_CLASS(devres, __field(struct device *, dev) __field(const char *, op) __field(void *, node) - __field(const char *, name) + __string(name, name) __field(size_t, size) ), TP_fast_assign( __assign_str(devname); __entry->op = op; __entry->node = node; - __entry->name = name; + __assign_str(name); __entry->size = size; ), TP_printk("%s %3s %p %s (%zu bytes)", __get_str(devname), - __entry->op, __entry->node, __entry->name, __entry->size) + __entry->op, __entry->node, __get_str(name), __entry->size) );
DEFINE_EVENT(devres, devres_log,