All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH for 4.19] tracepoint: Fix: out-of-bound tracepoint array iteration
@ 2018-10-12 20:05 Mathieu Desnoyers
  2018-10-12 20:18 ` Mathieu Desnoyers
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Mathieu Desnoyers @ 2018-10-12 20:05 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: linux-kernel, Mathieu Desnoyers, Michael Ellerman, Ingo Molnar,
	Ard Biesheuvel, Arnd Bergmann, Benjamin Herrenschmidt,
	Bjorn Helgaas, Catalin Marinas, James Morris, James Morris,
	Jessica Yu, Josh Poimboeuf, Kees Cook, Nicolas Pitre,
	Paul Mackerras, Petr Mladek, Russell King, Serge E. Hallyn,
	Sergey Senozhatsky, Thomas Garnier, Thomas Gleixner, Will Deacon,
	Andrew Morton, Linus Torvalds, Greg Kroah-Hartman

commit 46e0c9be206f ("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:

tracepoint_module_{coming,going} invoke
tp_module_going_check_quiescent() with mod->tracepoints_ptrs
as first argument, and computes the end address of the array
for the second argument with:

  mod->tracepoints_ptrs + mod->num_tracepoints

However, because the type of mod->tracepoint_ptrs in module.h
has not been changed from pointer to int, it passes an end
pointer which is twice larger than the array, causing out-of-bound
array accesses.

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.

Signed-off-by: Mathieu Desnoyers <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: Steven Rostedt (VMware) <rostedt@goodmis.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: Jessica Yu <jeyu@kernel.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>
---
 include/linux/module.h          |  2 +-
 include/linux/tracepoint-defs.h |  6 ++++++
 include/linux/tracepoint.h      | 36 +++++++++++++++++++++------------
 kernel/tracepoint.c             | 24 ++++++++--------------
 4 files changed, 38 insertions(+), 30 deletions(-)

diff --git a/include/linux/module.h b/include/linux/module.h
index f807f15bebbe..cdab2451d6be 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -430,7 +430,7 @@ struct module {
 
 #ifdef CONFIG_TRACEPOINTS
 	unsigned int num_tracepoints;
-	struct tracepoint * const *tracepoints_ptrs;
+	tracepoint_ptr_t *tracepoints_ptrs;
 #endif
 #ifdef HAVE_JUMP_LABEL
 	struct jump_entry *jump_entries;
diff --git a/include/linux/tracepoint-defs.h b/include/linux/tracepoint-defs.h
index 22c5a46e9693..49ba9cde7e4b 100644
--- a/include/linux/tracepoint-defs.h
+++ b/include/linux/tracepoint-defs.h
@@ -35,6 +35,12 @@ struct tracepoint {
 	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 tracepoint	*tp;
 	void			*bpf_func;
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
index 041f7e56a289..538ba1a58f5b 100644
--- a/include/linux/tracepoint.h
+++ b/include/linux/tracepoint.h
@@ -99,6 +99,29 @@ extern void syscall_unregfunc(void);
 #define TRACE_DEFINE_ENUM(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 */
 
 /*
@@ -253,19 +276,6 @@ extern void syscall_unregfunc(void);
 		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
  * structures, so we create an array of pointers that will be used for iteration
diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
index bf2c06ef9afc..a3be42304485 100644
--- a/kernel/tracepoint.c
+++ b/kernel/tracepoint.c
@@ -28,8 +28,8 @@
 #include <linux/sched/task.h>
 #include <linux/static_key.h>
 
-extern struct tracepoint * const __start___tracepoints_ptrs[];
-extern struct tracepoint * const __stop___tracepoints_ptrs[];
+extern tracepoint_ptr_t __start___tracepoints_ptrs[];
+extern tracepoint_ptr_t __stop___tracepoints_ptrs[];
 
 DEFINE_SRCU(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);
 
-static void for_each_tracepoint_range(struct tracepoint * const *begin,
-		struct tracepoint * const *end,
+static void for_each_tracepoint_range(
+		tracepoint_ptr_t *begin, tracepoint_ptr_t *end,
 		void (*fct)(struct tracepoint *tp, void *priv),
 		void *priv)
 {
+	tracepoint_ptr_t *iter;
+
 	if (!begin)
 		return;
-
-	if (IS_ENABLED(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)) {
-		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);
-	}
+	for (iter = begin; iter < end; iter++)
+		fct(tracepoint_ptr_deref(iter), priv);
 }
 
 #ifdef CONFIG_MODULES
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH for 4.19] tracepoint: Fix: out-of-bound tracepoint array iteration
  2018-10-12 20:05 [PATCH for 4.19] tracepoint: Fix: out-of-bound tracepoint array iteration Mathieu Desnoyers
@ 2018-10-12 20:18 ` Mathieu Desnoyers
  2018-10-12 21:07 ` Ard Biesheuvel
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Mathieu Desnoyers @ 2018-10-12 20:18 UTC (permalink / raw)
  To: rostedt
  Cc: linux-kernel, Michael Ellerman, Ingo Molnar, Ard Biesheuvel,
	Arnd Bergmann, Benjamin Herrenschmidt, Bjorn Helgaas,
	Catalin Marinas, James Morris, James Morris, Jessica Yu,
	Josh Poimboeuf, Kees Cook, Nicolas Pitre, Paul Mackerras,
	Petr Mladek, Russell King, ARM Linux, Serge E. Hallyn,
	Sergey Senozhatsky, Thomas Garnier, Thomas Gleixner, Will Deacon,
	Andrew Morton, Linus Torvalds, Greg Kroah-Hartman

----- On Oct 12, 2018, at 4:05 PM, Mathieu Desnoyers mathieu.desnoyers@efficios.com wrote:

> commit 46e0c9be206f ("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:

Actually, the above sentence should read:

"However, it does so without turning struct tracepoint * const into const int
elsewhere in the tracepoint code [...]" (I had mistakenly worded it "const int *").

Thanks,

Mathieu


> 
> tracepoint_module_{coming,going} invoke
> tp_module_going_check_quiescent() with mod->tracepoints_ptrs
> as first argument, and computes the end address of the array
> for the second argument with:
> 
>  mod->tracepoints_ptrs + mod->num_tracepoints
> 
> However, because the type of mod->tracepoint_ptrs in module.h
> has not been changed from pointer to int, it passes an end
> pointer which is twice larger than the array, causing out-of-bound
> array accesses.
> 
> 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.
> 
> Signed-off-by: Mathieu Desnoyers <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: Steven Rostedt (VMware) <rostedt@goodmis.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: Jessica Yu <jeyu@kernel.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>
> ---
> include/linux/module.h          |  2 +-
> include/linux/tracepoint-defs.h |  6 ++++++
> include/linux/tracepoint.h      | 36 +++++++++++++++++++++------------
> kernel/tracepoint.c             | 24 ++++++++--------------
> 4 files changed, 38 insertions(+), 30 deletions(-)
> 
> diff --git a/include/linux/module.h b/include/linux/module.h
> index f807f15bebbe..cdab2451d6be 100644
> --- a/include/linux/module.h
> +++ b/include/linux/module.h
> @@ -430,7 +430,7 @@ struct module {
> 
> #ifdef CONFIG_TRACEPOINTS
> 	unsigned int num_tracepoints;
> -	struct tracepoint * const *tracepoints_ptrs;
> +	tracepoint_ptr_t *tracepoints_ptrs;
> #endif
> #ifdef HAVE_JUMP_LABEL
> 	struct jump_entry *jump_entries;
> diff --git a/include/linux/tracepoint-defs.h b/include/linux/tracepoint-defs.h
> index 22c5a46e9693..49ba9cde7e4b 100644
> --- a/include/linux/tracepoint-defs.h
> +++ b/include/linux/tracepoint-defs.h
> @@ -35,6 +35,12 @@ struct tracepoint {
> 	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 tracepoint	*tp;
> 	void			*bpf_func;
> diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
> index 041f7e56a289..538ba1a58f5b 100644
> --- a/include/linux/tracepoint.h
> +++ b/include/linux/tracepoint.h
> @@ -99,6 +99,29 @@ extern void syscall_unregfunc(void);
> #define TRACE_DEFINE_ENUM(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 */
> 
> /*
> @@ -253,19 +276,6 @@ extern void syscall_unregfunc(void);
> 		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
>  * structures, so we create an array of pointers that will be used for iteration
> diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
> index bf2c06ef9afc..a3be42304485 100644
> --- a/kernel/tracepoint.c
> +++ b/kernel/tracepoint.c
> @@ -28,8 +28,8 @@
> #include <linux/sched/task.h>
> #include <linux/static_key.h>
> 
> -extern struct tracepoint * const __start___tracepoints_ptrs[];
> -extern struct tracepoint * const __stop___tracepoints_ptrs[];
> +extern tracepoint_ptr_t __start___tracepoints_ptrs[];
> +extern tracepoint_ptr_t __stop___tracepoints_ptrs[];
> 
> DEFINE_SRCU(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);
> 
> -static void for_each_tracepoint_range(struct tracepoint * const *begin,
> -		struct tracepoint * const *end,
> +static void for_each_tracepoint_range(
> +		tracepoint_ptr_t *begin, tracepoint_ptr_t *end,
> 		void (*fct)(struct tracepoint *tp, void *priv),
> 		void *priv)
> {
> +	tracepoint_ptr_t *iter;
> +
> 	if (!begin)
> 		return;
> -
> -	if (IS_ENABLED(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)) {
> -		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);
> -	}
> +	for (iter = begin; iter < end; iter++)
> +		fct(tracepoint_ptr_deref(iter), priv);
> }
> 
> #ifdef CONFIG_MODULES
> --
> 2.17.1

-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH for 4.19] tracepoint: Fix: out-of-bound tracepoint array iteration
  2018-10-12 20:05 [PATCH for 4.19] tracepoint: Fix: out-of-bound tracepoint array iteration Mathieu Desnoyers
  2018-10-12 20:18 ` Mathieu Desnoyers
@ 2018-10-12 21:07 ` Ard Biesheuvel
  2018-10-13 15:24   ` Ard Biesheuvel
  2018-10-13  2:08 ` kbuild test robot
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Ard Biesheuvel @ 2018-10-12 21:07 UTC (permalink / raw)
  To: Mathieu Desnoyers
  Cc: Steven Rostedt, Linux Kernel Mailing List, Michael Ellerman,
	Ingo Molnar, Arnd Bergmann, Benjamin Herrenschmidt,
	Bjorn Helgaas, Catalin Marinas, James Morris, James Morris,
	Jessica Yu, Josh Poimboeuf, Kees Cook, Nicolas Pitre,
	Paul Mackerras, Petr Mladek, Russell King, Serge E. Hallyn,
	Sergey Senozhatsky, Thomas Garnier, Thomas Gleixner, Will Deacon,
	Andrew Morton, Linus Torvalds, Greg Kroah-Hartman

Hi Mathieu,

On 12 October 2018 at 22:05, Mathieu Desnoyers
<mathieu.desnoyers@efficios.com> wrote:
> commit 46e0c9be206f ("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:
>
> tracepoint_module_{coming,going} invoke
> tp_module_going_check_quiescent() with mod->tracepoints_ptrs
> as first argument, and computes the end address of the array
> for the second argument with:
>
>   mod->tracepoints_ptrs + mod->num_tracepoints
>
> However, because the type of mod->tracepoint_ptrs in module.h
> has not been changed from pointer to int, it passes an end
> pointer which is twice larger than the array, causing out-of-bound
> array accesses.
>
> 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.
>

Apologies for the breakage. FWIW, this looks like the correct approach
to me (and mirrors what I did for initcalls in the same series)

> This issue appears in 4.19-rc kernels, and should ideally be fixed
> before the end of the rc cycle.
>

+1

> Signed-off-by: Mathieu Desnoyers <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: Steven Rostedt (VMware) <rostedt@goodmis.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: Jessica Yu <jeyu@kernel.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>

Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

> ---
>  include/linux/module.h          |  2 +-
>  include/linux/tracepoint-defs.h |  6 ++++++
>  include/linux/tracepoint.h      | 36 +++++++++++++++++++++------------
>  kernel/tracepoint.c             | 24 ++++++++--------------
>  4 files changed, 38 insertions(+), 30 deletions(-)
>
> diff --git a/include/linux/module.h b/include/linux/module.h
> index f807f15bebbe..cdab2451d6be 100644
> --- a/include/linux/module.h
> +++ b/include/linux/module.h
> @@ -430,7 +430,7 @@ struct module {
>
>  #ifdef CONFIG_TRACEPOINTS
>         unsigned int num_tracepoints;
> -       struct tracepoint * const *tracepoints_ptrs;
> +       tracepoint_ptr_t *tracepoints_ptrs;
>  #endif
>  #ifdef HAVE_JUMP_LABEL
>         struct jump_entry *jump_entries;
> diff --git a/include/linux/tracepoint-defs.h b/include/linux/tracepoint-defs.h
> index 22c5a46e9693..49ba9cde7e4b 100644
> --- a/include/linux/tracepoint-defs.h
> +++ b/include/linux/tracepoint-defs.h
> @@ -35,6 +35,12 @@ struct tracepoint {
>         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 tracepoint       *tp;
>         void                    *bpf_func;
> diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
> index 041f7e56a289..538ba1a58f5b 100644
> --- a/include/linux/tracepoint.h
> +++ b/include/linux/tracepoint.h
> @@ -99,6 +99,29 @@ extern void syscall_unregfunc(void);
>  #define TRACE_DEFINE_ENUM(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 */
>
>  /*
> @@ -253,19 +276,6 @@ extern void syscall_unregfunc(void);
>                 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
>   * structures, so we create an array of pointers that will be used for iteration
> diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
> index bf2c06ef9afc..a3be42304485 100644
> --- a/kernel/tracepoint.c
> +++ b/kernel/tracepoint.c
> @@ -28,8 +28,8 @@
>  #include <linux/sched/task.h>
>  #include <linux/static_key.h>
>
> -extern struct tracepoint * const __start___tracepoints_ptrs[];
> -extern struct tracepoint * const __stop___tracepoints_ptrs[];
> +extern tracepoint_ptr_t __start___tracepoints_ptrs[];
> +extern tracepoint_ptr_t __stop___tracepoints_ptrs[];
>
>  DEFINE_SRCU(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);
>
> -static void for_each_tracepoint_range(struct tracepoint * const *begin,
> -               struct tracepoint * const *end,
> +static void for_each_tracepoint_range(
> +               tracepoint_ptr_t *begin, tracepoint_ptr_t *end,
>                 void (*fct)(struct tracepoint *tp, void *priv),
>                 void *priv)
>  {
> +       tracepoint_ptr_t *iter;
> +
>         if (!begin)
>                 return;
> -
> -       if (IS_ENABLED(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)) {
> -               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);
> -       }
> +       for (iter = begin; iter < end; iter++)
> +               fct(tracepoint_ptr_deref(iter), priv);
>  }
>
>  #ifdef CONFIG_MODULES
> --
> 2.17.1
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH for 4.19] tracepoint: Fix: out-of-bound tracepoint array iteration
  2018-10-12 20:05 [PATCH for 4.19] tracepoint: Fix: out-of-bound tracepoint array iteration Mathieu Desnoyers
  2018-10-12 20:18 ` Mathieu Desnoyers
  2018-10-12 21:07 ` Ard Biesheuvel
@ 2018-10-13  2:08 ` kbuild test robot
  2018-10-13  9:43 ` kbuild test robot
  2018-10-15 11:34 ` Jessica Yu
  4 siblings, 0 replies; 10+ messages in thread
From: kbuild test robot @ 2018-10-13  2:08 UTC (permalink / raw)
  To: Mathieu Desnoyers
  Cc: kbuild-all, Steven Rostedt, linux-kernel, Mathieu Desnoyers,
	Michael Ellerman, Ingo Molnar, Ard Biesheuvel, Arnd Bergmann,
	Benjamin Herrenschmidt, Bjorn Helgaas, Catalin Marinas,
	James Morris, James Morris, Jessica Yu, Josh Poimboeuf,
	Kees Cook, Nicolas Pitre, Paul Mackerras, Petr Mladek,
	Russell King, Serge E. Hallyn, Sergey Senozhatsky,
	Thomas Garnier, Thomas Gleixner, Will Deacon, Andrew Morton,
	Linus Torvalds, Greg Kroah-Hartman

[-- Attachment #1: Type: text/plain, Size: 1962 bytes --]

Hi Mathieu,

I love your patch! Yet something to improve:

[auto build test ERROR on tip/perf/core]
[also build test ERROR on v4.19-rc7 next-20181012]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Mathieu-Desnoyers/tracepoint-Fix-out-of-bound-tracepoint-array-iteration/20181013-073410
config: arm-allyesconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=7.2.0 make.cross ARCH=arm 

All errors (new ones prefixed by >>):

   In file included from drivers/media/media-devnode.c:33:0:
>> include/linux/module.h:433:2: error: unknown type name 'tracepoint_ptr_t'
     tracepoint_ptr_t *tracepoints_ptrs;
     ^~~~~~~~~~~~~~~~

vim +/tracepoint_ptr_t +433 include/linux/module.h

   430	
   431	#ifdef CONFIG_TRACEPOINTS
   432		unsigned int num_tracepoints;
 > 433		tracepoint_ptr_t *tracepoints_ptrs;
   434	#endif
   435	#ifdef HAVE_JUMP_LABEL
   436		struct jump_entry *jump_entries;
   437		unsigned int num_jump_entries;
   438	#endif
   439	#ifdef CONFIG_TRACING
   440		unsigned int num_trace_bprintk_fmt;
   441		const char **trace_bprintk_fmt_start;
   442	#endif
   443	#ifdef CONFIG_EVENT_TRACING
   444		struct trace_event_call **trace_events;
   445		unsigned int num_trace_events;
   446		struct trace_eval_map **trace_evals;
   447		unsigned int num_trace_evals;
   448	#endif
   449	#ifdef CONFIG_FTRACE_MCOUNT_RECORD
   450		unsigned int num_ftrace_callsites;
   451		unsigned long *ftrace_callsites;
   452	#endif
   453	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 66613 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH for 4.19] tracepoint: Fix: out-of-bound tracepoint array iteration
  2018-10-12 20:05 [PATCH for 4.19] tracepoint: Fix: out-of-bound tracepoint array iteration Mathieu Desnoyers
                   ` (2 preceding siblings ...)
  2018-10-13  2:08 ` kbuild test robot
@ 2018-10-13  9:43 ` kbuild test robot
  2018-10-15 11:34 ` Jessica Yu
  4 siblings, 0 replies; 10+ messages in thread
From: kbuild test robot @ 2018-10-13  9:43 UTC (permalink / raw)
  To: Mathieu Desnoyers
  Cc: kbuild-all, Steven Rostedt, linux-kernel, Mathieu Desnoyers,
	Michael Ellerman, Ingo Molnar, Ard Biesheuvel, Arnd Bergmann,
	Benjamin Herrenschmidt, Bjorn Helgaas, Catalin Marinas,
	James Morris, James Morris, Jessica Yu, Josh Poimboeuf,
	Kees Cook, Nicolas Pitre, Paul Mackerras, Petr Mladek,
	Russell King, Serge E. Hallyn, Sergey Senozhatsky,
	Thomas Garnier, Thomas Gleixner, Will Deacon, Andrew Morton,
	Linus Torvalds, Greg Kroah-Hartman

[-- Attachment #1: Type: text/plain, Size: 5137 bytes --]

Hi Mathieu,

I love your patch! Yet something to improve:

[auto build test ERROR on tip/perf/core]
[also build test ERROR on v4.19-rc7 next-20181012]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Mathieu-Desnoyers/tracepoint-Fix-out-of-bound-tracepoint-array-iteration/20181013-073410
config: arm-allyesconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=7.2.0 make.cross ARCH=arm 

All errors (new ones prefixed by >>):

   In file included from kernel/tracepoint.c:18:0:
   include/linux/module.h:433:2: error: unknown type name 'tracepoint_ptr_t'
     tracepoint_ptr_t *tracepoints_ptrs;
     ^~~~~~~~~~~~~~~~
   kernel/tracepoint.c: In function 'tracepoint_module_going':
>> kernel/tracepoint.c:504:30: error: passing argument 1 of 'for_each_tracepoint_range' from incompatible pointer type [-Werror=incompatible-pointer-types]
       for_each_tracepoint_range(mod->tracepoints_ptrs,
                                 ^~~
   kernel/tracepoint.c:374:13: note: expected 'struct tracepoint * const*' but argument is of type 'int *'
    static void for_each_tracepoint_range(
                ^~~~~~~~~~~~~~~~~~~~~~~~~
   kernel/tracepoint.c:505:5: error: passing argument 2 of 'for_each_tracepoint_range' from incompatible pointer type [-Werror=incompatible-pointer-types]
        mod->tracepoints_ptrs + mod->num_tracepoints,
        ^~~
   kernel/tracepoint.c:374:13: note: expected 'struct tracepoint * const*' but argument is of type 'int *'
    static void for_each_tracepoint_range(
                ^~~~~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors

vim +/for_each_tracepoint_range +504 kernel/tracepoint.c

b75ef8b44 Mathieu Desnoyers        2011-08-10  485  
de7b29739 Mathieu Desnoyers        2014-04-08  486  static void tracepoint_module_going(struct module *mod)
b75ef8b44 Mathieu Desnoyers        2011-08-10  487  {
de7b29739 Mathieu Desnoyers        2014-04-08  488  	struct tp_module *tp_mod;
b75ef8b44 Mathieu Desnoyers        2011-08-10  489  
7dec935a3 Steven Rostedt (Red Hat  2014-02-26  490) 	if (!mod->num_tracepoints)
de7b29739 Mathieu Desnoyers        2014-04-08  491  		return;
7dec935a3 Steven Rostedt (Red Hat  2014-02-26  492) 
de7b29739 Mathieu Desnoyers        2014-04-08  493  	mutex_lock(&tracepoint_module_list_mutex);
de7b29739 Mathieu Desnoyers        2014-04-08  494  	list_for_each_entry(tp_mod, &tracepoint_module_list, list) {
eb7d035c5 Steven Rostedt (Red Hat  2014-04-08  495) 		if (tp_mod->mod == mod) {
de7b29739 Mathieu Desnoyers        2014-04-08  496  			blocking_notifier_call_chain(&tracepoint_notify_list,
de7b29739 Mathieu Desnoyers        2014-04-08  497  					MODULE_STATE_GOING, tp_mod);
de7b29739 Mathieu Desnoyers        2014-04-08  498  			list_del(&tp_mod->list);
de7b29739 Mathieu Desnoyers        2014-04-08  499  			kfree(tp_mod);
de7b29739 Mathieu Desnoyers        2014-04-08  500  			/*
de7b29739 Mathieu Desnoyers        2014-04-08  501  			 * Called the going notifier before checking for
de7b29739 Mathieu Desnoyers        2014-04-08  502  			 * quiescence.
de7b29739 Mathieu Desnoyers        2014-04-08  503  			 */
46e0c9be2 Ard Biesheuvel           2018-08-21 @504  			for_each_tracepoint_range(mod->tracepoints_ptrs,
46e0c9be2 Ard Biesheuvel           2018-08-21  505  				mod->tracepoints_ptrs + mod->num_tracepoints,
46e0c9be2 Ard Biesheuvel           2018-08-21  506  				tp_module_going_check_quiescent, NULL);
b75ef8b44 Mathieu Desnoyers        2011-08-10  507  			break;
b75ef8b44 Mathieu Desnoyers        2011-08-10  508  		}
b75ef8b44 Mathieu Desnoyers        2011-08-10  509  	}
b75ef8b44 Mathieu Desnoyers        2011-08-10  510  	/*
b75ef8b44 Mathieu Desnoyers        2011-08-10  511  	 * In the case of modules that were tainted at "coming", we'll simply
b75ef8b44 Mathieu Desnoyers        2011-08-10  512  	 * walk through the list without finding it. We cannot use the "tainted"
b75ef8b44 Mathieu Desnoyers        2011-08-10  513  	 * flag on "going", in case a module taints the kernel only after being
b75ef8b44 Mathieu Desnoyers        2011-08-10  514  	 * loaded.
b75ef8b44 Mathieu Desnoyers        2011-08-10  515  	 */
de7b29739 Mathieu Desnoyers        2014-04-08  516  	mutex_unlock(&tracepoint_module_list_mutex);
b75ef8b44 Mathieu Desnoyers        2011-08-10  517  }
227a83756 Ingo Molnar              2008-11-16  518  

:::::: The code at line 504 was first introduced by commit
:::::: 46e0c9be206fa7b11aca75da2d6b8535d0139752 kernel: tracepoints: add support for relative references

:::::: TO: Ard Biesheuvel <ard.biesheuvel@linaro.org>
:::::: CC: Linus Torvalds <torvalds@linux-foundation.org>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 66613 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH for 4.19] tracepoint: Fix: out-of-bound tracepoint array iteration
  2018-10-12 21:07 ` Ard Biesheuvel
@ 2018-10-13 15:24   ` Ard Biesheuvel
  2018-10-13 18:34     ` Mathieu Desnoyers
  0 siblings, 1 reply; 10+ messages in thread
From: Ard Biesheuvel @ 2018-10-13 15:24 UTC (permalink / raw)
  To: Mathieu Desnoyers
  Cc: Steven Rostedt, Linux Kernel Mailing List, Michael Ellerman,
	Ingo Molnar, Arnd Bergmann, Benjamin Herrenschmidt,
	Bjorn Helgaas, Catalin Marinas, James Morris, James Morris,
	Jessica Yu, Josh Poimboeuf, Kees Cook, Nicolas Pitre,
	Paul Mackerras, Petr Mladek, Russell King, Serge E. Hallyn,
	Sergey Senozhatsky, Thomas Garnier, Thomas Gleixner, Will Deacon,
	Andrew Morton, Linus Torvalds, Greg Kroah-Hartman

On 12 October 2018 at 23:07, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> Hi Mathieu,
>
> On 12 October 2018 at 22:05, Mathieu Desnoyers
> <mathieu.desnoyers@efficios.com> wrote:
>> commit 46e0c9be206f ("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:
>>
>> tracepoint_module_{coming,going} invoke
>> tp_module_going_check_quiescent() with mod->tracepoints_ptrs
>> as first argument, and computes the end address of the array
>> for the second argument with:
>>
>>   mod->tracepoints_ptrs + mod->num_tracepoints
>>
>> However, because the type of mod->tracepoint_ptrs in module.h
>> has not been changed from pointer to int, it passes an end
>> pointer which is twice larger than the array, causing out-of-bound
>> array accesses.
>>
>> 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.
>>
>
> Apologies for the breakage. FWIW, this looks like the correct approach
> to me (and mirrors what I did for initcalls in the same series)
>
>> This issue appears in 4.19-rc kernels, and should ideally be fixed
>> before the end of the rc cycle.
>>
>
> +1
>
>> Signed-off-by: Mathieu Desnoyers <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: Steven Rostedt (VMware) <rostedt@goodmis.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: Jessica Yu <jeyu@kernel.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>
>
> Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>

This fixes the build breakage for me that kbuild test robot reports.

diff --git a/include/linux/module.h b/include/linux/module.h
index cdab2451d6be..e19ae08c7fb8 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -20,6 +20,7 @@
 #include <linux/export.h>
 #include <linux/rbtree_latch.h>
 #include <linux/error-injection.h>
+#include <linux/tracepoint-defs.h>

 #include <linux/percpu.h>
 #include <asm/module.h>





>> ---
>>  include/linux/module.h          |  2 +-
>>  include/linux/tracepoint-defs.h |  6 ++++++
>>  include/linux/tracepoint.h      | 36 +++++++++++++++++++++------------
>>  kernel/tracepoint.c             | 24 ++++++++--------------
>>  4 files changed, 38 insertions(+), 30 deletions(-)
>>
>> diff --git a/include/linux/module.h b/include/linux/module.h
>> index f807f15bebbe..cdab2451d6be 100644
>> --- a/include/linux/module.h
>> +++ b/include/linux/module.h
>> @@ -430,7 +430,7 @@ struct module {
>>
>>  #ifdef CONFIG_TRACEPOINTS
>>         unsigned int num_tracepoints;
>> -       struct tracepoint * const *tracepoints_ptrs;
>> +       tracepoint_ptr_t *tracepoints_ptrs;
>>  #endif
>>  #ifdef HAVE_JUMP_LABEL
>>         struct jump_entry *jump_entries;
>> diff --git a/include/linux/tracepoint-defs.h b/include/linux/tracepoint-defs.h
>> index 22c5a46e9693..49ba9cde7e4b 100644
>> --- a/include/linux/tracepoint-defs.h
>> +++ b/include/linux/tracepoint-defs.h
>> @@ -35,6 +35,12 @@ struct tracepoint {
>>         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 tracepoint       *tp;
>>         void                    *bpf_func;
>> diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
>> index 041f7e56a289..538ba1a58f5b 100644
>> --- a/include/linux/tracepoint.h
>> +++ b/include/linux/tracepoint.h
>> @@ -99,6 +99,29 @@ extern void syscall_unregfunc(void);
>>  #define TRACE_DEFINE_ENUM(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 */
>>
>>  /*
>> @@ -253,19 +276,6 @@ extern void syscall_unregfunc(void);
>>                 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
>>   * structures, so we create an array of pointers that will be used for iteration
>> diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
>> index bf2c06ef9afc..a3be42304485 100644
>> --- a/kernel/tracepoint.c
>> +++ b/kernel/tracepoint.c
>> @@ -28,8 +28,8 @@
>>  #include <linux/sched/task.h>
>>  #include <linux/static_key.h>
>>
>> -extern struct tracepoint * const __start___tracepoints_ptrs[];
>> -extern struct tracepoint * const __stop___tracepoints_ptrs[];
>> +extern tracepoint_ptr_t __start___tracepoints_ptrs[];
>> +extern tracepoint_ptr_t __stop___tracepoints_ptrs[];
>>
>>  DEFINE_SRCU(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);
>>
>> -static void for_each_tracepoint_range(struct tracepoint * const *begin,
>> -               struct tracepoint * const *end,
>> +static void for_each_tracepoint_range(
>> +               tracepoint_ptr_t *begin, tracepoint_ptr_t *end,
>>                 void (*fct)(struct tracepoint *tp, void *priv),
>>                 void *priv)
>>  {
>> +       tracepoint_ptr_t *iter;
>> +
>>         if (!begin)
>>                 return;
>> -
>> -       if (IS_ENABLED(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)) {
>> -               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);
>> -       }
>> +       for (iter = begin; iter < end; iter++)
>> +               fct(tracepoint_ptr_deref(iter), priv);
>>  }
>>
>>  #ifdef CONFIG_MODULES
>> --
>> 2.17.1
>>

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH for 4.19] tracepoint: Fix: out-of-bound tracepoint array iteration
  2018-10-13 15:24   ` Ard Biesheuvel
@ 2018-10-13 18:34     ` Mathieu Desnoyers
  2018-10-13 19:05       ` Mathieu Desnoyers
  0 siblings, 1 reply; 10+ messages in thread
From: Mathieu Desnoyers @ 2018-10-13 18:34 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: rostedt, linux-kernel, Michael Ellerman, Ingo Molnar,
	Arnd Bergmann, Benjamin Herrenschmidt, Bjorn Helgaas,
	Catalin Marinas, James Morris, James Morris, Jessica Yu,
	Josh Poimboeuf, Kees Cook, Nicolas Pitre, Paul Mackerras,
	Petr Mladek, Russell King, ARM Linux, Serge E. Hallyn,
	Sergey Senozhatsky, Thomas Garnier, Thomas Gleixner, Will Deacon,
	Andrew Morton, Linus Torvalds, Greg Kroah-Hartman

----- On Oct 13, 2018, at 11:24 AM, Ard Biesheuvel ard.biesheuvel@linaro.org wrote:

> On 12 October 2018 at 23:07, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>> Hi Mathieu,
>>
>> On 12 October 2018 at 22:05, Mathieu Desnoyers
>> <mathieu.desnoyers@efficios.com> wrote:
>>> commit 46e0c9be206f ("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:
>>>
>>> tracepoint_module_{coming,going} invoke
>>> tp_module_going_check_quiescent() with mod->tracepoints_ptrs
>>> as first argument, and computes the end address of the array
>>> for the second argument with:
>>>
>>>   mod->tracepoints_ptrs + mod->num_tracepoints
>>>
>>> However, because the type of mod->tracepoint_ptrs in module.h
>>> has not been changed from pointer to int, it passes an end
>>> pointer which is twice larger than the array, causing out-of-bound
>>> array accesses.
>>>
>>> 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.
>>>
>>
>> Apologies for the breakage. FWIW, this looks like the correct approach
>> to me (and mirrors what I did for initcalls in the same series)
>>
>>> This issue appears in 4.19-rc kernels, and should ideally be fixed
>>> before the end of the rc cycle.
>>>
>>
>> +1
>>
>>> Signed-off-by: Mathieu Desnoyers <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: Steven Rostedt (VMware) <rostedt@goodmis.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: Jessica Yu <jeyu@kernel.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>
>>
>> Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>>
> 
> This fixes the build breakage for me that kbuild test robot reports.
> 
> diff --git a/include/linux/module.h b/include/linux/module.h
> index cdab2451d6be..e19ae08c7fb8 100644
> --- a/include/linux/module.h
> +++ b/include/linux/module.h
> @@ -20,6 +20,7 @@
> #include <linux/export.h>
> #include <linux/rbtree_latch.h>
> #include <linux/error-injection.h>
> +#include <linux/tracepoint-defs.h>

You've beat me to it :) I'll fold this change in a v2 of the patch,

Thanks!

Mathieu

> 
> #include <linux/percpu.h>
> #include <asm/module.h>
> 
> 
> 
> 
> 
>>> ---
>>>  include/linux/module.h          |  2 +-
>>>  include/linux/tracepoint-defs.h |  6 ++++++
>>>  include/linux/tracepoint.h      | 36 +++++++++++++++++++++------------
>>>  kernel/tracepoint.c             | 24 ++++++++--------------
>>>  4 files changed, 38 insertions(+), 30 deletions(-)
>>>
>>> diff --git a/include/linux/module.h b/include/linux/module.h
>>> index f807f15bebbe..cdab2451d6be 100644
>>> --- a/include/linux/module.h
>>> +++ b/include/linux/module.h
>>> @@ -430,7 +430,7 @@ struct module {
>>>
>>>  #ifdef CONFIG_TRACEPOINTS
>>>         unsigned int num_tracepoints;
>>> -       struct tracepoint * const *tracepoints_ptrs;
>>> +       tracepoint_ptr_t *tracepoints_ptrs;
>>>  #endif
>>>  #ifdef HAVE_JUMP_LABEL
>>>         struct jump_entry *jump_entries;
>>> diff --git a/include/linux/tracepoint-defs.h b/include/linux/tracepoint-defs.h
>>> index 22c5a46e9693..49ba9cde7e4b 100644
>>> --- a/include/linux/tracepoint-defs.h
>>> +++ b/include/linux/tracepoint-defs.h
>>> @@ -35,6 +35,12 @@ struct tracepoint {
>>>         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 tracepoint       *tp;
>>>         void                    *bpf_func;
>>> diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
>>> index 041f7e56a289..538ba1a58f5b 100644
>>> --- a/include/linux/tracepoint.h
>>> +++ b/include/linux/tracepoint.h
>>> @@ -99,6 +99,29 @@ extern void syscall_unregfunc(void);
>>>  #define TRACE_DEFINE_ENUM(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 */
>>>
>>>  /*
>>> @@ -253,19 +276,6 @@ extern void syscall_unregfunc(void);
>>>                 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
>>>   * structures, so we create an array of pointers that will be used for iteration
>>> diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
>>> index bf2c06ef9afc..a3be42304485 100644
>>> --- a/kernel/tracepoint.c
>>> +++ b/kernel/tracepoint.c
>>> @@ -28,8 +28,8 @@
>>>  #include <linux/sched/task.h>
>>>  #include <linux/static_key.h>
>>>
>>> -extern struct tracepoint * const __start___tracepoints_ptrs[];
>>> -extern struct tracepoint * const __stop___tracepoints_ptrs[];
>>> +extern tracepoint_ptr_t __start___tracepoints_ptrs[];
>>> +extern tracepoint_ptr_t __stop___tracepoints_ptrs[];
>>>
>>>  DEFINE_SRCU(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);
>>>
>>> -static void for_each_tracepoint_range(struct tracepoint * const *begin,
>>> -               struct tracepoint * const *end,
>>> +static void for_each_tracepoint_range(
>>> +               tracepoint_ptr_t *begin, tracepoint_ptr_t *end,
>>>                 void (*fct)(struct tracepoint *tp, void *priv),
>>>                 void *priv)
>>>  {
>>> +       tracepoint_ptr_t *iter;
>>> +
>>>         if (!begin)
>>>                 return;
>>> -
>>> -       if (IS_ENABLED(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)) {
>>> -               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);
>>> -       }
>>> +       for (iter = begin; iter < end; iter++)
>>> +               fct(tracepoint_ptr_deref(iter), priv);
>>>  }
>>>
>>>  #ifdef CONFIG_MODULES
>>> --
>>> 2.17.1

-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH for 4.19] tracepoint: Fix: out-of-bound tracepoint array iteration
  2018-10-13 18:34     ` Mathieu Desnoyers
@ 2018-10-13 19:05       ` Mathieu Desnoyers
  0 siblings, 0 replies; 10+ messages in thread
From: Mathieu Desnoyers @ 2018-10-13 19:05 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: rostedt, linux-kernel, Michael Ellerman, Ingo Molnar,
	Arnd Bergmann, Benjamin Herrenschmidt, Bjorn Helgaas,
	Catalin Marinas, James Morris, James Morris, Jessica Yu,
	Josh Poimboeuf, Kees Cook, Nicolas Pitre, Paul Mackerras,
	Petr Mladek, Russell King, ARM Linux, Serge E. Hallyn,
	Sergey Senozhatsky, Thomas Garnier, Thomas Gleixner, Will Deacon,
	Andrew Morton, Linus Torvalds, Greg Kroah-Hartman

----- On Oct 13, 2018, at 2:34 PM, Mathieu Desnoyers mathieu.desnoyers@efficios.com wrote:

> ----- On Oct 13, 2018, at 11:24 AM, Ard Biesheuvel ard.biesheuvel@linaro.org
> wrote:
> 
>> On 12 October 2018 at 23:07, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>>> Hi Mathieu,
>>>
>>> On 12 October 2018 at 22:05, Mathieu Desnoyers
>>> <mathieu.desnoyers@efficios.com> wrote:
>>>> commit 46e0c9be206f ("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:
>>>>
>>>> tracepoint_module_{coming,going} invoke
>>>> tp_module_going_check_quiescent() with mod->tracepoints_ptrs
>>>> as first argument, and computes the end address of the array
>>>> for the second argument with:
>>>>
>>>>   mod->tracepoints_ptrs + mod->num_tracepoints
>>>>
>>>> However, because the type of mod->tracepoint_ptrs in module.h
>>>> has not been changed from pointer to int, it passes an end
>>>> pointer which is twice larger than the array, causing out-of-bound
>>>> array accesses.
>>>>
>>>> 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.
>>>>
>>>
>>> Apologies for the breakage. FWIW, this looks like the correct approach
>>> to me (and mirrors what I did for initcalls in the same series)
>>>
>>>> This issue appears in 4.19-rc kernels, and should ideally be fixed
>>>> before the end of the rc cycle.
>>>>
>>>
>>> +1
>>>
>>>> Signed-off-by: Mathieu Desnoyers <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: Steven Rostedt (VMware) <rostedt@goodmis.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: Jessica Yu <jeyu@kernel.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>
>>>
>>> Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>>>
>> 
>> This fixes the build breakage for me that kbuild test robot reports.
>> 
>> diff --git a/include/linux/module.h b/include/linux/module.h
>> index cdab2451d6be..e19ae08c7fb8 100644
>> --- a/include/linux/module.h
>> +++ b/include/linux/module.h
>> @@ -20,6 +20,7 @@
>> #include <linux/export.h>
>> #include <linux/rbtree_latch.h>
>> #include <linux/error-injection.h>
>> +#include <linux/tracepoint-defs.h>
> 
> You've beat me to it :) I'll fold this change in a v2 of the patch,

Digging a bit deeper into module.c, I notice it's not really an
out-of-bound access that is generated by this issue, because
setting mod->num_tracepoints is done in by module.c like this:

        mod->tracepoints_ptrs = section_objs(info, "__tracepoints_ptrs",
                                             sizeof(*mod->tracepoints_ptrs),
                                             &mod->num_tracepoints);

So 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 we an odd number of tracepoints, we
lose 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.

So I'll also update the patch changelog in v2. Given it does not change
the patch content, I'll keep your acked-by. Please let me know if you
spot anything.

Thanks,

Mathieu



> 
> Thanks!
> 
> Mathieu
> 
>> 
>> #include <linux/percpu.h>
>> #include <asm/module.h>
>> 
>> 
>> 
>> 
>> 
>>>> ---
>>>>  include/linux/module.h          |  2 +-
>>>>  include/linux/tracepoint-defs.h |  6 ++++++
>>>>  include/linux/tracepoint.h      | 36 +++++++++++++++++++++------------
>>>>  kernel/tracepoint.c             | 24 ++++++++--------------
>>>>  4 files changed, 38 insertions(+), 30 deletions(-)
>>>>
>>>> diff --git a/include/linux/module.h b/include/linux/module.h
>>>> index f807f15bebbe..cdab2451d6be 100644
>>>> --- a/include/linux/module.h
>>>> +++ b/include/linux/module.h
>>>> @@ -430,7 +430,7 @@ struct module {
>>>>
>>>>  #ifdef CONFIG_TRACEPOINTS
>>>>         unsigned int num_tracepoints;
>>>> -       struct tracepoint * const *tracepoints_ptrs;
>>>> +       tracepoint_ptr_t *tracepoints_ptrs;
>>>>  #endif
>>>>  #ifdef HAVE_JUMP_LABEL
>>>>         struct jump_entry *jump_entries;
>>>> diff --git a/include/linux/tracepoint-defs.h b/include/linux/tracepoint-defs.h
>>>> index 22c5a46e9693..49ba9cde7e4b 100644
>>>> --- a/include/linux/tracepoint-defs.h
>>>> +++ b/include/linux/tracepoint-defs.h
>>>> @@ -35,6 +35,12 @@ struct tracepoint {
>>>>         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 tracepoint       *tp;
>>>>         void                    *bpf_func;
>>>> diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
>>>> index 041f7e56a289..538ba1a58f5b 100644
>>>> --- a/include/linux/tracepoint.h
>>>> +++ b/include/linux/tracepoint.h
>>>> @@ -99,6 +99,29 @@ extern void syscall_unregfunc(void);
>>>>  #define TRACE_DEFINE_ENUM(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 */
>>>>
>>>>  /*
>>>> @@ -253,19 +276,6 @@ extern void syscall_unregfunc(void);
>>>>                 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
>>>>   * structures, so we create an array of pointers that will be used for iteration
>>>> diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
>>>> index bf2c06ef9afc..a3be42304485 100644
>>>> --- a/kernel/tracepoint.c
>>>> +++ b/kernel/tracepoint.c
>>>> @@ -28,8 +28,8 @@
>>>>  #include <linux/sched/task.h>
>>>>  #include <linux/static_key.h>
>>>>
>>>> -extern struct tracepoint * const __start___tracepoints_ptrs[];
>>>> -extern struct tracepoint * const __stop___tracepoints_ptrs[];
>>>> +extern tracepoint_ptr_t __start___tracepoints_ptrs[];
>>>> +extern tracepoint_ptr_t __stop___tracepoints_ptrs[];
>>>>
>>>>  DEFINE_SRCU(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);
>>>>
>>>> -static void for_each_tracepoint_range(struct tracepoint * const *begin,
>>>> -               struct tracepoint * const *end,
>>>> +static void for_each_tracepoint_range(
>>>> +               tracepoint_ptr_t *begin, tracepoint_ptr_t *end,
>>>>                 void (*fct)(struct tracepoint *tp, void *priv),
>>>>                 void *priv)
>>>>  {
>>>> +       tracepoint_ptr_t *iter;
>>>> +
>>>>         if (!begin)
>>>>                 return;
>>>> -
>>>> -       if (IS_ENABLED(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)) {
>>>> -               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);
>>>> -       }
>>>> +       for (iter = begin; iter < end; iter++)
>>>> +               fct(tracepoint_ptr_deref(iter), priv);
>>>>  }
>>>>
>>>>  #ifdef CONFIG_MODULES
>>>> --
>>>> 2.17.1
> 
> --
> Mathieu Desnoyers
> EfficiOS Inc.
> http://www.efficios.com

-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH for 4.19] tracepoint: Fix: out-of-bound tracepoint array iteration
  2018-10-12 20:05 [PATCH for 4.19] tracepoint: Fix: out-of-bound tracepoint array iteration Mathieu Desnoyers
                   ` (3 preceding siblings ...)
  2018-10-13  9:43 ` kbuild test robot
@ 2018-10-15 11:34 ` Jessica Yu
  2018-10-15 15:47   ` Steven Rostedt
  4 siblings, 1 reply; 10+ messages in thread
From: Jessica Yu @ 2018-10-15 11:34 UTC (permalink / raw)
  To: Mathieu Desnoyers
  Cc: Steven Rostedt, linux-kernel, Michael Ellerman, Ingo Molnar,
	Ard Biesheuvel, Arnd Bergmann, Benjamin Herrenschmidt,
	Bjorn Helgaas, Catalin Marinas, James Morris, James Morris,
	Josh Poimboeuf, Kees Cook, Nicolas Pitre, Paul Mackerras,
	Petr Mladek, Russell King, Serge E. Hallyn, Sergey Senozhatsky,
	Thomas Garnier, Thomas Gleixner, Will Deacon, Andrew Morton,
	Linus Torvalds, Greg Kroah-Hartman

+++ Mathieu Desnoyers [12/10/18 16:05 -0400]:
>commit 46e0c9be206f ("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:
>
>tracepoint_module_{coming,going} invoke
>tp_module_going_check_quiescent() with mod->tracepoints_ptrs
>as first argument, and computes the end address of the array
>for the second argument with:
>
>  mod->tracepoints_ptrs + mod->num_tracepoints
>
>However, because the type of mod->tracepoint_ptrs in module.h
>has not been changed from pointer to int, it passes an end
>pointer which is twice larger than the array, causing out-of-bound
>array accesses.
>
>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.
>
>Signed-off-by: Mathieu Desnoyers <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: Steven Rostedt (VMware) <rostedt@goodmis.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: Jessica Yu <jeyu@kernel.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>

For module parts:

Acked-by: Jessica Yu <jeyu@kernel.org>

>---
> include/linux/module.h          |  2 +-
> include/linux/tracepoint-defs.h |  6 ++++++
> include/linux/tracepoint.h      | 36 +++++++++++++++++++++------------
> kernel/tracepoint.c             | 24 ++++++++--------------
> 4 files changed, 38 insertions(+), 30 deletions(-)
>
>diff --git a/include/linux/module.h b/include/linux/module.h
>index f807f15bebbe..cdab2451d6be 100644
>--- a/include/linux/module.h
>+++ b/include/linux/module.h
>@@ -430,7 +430,7 @@ struct module {
>
> #ifdef CONFIG_TRACEPOINTS
> 	unsigned int num_tracepoints;
>-	struct tracepoint * const *tracepoints_ptrs;
>+	tracepoint_ptr_t *tracepoints_ptrs;
> #endif
> #ifdef HAVE_JUMP_LABEL
> 	struct jump_entry *jump_entries;
>diff --git a/include/linux/tracepoint-defs.h b/include/linux/tracepoint-defs.h
>index 22c5a46e9693..49ba9cde7e4b 100644
>--- a/include/linux/tracepoint-defs.h
>+++ b/include/linux/tracepoint-defs.h
>@@ -35,6 +35,12 @@ struct tracepoint {
> 	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 tracepoint	*tp;
> 	void			*bpf_func;
>diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
>index 041f7e56a289..538ba1a58f5b 100644
>--- a/include/linux/tracepoint.h
>+++ b/include/linux/tracepoint.h
>@@ -99,6 +99,29 @@ extern void syscall_unregfunc(void);
> #define TRACE_DEFINE_ENUM(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 */
>
> /*
>@@ -253,19 +276,6 @@ extern void syscall_unregfunc(void);
> 		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
>  * structures, so we create an array of pointers that will be used for iteration
>diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
>index bf2c06ef9afc..a3be42304485 100644
>--- a/kernel/tracepoint.c
>+++ b/kernel/tracepoint.c
>@@ -28,8 +28,8 @@
> #include <linux/sched/task.h>
> #include <linux/static_key.h>
>
>-extern struct tracepoint * const __start___tracepoints_ptrs[];
>-extern struct tracepoint * const __stop___tracepoints_ptrs[];
>+extern tracepoint_ptr_t __start___tracepoints_ptrs[];
>+extern tracepoint_ptr_t __stop___tracepoints_ptrs[];
>
> DEFINE_SRCU(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);
>
>-static void for_each_tracepoint_range(struct tracepoint * const *begin,
>-		struct tracepoint * const *end,
>+static void for_each_tracepoint_range(
>+		tracepoint_ptr_t *begin, tracepoint_ptr_t *end,
> 		void (*fct)(struct tracepoint *tp, void *priv),
> 		void *priv)
> {
>+	tracepoint_ptr_t *iter;
>+
> 	if (!begin)
> 		return;
>-
>-	if (IS_ENABLED(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)) {
>-		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);
>-	}
>+	for (iter = begin; iter < end; iter++)
>+		fct(tracepoint_ptr_deref(iter), priv);
> }
>
> #ifdef CONFIG_MODULES
>-- 
>2.17.1
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH for 4.19] tracepoint: Fix: out-of-bound tracepoint array iteration
  2018-10-15 11:34 ` Jessica Yu
@ 2018-10-15 15:47   ` Steven Rostedt
  0 siblings, 0 replies; 10+ messages in thread
From: Steven Rostedt @ 2018-10-15 15:47 UTC (permalink / raw)
  To: Jessica Yu
  Cc: Mathieu Desnoyers, linux-kernel, Michael Ellerman, Ingo Molnar,
	Ard Biesheuvel, Arnd Bergmann, Benjamin Herrenschmidt,
	Bjorn Helgaas, Catalin Marinas, James Morris, James Morris,
	Josh Poimboeuf, Kees Cook, Nicolas Pitre, Paul Mackerras,
	Petr Mladek, Russell King, Serge E. Hallyn, Sergey Senozhatsky,
	Thomas Garnier, Thomas Gleixner, Will Deacon, Andrew Morton,
	Linus Torvalds, Greg Kroah-Hartman

On Mon, 15 Oct 2018 13:34:33 +0200
Jessica Yu <jeyu@kernel.org> wrote:

> For module parts:
> 
> Acked-by: Jessica Yu <jeyu@kernel.org>

Thanks Jessica!

Mathieu, I'm going to pull this into my test queue and start running
tests on it. It should be ready by tomorrow, if none of the tests fail
(note, I'm testing more than one patch, so hopefully none of them fail).

-- Steve

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2018-10-15 15:47 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-12 20:05 [PATCH for 4.19] tracepoint: Fix: out-of-bound tracepoint array iteration Mathieu Desnoyers
2018-10-12 20:18 ` Mathieu Desnoyers
2018-10-12 21:07 ` Ard Biesheuvel
2018-10-13 15:24   ` Ard Biesheuvel
2018-10-13 18:34     ` Mathieu Desnoyers
2018-10-13 19:05       ` Mathieu Desnoyers
2018-10-13  2:08 ` kbuild test robot
2018-10-13  9:43 ` kbuild test robot
2018-10-15 11:34 ` Jessica Yu
2018-10-15 15:47   ` Steven Rostedt

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.