]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
netfilter: nft_flow_offload: update tcp state flags under lock
authorFlorian Westphal <fw@strlen.de>
Mon, 13 Jan 2025 23:50:34 +0000 (00:50 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Sun, 19 Jan 2025 15:41:54 +0000 (16:41 +0100)
The conntrack entry is already public, there is a small chance that another
CPU is handling a packet in reply direction and racing with the tcp state
update.

Move this under ct spinlock.

This is done once, when ct is about to be offloaded, so this should
not result in a noticeable performance hit.

Fixes: 8437a6209f76 ("netfilter: nft_flow_offload: set liberal tracking mode for tcp")
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
net/netfilter/nft_flow_offload.c

index 3b474d235663889f437b15f5b6d2b44d16d016a6..221d50223018106f8292f92a791d5d02da1e66f0 100644 (file)
@@ -289,6 +289,15 @@ static bool nft_flow_offload_skip(struct sk_buff *skb, int family)
        return false;
 }
 
+static void flow_offload_ct_tcp(struct nf_conn *ct)
+{
+       /* conntrack will not see all packets, disable tcp window validation. */
+       spin_lock_bh(&ct->lock);
+       ct->proto.tcp.seen[0].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
+       ct->proto.tcp.seen[1].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
+       spin_unlock_bh(&ct->lock);
+}
+
 static void nft_flow_offload_eval(const struct nft_expr *expr,
                                  struct nft_regs *regs,
                                  const struct nft_pktinfo *pkt)
@@ -356,11 +365,8 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
                goto err_flow_alloc;
 
        flow_offload_route_init(flow, &route);
-
-       if (tcph) {
-               ct->proto.tcp.seen[0].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
-               ct->proto.tcp.seen[1].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
-       }
+       if (tcph)
+               flow_offload_ct_tcp(ct);
 
        __set_bit(NF_FLOW_HW_BIDIRECTIONAL, &flow->flags);
        ret = flow_offload_add(flowtable, flow);