Merge tag 'trace-fixes-v3.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace
Pull tracing fixes from Steven Rostedt: "This includes two fixes. 1) is a bug fix that happens when root does the following: echo function_graph > current_tracer modprobe foo echo nop > current_tracer This causes the ftrace internal accounting to get screwed up and crashes ftrace, preventing the user from using the function tracer after that. 2) if a TRACE_EVENT has a string field, and NULL is given for it. The internal trace event code does a strlen() and strcpy() on the source of field. If it is NULL it causes the system to oops. This bug has been there since 2.6.31, but no TRACE_EVENT ever passed in a NULL to the string field, until now" * tag 'trace-fixes-v3.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace: ftrace: Fix function graph with loading of modules tracing: Allow events to have NULL strings
This commit is contained in:
@@ -372,7 +372,8 @@ ftrace_define_fields_##call(struct ftrace_event_call *event_call) \
|
|||||||
__data_size += (len) * sizeof(type);
|
__data_size += (len) * sizeof(type);
|
||||||
|
|
||||||
#undef __string
|
#undef __string
|
||||||
#define __string(item, src) __dynamic_array(char, item, strlen(src) + 1)
|
#define __string(item, src) __dynamic_array(char, item, \
|
||||||
|
strlen((src) ? (const char *)(src) : "(null)") + 1)
|
||||||
|
|
||||||
#undef DECLARE_EVENT_CLASS
|
#undef DECLARE_EVENT_CLASS
|
||||||
#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
|
#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
|
||||||
@@ -501,7 +502,7 @@ static inline notrace int ftrace_get_offsets_##call( \
|
|||||||
|
|
||||||
#undef __assign_str
|
#undef __assign_str
|
||||||
#define __assign_str(dst, src) \
|
#define __assign_str(dst, src) \
|
||||||
strcpy(__get_str(dst), src);
|
strcpy(__get_str(dst), (src) ? (const char *)(src) : "(null)");
|
||||||
|
|
||||||
#undef TP_fast_assign
|
#undef TP_fast_assign
|
||||||
#define TP_fast_assign(args...) args
|
#define TP_fast_assign(args...) args
|
||||||
|
@@ -367,9 +367,6 @@ static int remove_ftrace_list_ops(struct ftrace_ops **list,
|
|||||||
|
|
||||||
static int __register_ftrace_function(struct ftrace_ops *ops)
|
static int __register_ftrace_function(struct ftrace_ops *ops)
|
||||||
{
|
{
|
||||||
if (unlikely(ftrace_disabled))
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
if (FTRACE_WARN_ON(ops == &global_ops))
|
if (FTRACE_WARN_ON(ops == &global_ops))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@@ -428,9 +425,6 @@ static int __unregister_ftrace_function(struct ftrace_ops *ops)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (ftrace_disabled)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
if (WARN_ON(!(ops->flags & FTRACE_OPS_FL_ENABLED)))
|
if (WARN_ON(!(ops->flags & FTRACE_OPS_FL_ENABLED)))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
@@ -2088,10 +2082,15 @@ static void ftrace_startup_enable(int command)
|
|||||||
static int ftrace_startup(struct ftrace_ops *ops, int command)
|
static int ftrace_startup(struct ftrace_ops *ops, int command)
|
||||||
{
|
{
|
||||||
bool hash_enable = true;
|
bool hash_enable = true;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (unlikely(ftrace_disabled))
|
if (unlikely(ftrace_disabled))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
|
ret = __register_ftrace_function(ops);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
ftrace_start_up++;
|
ftrace_start_up++;
|
||||||
command |= FTRACE_UPDATE_CALLS;
|
command |= FTRACE_UPDATE_CALLS;
|
||||||
|
|
||||||
@@ -2113,12 +2112,17 @@ static int ftrace_startup(struct ftrace_ops *ops, int command)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ftrace_shutdown(struct ftrace_ops *ops, int command)
|
static int ftrace_shutdown(struct ftrace_ops *ops, int command)
|
||||||
{
|
{
|
||||||
bool hash_disable = true;
|
bool hash_disable = true;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (unlikely(ftrace_disabled))
|
if (unlikely(ftrace_disabled))
|
||||||
return;
|
return -ENODEV;
|
||||||
|
|
||||||
|
ret = __unregister_ftrace_function(ops);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
ftrace_start_up--;
|
ftrace_start_up--;
|
||||||
/*
|
/*
|
||||||
@@ -2153,9 +2157,10 @@ static void ftrace_shutdown(struct ftrace_ops *ops, int command)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!command || !ftrace_enabled)
|
if (!command || !ftrace_enabled)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
ftrace_run_update_code(command);
|
ftrace_run_update_code(command);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ftrace_startup_sysctl(void)
|
static void ftrace_startup_sysctl(void)
|
||||||
@@ -3060,8 +3065,6 @@ static void __enable_ftrace_function_probe(void)
|
|||||||
if (i == FTRACE_FUNC_HASHSIZE)
|
if (i == FTRACE_FUNC_HASHSIZE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ret = __register_ftrace_function(&trace_probe_ops);
|
|
||||||
if (!ret)
|
|
||||||
ret = ftrace_startup(&trace_probe_ops, 0);
|
ret = ftrace_startup(&trace_probe_ops, 0);
|
||||||
|
|
||||||
ftrace_probe_registered = 1;
|
ftrace_probe_registered = 1;
|
||||||
@@ -3069,7 +3072,6 @@ static void __enable_ftrace_function_probe(void)
|
|||||||
|
|
||||||
static void __disable_ftrace_function_probe(void)
|
static void __disable_ftrace_function_probe(void)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!ftrace_probe_registered)
|
if (!ftrace_probe_registered)
|
||||||
@@ -3082,8 +3084,6 @@ static void __disable_ftrace_function_probe(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* no more funcs left */
|
/* no more funcs left */
|
||||||
ret = __unregister_ftrace_function(&trace_probe_ops);
|
|
||||||
if (!ret)
|
|
||||||
ftrace_shutdown(&trace_probe_ops, 0);
|
ftrace_shutdown(&trace_probe_ops, 0);
|
||||||
|
|
||||||
ftrace_probe_registered = 0;
|
ftrace_probe_registered = 0;
|
||||||
@@ -4368,10 +4368,13 @@ static inline void ftrace_startup_enable(int command) { }
|
|||||||
/* Keep as macros so we do not need to define the commands */
|
/* Keep as macros so we do not need to define the commands */
|
||||||
# define ftrace_startup(ops, command) \
|
# define ftrace_startup(ops, command) \
|
||||||
({ \
|
({ \
|
||||||
|
int ___ret = __register_ftrace_function(ops); \
|
||||||
|
if (!___ret) \
|
||||||
(ops)->flags |= FTRACE_OPS_FL_ENABLED; \
|
(ops)->flags |= FTRACE_OPS_FL_ENABLED; \
|
||||||
0; \
|
___ret; \
|
||||||
})
|
})
|
||||||
# define ftrace_shutdown(ops, command) do { } while (0)
|
# define ftrace_shutdown(ops, command) __unregister_ftrace_function(ops)
|
||||||
|
|
||||||
# define ftrace_startup_sysctl() do { } while (0)
|
# define ftrace_startup_sysctl() do { } while (0)
|
||||||
# define ftrace_shutdown_sysctl() do { } while (0)
|
# define ftrace_shutdown_sysctl() do { } while (0)
|
||||||
|
|
||||||
@@ -4780,8 +4783,6 @@ int register_ftrace_function(struct ftrace_ops *ops)
|
|||||||
|
|
||||||
mutex_lock(&ftrace_lock);
|
mutex_lock(&ftrace_lock);
|
||||||
|
|
||||||
ret = __register_ftrace_function(ops);
|
|
||||||
if (!ret)
|
|
||||||
ret = ftrace_startup(ops, 0);
|
ret = ftrace_startup(ops, 0);
|
||||||
|
|
||||||
mutex_unlock(&ftrace_lock);
|
mutex_unlock(&ftrace_lock);
|
||||||
@@ -4801,9 +4802,7 @@ int unregister_ftrace_function(struct ftrace_ops *ops)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
mutex_lock(&ftrace_lock);
|
mutex_lock(&ftrace_lock);
|
||||||
ret = __unregister_ftrace_function(ops);
|
ret = ftrace_shutdown(ops, 0);
|
||||||
if (!ret)
|
|
||||||
ftrace_shutdown(ops, 0);
|
|
||||||
mutex_unlock(&ftrace_lock);
|
mutex_unlock(&ftrace_lock);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -4997,6 +4996,13 @@ ftrace_suspend_notifier_call(struct notifier_block *bl, unsigned long state,
|
|||||||
return NOTIFY_DONE;
|
return NOTIFY_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Just a place holder for function graph */
|
||||||
|
static struct ftrace_ops fgraph_ops __read_mostly = {
|
||||||
|
.func = ftrace_stub,
|
||||||
|
.flags = FTRACE_OPS_FL_STUB | FTRACE_OPS_FL_GLOBAL |
|
||||||
|
FTRACE_OPS_FL_RECURSION_SAFE,
|
||||||
|
};
|
||||||
|
|
||||||
int register_ftrace_graph(trace_func_graph_ret_t retfunc,
|
int register_ftrace_graph(trace_func_graph_ret_t retfunc,
|
||||||
trace_func_graph_ent_t entryfunc)
|
trace_func_graph_ent_t entryfunc)
|
||||||
{
|
{
|
||||||
@@ -5023,7 +5029,7 @@ int register_ftrace_graph(trace_func_graph_ret_t retfunc,
|
|||||||
ftrace_graph_return = retfunc;
|
ftrace_graph_return = retfunc;
|
||||||
ftrace_graph_entry = entryfunc;
|
ftrace_graph_entry = entryfunc;
|
||||||
|
|
||||||
ret = ftrace_startup(&global_ops, FTRACE_START_FUNC_RET);
|
ret = ftrace_startup(&fgraph_ops, FTRACE_START_FUNC_RET);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&ftrace_lock);
|
mutex_unlock(&ftrace_lock);
|
||||||
@@ -5040,7 +5046,7 @@ void unregister_ftrace_graph(void)
|
|||||||
ftrace_graph_active--;
|
ftrace_graph_active--;
|
||||||
ftrace_graph_return = (trace_func_graph_ret_t)ftrace_stub;
|
ftrace_graph_return = (trace_func_graph_ret_t)ftrace_stub;
|
||||||
ftrace_graph_entry = ftrace_graph_entry_stub;
|
ftrace_graph_entry = ftrace_graph_entry_stub;
|
||||||
ftrace_shutdown(&global_ops, FTRACE_STOP_FUNC_RET);
|
ftrace_shutdown(&fgraph_ops, FTRACE_STOP_FUNC_RET);
|
||||||
unregister_pm_notifier(&ftrace_suspend_notifier);
|
unregister_pm_notifier(&ftrace_suspend_notifier);
|
||||||
unregister_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL);
|
unregister_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user