mirror of
https://github.com/torvalds/linux.git
synced 2026-09-28 20:12:01 +02:00
Probes fixes for v7.3-rc4:
- kprobes: Fix permanent hang when flushing the kprobe optimizer Fix a deadlock when disabling kprobe optimization via sysctl or debugfs where flushers hung waiting for optimizer_completion. Replaced the completion with an optimizer_passes counter and wait_var_event_mutex() under kprobe_mutex so concurrent flushers can wait and wake up safely. - fprobe: Terminate the fgraph_data list when the reservation is not filled Fix an issue where unused shadow stack data left uninitialized by fprobe_fgraph_entry() was misparsed as stale fprobe headers on return. Explicitly write a zero word to terminate the list and update read_fprobe_header() to handle the zeroed slot properly. - ftracetest: Fix unique symbol check in kprobe_non_uniq_symbol.tc Fix false test failures in kprobe_non_uniq_symbol.tc on architectures like s390 where a symbol exists once in core kernel but also in modules. Anchor the /proc/kallsyms search regex to the end of the line so that module symbols are not incorrectly counted. -----BEGIN PGP SIGNATURE----- iQFPBAABCgA5FiEEh7BulGwFlgAOi5DV2/sHvwUrPxsFAmq3llUbHG1hc2FtaS5o aXJhbWF0c3VAZ21haWwuY29tAAoJENv7B78FKz8bAhEH/0EAamjv7/EDUoUq+BOO a2gnlYqvr+zcrDVQLNgiYbvTRDfIFPOdB2LpY7Rguee3747qeL7kkNATD10WFr1F 5lXe5LaLncNIrvHDdtcT5eER5ePAuSDMSL5CwnJrRvXJw42iFsqegZ07nrvc9HFS 5zw7Ej9VnFJFxeXIY3J4U92wkntLJ3JhsNheomOtQmEZU1g5ZPAbdq0icNrC3CAb FTezYk60VG0CT/gNTSd8JFnI4P5vKlZpkFFCLLMmptW4yQU9+ZdT55JRgY7wJ8ye w5rLBTRJrFhDgNAjoehMkoAtxik3dKgede7qlwxUk0sv+gwXssw28b5zabRBJgee XQ8= =cHwO -----END PGP SIGNATURE----- Merge tag 'probes-fixes-v7.3-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace Pull probe fixes from Masami Hiramatsu: - kprobes: Fix permanent hang when flushing the kprobe optimizer Fix a deadlock when disabling kprobe optimization via sysctl or debugfs where flushers hung waiting for optimizer_completion. Replaced the completion with an optimizer_passes counter and wait_var_event_mutex() under kprobe_mutex so concurrent flushers can wait and wake up safely. - fprobe: Terminate the fgraph_data list when the reservation is not filled Fix an issue where unused shadow stack data left uninitialized by fprobe_fgraph_entry() was misparsed as stale fprobe headers on return. Explicitly write a zero word to terminate the list and update read_fprobe_header() to handle the zeroed slot properly. - ftracetest: Fix unique symbol check in kprobe_non_uniq_symbol.tc Fix false test failures in kprobe_non_uniq_symbol.tc on architectures like s390 where a symbol exists once in core kernel but also in modules. Anchor the /proc/kallsyms search regex to the end of the line so that module symbols are not incorrectly counted. * tag 'probes-fixes-v7.3-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: kprobes: Fix permanent hang when flushing the kprobe optimizer fprobe: Terminate the fgraph_data list when the reservation is not filled selftests/ftrace: Fix unique symbol check in kprobe_non_uniq_symbol.tc
This commit is contained in:
commit
efb27d4767
|
|
@ -42,6 +42,7 @@
|
|||
#include <linux/execmem.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/wait_bit.h>
|
||||
|
||||
#include <asm/sections.h>
|
||||
#include <asm/cacheflush.h>
|
||||
|
|
@ -526,7 +527,8 @@ enum {
|
|||
OPTIMIZER_ST_FLUSHING = 2,
|
||||
};
|
||||
|
||||
static DECLARE_COMPLETION(optimizer_completion);
|
||||
/* Bumped at the end of each kprobe_optimizer() pass, under 'kprobe_mutex' */
|
||||
static unsigned long optimizer_passes;
|
||||
|
||||
#define OPTIMIZE_DELAY 5
|
||||
|
||||
|
|
@ -654,9 +656,9 @@ static void kprobe_optimizer(void)
|
|||
do_free_cleaned_kprobes();
|
||||
}
|
||||
|
||||
/* Step 5: Kick optimizer again if needed. But if there is a flush requested, */
|
||||
if (completion_done(&optimizer_completion))
|
||||
complete(&optimizer_completion);
|
||||
/* Step 5: Wake up flushers, and kick optimizer again if needed. */
|
||||
optimizer_passes++;
|
||||
wake_up_var_locked(&optimizer_passes, &kprobe_mutex);
|
||||
|
||||
if (!list_empty(&optimizing_list) || !list_empty(&unoptimizing_list))
|
||||
kick_kprobe_optimizer(); /*normal kick*/
|
||||
|
|
@ -708,7 +710,8 @@ static void wait_for_kprobe_optimizer_locked(void)
|
|||
lockdep_assert_held(&kprobe_mutex);
|
||||
|
||||
while (!list_empty(&optimizing_list) || !list_empty(&unoptimizing_list)) {
|
||||
init_completion(&optimizer_completion);
|
||||
unsigned long passes = optimizer_passes;
|
||||
|
||||
/*
|
||||
* Set state to OPTIMIZER_ST_FLUSHING and wake up the thread if it's
|
||||
* idle. If it's already kicked, it will see the state change.
|
||||
|
|
@ -717,9 +720,12 @@ static void wait_for_kprobe_optimizer_locked(void)
|
|||
OPTIMIZER_ST_FLUSHING) != OPTIMIZER_ST_FLUSHING)
|
||||
wake_up(&kprobe_optimizer_wait);
|
||||
|
||||
mutex_unlock(&kprobe_mutex);
|
||||
wait_for_completion(&optimizer_completion);
|
||||
mutex_lock(&kprobe_mutex);
|
||||
/*
|
||||
* kprobe_optimizer() holds 'kprobe_mutex' for a whole pass, which
|
||||
* this drops while sleeping, so a new count means a full pass ran.
|
||||
*/
|
||||
wait_var_event_mutex(&optimizer_passes,
|
||||
optimizer_passes != passes, &kprobe_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -171,6 +171,11 @@ static inline bool write_fprobe_header(unsigned long *stack,
|
|||
static inline void read_fprobe_header(unsigned long *stack,
|
||||
struct fprobe **fp, unsigned int *size_words)
|
||||
{
|
||||
if (!*stack) {
|
||||
*fp = NULL;
|
||||
*size_words = 0;
|
||||
return;
|
||||
}
|
||||
*fp = arch_decode_fprobe_header_fp(*stack);
|
||||
*size_words = arch_decode_fprobe_header_size(*stack);
|
||||
}
|
||||
|
|
@ -203,6 +208,12 @@ static inline void read_fprobe_header(unsigned long *stack,
|
|||
{
|
||||
struct __fprobe_header *fph = (struct __fprobe_header *)stack;
|
||||
|
||||
if (!*stack) {
|
||||
*fp = NULL;
|
||||
*size_words = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
*fp = fph->fp;
|
||||
*size_words = fph->size_words;
|
||||
}
|
||||
|
|
@ -635,6 +646,10 @@ static int fprobe_fgraph_entry(struct ftrace_graph_ent *trace, struct fgraph_ops
|
|||
}
|
||||
}
|
||||
|
||||
/* Terminate the list, fgraph_reserve_data() does not clear it. */
|
||||
if (used && used < reserved_words)
|
||||
fgraph_data[used] = 0;
|
||||
|
||||
/* If any exit_handler is set, data must be used. */
|
||||
return used != 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
SYMBOL='name_show'
|
||||
|
||||
# We skip this test on kernel where SYMBOL is unique or does not exist.
|
||||
if [ "$(grep -c -E "[[:alnum:]]+ t ${SYMBOL}" /proc/kallsyms)" -le '1' ]; then
|
||||
if [ "$(grep -c -E "[[:alnum:]]+ t ${SYMBOL}$" /proc/kallsyms)" -le '1' ]; then
|
||||
exit_unsupported
|
||||
fi
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user