From: Steven Rostedt (VMware) <rostedt@goodmis.org>
Date: Wed, 5 Apr 2017 17:36:18 +0000 (-0400)
Subject: ftrace: If the hash for a probe fails to update then free what was initialized
X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=8d70725e452cac9796e9025ccd79c45ffcc4d109;p=linux.git

ftrace: If the hash for a probe fails to update then free what was initialized

If the ftrace_hash_move_and_update_ops() fails, and an ops->free() function
exists, then it needs to be called on all the ops that were added by this
registration.

Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---

diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 493c7ff7e8606..8394055e67937 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -4003,7 +4003,7 @@ register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
 	ret = ftrace_hash_move_and_update_ops(&ops->ops, orig_hash,
 						      hash, 1);
 	if (ret < 0)
-		goto out_unlock;
+		goto err_unlock;
 
 	if (list_empty(&ops->list))
 		list_add(&ops->list, &ftrace_func_probes);
@@ -4021,6 +4021,20 @@ register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
 	free_ftrace_hash(hash);
 
 	return ret;
+
+ err_unlock:
+	if (!ops->free)
+		goto out_unlock;
+
+	/* Failed to do the move, need to call the free functions */
+	for (i = 0; i < size; i++) {
+		hlist_for_each_entry(entry, &hash->buckets[i], hlist) {
+			if (ftrace_lookup_ip(old_hash, entry->ip))
+				continue;
+			ops->free(ops, entry->ip, NULL);
+		}
+	}
+	goto out_unlock;
 }
 
 int