Commit 8ae516aa authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'trace-fixes-v3.13-rc1' of...

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
parents 4f9e5df2 8a56d776
...@@ -372,7 +372,8 @@ ftrace_define_fields_##call(struct ftrace_event_call *event_call) \ ...@@ -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( \ ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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,16 +3065,13 @@ static void __enable_ftrace_function_probe(void) ...@@ -3060,16 +3065,13 @@ 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); ret = ftrace_startup(&trace_probe_ops, 0);
if (!ret)
ret = ftrace_startup(&trace_probe_ops, 0);
ftrace_probe_registered = 1; ftrace_probe_registered = 1;
} }
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,9 +3084,7 @@ static void __disable_ftrace_function_probe(void) ...@@ -3082,9 +3084,7 @@ static void __disable_ftrace_function_probe(void)
} }
/* no more funcs left */ /* no more funcs left */
ret = __unregister_ftrace_function(&trace_probe_ops); ftrace_shutdown(&trace_probe_ops, 0);
if (!ret)
ftrace_shutdown(&trace_probe_ops, 0);
ftrace_probe_registered = 0; ftrace_probe_registered = 0;
} }
...@@ -4366,12 +4366,15 @@ core_initcall(ftrace_nodyn_init); ...@@ -4366,12 +4366,15 @@ core_initcall(ftrace_nodyn_init);
static inline int ftrace_init_dyn_debugfs(struct dentry *d_tracer) { return 0; } static inline int ftrace_init_dyn_debugfs(struct dentry *d_tracer) { return 0; }
static inline void ftrace_startup_enable(int command) { } 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) \
({ \ ({ \
(ops)->flags |= FTRACE_OPS_FL_ENABLED; \ int ___ret = __register_ftrace_function(ops); \
0; \ if (!___ret) \
(ops)->flags |= FTRACE_OPS_FL_ENABLED; \
___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,9 +4783,7 @@ int register_ftrace_function(struct ftrace_ops *ops) ...@@ -4780,9 +4783,7 @@ int register_ftrace_function(struct ftrace_ops *ops)
mutex_lock(&ftrace_lock); mutex_lock(&ftrace_lock);
ret = __register_ftrace_function(ops); ret = ftrace_startup(ops, 0);
if (!ret)
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) ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment