From: Matt Mullins <mmullins@mmlx.us>
To: Steven Rostedt <rostedt@goodmis.org>
Cc: Florian Weimer <fw@deneb.enyo.de>,
Peter Zijlstra <peterz@infradead.org>,
Mathieu Desnoyers <mathieu.desnoyers@efficios.com>,
linux-kernel <linux-kernel@vger.kernel.org>,
Matt Mullins <mmullins@mmlx.us>, Ingo Molnar <mingo@redhat.com>,
Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Dmitry Vyukov <dvyukov@google.com>,
Martin KaFai Lau <kafai@fb.com>, Song Liu <songliubraving@fb.com>,
Yonghong Song <yhs@fb.com>, Andrii Nakryiko <andriin@fb.com>,
John Fastabend <john.fastabend@gmail.com>,
KP Singh <kpsingh@chromium.org>, netdev <netdev@vger.kernel.org>,
bpf <bpf@vger.kernel.org>, Kees Cook <keescook@chromium.org>,
Josh Poimboeuf <jpoimboe@redhat.com>,
linux-toolchains@vger.kernel.org
Subject: Re: [PATCH v3] tracepoint: Do not fail unregistering a probe due to memory allocation
Date: Mon, 23 Nov 2020 21:59:18 -0800 [thread overview]
Message-ID: <20201124055918.k5m6htif7ukhch6v@hydra.tuxags.com> (raw)
In-Reply-To: <20201118093405.7a6d2290@gandalf.local.home>
On Wed, Nov 18, 2020 at 09:34:05AM -0500, Steven Rostedt wrote:
> From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>
>
> The list of tracepoint callbacks is managed by an array that is protected
> by RCU. To update this array, a new array is allocated, the updates are
> copied over to the new array, and then the list of functions for the
> tracepoint is switched over to the new array. After a completion of an RCU
> grace period, the old array is freed.
>
> This process happens for both adding a callback as well as removing one.
> But on removing a callback, if the new array fails to be allocated, the
> callback is not removed, and may be used after it is freed by the clients
> of the tracepoint.
>
> There's really no reason to fail if the allocation for a new array fails
> when removing a function. Instead, the function can simply be replaced by a
> stub function that could be cleaned up on the next modification of the
> array. That is, instead of calling the function registered to the
> tracepoint, it would call a stub function in its place.
>
> Link: https://lore.kernel.org/r/20201115055256.65625-1-mmullins@mmlx.us
> Link: https://lore.kernel.org/r/20201116175107.02db396d@gandalf.local.home
> Link: https://lore.kernel.org/r/20201117211836.54acaef2@oasis.local.home
>
> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: Alexei Starovoitov <ast@kernel.org>
> Cc: Daniel Borkmann <daniel@iogearbox.net>
> Cc: Dmitry Vyukov <dvyukov@google.com>
> Cc: Martin KaFai Lau <kafai@fb.com>
> Cc: Song Liu <songliubraving@fb.com>
> Cc: Yonghong Song <yhs@fb.com>
> Cc: Andrii Nakryiko <andriin@fb.com>
> Cc: John Fastabend <john.fastabend@gmail.com>
> Cc: KP Singh <kpsingh@chromium.org>
> Cc: netdev <netdev@vger.kernel.org>
> Cc: bpf <bpf@vger.kernel.org>
> Cc: Kees Cook <keescook@chromium.org>
> Cc: Florian Weimer <fw@deneb.enyo.de>
> Fixes: 97e1c18e8d17b ("tracing: Kernel Tracepoints")
> Reported-by: syzbot+83aa762ef23b6f0d1991@syzkaller.appspotmail.com
> Reported-by: syzbot+d29e58bb557324e55e5e@syzkaller.appspotmail.com
> Reported-by: Matt Mullins <mmullins@mmlx.us>
> Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
I'm a bit late answering your initial query, but yes indeed this fixes
the bug I was hunting. I just watched it live through the reproducer
for about a half-hour, while unpatched I get an instant "BUG: unable to
handle page fault".
Tested-by: Matt Mullins <mmullins@mmlx.us>
> ---
> Changes since v2:
> - Went back to using a stub function and not touching
> the fast path.
> - Removed adding __GFP_NOFAIL from the allocation of the removal.
>
> kernel/tracepoint.c | 80 ++++++++++++++++++++++++++++++++++++---------
> 1 file changed, 64 insertions(+), 16 deletions(-)
>
> diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
> index 3f659f855074..3e261482296c 100644
> --- a/kernel/tracepoint.c
> +++ b/kernel/tracepoint.c
> @@ -53,6 +53,12 @@ struct tp_probes {
> struct tracepoint_func probes[];
> };
>
> +/* Called in removal of a func but failed to allocate a new tp_funcs */
> +static void tp_stub_func(void)
> +{
> + return;
> +}
> +
> static inline void *allocate_probes(int count)
> {
> struct tp_probes *p = kmalloc(struct_size(p, probes, count),
> @@ -131,6 +137,7 @@ func_add(struct tracepoint_func **funcs, struct tracepoint_func *tp_func,
> {
> struct tracepoint_func *old, *new;
> int nr_probes = 0;
> + int stub_funcs = 0;
> int pos = -1;
>
> if (WARN_ON(!tp_func->func))
> @@ -147,14 +154,34 @@ func_add(struct tracepoint_func **funcs, struct tracepoint_func *tp_func,
> if (old[nr_probes].func == tp_func->func &&
> old[nr_probes].data == tp_func->data)
> return ERR_PTR(-EEXIST);
> + if (old[nr_probes].func == tp_stub_func)
> + stub_funcs++;
> }
> }
> - /* + 2 : one for new probe, one for NULL func */
> - new = allocate_probes(nr_probes + 2);
> + /* + 2 : one for new probe, one for NULL func - stub functions */
> + new = allocate_probes(nr_probes + 2 - stub_funcs);
> if (new == NULL)
> return ERR_PTR(-ENOMEM);
> if (old) {
> - if (pos < 0) {
> + if (stub_funcs) {
> + /* Need to copy one at a time to remove stubs */
> + int probes = 0;
> +
> + pos = -1;
> + for (nr_probes = 0; old[nr_probes].func; nr_probes++) {
> + if (old[nr_probes].func == tp_stub_func)
> + continue;
> + if (pos < 0 && old[nr_probes].prio < prio)
> + pos = probes++;
> + new[probes++] = old[nr_probes];
> + }
> + nr_probes = probes;
> + if (pos < 0)
> + pos = probes;
> + else
> + nr_probes--; /* Account for insertion */
> +
> + } else if (pos < 0) {
> pos = nr_probes;
> memcpy(new, old, nr_probes * sizeof(struct tracepoint_func));
> } else {
> @@ -188,8 +215,9 @@ static void *func_remove(struct tracepoint_func **funcs,
> /* (N -> M), (N > 1, M >= 0) probes */
> if (tp_func->func) {
> for (nr_probes = 0; old[nr_probes].func; nr_probes++) {
> - if (old[nr_probes].func == tp_func->func &&
> - old[nr_probes].data == tp_func->data)
> + if ((old[nr_probes].func == tp_func->func &&
> + old[nr_probes].data == tp_func->data) ||
> + old[nr_probes].func == tp_stub_func)
> nr_del++;
> }
> }
> @@ -208,14 +236,32 @@ static void *func_remove(struct tracepoint_func **funcs,
> /* N -> M, (N > 1, M > 0) */
> /* + 1 for NULL */
> new = allocate_probes(nr_probes - nr_del + 1);
> - if (new == NULL)
> - return ERR_PTR(-ENOMEM);
> - for (i = 0; old[i].func; i++)
> - if (old[i].func != tp_func->func
> - || old[i].data != tp_func->data)
> - new[j++] = old[i];
> - new[nr_probes - nr_del].func = NULL;
> - *funcs = new;
> + if (new) {
> + for (i = 0; old[i].func; i++)
> + if ((old[i].func != tp_func->func
> + || old[i].data != tp_func->data)
> + && old[i].func != tp_stub_func)
> + new[j++] = old[i];
> + new[nr_probes - nr_del].func = NULL;
> + *funcs = new;
> + } else {
> + /*
> + * Failed to allocate, replace the old function
> + * with calls to tp_stub_func.
> + */
> + for (i = 0; old[i].func; i++)
> + if (old[i].func == tp_func->func &&
> + old[i].data == tp_func->data) {
> + old[i].func = tp_stub_func;
> + /* Set the prio to the next event. */
> + if (old[i + 1].func)
> + old[i].prio =
> + old[i + 1].prio;
> + else
> + old[i].prio = -1;
> + }
> + *funcs = old;
> + }
> }
> debug_print_probes(*funcs);
> return old;
> @@ -295,10 +341,12 @@ static int tracepoint_remove_func(struct tracepoint *tp,
> tp_funcs = rcu_dereference_protected(tp->funcs,
> lockdep_is_held(&tracepoints_mutex));
> old = func_remove(&tp_funcs, func);
> - if (IS_ERR(old)) {
> - WARN_ON_ONCE(PTR_ERR(old) != -ENOMEM);
> + if (WARN_ON_ONCE(IS_ERR(old)))
> return PTR_ERR(old);
> - }
> +
> + if (tp_funcs == old)
> + /* Failed allocating new tp_funcs, replaced func with stub */
> + return 0;
>
> if (!tp_funcs) {
> /* Removed last function */
> --
> 2.25.4
>
next prev parent reply other threads:[~2020-11-24 5:59 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-11-16 22:51 [PATCH] tracepoint: Do not fail unregistering a probe due to memory allocation Steven Rostedt
2020-11-16 23:16 ` Steven Rostedt
2020-11-17 19:15 ` Mathieu Desnoyers
2020-11-17 19:21 ` Steven Rostedt
2020-11-17 19:47 ` Mathieu Desnoyers
2020-11-17 20:34 ` Steven Rostedt
2020-11-17 20:58 ` Steven Rostedt
2020-11-17 21:22 ` Mathieu Desnoyers
2020-11-17 22:16 ` Steven Rostedt
2020-11-17 23:08 ` Mathieu Desnoyers
2020-11-18 1:11 ` Steven Rostedt
2020-11-17 21:08 ` Mathieu Desnoyers
2020-11-18 13:21 ` violating function pointer signature Peter Zijlstra
2020-11-18 13:59 ` Florian Weimer
2020-11-18 14:12 ` Peter Zijlstra
2020-11-18 14:18 ` Florian Weimer
2020-11-18 14:34 ` [PATCH v3] tracepoint: Do not fail unregistering a probe due to memory allocation Steven Rostedt
2020-11-24 5:59 ` Matt Mullins [this message]
2020-11-18 14:22 ` violating function pointer signature Steven Rostedt
2020-11-18 19:46 ` Alexei Starovoitov
2020-11-18 20:02 ` Steven Rostedt
2020-11-18 14:02 ` Steven Rostedt
2020-11-18 16:01 ` Mathieu Desnoyers
2020-11-18 16:19 ` David Laight
2020-11-18 16:50 ` Nick Desaulniers
2020-11-18 17:17 ` Steven Rostedt
2020-11-18 18:12 ` Segher Boessenkool
2020-11-18 18:31 ` Florian Weimer
2020-11-18 18:55 ` Segher Boessenkool
2020-11-18 18:58 ` Steven Rostedt
2020-11-18 18:59 ` Steven Rostedt
2020-11-18 19:11 ` Segher Boessenkool
2020-11-18 19:33 ` Steven Rostedt
2020-11-18 19:48 ` Segher Boessenkool
2020-11-18 20:44 ` Steven Rostedt
2020-11-19 8:21 ` Peter Zijlstra
2020-11-19 8:36 ` Peter Zijlstra
2020-11-19 14:37 ` Segher Boessenkool
2020-11-19 14:59 ` Steven Rostedt
2020-11-19 16:35 ` Segher Boessenkool
2020-11-19 17:42 ` David Laight
2020-11-19 19:27 ` Segher Boessenkool
2020-11-19 17:04 ` Alexei Starovoitov
2020-11-19 17:30 ` Steven Rostedt
2020-11-20 1:31 ` Nick Desaulniers
2020-11-17 21:33 ` [PATCH] tracepoint: Do not fail unregistering a probe due to memory allocation Kees Cook
2020-11-17 22:19 ` Steven Rostedt
2020-11-17 23:12 ` Mathieu Desnoyers
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=20201124055918.k5m6htif7ukhch6v@hydra.tuxags.com \
--to=mmullins@mmlx.us \
--cc=andriin@fb.com \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=dvyukov@google.com \
--cc=fw@deneb.enyo.de \
--cc=john.fastabend@gmail.com \
--cc=jpoimboe@redhat.com \
--cc=kafai@fb.com \
--cc=keescook@chromium.org \
--cc=kpsingh@chromium.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-toolchains@vger.kernel.org \
--cc=mathieu.desnoyers@efficios.com \
--cc=mingo@redhat.com \
--cc=netdev@vger.kernel.org \
--cc=peterz@infradead.org \
--cc=rostedt@goodmis.org \
--cc=songliubraving@fb.com \
--cc=yhs@fb.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).