From: Jiri Olsa <olsajiri@gmail.com>
To: Andrii Nakryiko <andrii@kernel.org>
Cc: linux-trace-kernel@vger.kernel.org, peterz@infradead.org,
oleg@redhat.com, rostedt@goodmis.org, mhiramat@kernel.org,
bpf@vger.kernel.org, linux-kernel@vger.kernel.org,
paulmck@kernel.org, willy@infradead.org, surenb@google.com,
akpm@linux-foundation.org, linux-mm@kvack.org
Subject: Re: [PATCH v3 04/13] uprobes: travers uprobe's consumer list locklessly under SRCU protection
Date: Thu, 22 Aug 2024 16:22:51 +0200 [thread overview]
Message-ID: <ZsdJuwIuJ-KFA6Rz@krava> (raw)
In-Reply-To: <20240813042917.506057-5-andrii@kernel.org>
On Mon, Aug 12, 2024 at 09:29:08PM -0700, Andrii Nakryiko wrote:
SNIP
> @@ -1125,18 +1103,31 @@ void uprobe_unregister(struct uprobe *uprobe, struct uprobe_consumer *uc)
> int err;
>
> down_write(&uprobe->register_rwsem);
> - if (WARN_ON(!consumer_del(uprobe, uc))) {
> - err = -ENOENT;
> - } else {
> - err = register_for_each_vma(uprobe, NULL);
> - /* TODO : cant unregister? schedule a worker thread */
> - if (unlikely(err))
> - uprobe_warn(current, "unregister, leaking uprobe");
> - }
> +
> + list_del_rcu(&uc->cons_node);
hi,
I'm using this patchset as base for my changes and stumbled on this today,
I'm probably missing something, but should we keep the 'uprobe->consumer_rwsem'
lock around the list_del_rcu?
jirka
> + err = register_for_each_vma(uprobe, NULL);
> +
> up_write(&uprobe->register_rwsem);
>
> - if (!err)
> - put_uprobe(uprobe);
> + /* TODO : cant unregister? schedule a worker thread */
> + if (unlikely(err)) {
> + uprobe_warn(current, "unregister, leaking uprobe");
> + goto out_sync;
> + }
> +
> + put_uprobe(uprobe);
> +
> +out_sync:
> + /*
> + * Now that handler_chain() and handle_uretprobe_chain() iterate over
> + * uprobe->consumers list under RCU protection without holding
> + * uprobe->register_rwsem, we need to wait for RCU grace period to
> + * make sure that we can't call into just unregistered
> + * uprobe_consumer's callbacks anymore. If we don't do that, fast and
> + * unlucky enough caller can free consumer's memory and cause
> + * handler_chain() or handle_uretprobe_chain() to do an use-after-free.
> + */
> + synchronize_srcu(&uprobes_srcu);
> }
> EXPORT_SYMBOL_GPL(uprobe_unregister);
>
> @@ -1214,13 +1205,20 @@ EXPORT_SYMBOL_GPL(uprobe_register);
> int uprobe_apply(struct uprobe *uprobe, struct uprobe_consumer *uc, bool add)
> {
> struct uprobe_consumer *con;
> - int ret = -ENOENT;
> + int ret = -ENOENT, srcu_idx;
>
> down_write(&uprobe->register_rwsem);
> - for (con = uprobe->consumers; con && con != uc ; con = con->next)
> - ;
> - if (con)
> - ret = register_for_each_vma(uprobe, add ? uc : NULL);
> +
> + srcu_idx = srcu_read_lock(&uprobes_srcu);
> + list_for_each_entry_srcu(con, &uprobe->consumers, cons_node,
> + srcu_read_lock_held(&uprobes_srcu)) {
> + if (con == uc) {
> + ret = register_for_each_vma(uprobe, add ? uc : NULL);
> + break;
> + }
> + }
> + srcu_read_unlock(&uprobes_srcu, srcu_idx);
> +
> up_write(&uprobe->register_rwsem);
>
> return ret;
> @@ -2085,10 +2083,12 @@ static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
> struct uprobe_consumer *uc;
> int remove = UPROBE_HANDLER_REMOVE;
> bool need_prep = false; /* prepare return uprobe, when needed */
> + bool has_consumers = false;
>
> - down_read(&uprobe->register_rwsem);
> current->utask->auprobe = &uprobe->arch;
> - for (uc = uprobe->consumers; uc; uc = uc->next) {
> +
> + list_for_each_entry_srcu(uc, &uprobe->consumers, cons_node,
> + srcu_read_lock_held(&uprobes_srcu)) {
> int rc = 0;
>
> if (uc->handler) {
> @@ -2101,17 +2101,24 @@ static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
> need_prep = true;
>
> remove &= rc;
> + has_consumers = true;
> }
> current->utask->auprobe = NULL;
>
> if (need_prep && !remove)
> prepare_uretprobe(uprobe, regs); /* put bp at return */
>
> - if (remove && uprobe->consumers) {
> - WARN_ON(!uprobe_is_active(uprobe));
> - unapply_uprobe(uprobe, current->mm);
> + if (remove && has_consumers) {
> + down_read(&uprobe->register_rwsem);
> +
> + /* re-check that removal is still required, this time under lock */
> + if (!filter_chain(uprobe, current->mm)) {
> + WARN_ON(!uprobe_is_active(uprobe));
> + unapply_uprobe(uprobe, current->mm);
> + }
> +
> + up_read(&uprobe->register_rwsem);
> }
> - up_read(&uprobe->register_rwsem);
> }
>
> static void
> @@ -2119,13 +2126,15 @@ handle_uretprobe_chain(struct return_instance *ri, struct pt_regs *regs)
> {
> struct uprobe *uprobe = ri->uprobe;
> struct uprobe_consumer *uc;
> + int srcu_idx;
>
> - down_read(&uprobe->register_rwsem);
> - for (uc = uprobe->consumers; uc; uc = uc->next) {
> + srcu_idx = srcu_read_lock(&uprobes_srcu);
> + list_for_each_entry_srcu(uc, &uprobe->consumers, cons_node,
> + srcu_read_lock_held(&uprobes_srcu)) {
> if (uc->ret_handler)
> uc->ret_handler(uc, ri->func, regs);
> }
> - up_read(&uprobe->register_rwsem);
> + srcu_read_unlock(&uprobes_srcu, srcu_idx);
> }
>
> static struct return_instance *find_next_ret_chain(struct return_instance *ri)
> --
> 2.43.5
>
next prev parent reply other threads:[~2024-08-22 14:22 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-08-13 4:29 [PATCH v3 00/13] uprobes: RCU-protected hot path optimizations Andrii Nakryiko
2024-08-13 4:29 ` [PATCH v3 01/13] uprobes: revamp uprobe refcounting and lifetime management Andrii Nakryiko
2024-08-13 4:29 ` [PATCH v3 02/13] uprobes: protected uprobe lifetime with SRCU Andrii Nakryiko
2024-08-13 4:29 ` [PATCH v3 03/13] uprobes: get rid of enum uprobe_filter_ctx in uprobe filter callbacks Andrii Nakryiko
2024-08-13 4:29 ` [PATCH v3 04/13] uprobes: travers uprobe's consumer list locklessly under SRCU protection Andrii Nakryiko
2024-08-22 14:22 ` Jiri Olsa [this message]
2024-08-22 16:59 ` Andrii Nakryiko
2024-08-22 17:35 ` Jiri Olsa
2024-08-22 17:51 ` Andrii Nakryiko
2024-08-13 4:29 ` [PATCH v3 05/13] perf/uprobe: split uprobe_unregister() Andrii Nakryiko
2024-08-13 4:29 ` [PATCH v3 06/13] rbtree: provide rb_find_rcu() / rb_find_add_rcu() Andrii Nakryiko
2024-08-13 4:29 ` [PATCH v3 07/13] uprobes: perform lockless SRCU-protected uprobes_tree lookup Andrii Nakryiko
2024-08-13 4:29 ` [PATCH v3 08/13] uprobes: switch to RCU Tasks Trace flavor for better performance Andrii Nakryiko
2024-08-13 4:29 ` [PATCH RFC v3 09/13] uprobes: SRCU-protect uretprobe lifetime (with timeout) Andrii Nakryiko
2024-08-19 13:41 ` Oleg Nesterov
2024-08-19 20:34 ` Andrii Nakryiko
2024-08-20 15:05 ` Oleg Nesterov
2024-08-20 18:01 ` Andrii Nakryiko
2024-08-13 4:29 ` [PATCH RFC v3 10/13] uprobes: implement SRCU-protected lifetime for single-stepped uprobe Andrii Nakryiko
2024-08-13 4:29 ` [PATCH RFC v3 11/13] mm: introduce mmap_lock_speculation_{start|end} Andrii Nakryiko
2024-08-13 4:29 ` [PATCH RFC v3 12/13] mm: add SLAB_TYPESAFE_BY_RCU to files_cache Andrii Nakryiko
2024-08-13 6:07 ` Mateusz Guzik
2024-08-13 14:49 ` Suren Baghdasaryan
2024-08-13 18:15 ` Andrii Nakryiko
2024-08-13 4:29 ` [PATCH RFC v3 13/13] uprobes: add speculative lockless VMA to inode resolution Andrii Nakryiko
2024-08-13 6:17 ` Mateusz Guzik
2024-08-13 15:36 ` Suren Baghdasaryan
2024-08-15 13:44 ` Mateusz Guzik
2024-08-15 16:47 ` Andrii Nakryiko
2024-08-15 17:45 ` Suren Baghdasaryan
2024-08-15 18:24 ` Mateusz Guzik
2024-08-15 18:58 ` Jann Horn
2024-08-15 19:07 ` Mateusz Guzik
2024-08-15 19:17 ` Arnaldo Carvalho de Melo
2024-08-15 19:18 ` Arnaldo Carvalho de Melo
2024-08-15 19:44 ` Suren Baghdasaryan
2024-08-15 20:17 ` Andrii Nakryiko
2024-08-15 13:24 ` [PATCH v3 00/13] uprobes: RCU-protected hot path optimizations Oleg Nesterov
2024-08-15 16:49 ` Andrii Nakryiko
2024-08-21 16:41 ` Andrii Nakryiko
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=ZsdJuwIuJ-KFA6Rz@krava \
--to=olsajiri@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=andrii@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=mhiramat@kernel.org \
--cc=oleg@redhat.com \
--cc=paulmck@kernel.org \
--cc=peterz@infradead.org \
--cc=rostedt@goodmis.org \
--cc=surenb@google.com \
--cc=willy@infradead.org \
/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).