summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJP Kobryn <inwardvessel@gmail.com>2023-12-01 14:53:55 +0900
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-12-13 18:45:31 +0100
commit95a4c959b99f10b2405356c07e8092aed1cc3bd8 (patch)
tree267cc5388920656e0ec99fde9b3fe42e7c4f96b7
parent395e52b7a1ad01e1b51adb09854a0aa5347428de (diff)
downloadlinux-starfive-95a4c959b99f10b2405356c07e8092aed1cc3bd8.tar.gz
linux-starfive-95a4c959b99f10b2405356c07e8092aed1cc3bd8.tar.bz2
linux-starfive-95a4c959b99f10b2405356c07e8092aed1cc3bd8.zip
kprobes: consistent rcu api usage for kretprobe holder
commit d839a656d0f3caca9f96e9bf912fd394ac6a11bc upstream. It seems that the pointer-to-kretprobe "rp" within the kretprobe_holder is RCU-managed, based on the (non-rethook) implementation of get_kretprobe(). The thought behind this patch is to make use of the RCU API where possible when accessing this pointer so that the needed barriers are always in place and to self-document the code. The __rcu annotation to "rp" allows for sparse RCU checking. Plain writes done to the "rp" pointer are changed to make use of the RCU macro for assignment. For the single read, the implementation of get_kretprobe() is simplified by making use of an RCU macro which accomplishes the same, but note that the log warning text will be more generic. I did find that there is a difference in assembly generated between the usage of the RCU macros vs without. For example, on arm64, when using rcu_assign_pointer(), the corresponding store instruction is a store-release (STLR) which has an implicit barrier. When normal assignment is done, a regular store (STR) is found. In the macro case, this seems to be a result of rcu_assign_pointer() using smp_store_release() when the value to write is not NULL. Link: https://lore.kernel.org/all/20231122132058.3359-1-inwardvessel@gmail.com/ Fixes: d741bf41d7c7 ("kprobes: Remove kretprobe hash") Cc: stable@vger.kernel.org Signed-off-by: JP Kobryn <inwardvessel@gmail.com> Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org> Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org> Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--include/linux/kprobes.h7
-rw-r--r--kernel/kprobes.c4
2 files changed, 4 insertions, 7 deletions
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 38a774287bde..8de5d51a0b5e 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -140,7 +140,7 @@ static inline bool kprobe_ftrace(struct kprobe *p)
*
*/
struct kretprobe_holder {
- struct kretprobe *rp;
+ struct kretprobe __rcu *rp;
refcount_t ref;
};
@@ -248,10 +248,7 @@ unsigned long kretprobe_trampoline_handler(struct pt_regs *regs,
static nokprobe_inline struct kretprobe *get_kretprobe(struct kretprobe_instance *ri)
{
- RCU_LOCKDEP_WARN(!rcu_read_lock_any_held(),
- "Kretprobe is accessed from instance under preemptive context");
-
- return READ_ONCE(ri->rph->rp);
+ return rcu_dereference_check(ri->rph->rp, rcu_read_lock_any_held());
}
static nokprobe_inline unsigned long get_kretprobe_retaddr(struct kretprobe_instance *ri)
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 0c6185aefaef..b486504766fb 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -2253,7 +2253,7 @@ int register_kretprobe(struct kretprobe *rp)
if (!rp->rph)
return -ENOMEM;
- rp->rph->rp = rp;
+ rcu_assign_pointer(rp->rph->rp, rp);
for (i = 0; i < rp->maxactive; i++) {
inst = kzalloc(struct_size(inst, data, rp->data_size), GFP_KERNEL);
if (inst == NULL) {
@@ -2313,7 +2313,7 @@ void unregister_kretprobes(struct kretprobe **rps, int num)
#ifdef CONFIG_KRETPROBE_ON_RETHOOK
rethook_free(rps[i]->rh);
#else
- rps[i]->rph->rp = NULL;
+ rcu_assign_pointer(rps[i]->rph->rp, NULL);
#endif
}
mutex_unlock(&kprobe_mutex);