forked from luck/tmp_suning_uos_patched
tracepoint: Fix tracepoint array element size mismatch
commit 46e0c9be20
("kernel: tracepoints: add support for relative
references") changes the layout of the __tracepoint_ptrs section on
architectures supporting relative references. However, it does so
without turning struct tracepoint * const into const int elsewhere in
the tracepoint code, which has the following side-effect:
Setting mod->num_tracepoints is done in by module.c:
mod->tracepoints_ptrs = section_objs(info, "__tracepoints_ptrs",
sizeof(*mod->tracepoints_ptrs),
&mod->num_tracepoints);
Basically, since sizeof(*mod->tracepoints_ptrs) is a pointer size
(rather than sizeof(int)), num_tracepoints is erroneously set to half the
size it should be on 64-bit arch. So a module with an odd number of
tracepoints misses the last tracepoint due to effect of integer
division.
So in the module going notifier:
for_each_tracepoint_range(mod->tracepoints_ptrs,
mod->tracepoints_ptrs + mod->num_tracepoints,
tp_module_going_check_quiescent, NULL);
the expression (mod->tracepoints_ptrs + mod->num_tracepoints) actually
evaluates to something within the bounds of the array, but miss the
last tracepoint if the number of tracepoints is odd on 64-bit arch.
Fix this by introducing a new typedef: tracepoint_ptr_t, which
is either "const int" on architectures that have PREL32 relocations,
or "struct tracepoint * const" on architectures that does not have
this feature.
Also provide a new tracepoint_ptr_defer() static inline to
encapsulate deferencing this type rather than duplicate code and
ugly idefs within the for_each_tracepoint_range() implementation.
This issue appears in 4.19-rc kernels, and should ideally be fixed
before the end of the rc cycle.
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Acked-by: Jessica Yu <jeyu@kernel.org>
Link: http://lkml.kernel.org/r/20181013191050.22389-1-mathieu.desnoyers@efficios.com
Link: http://lkml.kernel.org/r/20180704083651.24360-7-ard.biesheuvel@linaro.org
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: James Morris <james.morris@microsoft.com>
Cc: James Morris <jmorris@namei.org>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Nicolas Pitre <nico@linaro.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Petr Mladek <pmladek@suse.com>
Cc: Russell King <linux@armlinux.org.uk>
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Cc: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
Cc: Thomas Garnier <thgarnie@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
This commit is contained in:
parent
62165600ae
commit
9c0be3f6b5
|
@ -20,6 +20,7 @@
|
||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
#include <linux/rbtree_latch.h>
|
#include <linux/rbtree_latch.h>
|
||||||
#include <linux/error-injection.h>
|
#include <linux/error-injection.h>
|
||||||
|
#include <linux/tracepoint-defs.h>
|
||||||
|
|
||||||
#include <linux/percpu.h>
|
#include <linux/percpu.h>
|
||||||
#include <asm/module.h>
|
#include <asm/module.h>
|
||||||
|
@ -430,7 +431,7 @@ struct module {
|
||||||
|
|
||||||
#ifdef CONFIG_TRACEPOINTS
|
#ifdef CONFIG_TRACEPOINTS
|
||||||
unsigned int num_tracepoints;
|
unsigned int num_tracepoints;
|
||||||
struct tracepoint * const *tracepoints_ptrs;
|
tracepoint_ptr_t *tracepoints_ptrs;
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_JUMP_LABEL
|
#ifdef HAVE_JUMP_LABEL
|
||||||
struct jump_entry *jump_entries;
|
struct jump_entry *jump_entries;
|
||||||
|
|
|
@ -35,6 +35,12 @@ struct tracepoint {
|
||||||
struct tracepoint_func __rcu *funcs;
|
struct tracepoint_func __rcu *funcs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
|
||||||
|
typedef const int tracepoint_ptr_t;
|
||||||
|
#else
|
||||||
|
typedef struct tracepoint * const tracepoint_ptr_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
struct bpf_raw_event_map {
|
struct bpf_raw_event_map {
|
||||||
struct tracepoint *tp;
|
struct tracepoint *tp;
|
||||||
void *bpf_func;
|
void *bpf_func;
|
||||||
|
|
|
@ -99,6 +99,29 @@ extern void syscall_unregfunc(void);
|
||||||
#define TRACE_DEFINE_ENUM(x)
|
#define TRACE_DEFINE_ENUM(x)
|
||||||
#define TRACE_DEFINE_SIZEOF(x)
|
#define TRACE_DEFINE_SIZEOF(x)
|
||||||
|
|
||||||
|
#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
|
||||||
|
static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
|
||||||
|
{
|
||||||
|
return offset_to_ptr(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define __TRACEPOINT_ENTRY(name) \
|
||||||
|
asm(" .section \"__tracepoints_ptrs\", \"a\" \n" \
|
||||||
|
" .balign 4 \n" \
|
||||||
|
" .long __tracepoint_" #name " - . \n" \
|
||||||
|
" .previous \n")
|
||||||
|
#else
|
||||||
|
static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
|
||||||
|
{
|
||||||
|
return *p;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define __TRACEPOINT_ENTRY(name) \
|
||||||
|
static tracepoint_ptr_t __tracepoint_ptr_##name __used \
|
||||||
|
__attribute__((section("__tracepoints_ptrs"))) = \
|
||||||
|
&__tracepoint_##name
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* _LINUX_TRACEPOINT_H */
|
#endif /* _LINUX_TRACEPOINT_H */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -253,19 +276,6 @@ extern void syscall_unregfunc(void);
|
||||||
return static_key_false(&__tracepoint_##name.key); \
|
return static_key_false(&__tracepoint_##name.key); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
|
|
||||||
#define __TRACEPOINT_ENTRY(name) \
|
|
||||||
asm(" .section \"__tracepoints_ptrs\", \"a\" \n" \
|
|
||||||
" .balign 4 \n" \
|
|
||||||
" .long __tracepoint_" #name " - . \n" \
|
|
||||||
" .previous \n")
|
|
||||||
#else
|
|
||||||
#define __TRACEPOINT_ENTRY(name) \
|
|
||||||
static struct tracepoint * const __tracepoint_ptr_##name __used \
|
|
||||||
__attribute__((section("__tracepoints_ptrs"))) = \
|
|
||||||
&__tracepoint_##name
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have no guarantee that gcc and the linker won't up-align the tracepoint
|
* We have no guarantee that gcc and the linker won't up-align the tracepoint
|
||||||
* structures, so we create an array of pointers that will be used for iteration
|
* structures, so we create an array of pointers that will be used for iteration
|
||||||
|
|
|
@ -28,8 +28,8 @@
|
||||||
#include <linux/sched/task.h>
|
#include <linux/sched/task.h>
|
||||||
#include <linux/static_key.h>
|
#include <linux/static_key.h>
|
||||||
|
|
||||||
extern struct tracepoint * const __start___tracepoints_ptrs[];
|
extern tracepoint_ptr_t __start___tracepoints_ptrs[];
|
||||||
extern struct tracepoint * const __stop___tracepoints_ptrs[];
|
extern tracepoint_ptr_t __stop___tracepoints_ptrs[];
|
||||||
|
|
||||||
DEFINE_SRCU(tracepoint_srcu);
|
DEFINE_SRCU(tracepoint_srcu);
|
||||||
EXPORT_SYMBOL_GPL(tracepoint_srcu);
|
EXPORT_SYMBOL_GPL(tracepoint_srcu);
|
||||||
|
@ -371,25 +371,17 @@ int tracepoint_probe_unregister(struct tracepoint *tp, void *probe, void *data)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(tracepoint_probe_unregister);
|
EXPORT_SYMBOL_GPL(tracepoint_probe_unregister);
|
||||||
|
|
||||||
static void for_each_tracepoint_range(struct tracepoint * const *begin,
|
static void for_each_tracepoint_range(
|
||||||
struct tracepoint * const *end,
|
tracepoint_ptr_t *begin, tracepoint_ptr_t *end,
|
||||||
void (*fct)(struct tracepoint *tp, void *priv),
|
void (*fct)(struct tracepoint *tp, void *priv),
|
||||||
void *priv)
|
void *priv)
|
||||||
{
|
{
|
||||||
|
tracepoint_ptr_t *iter;
|
||||||
|
|
||||||
if (!begin)
|
if (!begin)
|
||||||
return;
|
return;
|
||||||
|
for (iter = begin; iter < end; iter++)
|
||||||
if (IS_ENABLED(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)) {
|
fct(tracepoint_ptr_deref(iter), priv);
|
||||||
const int *iter;
|
|
||||||
|
|
||||||
for (iter = (const int *)begin; iter < (const int *)end; iter++)
|
|
||||||
fct(offset_to_ptr(iter), priv);
|
|
||||||
} else {
|
|
||||||
struct tracepoint * const *iter;
|
|
||||||
|
|
||||||
for (iter = begin; iter < end; iter++)
|
|
||||||
fct(*iter, priv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_MODULES
|
#ifdef CONFIG_MODULES
|
||||||
|
|
Loading…
Reference in New Issue
Block a user