All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
To: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: rostedt <rostedt@goodmis.org>,
	linux-kernel <linux-kernel@vger.kernel.org>,
	Michael Ellerman <mpe@ellerman.id.au>,
	Ingo Molnar <mingo@kernel.org>, Arnd Bergmann <arnd@arndb.de>,
	Benjamin Herrenschmidt <benh@kernel.crashing.org>,
	Bjorn Helgaas <bhelgaas@google.com>,
	Catalin Marinas <catalin.marinas@arm.com>,
	James Morris <james.morris@microsoft.com>,
	James Morris <jmorris@namei.org>, Jessica Yu <jeyu@kernel.org>,
	Josh Poimboeuf <jpoimboe@redhat.com>,
	Kees Cook <keescook@chromium.org>,
	Nicolas Pitre <nico@linaro.org>,
	Paul Mackerras <paulus@samba.org>, Petr Mladek <pmladek@suse.com>,
	"Russell King, ARM Linux" <linux@armlinux.org.uk>,
	"Serge E. Hallyn" <serge@hallyn.com>,
	Sergey Senozhatsky <sergey.senozhatsky@gmail.com>,
	Thomas Garnier <thgarnie@google.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	Will Deacon <will.deacon@arm.com>,
	Andrew Morton <akpm@linux-foundation.org>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Subject: Re: [PATCH for 4.19] tracepoint: Fix: out-of-bound tracepoint array iteration
Date: Sat, 13 Oct 2018 15:05:51 -0400 (EDT)	[thread overview]
Message-ID: <733933348.3575.1539457551669.JavaMail.zimbra@efficios.com> (raw)
In-Reply-To: <1921357606.3547.1539455663932.JavaMail.zimbra@efficios.com>

----- 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

  reply	other threads:[~2018-10-13 19:05 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=733933348.3575.1539457551669.JavaMail.zimbra@efficios.com \
    --to=mathieu.desnoyers@efficios.com \
    --cc=akpm@linux-foundation.org \
    --cc=ard.biesheuvel@linaro.org \
    --cc=arnd@arndb.de \
    --cc=benh@kernel.crashing.org \
    --cc=bhelgaas@google.com \
    --cc=catalin.marinas@arm.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=james.morris@microsoft.com \
    --cc=jeyu@kernel.org \
    --cc=jmorris@namei.org \
    --cc=jpoimboe@redhat.com \
    --cc=keescook@chromium.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@armlinux.org.uk \
    --cc=mingo@kernel.org \
    --cc=mpe@ellerman.id.au \
    --cc=nico@linaro.org \
    --cc=paulus@samba.org \
    --cc=pmladek@suse.com \
    --cc=rostedt@goodmis.org \
    --cc=serge@hallyn.com \
    --cc=sergey.senozhatsky@gmail.com \
    --cc=tglx@linutronix.de \
    --cc=thgarnie@google.com \
    --cc=torvalds@linux-foundation.org \
    --cc=will.deacon@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.