From: Paolo Abeni <pabeni@redhat.com>
To: Jamal Hadi Salim <jhs@mojatatu.com>, netdev@vger.kernel.org
Cc: kuba@kernel.org, davem@davemloft.net, edumazet@google.com,
horms@kernel.org, john.fastabend@gmail.com, jiri@resnulli.us,
zdi-disclosures@trendmicro.com, sh.kalluri129@gmail.com,
victor@mojatatu.com, security@kernel.org, stable@vger.kernel.org,
Santosh Kalluri <santosh.kalluri129@gmail.com>
Subject: Re: [PATCH net 1/1] net/sched: cls_route: fix fastmap use-after-free on filter
Date: Tue, 28 Jul 2026 12:34:32 +0200 [thread overview]
Message-ID: <3914dd5c-77c8-4f96-8bfc-986f0a00f722@redhat.com> (raw)
In-Reply-To: <20260723105210.817079-1-jhs@mojatatu.com>
On 7/23/26 12:52 PM, Jamal Hadi Salim wrote:
> diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
> index bd6f945bd388..700f878fc3cd 100644
> --- a/net/sched/cls_route.c
> +++ b/net/sched/cls_route.c
> @@ -297,16 +297,29 @@ static void route4_destroy(struct tcf_proto *tp, bool rtnl_held,
> next = rtnl_dereference(f->next);
> RCU_INIT_POINTER(b->ht[h2], next);
> tcf_unbind_filter(tp, &f->res);
> - if (tcf_exts_get_net(&f->exts))
> - route4_queue_work(f);
> - else
> - __route4_delete_filter(f);
> + /* Always defer the free. The direct
> + * __route4_delete_filter() path has no
> + * grace period and races with readers
> + * that cached f in the fastmap.
> + */
> + tcf_exts_get_net(&f->exts);
> + route4_queue_work(f);
Sashiko fears the above would be race prone:
https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260723105210.817079-1-jhs%40mojatatu.com
> }
> }
> RCU_INIT_POINTER(head->table[h1], NULL);
> kfree_rcu(b, rcu);
> }
> }
> +
> + /* All filters are unlinked; no new reader can find them on the
> + * chain. Wait for in-flight readers that may still hold a filter
> + * pointer and have published it into the fastmap after we unlinked.
> + * Then flush the stale entries while head is still valid under
> + * RTNL, matching the route4_delete() pattern.
> + */
> + synchronize_rcu();
> + route4_reset_fastmap(head);
This really looks like quite a big hammer. Since there is already a
synchronization point for both reader and write while acquiring the
fastmap_lock, I'm wondering if something alike the following could work ?!?
(completely untested!!!):
---
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
index bd6f945bd388..8cecc945dcde 100644
--- a/net/sched/cls_route.c
+++ b/net/sched/cls_route.c
@@ -52,6 +52,7 @@ struct route4_filter {
struct tcf_result res;
struct tcf_exts exts;
u32 handle;
+ bool dying;
struct route4_bucket *bkt;
struct tcf_proto *tp;
struct rcu_work rwork;
@@ -66,9 +67,11 @@ static inline int route4_fastmap_hash(u32 id, int iif)
static DEFINE_SPINLOCK(fastmap_lock);
static void
-route4_reset_fastmap(struct route4_head *head)
+route4_reset_fastmap(struct route4_head *head, struct route4_filter *f)
{
spin_lock_bh(&fastmap_lock);
+ if (f)
+ f->dying = true;
memset(head->fastmap, 0, sizeof(head->fastmap));
spin_unlock_bh(&fastmap_lock);
}
@@ -81,9 +84,11 @@ route4_set_fastmap(struct route4_head *head, u32 id, int iif,
/* fastmap updates must look atomic to aling id, iff, filter */
spin_lock_bh(&fastmap_lock);
- head->fastmap[h].id = id;
- head->fastmap[h].iif = iif;
- head->fastmap[h].filter = f;
+ if (!f->dying) {
+ head->fastmap[h].id = id;
+ head->fastmap[h].iif = iif;
+ head->fastmap[h].filter = f;
+ }
spin_unlock_bh(&fastmap_lock);
}
@@ -338,7 +343,7 @@ static int route4_delete(struct tcf_proto *tp, void *arg, bool *last,
* notice we unlink'd the filter so we can't get it
* back in the fastmap.
*/
- route4_reset_fastmap(head);
+ route4_reset_fastmap(head, f);
/* Delete it */
tcf_unbind_filter(tp, &f->res);
@@ -558,7 +563,7 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
}
}
- route4_reset_fastmap(head);
+ route4_reset_fastmap(head, fold);
*arg = f;
if (fold) {
tcf_unbind_filter(tp, &fold->res);
next prev parent reply other threads:[~2026-07-28 10:34 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-23 10:52 [PATCH net 1/1] net/sched: cls_route: fix fastmap use-after-free on filter Jamal Hadi Salim
2026-07-28 10:34 ` Paolo Abeni [this message]
2026-07-28 12:37 ` Jamal Hadi Salim
2026-07-28 13:05 ` Paolo Abeni
2026-07-28 13:12 ` Jamal Hadi Salim
2026-07-28 14:03 ` Paolo Abeni
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=3914dd5c-77c8-4f96-8bfc-986f0a00f722@redhat.com \
--to=pabeni@redhat.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=jhs@mojatatu.com \
--cc=jiri@resnulli.us \
--cc=john.fastabend@gmail.com \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=santosh.kalluri129@gmail.com \
--cc=security@kernel.org \
--cc=sh.kalluri129@gmail.com \
--cc=stable@vger.kernel.org \
--cc=victor@mojatatu.com \
--cc=zdi-disclosures@trendmicro.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