From afe2d8dfe6fa2a85532a0ca799d1437bedd86734 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 5 Jun 2026 15:11:19 +0200 Subject: [PATCH] netfilter: nf_conncount: callers must hold rcu read lock [ Upstream commit 64d7d5abe2160bba369b4a8f06bdf5630573bab0 ] rcu_derefence_raw() should not have been used here, it concealed this bug. Its used because struct rb_node lacks __rcu annotated pointers, so plain rcu_derefence causes sparse warnings. The major tradeoff is that rcu_derefence_raw() doesn't warn when the caller isn't in a rcu read section. Extend the rcu read lock scope accordingly and cause sparse warnings, those warnings are the lesser evil. Fixes: 11efd5cb04a1 ("openvswitch: Support conntrack zone limit") Closes: https://sashiko.dev/#/patchset/20260603230610.7900-1-fw%40strlen.de Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso Signed-off-by: Sasha Levin --- net/netfilter/nf_conncount.c | 6 +++--- net/openvswitch/conntrack.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/net/netfilter/nf_conncount.c b/net/netfilter/nf_conncount.c index ae9ad439449f..b9265a8cdb2b 100644 --- a/net/netfilter/nf_conncount.c +++ b/net/netfilter/nf_conncount.c @@ -499,7 +499,7 @@ count_tree(struct net *net, hash = jhash2(key, data->keylen, conncount_rnd) % CONNCOUNT_SLOTS; root = &data->root[hash]; - parent = rcu_dereference_raw(root->rb_node); + parent = rcu_dereference(root->rb_node); while (parent) { int diff; @@ -507,9 +507,9 @@ count_tree(struct net *net, diff = key_diff(key, rbconn->key, data->keylen); if (diff < 0) { - parent = rcu_dereference_raw(parent->rb_left); + parent = rcu_dereference(parent->rb_left); } else if (diff > 0) { - parent = rcu_dereference_raw(parent->rb_right); + parent = rcu_dereference(parent->rb_right); } else { int ret; diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c index b6ec5497b930..e0ff87aaf979 100644 --- a/net/openvswitch/conntrack.c +++ b/net/openvswitch/conntrack.c @@ -2096,10 +2096,10 @@ static int ovs_ct_limit_get_zone_limit(struct net *net, } else { rcu_read_lock(); limit = ct_limit_get(info, zone); - rcu_read_unlock(); err = __ovs_ct_limit_get_zone_limit( net, info->data, zone, limit, reply); + rcu_read_unlock(); if (err) return err; }