]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
netfilter: nft_synproxy: stop bypassing the priv->info snapshot
authorRunyu Xiao <runyu.xiao@seu.edu.cn>
Thu, 11 Jun 2026 04:21:20 +0000 (12:21 +0800)
committerPablo Neira Ayuso <pablo@netfilter.org>
Tue, 23 Jun 2026 06:11:22 +0000 (08:11 +0200)
nft_synproxy_eval_v4() and nft_synproxy_eval_v6() already take a
whole-object READ_ONCE() snapshot of the shared priv->info state before
building the SYNACK reply, but nft_synproxy_tcp_options() still masks
opts->options with priv->info.options from the live shared object.

When a named synproxy object is updated concurrently with SYN traffic,
the eval path can then mix mss and timestamp handling from the local
snapshot with an options mask taken from a newer configuration, so one
SYNACK no longer reflects a coherent synproxy configuration.

Use info->options so nft_synproxy_tcp_options() stays on the same local
snapshot that the eval path already copied from priv->info.

Fixes: ee394f96ad75 ("netfilter: nft_synproxy: add synproxy stateful object support")
Signed-off-by: Runyu Xiao <runyu.xiao@seu.edu.cn>
Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
net/netfilter/nft_synproxy.c

index 7641f249614c9728846aeaecd8eb988037c315c3..9ed288c9d168800a970bf772b186f9342811886e 100644 (file)
@@ -24,14 +24,13 @@ static const struct nla_policy nft_synproxy_policy[NFTA_SYNPROXY_MAX + 1] = {
 static void nft_synproxy_tcp_options(struct synproxy_options *opts,
                                     const struct tcphdr *tcp,
                                     struct synproxy_net *snet,
-                                    struct nf_synproxy_info *info,
-                                    const struct nft_synproxy *priv)
+                                    struct nf_synproxy_info *info)
 {
        this_cpu_inc(snet->stats->syn_received);
        if (tcp->ece && tcp->cwr)
                opts->options |= NF_SYNPROXY_OPT_ECN;
 
-       opts->options &= priv->info.options;
+       opts->options &= info->options;
        opts->mss_encode = opts->mss_option;
        opts->mss_option = info->mss;
        if (opts->options & NF_SYNPROXY_OPT_TIMESTAMP)
@@ -56,7 +55,7 @@ static void nft_synproxy_eval_v4(const struct nft_synproxy *priv,
 
        if (tcp->syn) {
                /* Initial SYN from client */
-               nft_synproxy_tcp_options(opts, tcp, snet, &info, priv);
+               nft_synproxy_tcp_options(opts, tcp, snet, &info);
                synproxy_send_client_synack(net, skb, tcp, opts);
                consume_skb(skb);
                regs->verdict.code = NF_STOLEN;
@@ -87,7 +86,7 @@ static void nft_synproxy_eval_v6(const struct nft_synproxy *priv,
 
        if (tcp->syn) {
                /* Initial SYN from client */
-               nft_synproxy_tcp_options(opts, tcp, snet, &info, priv);
+               nft_synproxy_tcp_options(opts, tcp, snet, &info);
                synproxy_send_client_synack_ipv6(net, skb, tcp, opts);
                consume_skb(skb);
                regs->verdict.code = NF_STOLEN;