Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -372,7 +372,8 @@ ftrace_define_fields_##call(struct ftrace_event_call *event_call) \
	__data_size += (len) * sizeof(type);

#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
#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
#define __assign_str(dst, src)						\
	strcpy(__get_str(dst), src);
	strcpy(__get_str(dst), (src) ? (const char *)(src) : "(null)");

#undef TP_fast_assign
#define TP_fast_assign(args...) args
+35 −29
Original line number Diff line number Diff line
@@ -367,9 +367,6 @@ static int remove_ftrace_list_ops(struct ftrace_ops **list,

static int __register_ftrace_function(struct ftrace_ops *ops)
{
	if (unlikely(ftrace_disabled))
		return -ENODEV;

	if (FTRACE_WARN_ON(ops == &global_ops))
		return -EINVAL;

@@ -428,9 +425,6 @@ static int __unregister_ftrace_function(struct ftrace_ops *ops)
{
	int ret;

	if (ftrace_disabled)
		return -ENODEV;

	if (WARN_ON(!(ops->flags & FTRACE_OPS_FL_ENABLED)))
		return -EBUSY;

@@ -2088,10 +2082,15 @@ static void ftrace_startup_enable(int command)
static int ftrace_startup(struct ftrace_ops *ops, int command)
{
	bool hash_enable = true;
	int ret;

	if (unlikely(ftrace_disabled))
		return -ENODEV;

	ret = __register_ftrace_function(ops);
	if (ret)
		return ret;

	ftrace_start_up++;
	command |= FTRACE_UPDATE_CALLS;

@@ -2113,12 +2112,17 @@ static int ftrace_startup(struct ftrace_ops *ops, int command)
	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;
	int ret;

	if (unlikely(ftrace_disabled))
		return;
		return -ENODEV;

	ret = __unregister_ftrace_function(ops);
	if (ret)
		return ret;

	ftrace_start_up--;
	/*
@@ -2153,9 +2157,10 @@ static void ftrace_shutdown(struct ftrace_ops *ops, int command)
	}

	if (!command || !ftrace_enabled)
		return;
		return 0;

	ftrace_run_update_code(command);
	return 0;
}

static void ftrace_startup_sysctl(void)
@@ -3060,8 +3065,6 @@ static void __enable_ftrace_function_probe(void)
	if (i == FTRACE_FUNC_HASHSIZE)
		return;

	ret = __register_ftrace_function(&trace_probe_ops);
	if (!ret)
	ret = ftrace_startup(&trace_probe_ops, 0);

	ftrace_probe_registered = 1;
@@ -3069,7 +3072,6 @@ static void __enable_ftrace_function_probe(void)

static void __disable_ftrace_function_probe(void)
{
	int ret;
	int i;

	if (!ftrace_probe_registered)
@@ -3082,8 +3084,6 @@ static void __disable_ftrace_function_probe(void)
	}

	/* no more funcs left */
	ret = __unregister_ftrace_function(&trace_probe_ops);
	if (!ret)
	ftrace_shutdown(&trace_probe_ops, 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 */
# define ftrace_startup(ops, command)					\
	({								\
		int ___ret = __register_ftrace_function(ops);		\
		if (!___ret)						\
			(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_shutdown_sysctl()	do { } while (0)

@@ -4780,8 +4783,6 @@ int register_ftrace_function(struct ftrace_ops *ops)

	mutex_lock(&ftrace_lock);

	ret = __register_ftrace_function(ops);
	if (!ret)
	ret = ftrace_startup(ops, 0);

	mutex_unlock(&ftrace_lock);
@@ -4801,9 +4802,7 @@ int unregister_ftrace_function(struct ftrace_ops *ops)
	int ret;

	mutex_lock(&ftrace_lock);
	ret = __unregister_ftrace_function(ops);
	if (!ret)
		ftrace_shutdown(ops, 0);
	ret = ftrace_shutdown(ops, 0);
	mutex_unlock(&ftrace_lock);

	return ret;
@@ -4997,6 +4996,13 @@ ftrace_suspend_notifier_call(struct notifier_block *bl, unsigned long state,
	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,
			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_entry = entryfunc;

	ret = ftrace_startup(&global_ops, FTRACE_START_FUNC_RET);
	ret = ftrace_startup(&fgraph_ops, FTRACE_START_FUNC_RET);

out:
	mutex_unlock(&ftrace_lock);
@@ -5040,7 +5046,7 @@ void unregister_ftrace_graph(void)
	ftrace_graph_active--;
	ftrace_graph_return = (trace_func_graph_ret_t)ftrace_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_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL);