Skip to content

Commit 6ad51ad

Browse files
committed
tracing/fprobe: Reject registration of a registered fprobe before init
Reject registration of a registered fprobe which is on the fprobe hash table before initializing fprobe. The add_fprobe_hash() checks this re-register fprobe, but since fprobe_init() clears hlist_array field, it is too late to check it. It has to check the re-registration before touncing fprobe. Link: https://lore.kernel.org/all/177669364845.132053.18375367916162315835.stgit@mhiramat.tok.corp.google.com/ Fixes: 4346ba1 ("fprobe: Rewrite fprobe on function-graph tracer") Cc: stable@vger.kernel.org Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
1 parent b4e0758 commit 6ad51ad

1 file changed

Lines changed: 10 additions & 11 deletions

File tree

kernel/trace/fprobe.c

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
#define pr_fmt(fmt) "fprobe: " fmt
66

7+
#include <linux/cleanup.h>
78
#include <linux/err.h>
89
#include <linux/fprobe.h>
910
#include <linux/kallsyms.h>
@@ -107,7 +108,7 @@ static bool delete_fprobe_node(struct fprobe_hlist_node *node)
107108
}
108109

109110
/* Check existence of the fprobe */
110-
static bool is_fprobe_still_exist(struct fprobe *fp)
111+
static bool fprobe_registered(struct fprobe *fp)
111112
{
112113
struct hlist_head *head;
113114
struct fprobe_hlist *fph;
@@ -120,7 +121,7 @@ static bool is_fprobe_still_exist(struct fprobe *fp)
120121
}
121122
return false;
122123
}
123-
NOKPROBE_SYMBOL(is_fprobe_still_exist);
124+
NOKPROBE_SYMBOL(fprobe_registered);
124125

125126
static int add_fprobe_hash(struct fprobe *fp)
126127
{
@@ -132,9 +133,6 @@ static int add_fprobe_hash(struct fprobe *fp)
132133
if (WARN_ON_ONCE(!fph))
133134
return -EINVAL;
134135

135-
if (is_fprobe_still_exist(fp))
136-
return -EEXIST;
137-
138136
head = &fprobe_table[hash_ptr(fp, FPROBE_HASH_BITS)];
139137
hlist_add_head_rcu(&fp->hlist_array->hlist, head);
140138
return 0;
@@ -149,7 +147,7 @@ static int del_fprobe_hash(struct fprobe *fp)
149147
if (WARN_ON_ONCE(!fph))
150148
return -EINVAL;
151149

152-
if (!is_fprobe_still_exist(fp))
150+
if (!fprobe_registered(fp))
153151
return -ENOENT;
154152

155153
fph->fp = NULL;
@@ -480,7 +478,7 @@ static void fprobe_return(struct ftrace_graph_ret *trace,
480478
if (!fp)
481479
break;
482480
curr += FPROBE_HEADER_SIZE_IN_LONG;
483-
if (is_fprobe_still_exist(fp) && !fprobe_disabled(fp)) {
481+
if (fprobe_registered(fp) && !fprobe_disabled(fp)) {
484482
if (WARN_ON_ONCE(curr + size > size_words))
485483
break;
486484
fp->exit_handler(fp, trace->func, ret_ip, fregs,
@@ -839,12 +837,14 @@ int register_fprobe_ips(struct fprobe *fp, unsigned long *addrs, int num)
839837
struct fprobe_hlist *hlist_array;
840838
int ret, i;
841839

840+
guard(mutex)(&fprobe_mutex);
841+
if (fprobe_registered(fp))
842+
return -EEXIST;
843+
842844
ret = fprobe_init(fp, addrs, num);
843845
if (ret)
844846
return ret;
845847

846-
mutex_lock(&fprobe_mutex);
847-
848848
hlist_array = fp->hlist_array;
849849
if (fprobe_is_ftrace(fp))
850850
ret = fprobe_ftrace_add_ips(addrs, num);
@@ -864,7 +864,6 @@ int register_fprobe_ips(struct fprobe *fp, unsigned long *addrs, int num)
864864
delete_fprobe_node(&hlist_array->array[i]);
865865
}
866866
}
867-
mutex_unlock(&fprobe_mutex);
868867

869868
if (ret)
870869
fprobe_fail_cleanup(fp);
@@ -926,7 +925,7 @@ int unregister_fprobe(struct fprobe *fp)
926925
int ret = 0, i, count;
927926

928927
mutex_lock(&fprobe_mutex);
929-
if (!fp || !is_fprobe_still_exist(fp)) {
928+
if (!fp || !fprobe_registered(fp)) {
930929
ret = -EINVAL;
931930
goto out;
932931
}

0 commit comments

Comments
 (0)