mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-15 22:31:47 -04:00
Merge tag 'probes-fixes-v7.1-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace
Pull probes fixes from Masami Hiramatsu: - kprobes: skip non-symbol addresses in kprobe_add_ksym_blacklist() Since the ftrace adds its NOPs at .kprobes.text section (which stores an array), a wrong entry is added when loading a module which uses "__kprobes" attribute. To solve this, add "notrace" to __kprobes functions - test_kprobes: clear kprobes between test runs Clear all kprobes in the test program after running a test set, because Kunit test can run several times - fprobe: Fix unregister_fprobe() to wait for RCU grace period Since the fprobe data structure is removed with hlist_del_rcu(), it should wait for the RCU grace period. If the caller waits for RCU, we can use the async variant (e.g. eBPF) * tag 'probes-fixes-v7.1-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: fprobe: Fix unregister_fprobe() to wait for RCU grace period test_kprobes: clear kprobes between test runs kprobes: skip non-symbol addresses in kprobe_add_ksym_blacklist()
This commit is contained in:
@@ -14,7 +14,7 @@ static unsigned long __used \
|
||||
_kbl_addr_##fname = (unsigned long)fname;
|
||||
# define NOKPROBE_SYMBOL(fname) __NOKPROBE_SYMBOL(fname)
|
||||
/* Use this to forbid a kprobes attach on very low level functions */
|
||||
# define __kprobes __section(".kprobes.text")
|
||||
# define __kprobes notrace __section(".kprobes.text")
|
||||
# define nokprobe_inline __always_inline
|
||||
#else
|
||||
# define NOKPROBE_SYMBOL(fname)
|
||||
|
||||
@@ -94,6 +94,7 @@ int register_fprobe(struct fprobe *fp, const char *filter, const char *notfilter
|
||||
int register_fprobe_ips(struct fprobe *fp, unsigned long *addrs, int num);
|
||||
int register_fprobe_syms(struct fprobe *fp, const char **syms, int num);
|
||||
int unregister_fprobe(struct fprobe *fp);
|
||||
int unregister_fprobe_async(struct fprobe *fp);
|
||||
bool fprobe_is_registered(struct fprobe *fp);
|
||||
int fprobe_count_ips_from_filter(const char *filter, const char *notfilter);
|
||||
#else
|
||||
@@ -113,6 +114,10 @@ static inline int unregister_fprobe(struct fprobe *fp)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static inline int unregister_fprobe_async(struct fprobe *fp)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static inline bool fprobe_is_registered(struct fprobe *fp)
|
||||
{
|
||||
return false;
|
||||
|
||||
@@ -2384,7 +2384,8 @@ static void bpf_kprobe_multi_link_release(struct bpf_link *link)
|
||||
struct bpf_kprobe_multi_link *kmulti_link;
|
||||
|
||||
kmulti_link = container_of(link, struct bpf_kprobe_multi_link, link);
|
||||
unregister_fprobe(&kmulti_link->fp);
|
||||
/* Don't wait for RCU GP here. */
|
||||
unregister_fprobe_async(&kmulti_link->fp);
|
||||
kprobe_multi_put_modules(kmulti_link->mods, kmulti_link->mods_cnt);
|
||||
}
|
||||
|
||||
|
||||
@@ -1093,14 +1093,15 @@ static int unregister_fprobe_nolock(struct fprobe *fp)
|
||||
}
|
||||
|
||||
/**
|
||||
* unregister_fprobe() - Unregister fprobe.
|
||||
* unregister_fprobe_async() - Unregister fprobe without RCU GP wait
|
||||
* @fp: A fprobe data structure to be unregistered.
|
||||
*
|
||||
* Unregister fprobe (and remove ftrace hooks from the function entries).
|
||||
* This function will NOT wait until the fprobe is no longer used.
|
||||
*
|
||||
* Return 0 if @fp is unregistered successfully, -errno if not.
|
||||
*/
|
||||
int unregister_fprobe(struct fprobe *fp)
|
||||
int unregister_fprobe_async(struct fprobe *fp)
|
||||
{
|
||||
guard(mutex)(&fprobe_mutex);
|
||||
if (!fp || !fprobe_registered(fp))
|
||||
@@ -1108,6 +1109,24 @@ int unregister_fprobe(struct fprobe *fp)
|
||||
|
||||
return unregister_fprobe_nolock(fp);
|
||||
}
|
||||
|
||||
/**
|
||||
* unregister_fprobe() - Unregister fprobe with RCU GP wait
|
||||
* @fp: A fprobe data structure to be unregistered.
|
||||
*
|
||||
* Unregister fprobe (and remove ftrace hooks from the function entries).
|
||||
* This function will block until the fprobe is no longer used.
|
||||
*
|
||||
* Return 0 if @fp is unregistered successfully, -errno if not.
|
||||
*/
|
||||
int unregister_fprobe(struct fprobe *fp)
|
||||
{
|
||||
int ret = unregister_fprobe_async(fp);
|
||||
|
||||
if (!ret)
|
||||
synchronize_rcu();
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(unregister_fprobe);
|
||||
|
||||
static int __init fprobe_initcall(void)
|
||||
|
||||
@@ -12,6 +12,12 @@
|
||||
|
||||
#define div_factor 3
|
||||
|
||||
#define KP_CLEAR(_kp) \
|
||||
do { \
|
||||
(_kp).addr = NULL; \
|
||||
(_kp).flags = 0; \
|
||||
} while (0)
|
||||
|
||||
static u32 rand1, preh_val, posth_val;
|
||||
static u32 (*target)(u32 value);
|
||||
static u32 (*recursed_target)(u32 value);
|
||||
@@ -125,10 +131,6 @@ static void test_kprobes(struct kunit *test)
|
||||
|
||||
current_test = test;
|
||||
|
||||
/* addr and flags should be cleard for reusing kprobe. */
|
||||
kp.addr = NULL;
|
||||
kp.flags = 0;
|
||||
|
||||
KUNIT_EXPECT_EQ(test, 0, register_kprobes(kps, 2));
|
||||
preh_val = 0;
|
||||
posth_val = 0;
|
||||
@@ -226,9 +228,6 @@ static void test_kretprobes(struct kunit *test)
|
||||
struct kretprobe *rps[2] = {&rp, &rp2};
|
||||
|
||||
current_test = test;
|
||||
/* addr and flags should be cleard for reusing kprobe. */
|
||||
rp.kp.addr = NULL;
|
||||
rp.kp.flags = 0;
|
||||
KUNIT_EXPECT_EQ(test, 0, register_kretprobes(rps, 2));
|
||||
|
||||
krph_val = 0;
|
||||
@@ -290,8 +289,6 @@ static void test_stacktrace_on_kretprobe(struct kunit *test)
|
||||
unsigned long myretaddr = (unsigned long)__builtin_return_address(0);
|
||||
|
||||
current_test = test;
|
||||
rp3.kp.addr = NULL;
|
||||
rp3.kp.flags = 0;
|
||||
|
||||
/*
|
||||
* Run the stacktrace_driver() to record correct return address in
|
||||
@@ -352,8 +349,6 @@ static void test_stacktrace_on_nested_kretprobe(struct kunit *test)
|
||||
struct kretprobe *rps[2] = {&rp3, &rp4};
|
||||
|
||||
current_test = test;
|
||||
rp3.kp.addr = NULL;
|
||||
rp3.kp.flags = 0;
|
||||
|
||||
//KUNIT_ASSERT_NE(test, myretaddr, stacktrace_driver());
|
||||
|
||||
@@ -367,6 +362,18 @@ static void test_stacktrace_on_nested_kretprobe(struct kunit *test)
|
||||
|
||||
static int kprobes_test_init(struct kunit *test)
|
||||
{
|
||||
KP_CLEAR(kp);
|
||||
KP_CLEAR(kp2);
|
||||
KP_CLEAR(kp_missed);
|
||||
#ifdef CONFIG_KRETPROBES
|
||||
KP_CLEAR(rp.kp);
|
||||
KP_CLEAR(rp2.kp);
|
||||
#ifdef CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE
|
||||
KP_CLEAR(rp3.kp);
|
||||
KP_CLEAR(rp4.kp);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
target = kprobe_target;
|
||||
target2 = kprobe_target2;
|
||||
recursed_target = kprobe_recursed_target;
|
||||
|
||||
Reference in New Issue
Block a user