AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/06/23 22:41 flow patch-triage
1m Args:
null

Results:
{
  "EnableConfigs": [
    "NETFILTER_CONNCOUNT",
    "NF_CONNTRACK",
    "NF_CT_NETLINK",
    "NF_FLOW_TABLE",
    "NFT_COMPAT",
    "NFT_CT",
    "NFT_SYNPROXY"
  ],
  "FocusSymbols": [
    "__nf_conncount_add",
    "__nf_ct_expect_check",
    "__nf_conntrack_helper_register",
    "ctnetlink_change_helper",
    "ctnetlink_alloc_expect",
    "nf_flow_ip4_tunnel_proto",
    "nft_target_bridge_validate",
    "nft_ct_expect_obj_init",
    "nft_ct_expect_obj_eval",
    "nft_synproxy_eval_v4",
    "nft_synproxy_eval_v6"
  ],
  "Reasoning": "The patch series makes functional changes to netfilter, including connection tracking, flow tables, and nftables compatibility. It modifies the logic for connection counting, expectation checking, helper registration, and netlink handling. It also adds a new validation function for bridge targets in nft_compat and fixes timeout handling in nft_ct. These changes affect core netfilter functionality and are reachable from userspace via netlink or by processing network packets, making them suitable for fuzzing.",
  "WorthFuzzing": true
}

1/1 2026/06/23 22:41 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit 0521dd18f12b62aba26f086a31e4902031db9962\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Tue Jun 23 22:41:17 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h\nindex 20d70dddbe5098..25062f4a0dd5f1 100644\n--- a/include/linux/netfilter/x_tables.h\n+++ b/include/linux/netfilter/x_tables.h\n@@ -18,7 +18,7 @@\n  * @match:\tthe match extension\n  * @target:\tthe target extension\n  * @matchinfo:\tper-match data\n- * @targetinfo:\tper-target data\n+ * @targinfo:\tper-target data\n  * @state:\tpointer to hook state this packet came from\n  * @fragoff:\tpacket is a fragment, this is the data offset\n  * @thoff:\tposition of transport header relative to skb-\u003edata\n@@ -77,7 +77,9 @@ static inline u_int8_t xt_family(const struct xt_action_param *par)\n  * @match:\tstruct xt_match through which this function was invoked\n  * @matchinfo:\tper-match data\n  * @hook_mask:\tvia which hooks the new rule is reachable\n- * Other fields as above.\n+ * @family:\tactual NFPROTO_* through which the function is invoked\n+ *\t\t(helpful when match-\u003efamily == NFPROTO_UNSPEC)\n+ * @nft_compat:\trunning from the nft compat layer if true\n  */\n struct xt_mtchk_param {\n \tstruct net *net;\n@@ -91,8 +93,13 @@ struct xt_mtchk_param {\n };\n \n /**\n- * struct xt_mdtor_param - match destructor parameters\n- * Fields as above.\n+ * struct xt_mtdtor_param - match destructor parameters\n+ *\n+ * @net:\tnetwork namespace through which the check was invoked\n+ * @match:\tstruct xt_match through which this function was invoked\n+ * @matchinfo:\tper-match data\n+ * @family:\tactual NFPROTO_* through which the function is invoked\n+ *\t\t(helpful when match-\u003efamily == NFPROTO_UNSPEC)\n  */\n struct xt_mtdtor_param {\n \tstruct net *net;\n@@ -105,10 +112,16 @@ struct xt_mtdtor_param {\n  * struct xt_tgchk_param - parameters for target extensions'\n  * checkentry functions\n  *\n+ * @net:\tnetwork namespace through which the check was invoked\n+ * @table:\ttable the rule is tried to be inserted into\n  * @entryinfo:\tthe family-specific rule data\n  * \t\t(struct ipt_entry, ip6t_entry, arpt_entry, ebt_entry)\n- *\n- * Other fields see above.\n+ * @target:\tthe target extension\n+ * @targinfo:\tper-target data\n+ * @hook_mask:\tvia which hooks the new rule is reachable\n+ * @family:\tactual NFPROTO_* through which the function is invoked\n+ *\t\t(helpful when match-\u003efamily == NFPROTO_UNSPEC)\n+ * @nft_compat:\trunning from the nft compat layer if true\n  */\n struct xt_tgchk_param {\n \tstruct net *net;\n@@ -336,9 +349,9 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size);\n void xt_free_table_info(struct xt_table_info *info);\n \n /**\n- * xt_recseq - recursive seqcount for netfilter use\n+ * var xt_recseq - recursive seqcount for netfilter use\n  *\n- * Packet processing changes the seqcount only if no recursion happened\n+ * Packet processing changes the seqcount only if no recursion happened.\n  * get_counters() can use read_seqcount_begin()/read_seqcount_retry(),\n  * because we use the normal seqcount convention :\n  * Low order bit set to 1 if a writer is active.\ndiff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h\nindex be4a120d549eb3..c024345c9bd862 100644\n--- a/include/net/netfilter/nf_conntrack_expect.h\n+++ b/include/net/netfilter/nf_conntrack_expect.h\n@@ -26,6 +26,7 @@ struct nf_conntrack_expect {\n \tpossible_net_t net;\n \n \t/* We expect this tuple, with the following mask */\n+\tstruct nf_conntrack_tuple master_tuple;\n \tstruct nf_conntrack_tuple tuple;\n \tstruct nf_conntrack_tuple_mask mask;\n \ndiff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h\nindex 81025101f86daa..c761cd8158b253 100644\n--- a/include/net/netfilter/nf_conntrack_helper.h\n+++ b/include/net/netfilter/nf_conntrack_helper.h\n@@ -114,6 +114,10 @@ int nf_conntrack_helpers_register(struct nf_conntrack_helper *, unsigned int,\n void nf_conntrack_helpers_unregister(struct nf_conntrack_helper **,\n \t\t\t\t     unsigned int);\n \n+#define nf_conntrack_helper_deprecated(name) \\\n+\tpr_warn(\"The %s conntrack helper is scheduled for removal.\\n\"\t\\\n+\t\t\"Please contact the netfilter-devel mailing list if you still need this.\\n\", name)\n+\n struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp);\n \n int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,\ndiff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig\nindex 665f8008cc4b27..4c04cd8d40a229 100644\n--- a/net/netfilter/Kconfig\n+++ b/net/netfilter/Kconfig\n@@ -256,8 +256,7 @@ config NF_CONNTRACK_H323\n \t  To compile it as a module, choose M here.  If unsure, say N.\n \n config NF_CONNTRACK_IRC\n-\ttristate \"IRC protocol support\"\n-\tdefault m if NETFILTER_ADVANCED=n\n+\ttristate \"IRC DCC protocol support (obsolete)\"\n \thelp\n \t  There is a commonly-used extension to IRC called\n \t  Direct Client-to-Client Protocol (DCC).  This enables users to send\n@@ -267,6 +266,8 @@ config NF_CONNTRACK_IRC\n \t  using NAT, this extension will enable you to send files and initiate\n \t  chats.  Note that you do NOT need this extension to get files or\n \t  have others initiate chats, or everything else in IRC.\n+\t  DCC tracking behind NAT requires plaintext (unencrypted) IRC, so\n+\t  this helper is of limited use these days.\n \n \t  To compile it as a module, choose M here.  If unsure, say N.\n \n@@ -308,17 +309,17 @@ config NF_CONNTRACK_SNMP\n \t  To compile it as a module, choose M here.  If unsure, say N.\n \n config NF_CONNTRACK_PPTP\n-\ttristate \"PPtP protocol support\"\n+\ttristate \"PPtP protocol support (deprecated)\"\n \tdepends on NETFILTER_ADVANCED\n \tselect NF_CT_PROTO_GRE\n \thelp\n \t  This module adds support for PPTP (Point to Point Tunnelling\n \t  Protocol, RFC2637) connection tracking and NAT.\n \n-\t  If you are running PPTP sessions over a stateful firewall or NAT\n+\t  If you are still running PPTP sessions over a stateful firewall or NAT\n \t  box, you may want to enable this feature.\n \n-\t  Please note that not all PPTP modes of operation are supported yet.\n+\t  Please note that not all PPTP modes of operation are supported.\n \t  Specifically these limitations exist:\n \t    - Blindly assumes that control connections are always established\n \t      in PNS-\u003ePAC direction. This is a violation of RFC2637.\ndiff --git a/net/netfilter/nf_conncount.c b/net/netfilter/nf_conncount.c\nindex dd67004a5cc09e..91582069f6d2ee 100644\n--- a/net/netfilter/nf_conncount.c\n+++ b/net/netfilter/nf_conncount.c\n@@ -183,17 +183,16 @@ static int __nf_conncount_add(struct net *net,\n \t\treturn -ENOENT;\n \n \tif (ct \u0026\u0026 nf_ct_is_confirmed(ct)) {\n-\t\t/* local connections are confirmed in postrouting so confirmation\n-\t\t * might have happened before hitting connlimit\n+\t\t/* Connection is confirmed but might still be in the setup phase.\n+\t\t * Only skip the tracking if it is fully assured. This guarantees\n+\t\t * that setup packets or retransmissions are properly counted and\n+\t\t * deduplicated.\n \t\t */\n-\t\tif (skb-\u003eskb_iif != LOOPBACK_IFINDEX) {\n+\t\tif (test_bit(IPS_ASSURED_BIT, \u0026ct-\u003estatus)) {\n \t\t\terr = -EEXIST;\n \t\t\tgoto out_put;\n \t\t}\n \n-\t\t/* this is likely a local connection, skip optimization to avoid\n-\t\t * adding duplicates from a 'packet train'\n-\t\t */\n \t\tgoto check_connections;\n \t}\n \ndiff --git a/net/netfilter/nf_conntrack_broadcast.c b/net/netfilter/nf_conntrack_broadcast.c\nindex 400119b6320e72..bf78828c7549d4 100644\n--- a/net/netfilter/nf_conntrack_broadcast.c\n+++ b/net/netfilter/nf_conntrack_broadcast.c\n@@ -62,6 +62,7 @@ int nf_conntrack_broadcast_help(struct sk_buff *skb,\n \tif (exp == NULL)\n \t\tgoto out;\n \n+\texp-\u003emaster_tuple\t  = ct-\u003etuplehash[IP_CT_DIR_ORIGINAL].tuple;\n \texp-\u003etuple                = ct-\u003etuplehash[IP_CT_DIR_REPLY].tuple;\n \n \thelper = rcu_dereference(help-\u003ehelper);\ndiff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c\nindex 49e18eda037ef1..38630c5e006f08 100644\n--- a/net/netfilter/nf_conntrack_expect.c\n+++ b/net/netfilter/nf_conntrack_expect.c\n@@ -355,6 +355,8 @@ void nf_ct_expect_init(struct nf_conntrack_expect *exp, unsigned int class,\n \texp-\u003etuple.src.l3num = family;\n \texp-\u003etuple.dst.protonum = proto;\n \n+\texp-\u003emaster_tuple = ct-\u003etuplehash[IP_CT_DIR_ORIGINAL].tuple;\n+\n \tif (saddr) {\n \t\tmemcpy(\u0026exp-\u003etuple.src.u3, saddr, len);\n \t\tif (sizeof(exp-\u003etuple.src.u3) \u003e len)\n@@ -494,9 +496,15 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect,\n \t\t\t\t\t   lockdep_is_held(\u0026nf_conntrack_expect_lock));\n \tif (helper) {\n \t\tp = \u0026helper-\u003eexpect_policy[expect-\u003eclass];\n-\t\tif (p-\u003emax_expected \u0026\u0026\n-\t\t    master_help-\u003eexpecting[expect-\u003eclass] \u003e= p-\u003emax_expected)\n+\t\tif (master_help-\u003eexpecting[expect-\u003eclass] \u003e= p-\u003emax_expected)\n \t\t\tevict_oldest_expect(master_help, expect, p);\n+\t} else {\n+\t\tconst struct nf_conntrack_expect_policy default_exp_policy = {\n+\t\t\t.max_expected = NF_CT_EXPECT_MAX_CNT,\n+\t\t};\n+\n+\t\tif (master_help-\u003eexpecting[expect-\u003eclass] \u003e= default_exp_policy.max_expected)\n+\t\t\tevict_oldest_expect(master_help, expect, \u0026default_exp_policy);\n \t}\n \n \tcnet = nf_ct_pernet(net);\ndiff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c\nindex 8b94001c243066..500509b17663ed 100644\n--- a/net/netfilter/nf_conntrack_helper.c\n+++ b/net/netfilter/nf_conntrack_helper.c\n@@ -374,8 +374,13 @@ int __nf_conntrack_helper_register(struct nf_conntrack_helper *me)\n \tif (!nf_ct_helper_hash)\n \t\treturn -ENOENT;\n \n-\tif (me-\u003eexpect_policy-\u003emax_expected \u003e NF_CT_EXPECT_MAX_CNT)\n-\t\treturn -EINVAL;\n+\tfor (i = 0; i \u003c= me-\u003eexpect_class_max; i++) {\n+\t\tif (!me-\u003eexpect_policy[i].max_expected)\n+\t\t\tme-\u003eexpect_policy[i].max_expected = NF_CT_EXPECT_MAX_CNT;\n+\n+\t\tif (me-\u003eexpect_policy[i].max_expected \u003e NF_CT_EXPECT_MAX_CNT)\n+\t\t\treturn -EINVAL;\n+\t}\n \n \tmutex_lock(\u0026nf_ct_helper_mutex);\n \tfor (i = 0; i \u003c nf_ct_helper_hsize; i++) {\ndiff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c\nindex 0c117b8492e992..193ab34db795f9 100644\n--- a/net/netfilter/nf_conntrack_irc.c\n+++ b/net/netfilter/nf_conntrack_irc.c\n@@ -262,6 +262,8 @@ static int __init nf_conntrack_irc_init(void)\n {\n \tint i, ret;\n \n+\tnf_conntrack_helper_deprecated(HELPER_NAME);\n+\n \tif (max_dcc_channels \u003c 1) {\n \t\tpr_err(\"max_dcc_channels must not be zero\\n\");\n \t\treturn -EINVAL;\ndiff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c\nindex 4e78d24829895e..4217715d42dc24 100644\n--- a/net/netfilter/nf_conntrack_netlink.c\n+++ b/net/netfilter/nf_conntrack_netlink.c\n@@ -1953,19 +1953,6 @@ static int ctnetlink_change_helper(struct nf_conn *ct,\n \t\treturn err;\n \t}\n \n-\tif (!strcmp(helpname, \"\") \u0026\u0026 help) {\n-\t\thelper = rcu_dereference(help-\u003ehelper);\n-\t\tif (helper) {\n-\t\t\t/* we had a helper before ... */\n-\t\t\tnf_ct_remove_expectations(ct);\n-\t\t\tRCU_INIT_POINTER(help-\u003ehelper, NULL);\n-\t\t\tif (refcount_dec_and_test(\u0026helper-\u003ect_refcnt))\n-\t\t\t\tkfree_rcu(helper, rcu);\n-\t\t}\n-\t\trcu_read_unlock();\n-\t\treturn 0;\n-\t}\n-\n \thelper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct),\n \t\t\t\t\t    nf_ct_protonum(ct));\n \tif (helper == NULL) {\n@@ -3015,7 +3002,6 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,\n \t\t\t  const struct nf_conntrack_expect *exp)\n {\n \t__s32 timeout = (__s32)(READ_ONCE(exp-\u003etimeout) - nfct_time_stamp) / HZ;\n-\tstruct nf_conn *master = exp-\u003emaster;\n \tstruct nf_conntrack_helper *helper;\n #if IS_ENABLED(CONFIG_NF_NAT)\n \tstruct nlattr *nest_parms;\n@@ -3030,9 +3016,7 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,\n \t\tgoto nla_put_failure;\n \tif (ctnetlink_exp_dump_mask(skb, \u0026exp-\u003etuple, \u0026exp-\u003emask) \u003c 0)\n \t\tgoto nla_put_failure;\n-\tif (ctnetlink_exp_dump_tuple(skb,\n-\t\t\t\t \u0026master-\u003etuplehash[IP_CT_DIR_ORIGINAL].tuple,\n-\t\t\t\t CTA_EXPECT_MASTER) \u003c 0)\n+\tif (ctnetlink_exp_dump_tuple(skb, \u0026exp-\u003emaster_tuple, CTA_EXPECT_MASTER) \u003c 0)\n \t\tgoto nla_put_failure;\n \n #if IS_ENABLED(CONFIG_NF_NAT)\n@@ -3045,9 +3029,9 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,\n \t\tif (nla_put_be32(skb, CTA_EXPECT_NAT_DIR, htonl(exp-\u003edir)))\n \t\t\tgoto nla_put_failure;\n \n-\t\tnat_tuple.src.l3num = nf_ct_l3num(master);\n+\t\tnat_tuple.src.l3num = exp-\u003emaster_tuple.src.l3num;\n \t\tnat_tuple.src.u3 = exp-\u003esaved_addr;\n-\t\tnat_tuple.dst.protonum = nf_ct_protonum(master);\n+\t\tnat_tuple.dst.protonum = exp-\u003emaster_tuple.dst.protonum;\n \t\tnat_tuple.src.u = exp-\u003esaved_proto;\n \n \t\tif (ctnetlink_exp_dump_tuple(skb, \u0026nat_tuple,\n@@ -3589,6 +3573,7 @@ ctnetlink_alloc_expect(const struct nlattr * const cda[], struct nf_conn *ct,\n #endif\n \trcu_assign_pointer(exp-\u003ehelper, helper);\n \trcu_assign_pointer(exp-\u003eassign_helper, assign_helper);\n+\texp-\u003emaster_tuple = ct-\u003etuplehash[IP_CT_DIR_ORIGINAL].tuple;\n \texp-\u003etuple = *tuple;\n \texp-\u003emask.src.u3 = mask-\u003esrc.u3;\n \texp-\u003emask.src.u.all = mask-\u003esrc.u.all;\ndiff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c\nindex 776505a78e6456..80fc14c87ddc4b 100644\n--- a/net/netfilter/nf_conntrack_pptp.c\n+++ b/net/netfilter/nf_conntrack_pptp.c\n@@ -545,6 +545,8 @@ static int __init nf_conntrack_pptp_init(void)\n \n \tpptp.destroy = gre_pptp_destroy_siblings;\n \n+\tnf_conntrack_helper_deprecated(pptp.name);\n+\n \treturn nf_conntrack_helper_register(\u0026pptp, \u0026pptp_ptr);\n }\n \ndiff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c\nindex e7a3fb2b2d9466..29e93ac1e2e400 100644\n--- a/net/netfilter/nf_flow_table_ip.c\n+++ b/net/netfilter/nf_flow_table_ip.c\n@@ -326,8 +326,10 @@ static bool nf_flow_ip4_tunnel_proto(struct nf_flowtable_ctx *ctx,\n \t\treturn false;\n \n \tiph = (struct iphdr *)(skb_network_header(skb) + ctx-\u003eoffset);\n-\tsize = iph-\u003eihl \u003c\u003c 2;\n+\tif (iph-\u003eihl \u003c 5)\n+\t\treturn false;\n \n+\tsize = iph-\u003eihl \u003c\u003c 2;\n \tif (ip_is_fragment(iph) || unlikely(ip_has_options(size)))\n \t\treturn false;\n \n@@ -335,9 +337,9 @@ static bool nf_flow_ip4_tunnel_proto(struct nf_flowtable_ctx *ctx,\n \t\treturn false;\n \n \tif (iph-\u003eprotocol == IPPROTO_IPIP) {\n-\t\tctx-\u003etun.proto = IPPROTO_IPIP;\n+\t\tctx-\u003etun.proto = iph-\u003eprotocol;\n \t\tctx-\u003etun.hdr_size = size;\n-\t\tctx-\u003eoffset += size;\n+\t\tctx-\u003eoffset += ctx-\u003etun.hdr_size;\n \t}\n \n \treturn true;\ndiff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c\nindex 2bbf5163c0e273..63ff6b4d5d214a 100644\n--- a/net/netfilter/nf_nat_core.c\n+++ b/net/netfilter/nf_nat_core.c\n@@ -1181,6 +1181,16 @@ int nf_nat_register_fn(struct net *net, u8 pf, const struct nf_hook_ops *ops,\n \tstruct nf_hook_ops *nat_ops;\n \tint i, ret;\n \n+#ifndef MODULE\n+\t/* If nf_nat_core is built-in and nf_nat_init() fails, dependent\n+\t * modules like nft_chain_nat.ko may still call this function.\n+\t * However, nat_net would be invalid, likely pointing to some other\n+\t * per-net structure.\n+\t */\n+\tif (WARN_ON_ONCE(!nf_nat_hook))\n+\t\treturn -EOPNOTSUPP;\n+#endif\n+\n \tif (WARN_ON_ONCE(pf \u003e= ARRAY_SIZE(nat_net-\u003enat_proto_net)))\n \t\treturn -EINVAL;\n \ndiff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c\nindex 0caa9304d2d030..63864b92825909 100644\n--- a/net/netfilter/nft_compat.c\n+++ b/net/netfilter/nft_compat.c\n@@ -397,6 +397,22 @@ static int nft_target_validate(const struct nft_ctx *ctx,\n \treturn 0;\n }\n \n+static int nft_target_bridge_validate(const struct nft_ctx *ctx,\n+\t\t\t\t      const struct nft_expr *expr)\n+{\n+\tstruct xt_target *target = expr-\u003eops-\u003edata;\n+\n+\t/* Do not allow UNSPEC to stand-in for NFPROTO_BRIDGE\n+\t * targets: they are incompatible.  ebtables targets return\n+\t * EBT_ACCEPT, DROP and so on which are not compatible with\n+\t * NF_ACCEPT, NF_DROP and so on.\n+\t */\n+\tif (target-\u003efamily != NFPROTO_BRIDGE)\n+\t\treturn -ENOENT;\n+\n+\treturn nft_target_validate(ctx, expr);\n+}\n+\n static void __nft_match_eval(const struct nft_expr *expr,\n \t\t\t     struct nft_regs *regs,\n \t\t\t     const struct nft_pktinfo *pkt,\n@@ -932,13 +948,15 @@ nft_target_select_ops(const struct nft_ctx *ctx,\n \tops-\u003einit = nft_target_init;\n \tops-\u003edestroy = nft_target_destroy;\n \tops-\u003edump = nft_target_dump;\n-\tops-\u003evalidate = nft_target_validate;\n \tops-\u003edata = target;\n \n-\tif (family == NFPROTO_BRIDGE)\n+\tif (family == NFPROTO_BRIDGE) {\n \t\tops-\u003eeval = nft_target_eval_bridge;\n-\telse\n+\t\tops-\u003evalidate = nft_target_bridge_validate;\n+\t} else {\n \t\tops-\u003eeval = nft_target_eval_xt;\n+\t\tops-\u003evalidate = nft_target_validate;\n+\t}\n \n \treturn ops;\n err:\ndiff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c\nindex 958054dd2e2ecc..03a88c77e0f028 100644\n--- a/net/netfilter/nft_ct.c\n+++ b/net/netfilter/nft_ct.c\n@@ -1215,11 +1215,23 @@ struct nft_ct_expect_obj {\n \tu32\t\ttimeout;\n };\n \n+static int nft_ct_expect_timeout_get(const struct nlattr *attr, u32 *val)\n+{\n+\tunsigned long jiffies_val = msecs_to_jiffies(nla_get_u32(attr));\n+\n+\tif (jiffies_val \u003e UINT_MAX)\n+\t\treturn -ERANGE;\n+\n+\t*val = jiffies_val;\n+\treturn 0;\n+}\n+\n static int nft_ct_expect_obj_init(const struct nft_ctx *ctx,\n \t\t\t\t  const struct nlattr * const tb[],\n \t\t\t\t  struct nft_object *obj)\n {\n \tstruct nft_ct_expect_obj *priv = nft_obj_data(obj);\n+\tint err;\n \n \tif (!tb[NFTA_CT_EXPECT_L4PROTO] ||\n \t    !tb[NFTA_CT_EXPECT_DPORT] ||\n@@ -1254,8 +1266,11 @@ static int nft_ct_expect_obj_init(const struct nft_ctx *ctx,\n \t\treturn -EOPNOTSUPP;\n \t}\n \n+\terr = nft_ct_expect_timeout_get(tb[NFTA_CT_EXPECT_TIMEOUT], \u0026priv-\u003etimeout);\n+\tif (err)\n+\t\treturn err;\n+\n \tpriv-\u003edport = nla_get_be16(tb[NFTA_CT_EXPECT_DPORT]);\n-\tpriv-\u003etimeout = nla_get_u32(tb[NFTA_CT_EXPECT_TIMEOUT]);\n \tpriv-\u003esize = nla_get_u8(tb[NFTA_CT_EXPECT_SIZE]);\n \n \treturn nf_ct_netns_get(ctx-\u003enet, ctx-\u003efamily);\n@@ -1275,7 +1290,7 @@ static int nft_ct_expect_obj_dump(struct sk_buff *skb,\n \tif (nla_put_be16(skb, NFTA_CT_EXPECT_L3PROTO, htons(priv-\u003el3num)) ||\n \t    nla_put_u8(skb, NFTA_CT_EXPECT_L4PROTO, priv-\u003el4proto) ||\n \t    nla_put_be16(skb, NFTA_CT_EXPECT_DPORT, priv-\u003edport) ||\n-\t    nla_put_u32(skb, NFTA_CT_EXPECT_TIMEOUT, priv-\u003etimeout) ||\n+\t    nla_put_u32(skb, NFTA_CT_EXPECT_TIMEOUT, jiffies_to_msecs(priv-\u003etimeout)) ||\n \t    nla_put_u8(skb, NFTA_CT_EXPECT_SIZE, priv-\u003esize))\n \t\treturn -1;\n \n@@ -1325,7 +1340,7 @@ static void nft_ct_expect_obj_eval(struct nft_object *obj,\n \t\t          \u0026ct-\u003etuplehash[!dir].tuple.src.u3,\n \t\t          \u0026ct-\u003etuplehash[!dir].tuple.dst.u3,\n \t\t          priv-\u003el4proto, NULL, \u0026priv-\u003edport);\n-\texp-\u003etimeout += priv-\u003etimeout * HZ;\n+\texp-\u003etimeout += priv-\u003etimeout;\n \n \tif (nf_ct_expect_related(exp, 0) != 0)\n \t\tregs-\u003everdict.code = NF_DROP;\ndiff --git a/net/netfilter/nft_synproxy.c b/net/netfilter/nft_synproxy.c\nindex 7641f249614c97..9ed288c9d16880 100644\n--- a/net/netfilter/nft_synproxy.c\n+++ b/net/netfilter/nft_synproxy.c\n@@ -24,14 +24,13 @@ static const struct nla_policy nft_synproxy_policy[NFTA_SYNPROXY_MAX + 1] = {\n static void nft_synproxy_tcp_options(struct synproxy_options *opts,\n \t\t\t\t     const struct tcphdr *tcp,\n \t\t\t\t     struct synproxy_net *snet,\n-\t\t\t\t     struct nf_synproxy_info *info,\n-\t\t\t\t     const struct nft_synproxy *priv)\n+\t\t\t\t     struct nf_synproxy_info *info)\n {\n \tthis_cpu_inc(snet-\u003estats-\u003esyn_received);\n \tif (tcp-\u003eece \u0026\u0026 tcp-\u003ecwr)\n \t\topts-\u003eoptions |= NF_SYNPROXY_OPT_ECN;\n \n-\topts-\u003eoptions \u0026= priv-\u003einfo.options;\n+\topts-\u003eoptions \u0026= info-\u003eoptions;\n \topts-\u003emss_encode = opts-\u003emss_option;\n \topts-\u003emss_option = info-\u003emss;\n \tif (opts-\u003eoptions \u0026 NF_SYNPROXY_OPT_TIMESTAMP)\n@@ -56,7 +55,7 @@ static void nft_synproxy_eval_v4(const struct nft_synproxy *priv,\n \n \tif (tcp-\u003esyn) {\n \t\t/* Initial SYN from client */\n-\t\tnft_synproxy_tcp_options(opts, tcp, snet, \u0026info, priv);\n+\t\tnft_synproxy_tcp_options(opts, tcp, snet, \u0026info);\n \t\tsynproxy_send_client_synack(net, skb, tcp, opts);\n \t\tconsume_skb(skb);\n \t\tregs-\u003everdict.code = NF_STOLEN;\n@@ -87,7 +86,7 @@ static void nft_synproxy_eval_v6(const struct nft_synproxy *priv,\n \n \tif (tcp-\u003esyn) {\n \t\t/* Initial SYN from client */\n-\t\tnft_synproxy_tcp_options(opts, tcp, snet, \u0026info, priv);\n+\t\tnft_synproxy_tcp_options(opts, tcp, snet, \u0026info);\n \t\tsynproxy_send_client_synack_ipv6(net, skb, tcp, opts);\n \t\tconsume_skb(skb);\n \t\tregs-\u003everdict.code = NF_STOLEN;\ndiff --git a/tools/testing/selftests/net/netfilter/conntrack_sctp_collision.sh b/tools/testing/selftests/net/netfilter/conntrack_sctp_collision.sh\nindex d860f7d9744bf8..7261975957ef18 100755\n--- a/tools/testing/selftests/net/netfilter/conntrack_sctp_collision.sh\n+++ b/tools/testing/selftests/net/netfilter/conntrack_sctp_collision.sh\n@@ -2,18 +2,32 @@\n # SPDX-License-Identifier: GPL-2.0\n #\n # Testing For SCTP COLLISION SCENARIO as Below:\n-#\n+# 1. Stale INIT_ACK capture:\n #   14:35:47.655279 IP CLIENT_IP.PORT \u003e SERVER_IP.PORT: sctp (1) [INIT] [init tag: 2017837359]\n #   14:35:48.353250 IP SERVER_IP.PORT \u003e CLIENT_IP.PORT: sctp (1) [INIT] [init tag: 1187206187]\n #   14:35:48.353275 IP CLIENT_IP.PORT \u003e SERVER_IP.PORT: sctp (1) [INIT ACK] [init tag: 2017837359]\n #   14:35:48.353283 IP SERVER_IP.PORT \u003e CLIENT_IP.PORT: sctp (1) [COOKIE ECHO]\n #   14:35:48.353977 IP CLIENT_IP.PORT \u003e SERVER_IP.PORT: sctp (1) [COOKIE ACK]\n #   14:35:48.855335 IP SERVER_IP.PORT \u003e CLIENT_IP.PORT: sctp (1) [INIT ACK] [init tag: 164579970]\n+#   (Delayed)\n+#\n+# 2. Stale INIT capture:\n+#   14:35:48.353250 IP SERVER_IP.PORT \u003e CLIENT_IP.PORT: sctp (1) [INIT] [init tag: 1187206187]\n+#   14:35:48.353275 IP CLIENT_IP.PORT \u003e SERVER_IP.PORT: sctp (1) [INIT ACK] [init tag: 2017837359]\n+#   14:35:48.353283 IP SERVER_IP.PORT \u003e CLIENT_IP.PORT: sctp (1) [COOKIE ECHO]\n+#   14:35:48.353977 IP CLIENT_IP.PORT \u003e SERVER_IP.PORT: sctp (1) [COOKIE ACK]\n+#   14:35:47.655279 IP CLIENT_IP.PORT \u003e SERVER_IP.PORT: sctp (1) [INIT] [init tag: 2017837359]\n+#   (Delayed)\n+#   14:35:48.855335 IP SERVER_IP.PORT \u003e CLIENT_IP.PORT: sctp (1) [INIT ACK] [init tag: 164579970]\n #\n # TOPO: SERVER_NS (link0)\u003c---\u003e(link1) ROUTER_NS (link2)\u003c---\u003e(link3) CLIENT_NS\n \n source lib.sh\n \n+checktool \"nft --version\" \"run test without nft\"\n+checktool \"tc -h\" \"run test without tc\"\n+checktool \"modprobe -q sctp\" \"load sctp module\"\n+\n CLIENT_IP=\"198.51.200.1\"\n CLIENT_PORT=1234\n \n@@ -24,7 +38,8 @@ CLIENT_GW=\"198.51.200.2\"\n SERVER_GW=\"198.51.100.2\"\n \n # setup the topo\n-setup() {\n+topo_setup() {\n+\t# setup_ns cleans up existing net namespaces first.\n \tsetup_ns CLIENT_NS SERVER_NS ROUTER_NS\n \tip -n \"$SERVER_NS\" link add link0 type veth peer name link1 netns \"$ROUTER_NS\"\n \tip -n \"$CLIENT_NS\" link add link3 type veth peer name link2 netns \"$ROUTER_NS\"\n@@ -38,35 +53,53 @@ setup() {\n \tip -n \"$ROUTER_NS\" addr add $SERVER_GW/24 dev link1\n \tip -n \"$ROUTER_NS\" addr add $CLIENT_GW/24 dev link2\n \tip net exec \"$ROUTER_NS\" sysctl -wq net.ipv4.ip_forward=1\n+\tsysctl -wq net.netfilter.nf_log_all_netns=1\n \n \tip -n \"$CLIENT_NS\" link set link3 up\n \tip -n \"$CLIENT_NS\" addr add $CLIENT_IP/24 dev link3\n \tip -n \"$CLIENT_NS\" route add $SERVER_IP dev link3 via $CLIENT_GW\n+}\n+\n+conf_delay()\n+{\n+\t# simulate the delay on OVS upcall by setting up a delay for INIT_ACK/INIT with\n+\tlocal ns=$1\n+\tlocal link=$2\n+\tlocal chunk_type=$3\n \n-\t# simulate the delay on OVS upcall by setting up a delay for INIT_ACK with\n-\t# tc on $SERVER_NS side\n-\ttc -n \"$SERVER_NS\" qdisc add dev link0 root handle 1: htb r2q 64\n-\ttc -n \"$SERVER_NS\" class add dev link0 parent 1: classid 1:1 htb rate 100mbit\n-\ttc -n \"$SERVER_NS\" filter add dev link0 parent 1: protocol ip u32 match ip protocol 132 \\\n-\t\t0xff match u8 2 0xff at 32 flowid 1:1\n-\tif ! tc -n \"$SERVER_NS\" qdisc add dev link0 parent 1:1 handle 10: netem delay 1200ms; then\n+\t# use a smaller number for assoc's max_retrans to reproduce the issue\n+\tip net exec \"$CLIENT_NS\" sysctl -wq net.sctp.association_max_retrans=3\n+\n+\ttc -n \"$ns\" qdisc add dev \"$link\" root handle 1: htb r2q 64\n+\ttc -n \"$ns\" class add dev \"$link\" parent 1: classid 1:1 htb rate 100mbit\n+\ttc -n \"$ns\" filter add dev \"$link\" parent 1: protocol ip \\\n+\t\tu32 match ip protocol 132 0xff match u8 \"$chunk_type\" 0xff at 32 flowid 1:1\n+\tif ! tc -n \"$ns\" qdisc add dev \"$link\" parent 1:1 handle 10: netem delay 1200ms; then\n \t\techo \"SKIP: Cannot add netem qdisc\"\n-\t\texit $ksft_skip\n+\t\treturn $ksft_skip\n \tfi\n \n \t# simulate the ctstate check on OVS nf_conntrack\n-\tip net exec \"$ROUTER_NS\" iptables -A FORWARD -m state --state INVALID,UNTRACKED -j DROP\n-\tip net exec \"$ROUTER_NS\" iptables -A INPUT -p sctp -j DROP\n-\n-\t# use a smaller number for assoc's max_retrans to reproduce the issue\n-\tmodprobe -q sctp\n-\tip net exec \"$CLIENT_NS\" sysctl -wq net.sctp.association_max_retrans=3\n+\tip net exec \"$ROUTER_NS\" nft -f - \u003c\u003c-EOF\n+\ttable ip t {\n+\t\tchain forward {\n+\t\t\ttype filter hook forward priority filter; policy accept;\n+\t\t\tmeta l4proto icmp counter accept\n+\t\t\tct state new counter accept\n+\t\t\tct state established,related counter accept\n+\t\t\tct state invalid log flags all counter drop comment \\\n+\t\t\t\"Expect to drop stale INIT/INIT_ACK chunks\"\n+\t\t\tcounter\n+\t\t}\n+\t}\n+\tEOF\n+\treturn 0\n }\n \n cleanup() {\n-\tip net exec \"$CLIENT_NS\" pkill sctp_collision \u003e/dev/null 2\u003e\u00261\n-\tip net exec \"$SERVER_NS\" pkill sctp_collision \u003e/dev/null 2\u003e\u00261\n+\t# cleanup_all_ns terminates running processes in the namespaces.\n \tcleanup_all_ns\n+\tsysctl -wq net.netfilter.nf_log_all_netns=0\n }\n \n do_test() {\n@@ -81,7 +114,19 @@ do_test() {\n \n # run the test case\n trap cleanup EXIT\n-setup \u0026\u0026 \\\n-echo \"Test for SCTP Collision in nf_conntrack:\" \u0026\u0026 \\\n-do_test \u0026\u0026 echo \"PASS!\"\n-exit $?\n+\n+echo \"Test for SCTP INIT_ACK Collision in nf_conntrack:\"\n+topo_setup || exit $?\n+conf_delay $SERVER_NS link0 2 || exit $?\n+\n+if ! do_test; then\n+\texit $ksft_fail\n+fi\n+\n+echo \"Test for SCTP INIT Collision in nf_conntrack:\"\n+topo_setup || exit $?\n+conf_delay $CLIENT_NS link3 1 || exit $?\n+\n+if ! do_test; then\n+\texit $ksft_fail\n+fi\ndiff --git a/tools/testing/selftests/net/netfilter/nft_queue.sh b/tools/testing/selftests/net/netfilter/nft_queue.sh\nindex d80390848e8509..7c857a2e0f3494 100755\n--- a/tools/testing/selftests/net/netfilter/nft_queue.sh\n+++ b/tools/testing/selftests/net/netfilter/nft_queue.sh\n@@ -85,11 +85,12 @@ ip -net \"$ns3\" route add default via 10.0.3.1\n ip -net \"$ns3\" route add default via dead:3::1\n \n load_ruleset() {\n-\tlocal name=$1\n-\tlocal prio=$2\n+\tlocal family=$1\n+\tlocal name=$2\n+\tlocal prio=$3\n \n ip netns exec \"$nsrouter\" nft -f /dev/stdin \u003c\u003cEOF\n-table inet $name {\n+table $family $name {\n \tchain nfq {\n \t\tip protocol icmp queue bypass\n \t\ticmpv6 type { \"echo-request\", \"echo-reply\" } queue num 1 bypass\n@@ -228,6 +229,7 @@ nf_queue_wait()\n test_queue()\n {\n \tlocal expected=\"$1\"\n+\tlocal family=\"$2\"\n \tlocal last=\"\"\n \n \t# spawn nf_queue listeners\n@@ -255,11 +257,13 @@ test_queue()\n \t\tif [ x\"$last\" != x\"$expected packets total\" ]; then\n \t\t\techo \"FAIL: Expected $expected packets total, but got $last\" 1\u003e\u00262\n \t\t\tip netns exec \"$nsrouter\" nft list ruleset\n+\t\t\techo -n \"$TMPFILE0: \";cat \"$TMPFILE0\"\n+\t\t\techo -n \"$TMPFILE1: \";cat \"$TMPFILE1\"\n \t\t\texit 1\n \t\tfi\n \tdone\n \n-\techo \"PASS: Expected and received $last\"\n+\techo \"PASS: Expected and received $last ($family)\"\n }\n \n listener_ready()\n@@ -400,6 +404,8 @@ EOF\n \n \tkill \"$nfqpid\"\n \techo \"PASS: icmp+nfqueue via vrf\"\n+\tip -net \"$ns1\" link del tvrf\n+\tip netns exec \"$ns1\" nft flush ruleset\n }\n \n sctp_listener_ready()\n@@ -814,12 +820,53 @@ EOF\n \tcheck_tainted \"queue program exiting while packets queued\"\n }\n \n+test_queue_bridge()\n+{\n+\tip -net \"$nsrouter\" addr flush dev veth0\n+\tip -net \"$nsrouter\" addr flush dev veth1\n+\n+\tip -net \"$nsrouter\" link add br0 type bridge\n+\tip -net \"$nsrouter\" link set veth0 master br0\n+\tip -net \"$nsrouter\" link set veth1 master br0\n+\n+\tip -net \"$nsrouter\" link set br0 up\n+\n+\tip -net \"$nsrouter\" addr add 10.0.2.1/16 dev br0\n+\tip -net \"$nsrouter\" addr add dead:2::1/64 dev br0 nodad\n+\n+\tip -net \"$ns1\" addr flush dev eth0\n+\tip -net \"$ns2\" addr flush dev eth0\n+\n+\tip -net \"$ns1\" addr add 10.0.1.1/16 dev eth0\n+\tip -net \"$ns1\" addr add dead:2::2/64 dev eth0 nodad\n+\n+\tip -net \"$ns2\" addr add 10.0.2.99/16 dev eth0\n+\tip -net \"$ns2\" addr add dead:2::99/64 dev eth0 nodad\n+\n+\tip netns exec \"$nsrouter\" nft flush ruleset\n+\n+\tip netns exec \"$nsrouter\" sysctl net.ipv6.conf.all.forwarding=0 \u003e /dev/null\n+\tip netns exec \"$nsrouter\" sysctl net.ipv4.conf.veth0.forwarding=0 \u003e /dev/null\n+\tip netns exec \"$nsrouter\" sysctl net.ipv4.conf.veth1.forwarding=0 \u003e /dev/null\n+\n+\tif ! test_ping;then\n+\t\techo \"FAIL: netns bridge connectivity\" 1\u003e\u00262\n+\t\texit $ret\n+\tfi\n+\n+\tload_ruleset \"bridge\" \"filter\" 10\n+\ttest_queue 10 \"bridge\"\n+\n+\tload_ruleset \"bridge\" \"filter2\" 20\n+\ttest_queue 20 \"bridge\"\n+}\n+\n ip netns exec \"$nsrouter\" sysctl net.ipv6.conf.all.forwarding=1 \u003e /dev/null\n ip netns exec \"$nsrouter\" sysctl net.ipv4.conf.veth0.forwarding=1 \u003e /dev/null\n ip netns exec \"$nsrouter\" sysctl net.ipv4.conf.veth1.forwarding=1 \u003e /dev/null\n ip netns exec \"$nsrouter\" sysctl net.ipv4.conf.veth2.forwarding=1 \u003e /dev/null\n \n-load_ruleset \"filter\" 0\n+load_ruleset \"inet\" \"filter\" 0\n \n if test_ping; then\n \t# queue bypass works (rules were skipped, no listener)\n@@ -842,11 +889,11 @@ load_counter_ruleset 10\n # 1x icmp prerouting,forward,postrouting -\u003e 3 queue events (6 incl. reply).\n # 1x icmp prerouting,input,output postrouting -\u003e 4 queue events incl. reply.\n # so we expect that userspace program receives 10 packets.\n-test_queue 10\n+test_queue 10 \"inet\"\n \n # same.  We queue to a second program as well.\n-load_ruleset \"filter2\" 20\n-test_queue 20\n+load_ruleset \"inet\" \"filter2\" 20\n+test_queue 20 \"inet\"\n ip netns exec \"$ns1\" nft flush ruleset\n \n test_tcp_forward\n@@ -863,4 +910,7 @@ test_queue_stress\n test_icmp_vrf\n test_queue_removal\n \n+# turns router into a bridge\n+test_queue_bridge\n+\n exit $ret\n"
}

2/1 2026/06/23 22:41 agent patch-evaluator
1m Model:
gemini-3.1-pro-preview

Args:
null

Results:
{
  "EnableConfigs": [
    "NETFILTER_CONNCOUNT",
    "NF_CONNTRACK",
    "NF_CT_NETLINK",
    "NF_FLOW_TABLE",
    "NFT_COMPAT",
    "NFT_CT",
    "NFT_SYNPROXY"
  ],
  "FocusSymbols": [
    "__nf_conncount_add",
    "__nf_ct_expect_check",
    "__nf_conntrack_helper_register",
    "ctnetlink_change_helper",
    "ctnetlink_alloc_expect",
    "nf_flow_ip4_tunnel_proto",
    "nft_target_bridge_validate",
    "nft_ct_expect_obj_init",
    "nft_ct_expect_obj_eval",
    "nft_synproxy_eval_v4",
    "nft_synproxy_eval_v6"
  ],
  "Reasoning": "The patch series makes functional changes to netfilter, including connection tracking, flow tables, and nftables compatibility. It modifies the logic for connection counting, expectation checking, helper registration, and netlink handling. It also adds a new validation function for bridge targets in nft_compat and fixes timeout handling in nft_ct. These changes affect core netfilter functionality and are reachable from userspace via netlink or by processing network packets, making them suitable for fuzzing.",
  "WorthFuzzing": true
}

Instruction:
You are an expert Linux kernel maintainer.
Your job is to review a provided patch series and determine
if it makes functional changes to the kernel that should be fuzzed.

IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively
use your code access tools to examine the actual source code and confirm any assumptions.

Return WorthFuzzing=false if the patch only contains:
- Modifications to Documentation/, Kconfig files, or code comments.
- Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints.
- Changes to numeric constants or macros that do not functionally alter execution flow.
- Code paths that are impossible to reach in virtualized environments like GCE or QEMU,
even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim).

If it modifies reachable core kernel logic, drivers, or architectures, use your code search
tools to verify the code can be executed, then return WorthFuzzing=true.

When returning WorthFuzzing=true, you MUST ALSO:
1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols.
   Avoid listing generic hot-path functions to prevent skewed test distributions.
2. Identify any specific CONFIG_ options required to properly test this new/modified feature.
   Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions.
   Do not list too generic configs (we already have them enabled). Only list those that
   specifically cover the modified code. List them in the EnableConfigs output array,
   and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.


Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.

Prompt:
For your convenience, here is the diff of the changes:
commit 0521dd18f12b62aba26f086a31e4902031db9962
Author: syz-cluster <triage@syzkaller.com>
Date:   Tue Jun 23 22:41:17 2026 +0000

    syz-cluster: applied patch under review

diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 20d70dddbe5098..25062f4a0dd5f1 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -18,7 +18,7 @@
  * @match:	the match extension
  * @target:	the target extension
  * @matchinfo:	per-match data
- * @targetinfo:	per-target data
+ * @targinfo:	per-target data
  * @state:	pointer to hook state this packet came from
  * @fragoff:	packet is a fragment, this is the data offset
  * @thoff:	position of transport header relative to skb->data
@@ -77,7 +77,9 @@ static inline u_int8_t xt_family(const struct xt_action_param *par)
  * @match:	struct xt_match through which this function was invoked
  * @matchinfo:	per-match data
  * @hook_mask:	via which hooks the new rule is reachable
- * Other fields as above.
+ * @family:	actual NFPROTO_* through which the function is invoked
+ *		(helpful when match->family == NFPROTO_UNSPEC)
+ * @nft_compat:	running from the nft compat layer if true
  */
 struct xt_mtchk_param {
 	struct net *net;
@@ -91,8 +93,13 @@ struct xt_mtchk_param {
 };
 
 /**
- * struct xt_mdtor_param - match destructor parameters
- * Fields as above.
+ * struct xt_mtdtor_param - match destructor parameters
+ *
+ * @net:	network namespace through which the check was invoked
+ * @match:	struct xt_match through which this function was invoked
+ * @matchinfo:	per-match data
+ * @family:	actual NFPROTO_* through which the function is invoked
+ *		(helpful when match->family == NFPROTO_UNSPEC)
  */
 struct xt_mtdtor_param {
 	struct net *net;
@@ -105,10 +112,16 @@ struct xt_mtdtor_param {
  * struct xt_tgchk_param - parameters for target extensions'
  * checkentry functions
  *
+ * @net:	network namespace through which the check was invoked
+ * @table:	table the rule is tried to be inserted into
  * @entryinfo:	the family-specific rule data
  * 		(struct ipt_entry, ip6t_entry, arpt_entry, ebt_entry)
- *
- * Other fields see above.
+ * @target:	the target extension
+ * @targinfo:	per-target data
+ * @hook_mask:	via which hooks the new rule is reachable
+ * @family:	actual NFPROTO_* through which the function is invoked
+ *		(helpful when match->family == NFPROTO_UNSPEC)
+ * @nft_compat:	running from the nft compat layer if true
  */
 struct xt_tgchk_param {
 	struct net *net;
@@ -336,9 +349,9 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size);
 void xt_free_table_info(struct xt_table_info *info);
 
 /**
- * xt_recseq - recursive seqcount for netfilter use
+ * var xt_recseq - recursive seqcount for netfilter use
  *
- * Packet processing changes the seqcount only if no recursion happened
+ * Packet processing changes the seqcount only if no recursion happened.
  * get_counters() can use read_seqcount_begin()/read_seqcount_retry(),
  * because we use the normal seqcount convention :
  * Low order bit set to 1 if a writer is active.
diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h
index be4a120d549eb3..c024345c9bd862 100644
--- a/include/net/netfilter/nf_conntrack_expect.h
+++ b/include/net/netfilter/nf_conntrack_expect.h
@@ -26,6 +26,7 @@ struct nf_conntrack_expect {
 	possible_net_t net;
 
 	/* We expect this tuple, with the following mask */
+	struct nf_conntrack_tuple master_tuple;
 	struct nf_conntrack_tuple tuple;
 	struct nf_conntrack_tuple_mask mask;
 
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
index 81025101f86daa..c761cd8158b253 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -114,6 +114,10 @@ int nf_conntrack_helpers_register(struct nf_conntrack_helper *, unsigned int,
 void nf_conntrack_helpers_unregister(struct nf_conntrack_helper **,
 				     unsigned int);
 
+#define nf_conntrack_helper_deprecated(name) \
+	pr_warn("The %s conntrack helper is scheduled for removal.\n"	\
+		"Please contact the netfilter-devel mailing list if you still need this.\n", name)
+
 struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp);
 
 int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 665f8008cc4b27..4c04cd8d40a229 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -256,8 +256,7 @@ config NF_CONNTRACK_H323
 	  To compile it as a module, choose M here.  If unsure, say N.
 
 config NF_CONNTRACK_IRC
-	tristate "IRC protocol support"
-	default m if NETFILTER_ADVANCED=n
+	tristate "IRC DCC protocol support (obsolete)"
 	help
 	  There is a commonly-used extension to IRC called
 	  Direct Client-to-Client Protocol (DCC).  This enables users to send
@@ -267,6 +266,8 @@ config NF_CONNTRACK_IRC
 	  using NAT, this extension will enable you to send files and initiate
 	  chats.  Note that you do NOT need this extension to get files or
 	  have others initiate chats, or everything else in IRC.
+	  DCC tracking behind NAT requires plaintext (unencrypted) IRC, so
+	  this helper is of limited use these days.
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
@@ -308,17 +309,17 @@ config NF_CONNTRACK_SNMP
 	  To compile it as a module, choose M here.  If unsure, say N.
 
 config NF_CONNTRACK_PPTP
-	tristate "PPtP protocol support"
+	tristate "PPtP protocol support (deprecated)"
 	depends on NETFILTER_ADVANCED
 	select NF_CT_PROTO_GRE
 	help
 	  This module adds support for PPTP (Point to Point Tunnelling
 	  Protocol, RFC2637) connection tracking and NAT.
 
-	  If you are running PPTP sessions over a stateful firewall or NAT
+	  If you are still running PPTP sessions over a stateful firewall or NAT
 	  box, you may want to enable this feature.
 
-	  Please note that not all PPTP modes of operation are supported yet.
+	  Please note that not all PPTP modes of operation are supported.
 	  Specifically these limitations exist:
 	    - Blindly assumes that control connections are always established
 	      in PNS->PAC direction. This is a violation of RFC2637.
diff --git a/net/netfilter/nf_conncount.c b/net/netfilter/nf_conncount.c
index dd67004a5cc09e..91582069f6d2ee 100644
--- a/net/netfilter/nf_conncount.c
+++ b/net/netfilter/nf_conncount.c
@@ -183,17 +183,16 @@ static int __nf_conncount_add(struct net *net,
 		return -ENOENT;
 
 	if (ct && nf_ct_is_confirmed(ct)) {
-		/* local connections are confirmed in postrouting so confirmation
-		 * might have happened before hitting connlimit
+		/* Connection is confirmed but might still be in the setup phase.
+		 * Only skip the tracking if it is fully assured. This guarantees
+		 * that setup packets or retransmissions are properly counted and
+		 * deduplicated.
 		 */
-		if (skb->skb_iif != LOOPBACK_IFINDEX) {
+		if (test_bit(IPS_ASSURED_BIT, &ct->status)) {
 			err = -EEXIST;
 			goto out_put;
 		}
 
-		/* this is likely a local connection, skip optimization to avoid
-		 * adding duplicates from a 'packet train'
-		 */
 		goto check_connections;
 	}
 
diff --git a/net/netfilter/nf_conntrack_broadcast.c b/net/netfilter/nf_conntrack_broadcast.c
index 400119b6320e72..bf78828c7549d4 100644
--- a/net/netfilter/nf_conntrack_broadcast.c
+++ b/net/netfilter/nf_conntrack_broadcast.c
@@ -62,6 +62,7 @@ int nf_conntrack_broadcast_help(struct sk_buff *skb,
 	if (exp == NULL)
 		goto out;
 
+	exp->master_tuple	  = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
 	exp->tuple                = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
 
 	helper = rcu_dereference(help->helper);
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 49e18eda037ef1..38630c5e006f08 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -355,6 +355,8 @@ void nf_ct_expect_init(struct nf_conntrack_expect *exp, unsigned int class,
 	exp->tuple.src.l3num = family;
 	exp->tuple.dst.protonum = proto;
 
+	exp->master_tuple = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
+
 	if (saddr) {
 		memcpy(&exp->tuple.src.u3, saddr, len);
 		if (sizeof(exp->tuple.src.u3) > len)
@@ -494,9 +496,15 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect,
 					   lockdep_is_held(&nf_conntrack_expect_lock));
 	if (helper) {
 		p = &helper->expect_policy[expect->class];
-		if (p->max_expected &&
-		    master_help->expecting[expect->class] >= p->max_expected)
+		if (master_help->expecting[expect->class] >= p->max_expected)
 			evict_oldest_expect(master_help, expect, p);
+	} else {
+		const struct nf_conntrack_expect_policy default_exp_policy = {
+			.max_expected = NF_CT_EXPECT_MAX_CNT,
+		};
+
+		if (master_help->expecting[expect->class] >= default_exp_policy.max_expected)
+			evict_oldest_expect(master_help, expect, &default_exp_policy);
 	}
 
 	cnet = nf_ct_pernet(net);
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index 8b94001c243066..500509b17663ed 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -374,8 +374,13 @@ int __nf_conntrack_helper_register(struct nf_conntrack_helper *me)
 	if (!nf_ct_helper_hash)
 		return -ENOENT;
 
-	if (me->expect_policy->max_expected > NF_CT_EXPECT_MAX_CNT)
-		return -EINVAL;
+	for (i = 0; i <= me->expect_class_max; i++) {
+		if (!me->expect_policy[i].max_expected)
+			me->expect_policy[i].max_expected = NF_CT_EXPECT_MAX_CNT;
+
+		if (me->expect_policy[i].max_expected > NF_CT_EXPECT_MAX_CNT)
+			return -EINVAL;
+	}
 
 	mutex_lock(&nf_ct_helper_mutex);
 	for (i = 0; i < nf_ct_helper_hsize; i++) {
diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c
index 0c117b8492e992..193ab34db795f9 100644
--- a/net/netfilter/nf_conntrack_irc.c
+++ b/net/netfilter/nf_conntrack_irc.c
@@ -262,6 +262,8 @@ static int __init nf_conntrack_irc_init(void)
 {
 	int i, ret;
 
+	nf_conntrack_helper_deprecated(HELPER_NAME);
+
 	if (max_dcc_channels < 1) {
 		pr_err("max_dcc_channels must not be zero\n");
 		return -EINVAL;
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 4e78d24829895e..4217715d42dc24 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1953,19 +1953,6 @@ static int ctnetlink_change_helper(struct nf_conn *ct,
 		return err;
 	}
 
-	if (!strcmp(helpname, "") && help) {
-		helper = rcu_dereference(help->helper);
-		if (helper) {
-			/* we had a helper before ... */
-			nf_ct_remove_expectations(ct);
-			RCU_INIT_POINTER(help->helper, NULL);
-			if (refcount_dec_and_test(&helper->ct_refcnt))
-				kfree_rcu(helper, rcu);
-		}
-		rcu_read_unlock();
-		return 0;
-	}
-
 	helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct),
 					    nf_ct_protonum(ct));
 	if (helper == NULL) {
@@ -3015,7 +3002,6 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,
 			  const struct nf_conntrack_expect *exp)
 {
 	__s32 timeout = (__s32)(READ_ONCE(exp->timeout) - nfct_time_stamp) / HZ;
-	struct nf_conn *master = exp->master;
 	struct nf_conntrack_helper *helper;
 #if IS_ENABLED(CONFIG_NF_NAT)
 	struct nlattr *nest_parms;
@@ -3030,9 +3016,7 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,
 		goto nla_put_failure;
 	if (ctnetlink_exp_dump_mask(skb, &exp->tuple, &exp->mask) < 0)
 		goto nla_put_failure;
-	if (ctnetlink_exp_dump_tuple(skb,
-				 &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
-				 CTA_EXPECT_MASTER) < 0)
+	if (ctnetlink_exp_dump_tuple(skb, &exp->master_tuple, CTA_EXPECT_MASTER) < 0)
 		goto nla_put_failure;
 
 #if IS_ENABLED(CONFIG_NF_NAT)
@@ -3045,9 +3029,9 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,
 		if (nla_put_be32(skb, CTA_EXPECT_NAT_DIR, htonl(exp->dir)))
 			goto nla_put_failure;
 
-		nat_tuple.src.l3num = nf_ct_l3num(master);
+		nat_tuple.src.l3num = exp->master_tuple.src.l3num;
 		nat_tuple.src.u3 = exp->saved_addr;
-		nat_tuple.dst.protonum = nf_ct_protonum(master);
+		nat_tuple.dst.protonum = exp->master_tuple.dst.protonum;
 		nat_tuple.src.u = exp->saved_proto;
 
 		if (ctnetlink_exp_dump_tuple(skb, &nat_tuple,
@@ -3589,6 +3573,7 @@ ctnetlink_alloc_expect(const struct nlattr * const cda[], struct nf_conn *ct,
 #endif
 	rcu_assign_pointer(exp->helper, helper);
 	rcu_assign_pointer(exp->assign_helper, assign_helper);
+	exp->master_tuple = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
 	exp->tuple = *tuple;
 	exp->mask.src.u3 = mask->src.u3;
 	exp->mask.src.u.all = mask->src.u.all;
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c
index 776505a78e6456..80fc14c87ddc4b 100644
--- a/net/netfilter/nf_conntrack_pptp.c
+++ b/net/netfilter/nf_conntrack_pptp.c
@@ -545,6 +545,8 @@ static int __init nf_conntrack_pptp_init(void)
 
 	pptp.destroy = gre_pptp_destroy_siblings;
 
+	nf_conntrack_helper_deprecated(pptp.name);
+
 	return nf_conntrack_helper_register(&pptp, &pptp_ptr);
 }
 
diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
index e7a3fb2b2d9466..29e93ac1e2e400 100644
--- a/net/netfilter/nf_flow_table_ip.c
+++ b/net/netfilter/nf_flow_table_ip.c
@@ -326,8 +326,10 @@ static bool nf_flow_ip4_tunnel_proto(struct nf_flowtable_ctx *ctx,
 		return false;
 
 	iph = (struct iphdr *)(skb_network_header(skb) + ctx->offset);
-	size = iph->ihl << 2;
+	if (iph->ihl < 5)
+		return false;
 
+	size = iph->ihl << 2;
 	if (ip_is_fragment(iph) || unlikely(ip_has_options(size)))
 		return false;
 
@@ -335,9 +337,9 @@ static bool nf_flow_ip4_tunnel_proto(struct nf_flowtable_ctx *ctx,
 		return false;
 
 	if (iph->protocol == IPPROTO_IPIP) {
-		ctx->tun.proto = IPPROTO_IPIP;
+		ctx->tun.proto = iph->protocol;
 		ctx->tun.hdr_size = size;
-		ctx->offset += size;
+		ctx->offset += ctx->tun.hdr_size;
 	}
 
 	return true;
diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
index 2bbf5163c0e273..63ff6b4d5d214a 100644
--- a/net/netfilter/nf_nat_core.c
+++ b/net/netfilter/nf_nat_core.c
@@ -1181,6 +1181,16 @@ int nf_nat_register_fn(struct net *net, u8 pf, const struct nf_hook_ops *ops,
 	struct nf_hook_ops *nat_ops;
 	int i, ret;
 
+#ifndef MODULE
+	/* If nf_nat_core is built-in and nf_nat_init() fails, dependent
+	 * modules like nft_chain_nat.ko may still call this function.
+	 * However, nat_net would be invalid, likely pointing to some other
+	 * per-net structure.
+	 */
+	if (WARN_ON_ONCE(!nf_nat_hook))
+		return -EOPNOTSUPP;
+#endif
+
 	if (WARN_ON_ONCE(pf >= ARRAY_SIZE(nat_net->nat_proto_net)))
 		return -EINVAL;
 
diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c
index 0caa9304d2d030..63864b92825909 100644
--- a/net/netfilter/nft_compat.c
+++ b/net/netfilter/nft_compat.c
@@ -397,6 +397,22 @@ static int nft_target_validate(const struct nft_ctx *ctx,
 	return 0;
 }
 
+static int nft_target_bridge_validate(const struct nft_ctx *ctx,
+				      const struct nft_expr *expr)
+{
+	struct xt_target *target = expr->ops->data;
+
+	/* Do not allow UNSPEC to stand-in for NFPROTO_BRIDGE
+	 * targets: they are incompatible.  ebtables targets return
+	 * EBT_ACCEPT, DROP and so on which are not compatible with
+	 * NF_ACCEPT, NF_DROP and so on.
+	 */
+	if (target->family != NFPROTO_BRIDGE)
+		return -ENOENT;
+
+	return nft_target_validate(ctx, expr);
+}
+
 static void __nft_match_eval(const struct nft_expr *expr,
 			     struct nft_regs *regs,
 			     const struct nft_pktinfo *pkt,
@@ -932,13 +948,15 @@ nft_target_select_ops(const struct nft_ctx *ctx,
 	ops->init = nft_target_init;
 	ops->destroy = nft_target_destroy;
 	ops->dump = nft_target_dump;
-	ops->validate = nft_target_validate;
 	ops->data = target;
 
-	if (family == NFPROTO_BRIDGE)
+	if (family == NFPROTO_BRIDGE) {
 		ops->eval = nft_target_eval_bridge;
-	else
+		ops->validate = nft_target_bridge_validate;
+	} else {
 		ops->eval = nft_target_eval_xt;
+		ops->validate = nft_target_validate;
+	}
 
 	return ops;
 err:
diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c
index 958054dd2e2ecc..03a88c77e0f028 100644
--- a/net/netfilter/nft_ct.c
+++ b/net/netfilter/nft_ct.c
@@ -1215,11 +1215,23 @@ struct nft_ct_expect_obj {
 	u32		timeout;
 };
 
+static int nft_ct_expect_timeout_get(const struct nlattr *attr, u32 *val)
+{
+	unsigned long jiffies_val = msecs_to_jiffies(nla_get_u32(attr));
+
+	if (jiffies_val > UINT_MAX)
+		return -ERANGE;
+
+	*val = jiffies_val;
+	return 0;
+}
+
 static int nft_ct_expect_obj_init(const struct nft_ctx *ctx,
 				  const struct nlattr * const tb[],
 				  struct nft_object *obj)
 {
 	struct nft_ct_expect_obj *priv = nft_obj_data(obj);
+	int err;
 
 	if (!tb[NFTA_CT_EXPECT_L4PROTO] ||
 	    !tb[NFTA_CT_EXPECT_DPORT] ||
@@ -1254,8 +1266,11 @@ static int nft_ct_expect_obj_init(const struct nft_ctx *ctx,
 		return -EOPNOTSUPP;
 	}
 
+	err = nft_ct_expect_timeout_get(tb[NFTA_CT_EXPECT_TIMEOUT], &priv->timeout);
+	if (err)
+		return err;
+
 	priv->dport = nla_get_be16(tb[NFTA_CT_EXPECT_DPORT]);
-	priv->timeout = nla_get_u32(tb[NFTA_CT_EXPECT_TIMEOUT]);
 	priv->size = nla_get_u8(tb[NFTA_CT_EXPECT_SIZE]);
 
 	return nf_ct_netns_get(ctx->net, ctx->family);
@@ -1275,7 +1290,7 @@ static int nft_ct_expect_obj_dump(struct sk_buff *skb,
 	if (nla_put_be16(skb, NFTA_CT_EXPECT_L3PROTO, htons(priv->l3num)) ||
 	    nla_put_u8(skb, NFTA_CT_EXPECT_L4PROTO, priv->l4proto) ||
 	    nla_put_be16(skb, NFTA_CT_EXPECT_DPORT, priv->dport) ||
-	    nla_put_u32(skb, NFTA_CT_EXPECT_TIMEOUT, priv->timeout) ||
+	    nla_put_u32(skb, NFTA_CT_EXPECT_TIMEOUT, jiffies_to_msecs(priv->timeout)) ||
 	    nla_put_u8(skb, NFTA_CT_EXPECT_SIZE, priv->size))
 		return -1;
 
@@ -1325,7 +1340,7 @@ static void nft_ct_expect_obj_eval(struct nft_object *obj,
 		          &ct->tuplehash[!dir].tuple.src.u3,
 		          &ct->tuplehash[!dir].tuple.dst.u3,
 		          priv->l4proto, NULL, &priv->dport);
-	exp->timeout += priv->timeout * HZ;
+	exp->timeout += priv->timeout;
 
 	if (nf_ct_expect_related(exp, 0) != 0)
 		regs->verdict.code = NF_DROP;
diff --git a/net/netfilter/nft_synproxy.c b/net/netfilter/nft_synproxy.c
index 7641f249614c97..9ed288c9d16880 100644
--- a/net/netfilter/nft_synproxy.c
+++ b/net/netfilter/nft_synproxy.c
@@ -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;
diff --git a/tools/testing/selftests/net/netfilter/conntrack_sctp_collision.sh b/tools/testing/selftests/net/netfilter/conntrack_sctp_collision.sh
index d860f7d9744bf8..7261975957ef18 100755
--- a/tools/testing/selftests/net/netfilter/conntrack_sctp_collision.sh
+++ b/tools/testing/selftests/net/netfilter/conntrack_sctp_collision.sh
@@ -2,18 +2,32 @@
 # SPDX-License-Identifier: GPL-2.0
 #
 # Testing For SCTP COLLISION SCENARIO as Below:
-#
+# 1. Stale INIT_ACK capture:
 #   14:35:47.655279 IP CLIENT_IP.PORT > SERVER_IP.PORT: sctp (1) [INIT] [init tag: 2017837359]
 #   14:35:48.353250 IP SERVER_IP.PORT > CLIENT_IP.PORT: sctp (1) [INIT] [init tag: 1187206187]
 #   14:35:48.353275 IP CLIENT_IP.PORT > SERVER_IP.PORT: sctp (1) [INIT ACK] [init tag: 2017837359]
 #   14:35:48.353283 IP SERVER_IP.PORT > CLIENT_IP.PORT: sctp (1) [COOKIE ECHO]
 #   14:35:48.353977 IP CLIENT_IP.PORT > SERVER_IP.PORT: sctp (1) [COOKIE ACK]
 #   14:35:48.855335 IP SERVER_IP.PORT > CLIENT_IP.PORT: sctp (1) [INIT ACK] [init tag: 164579970]
+#   (Delayed)
+#
+# 2. Stale INIT capture:
+#   14:35:48.353250 IP SERVER_IP.PORT > CLIENT_IP.PORT: sctp (1) [INIT] [init tag: 1187206187]
+#   14:35:48.353275 IP CLIENT_IP.PORT > SERVER_IP.PORT: sctp (1) [INIT ACK] [init tag: 2017837359]
+#   14:35:48.353283 IP SERVER_IP.PORT > CLIENT_IP.PORT: sctp (1) [COOKIE ECHO]
+#   14:35:48.353977 IP CLIENT_IP.PORT > SERVER_IP.PORT: sctp (1) [COOKIE ACK]
+#   14:35:47.655279 IP CLIENT_IP.PORT > SERVER_IP.PORT: sctp (1) [INIT] [init tag: 2017837359]
+#   (Delayed)
+#   14:35:48.855335 IP SERVER_IP.PORT > CLIENT_IP.PORT: sctp (1) [INIT ACK] [init tag: 164579970]
 #
 # TOPO: SERVER_NS (link0)<--->(link1) ROUTER_NS (link2)<--->(link3) CLIENT_NS
 
 source lib.sh
 
+checktool "nft --version" "run test without nft"
+checktool "tc -h" "run test without tc"
+checktool "modprobe -q sctp" "load sctp module"
+
 CLIENT_IP="198.51.200.1"
 CLIENT_PORT=1234
 
@@ -24,7 +38,8 @@ CLIENT_GW="198.51.200.2"
 SERVER_GW="198.51.100.2"
 
 # setup the topo
-setup() {
+topo_setup() {
+	# setup_ns cleans up existing net namespaces first.
 	setup_ns CLIENT_NS SERVER_NS ROUTER_NS
 	ip -n "$SERVER_NS" link add link0 type veth peer name link1 netns "$ROUTER_NS"
 	ip -n "$CLIENT_NS" link add link3 type veth peer name link2 netns "$ROUTER_NS"
@@ -38,35 +53,53 @@ setup() {
 	ip -n "$ROUTER_NS" addr add $SERVER_GW/24 dev link1
 	ip -n "$ROUTER_NS" addr add $CLIENT_GW/24 dev link2
 	ip net exec "$ROUTER_NS" sysctl -wq net.ipv4.ip_forward=1
+	sysctl -wq net.netfilter.nf_log_all_netns=1
 
 	ip -n "$CLIENT_NS" link set link3 up
 	ip -n "$CLIENT_NS" addr add $CLIENT_IP/24 dev link3
 	ip -n "$CLIENT_NS" route add $SERVER_IP dev link3 via $CLIENT_GW
+}
+
+conf_delay()
+{
+	# simulate the delay on OVS upcall by setting up a delay for INIT_ACK/INIT with
+	local ns=$1
+	local link=$2
+	local chunk_type=$3
 
-	# simulate the delay on OVS upcall by setting up a delay for INIT_ACK with
-	# tc on $SERVER_NS side
-	tc -n "$SERVER_NS" qdisc add dev link0 root handle 1: htb r2q 64
-	tc -n "$SERVER_NS" class add dev link0 parent 1: classid 1:1 htb rate 100mbit
-	tc -n "$SERVER_NS" filter add dev link0 parent 1: protocol ip u32 match ip protocol 132 \
-		0xff match u8 2 0xff at 32 flowid 1:1
-	if ! tc -n "$SERVER_NS" qdisc add dev link0 parent 1:1 handle 10: netem delay 1200ms; then
+	# use a smaller number for assoc's max_retrans to reproduce the issue
+	ip net exec "$CLIENT_NS" sysctl -wq net.sctp.association_max_retrans=3
+
+	tc -n "$ns" qdisc add dev "$link" root handle 1: htb r2q 64
+	tc -n "$ns" class add dev "$link" parent 1: classid 1:1 htb rate 100mbit
+	tc -n "$ns" filter add dev "$link" parent 1: protocol ip \
+		u32 match ip protocol 132 0xff match u8 "$chunk_type" 0xff at 32 flowid 1:1
+	if ! tc -n "$ns" qdisc add dev "$link" parent 1:1 handle 10: netem delay 1200ms; then
 		echo "SKIP: Cannot add netem qdisc"
-		exit $ksft_skip
+		return $ksft_skip
 	fi
 
 	# simulate the ctstate check on OVS nf_conntrack
-	ip net exec "$ROUTER_NS" iptables -A FORWARD -m state --state INVALID,UNTRACKED -j DROP
-	ip net exec "$ROUTER_NS" iptables -A INPUT -p sctp -j DROP
-
-	# use a smaller number for assoc's max_retrans to reproduce the issue
-	modprobe -q sctp
-	ip net exec "$CLIENT_NS" sysctl -wq net.sctp.association_max_retrans=3
+	ip net exec "$ROUTER_NS" nft -f - <<-EOF
+	table ip t {
+		chain forward {
+			type filter hook forward priority filter; policy accept;
+			meta l4proto icmp counter accept
+			ct state new counter accept
+			ct state established,related counter accept
+			ct state invalid log flags all counter drop comment \
+			"Expect to drop stale INIT/INIT_ACK chunks"
+			counter
+		}
+	}
+	EOF
+	return 0
 }
 
 cleanup() {
-	ip net exec "$CLIENT_NS" pkill sctp_collision >/dev/null 2>&1
-	ip net exec "$SERVER_NS" pkill sctp_collision >/dev/null 2>&1
+	# cleanup_all_ns terminates running processes in the namespaces.
 	cleanup_all_ns
+	sysctl -wq net.netfilter.nf_log_all_netns=0
 }
 
 do_test() {
@@ -81,7 +114,19 @@ do_test() {
 
 # run the test case
 trap cleanup EXIT
-setup && \
-echo "Test for SCTP Collision in nf_conntrack:" && \
-do_test && echo "PASS!"
-exit $?
+
+echo "Test for SCTP INIT_ACK Collision in nf_conntrack:"
+topo_setup || exit $?
+conf_delay $SERVER_NS link0 2 || exit $?
+
+if ! do_test; then
+	exit $ksft_fail
+fi
+
+echo "Test for SCTP INIT Collision in nf_conntrack:"
+topo_setup || exit $?
+conf_delay $CLIENT_NS link3 1 || exit $?
+
+if ! do_test; then
+	exit $ksft_fail
+fi
diff --git a/tools/testing/selftests/net/netfilter/nft_queue.sh b/tools/testing/selftests/net/netfilter/nft_queue.sh
index d80390848e8509..7c857a2e0f3494 100755
--- a/tools/testing/selftests/net/netfilter/nft_queue.sh
+++ b/tools/testing/selftests/net/netfilter/nft_queue.sh
@@ -85,11 +85,12 @@ ip -net "$ns3" route add default via 10.0.3.1
 ip -net "$ns3" route add default via dead:3::1
 
 load_ruleset() {
-	local name=$1
-	local prio=$2
+	local family=$1
+	local name=$2
+	local prio=$3
 
 ip netns exec "$nsrouter" nft -f /dev/stdin <<EOF
-table inet $name {
+table $family $name {
 	chain nfq {
 		ip protocol icmp queue bypass
 		icmpv6 type { "echo-request", "echo-reply" } queue num 1 bypass
@@ -228,6 +229,7 @@ nf_queue_wait()
 test_queue()
 {
 	local expected="$1"
+	local family="$2"
 	local last=""
 
 	# spawn nf_queue listeners
@@ -255,11 +257,13 @@ test_queue()
 		if [ x"$last" != x"$expected packets total" ]; then
 			echo "FAIL: Expected $expected packets total, but got $last" 1>&2
 			ip netns exec "$nsrouter" nft list ruleset
+			echo -n "$TMPFILE0: ";cat "$TMPFILE0"
+			echo -n "$TMPFILE1: ";cat "$TMPFILE1"
 			exit 1
 		fi
 	done
 
-	echo "PASS: Expected and received $last"
+	echo "PASS: Expected and received $last ($family)"
 }
 
 listener_ready()
@@ -400,6 +404,8 @@ EOF
 
 	kill "$nfqpid"
 	echo "PASS: icmp+nfqueue via vrf"
+	ip -net "$ns1" link del tvrf
+	ip netns exec "$ns1" nft flush ruleset
 }
 
 sctp_listener_ready()
@@ -814,12 +820,53 @@ EOF
 	check_tainted "queue program exiting while packets queued"
 }
 
+test_queue_bridge()
+{
+	ip -net "$nsrouter" addr flush dev veth0
+	ip -net "$nsrouter" addr flush dev veth1
+
+	ip -net "$nsrouter" link add br0 type bridge
+	ip -net "$nsrouter" link set veth0 master br0
+	ip -net "$nsrouter" link set veth1 master br0
+
+	ip -net "$nsrouter" link set br0 up
+
+	ip -net "$nsrouter" addr add 10.0.2.1/16 dev br0
+	ip -net "$nsrouter" addr add dead:2::1/64 dev br0 nodad
+
+	ip -net "$ns1" addr flush dev eth0
+	ip -net "$ns2" addr flush dev eth0
+
+	ip -net "$ns1" addr add 10.0.1.1/16 dev eth0
+	ip -net "$ns1" addr add dead:2::2/64 dev eth0 nodad
+
+	ip -net "$ns2" addr add 10.0.2.99/16 dev eth0
+	ip -net "$ns2" addr add dead:2::99/64 dev eth0 nodad
+
+	ip netns exec "$nsrouter" nft flush ruleset
+
+	ip netns exec "$nsrouter" sysctl net.ipv6.conf.all.forwarding=0 > /dev/null
+	ip netns exec "$nsrouter" sysctl net.ipv4.conf.veth0.forwarding=0 > /dev/null
+	ip netns exec "$nsrouter" sysctl net.ipv4.conf.veth1.forwarding=0 > /dev/null
+
+	if ! test_ping;then
+		echo "FAIL: netns bridge connectivity" 1>&2
+		exit $ret
+	fi
+
+	load_ruleset "bridge" "filter" 10
+	test_queue 10 "bridge"
+
+	load_ruleset "bridge" "filter2" 20
+	test_queue 20 "bridge"
+}
+
 ip netns exec "$nsrouter" sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
 ip netns exec "$nsrouter" sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
 ip netns exec "$nsrouter" sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
 ip netns exec "$nsrouter" sysctl net.ipv4.conf.veth2.forwarding=1 > /dev/null
 
-load_ruleset "filter" 0
+load_ruleset "inet" "filter" 0
 
 if test_ping; then
 	# queue bypass works (rules were skipped, no listener)
@@ -842,11 +889,11 @@ load_counter_ruleset 10
 # 1x icmp prerouting,forward,postrouting -> 3 queue events (6 incl. reply).
 # 1x icmp prerouting,input,output postrouting -> 4 queue events incl. reply.
 # so we expect that userspace program receives 10 packets.
-test_queue 10
+test_queue 10 "inet"
 
 # same.  We queue to a second program as well.
-load_ruleset "filter2" 20
-test_queue 20
+load_ruleset "inet" "filter2" 20
+test_queue 20 "inet"
 ip netns exec "$ns1" nft flush ruleset
 
 test_tcp_forward
@@ -863,4 +910,7 @@ test_queue_stress
 test_icmp_vrf
 test_queue_removal
 
+# turns router into a bridge
+test_queue_bridge
+
 exit $ret

3/2 2026/06/23 22:41 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 13563
							output: 32
							thoughts: 1651
						

Thoughts:
**Netfilter Patch Series Review**

Alright, let's break down this netfilter patch series. It looks like we have a substantial set of changes across various components, touching both core conntrack and the newer nftables infrastructure. My initial assessment is that this is more than just a minor tweak, so we need to carefully consider the potential impact.

First, I see several modifications to the `xtables` infrastructure, primarily in the `xt_mtchk_param`, `xt_mtdtor_param`, `xt_tgchk_param`, and `xt_action_param` structures.  The addition of `family`, `nft_compat`, `net`, `match`, and other fields indicates a deeper integration with the network namespace and nftables compatibility. It's clear that this series is facilitating a closer connection between the legacy `xtables` and the newer nftables framework. Specifically, I'm watching the `nft_compat` flags closely, as those are often indicators of legacy code that still needs support for backwards compatibility.

The modifications to `nf_conntrack_expect.h`, `nf_conntrack_helper.h`, and related files are also significant. Adding the `master_tuple` field to `nf_conntrack_expect` and incorporating the `nf_conntrack_helper_deprecated` macro suggests refactoring and a move towards more explicit handling of connection expectations and helper deprecation, likely in preparation for removing some legacy functionality. The changes in `nf_ct_expect_init` and `__nf_ct_expect_check` deserve attention, as the use of `default_exp_policy` if `helper` is NULL has subtle but important implications. I want to understand the consequences of these changes thoroughly.

The changes in `nf_conncount.c`, specifically the shift from `skb->skb_iif != LOOPBACK_IFINDEX` to `test_bit(IPS_ASSURED_BIT, &ct->status)` in `__nf_conncount_add`, looks like a performance/accuracy optimization. This deserves a closer look to see how it might affect performance under load. Likewise, changes to `nf_conntrack_broadcast.c` and `nf_conntrack_netlink.c`, which now use `exp->master_tuple` heavily, warrant testing, as well as the addition to `nf_conntrack_pptp.c` and `nf_conntrack_irc.c` that deprecate the helper.

The `nf_flow_table_ip.c` change, with the added `iph->ihl < 5` check in `nf_flow_ip4_tunnel_proto`, looks like a packet sanity check, presumably to prevent a crash or some other unexpected behavior.  I also see some added checks in `nf_nat_core.c` for `!nf_nat_hook` in `nf_nat_register_fn`. These are basic sanity checks that should be tested, but they should be easily fuzzable.

The nftables changes, especially in `nft_compat.c` with the introduction of `nft_target_bridge_validate` and its integration with `NFPROTO_BRIDGE`, strongly indicate further bridge support and potential compatibility upgrades.  I'm also seeing an extension on the timeout handling in `nft_ct.c` with `nft_ct_expect_timeout_get` being added, and changes to how the timeout is used in several locations. Changes in `nft_synproxy.c` simplifying `nft_synproxy_tcp_options` with removal of the `priv` argument seem fairly minor.

Finally, the updates to the self-tests in `conntrack_sctp_collision.sh` and `nft_queue.sh` are positive signs. Good tests are critical to verify all this, so they should be integrated into our test infrastructure.

**Functional Changes and Configuration**

From a fuzzing perspective, the most interesting changes are:

*   `nf_conncount.c`:  Altered logic in `__nf_conncount_add`.
*   `nf_conntrack_expect.c`: Modification to `__nf_ct_expect_check`
*   `nf_conntrack_helper.c`: Changes in `__nf_conntrack_helper_register`.
*   `nf_conntrack_netlink.c`:  Changes around `ctnetlink_change_helper` and `exp->master_tuple`.
*   `nf_flow_table_ip.c`:  The new check in `nf_flow_ip4_tunnel_proto`.
*   `nft_compat.c`: The addition of `nft_target_bridge_validate`.
*   `nft_ct.c`: The added


4/2 2026/06/23 22:41 tool grepper
0m Args:
{
  "Expression": "nf_conncount.o",
  "PathPrefix": "net/netfilter/Makefile"
}

Results:
{
  "Output": "net/netfilter/Makefile=79=obj-$(CONFIG_NETFILTER_SYNPROXY) += nf_synproxy_core.o\nnet/netfilter/Makefile-80-\nnet/netfilter/Makefile:81:obj-$(CONFIG_NETFILTER_CONNCOUNT) += nf_conncount.o\nnet/netfilter/Makefile-82-\n"
}

5/2 2026/06/23 22:41 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 16365
							output: 35
							thoughts: 18
						

Thoughts:
Okay, let's dive into this. Here's my understanding, presented as my own mental processing:

**Examining Object Files**

Alright, time to get to work. My immediate focus is on understanding this system's architecture. The clue is in the file names. I should start by looking closely at `nf_flow_table_ip.o` and any other similar object files. This is my starting point to understand the implementation of the flow table for IP traffic. I need to figure out the code organization, its dependencies, and especially, the data structures it uses. I'm already anticipating questions about performance and scalability, so I need a solid grasp of this section. This is where the core of the functionality lies, so I can extrapolate what else might exist in the larger kernel space.



6/2 2026/06/23 22:41 tool grepper
0m Args:
{
  "Expression": "nf_flow_table_ip.o",
  "PathPrefix": "net/netfilter/Makefile"
}

Results:
{
  "Output": "net/netfilter/Makefile=142=obj-$(CONFIG_NF_FLOW_TABLE)\t+= nf_flow_table.o\nnet/netfilter/Makefile:143:nf_flow_table-objs\t\t:= nf_flow_table_core.o nf_flow_table_ip.o \\\nnet/netfilter/Makefile-144-\t\t\t\t   nf_flow_table_path.o \\\n"
}

7/2 2026/06/23 22:41 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 16693
							output: 44
							thoughts: 26
						

Thoughts:
Okay, let's dive into this. Here's my thought process on this:

**Examining Netfilter Compatibility Modules**

Alright, I need to take a look at a few Netfilter modules. I'm going to start with a check on `nft_compat.o`, then move on to `nft_ct.o`, and finally, I'll examine `nft_synproxy.o`. Gotta make sure everything's behaving as expected and identify anything that needs tweaking or further investigation. These are key components, so thoroughness is paramount. I need to understand how these integrate and function within the broader framework. I'm thinking about performance implications, potential conflicts, and, of course, any potential security vulnerabilities. Time to dig in!



8/2 2026/06/23 22:41 tool grepper
0m Args:
{
  "Expression": "nft_compat.o|nft_ct.o|nft_synproxy.o",
  "PathPrefix": "net/netfilter/Makefile"
}

Results:
{
  "Output": "net/netfilter/Makefile=108=obj-$(CONFIG_NF_TABLES)\t\t+= nf_tables.o\nnet/netfilter/Makefile:109:obj-$(CONFIG_NFT_COMPAT)\t+= nft_compat.o\nnet/netfilter/Makefile-110-obj-$(CONFIG_NFT_CONNLIMIT)\t+= nft_connlimit.o\nnet/netfilter/Makefile=111=obj-$(CONFIG_NFT_NUMGEN)\t+= nft_numgen.o\nnet/netfilter/Makefile:112:obj-$(CONFIG_NFT_CT)\t\t+= nft_ct.o\nnet/netfilter/Makefile-113-obj-$(CONFIG_NFT_FLOW_OFFLOAD)\t+= nft_flow_offload.o\n--\nnet/netfilter/Makefile=132=obj-$(CONFIG_NFT_XFRM)\t\t+= nft_xfrm.o\nnet/netfilter/Makefile:133:obj-$(CONFIG_NFT_SYNPROXY)\t+= nft_synproxy.o\nnet/netfilter/Makefile-134-\n"
}

9/2 2026/06/23 22:41 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 17188
							output: 36
							thoughts: 16
						

Thoughts:
Here's my attempt at summarizing the thought process, tailored for an expert audience and written in the first person:

**Investigating `nf_conntrack_netlink.o`**

Okay, let's dive into this. The target is `nf_conntrack_netlink.o`. Given my experience, I'm immediately thinking about netlink sockets and how they interact with connection tracking within the Netfilter framework. This particular module likely handles the communication interface between userspace tools and the kernel's connection tracking subsystem. I expect to see evidence of the netlink protocol implementation here – the message structures, the attribute handling, and the likely interaction with the conntrack table itself. I'm going to want to examine how it handles connection creation, deletion, and modification events. I'll be looking for potential areas of interest related to security vulnerabilities: Are there any buffer overflows in how it handles user-provided data? Does it correctly validate input before passing it to kernel internals? Are there any race conditions when handling concurrent netlink messages? I'll probably start by looking at the module's exported functions, particularly those related to netlink message handling and data parsing. It'll be essential to understand the kernel's concurrency model (spinlocks, RCU, etc.) to evaluate any potential race conditions within the code. Let's see what we can find.



10/2 2026/06/23 22:41 tool grepper
0m Args:
{
  "Expression": "nf_conntrack_netlink.o",
  "PathPrefix": "net/netfilter/Makefile"
}

Results:
{
  "Output": "net/netfilter/Makefile=34=obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o\n--\nnet/netfilter/Makefile-36-# netlink interface for nf_conntrack\nnet/netfilter/Makefile:37:obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o\nnet/netfilter/Makefile-38-obj-$(CONFIG_NF_CT_NETLINK_TIMEOUT) += nfnetlink_cttimeout.o\n"
}

11/2 2026/06/23 22:41 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 17658
							output: 35
							thoughts: 263
						

Thoughts:
**My Analysis of Netfilter Configurations and Function Dependencies**

Okay, so I'm looking at this set of configurations: `NETFILTER_CONNCOUNT`, `NF_CONNTRACK`, `NF_CT_NETLINK`, `NF_FLOW_TABLE`, `NFT_COMPAT`, `NFT_CT`, and `NFT_SYNPROXY`. My immediate goal is to understand their interdependencies and the key functions involved. I need to get a high-level view of how these features are connected within the netfilter framework.

Let me zero in on the key symbols that likely represent the core logic. I see: `__nf_conncount_add`, which probably handles connection counting; `__nf_ct_expect_check`, involved in connection tracking expectations; `__nf_conntrack_helper_register`, dealing with helper modules; `ctnetlink_change_helper`, which likely ties into netlink configuration; `ctnetlink_alloc_expect` for allocating expectations via netlink; `nf_flow_ip4_tunnel_proto` seems specific to IPv4 tunnel protocols; `nft_target_bridge_validate` for bridge validations in nftables; and, the nftables connection tracking and synproxy functions: `nft_ct_expect_obj_init`, `nft_ct_expect_obj_eval`, `nft_synproxy_eval_v4`, and `nft_synproxy_eval_v6`. That set gives me a great picture of the pieces.

Now I need to broaden the scope and look for other functions that may be linked to those primary functions. I am seeing `nf_conntrack_broadcast_help`, `nf_ct_expect_init`, `nf_nat_register_fn`, and `nft_target_select_ops`. I'll want to check to make sure I understand the full scope of any changes made to `nf_flow_ip4_tunnel_proto`. This is giving me a complete picture of the dependencies and how the pieces fit together.



12/2 2026/06/23 22:41 tool grepper
0m Args:
{
  "Expression": "nf_flow_ip4_tunnel_proto",
  "PathPrefix": "net/netfilter/"
}

Results:
{
  "Output": "net/netfilter/nf_flow_table_ip.c=309=static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb,\n--\nnet/netfilter/nf_flow_table_ip.c-318-\nnet/netfilter/nf_flow_table_ip.c:319:static bool nf_flow_ip4_tunnel_proto(struct nf_flowtable_ctx *ctx,\nnet/netfilter/nf_flow_table_ip.c-320-\t\t\t\t     struct sk_buff *skb)\n--\nnet/netfilter/nf_flow_table_ip.c=387=static bool nf_flow_skb_encap_protocol(struct nf_flowtable_ctx *ctx,\n--\nnet/netfilter/nf_flow_table_ip.c-416-\tcase htons(ETH_P_IP):\nnet/netfilter/nf_flow_table_ip.c:417:\t\tret = nf_flow_ip4_tunnel_proto(ctx, skb);\nnet/netfilter/nf_flow_table_ip.c-418-\t\tbreak;\n"
}

13/2 2026/06/23 22:41 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 18668
							output: 32
							thoughts: 54
						

Thoughts:
Here's my summary, as if I were thinking these thoughts:

**Analyzing Network Flow Encapsulation**

Okay, so I'm looking at `nf_flow_ip4_tunnel_proto`. This seems like a pretty important function, especially since it's statically called by `nf_flow_skb_encap_protocol`. That makes it a good symbol to focus on when tracing network encapsulation behavior. Let's see if this lines up with how the bridge target is validated. I'll take a look at `nft_target_bridge_validate`.



14/2 2026/06/23 22:41 tool grepper
0m Args:
{
  "Expression": "nft_target_bridge_validate",
  "PathPrefix": "net/netfilter/"
}

Results:
{
  "Output": "net/netfilter/nft_compat.c=353=static int nft_target_validate(const struct nft_ctx *ctx,\n--\nnet/netfilter/nft_compat.c-399-\nnet/netfilter/nft_compat.c:400:static int nft_target_bridge_validate(const struct nft_ctx *ctx,\nnet/netfilter/nft_compat.c-401-\t\t\t\t      const struct nft_expr *expr)\n--\nnet/netfilter/nft_compat.c=903=nft_target_select_ops(const struct nft_ctx *ctx,\n--\nnet/netfilter/nft_compat.c-954-\t\tops-\u003eeval = nft_target_eval_bridge;\nnet/netfilter/nft_compat.c:955:\t\tops-\u003evalidate = nft_target_bridge_validate;\nnet/netfilter/nft_compat.c-956-\t} else {\n"
}

15/2 2026/06/23 22:41 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 19111
							output: 34
							thoughts: 43
						

Thoughts:
Here's my take on those thoughts:

**Analyzing `nft_target_bridge_validate` and `nft_ct_expect_obj_init`**

Alright, so `nft_target_bridge_validate` is a static function acting as a callback. That makes it a solid focus point for analysis – it's likely a critical piece of the puzzle within the bridge's operation. I'm going to dig into it, see what it's responsible for validating. My expectation is this function is validating that the data that is being bridged is legitimate.

Let's shift gears now. I need to understand how this bridge operates, especially within the conntrack context. Let's look at `nft_ct_expect_obj_init` to understand how the connection tracking aspects are set up. I'm eager to understand how the expectations are initialized to see if this explains the bridge in any way.



16/2 2026/06/23 22:42 tool grepper
0m Args:
{
  "Expression": "nft_ct_expect_obj_init",
  "PathPrefix": "net/netfilter/"
}

Results:
{
  "Output": "net/netfilter/nft_ct.c=1218=static int nft_ct_expect_timeout_get(const struct nlattr *attr, u32 *val)\n--\nnet/netfilter/nft_ct.c-1228-\nnet/netfilter/nft_ct.c:1229:static int nft_ct_expect_obj_init(const struct nft_ctx *ctx,\nnet/netfilter/nft_ct.c-1230-\t\t\t\t  const struct nlattr * const tb[],\n--\nnet/netfilter/nft_ct.c=1361=static const struct nft_object_ops nft_ct_expect_obj_ops = {\n--\nnet/netfilter/nft_ct.c-1364-\t.eval\t\t= nft_ct_expect_obj_eval,\nnet/netfilter/nft_ct.c:1365:\t.init\t\t= nft_ct_expect_obj_init,\nnet/netfilter/nft_ct.c-1366-\t.destroy\t= nft_ct_expect_obj_destroy,\n"
}

17/2 2026/06/23 22:42 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 19654
							output: 34
							thoughts: 44
						

Thoughts:
Okay, here's my take on those symbols, presented as my own internal thought process:

**Diving into NFtables Connection Tracking**

Right, `nft_ct_expect_obj_init` and `nft_ct_expect_obj_eval` - those are good starting points. They clearly define the initialization and evaluation steps for connection tracking expectations, which is precisely where I'd expect the core logic to reside when dealing with expected connections. Let's make a note of those as our primary targets for further investigation into this.

Okay, let's now switch our attention over to `nft_synproxy_eval_v4` since this seems like a related and interesting function.



18/2 2026/06/23 22:42 tool grepper
0m Args:
{
  "Expression": "nft_synproxy_eval_v4",
  "PathPrefix": "net/netfilter/"
}

Results:
{
  "Output": "net/netfilter/nft_synproxy.c=24=static void nft_synproxy_tcp_options(struct synproxy_options *opts,\n--\nnet/netfilter/nft_synproxy.c-43-\nnet/netfilter/nft_synproxy.c:44:static void nft_synproxy_eval_v4(const struct nft_synproxy *priv,\nnet/netfilter/nft_synproxy.c-45-\t\t\t\t struct nft_regs *regs,\n--\nnet/netfilter/nft_synproxy.c=106=static void nft_synproxy_do_eval(const struct nft_synproxy *priv,\n--\nnet/netfilter/nft_synproxy.c-140-\tcase htons(ETH_P_IP):\nnet/netfilter/nft_synproxy.c:141:\t\tnft_synproxy_eval_v4(priv, regs, pkt, tcp, \u0026_tcph, \u0026opts);\nnet/netfilter/nft_synproxy.c-142-\t\treturn;\n"
}

19/2 2026/06/23 22:42 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 20135
							output: 32
							thoughts: 42
						

Thoughts:
Okay, here's my take on those thoughts, framed as my own:

**Initial Assessment: Focusing on Key Symbols**

Right, `nft_synproxy_eval_v4` and `nft_synproxy_eval_v6` seem like good jumping-off points. Those are the functions I want to examine closely, they probably contain the core logic for the synproxy functionality. I'll make sure to note these as starting points to work from. Let's see if the functionality has been generalized.

Now, let's also have a look at the `__nf_conncount_add` symbol.



20/2 2026/06/23 22:42 tool grepper
0m Args:
{
  "Expression": "__nf_conncount_add",
  "PathPrefix": "net/netfilter/"
}

Results:
{
  "Output": "net/netfilter/nf_conncount.c=130=static bool get_ct_or_tuple_from_skb(struct net *net,\n--\nnet/netfilter/nf_conncount.c-166-\nnet/netfilter/nf_conncount.c:167:static int __nf_conncount_add(struct net *net,\nnet/netfilter/nf_conncount.c-168-\t\t\t      const struct sk_buff *skb,\n--\nnet/netfilter/nf_conncount.c=276=int nf_conncount_add_skb(struct net *net,\n--\nnet/netfilter/nf_conncount.c-284-\tspin_lock_bh(\u0026list-\u003elist_lock);\nnet/netfilter/nf_conncount.c:285:\tret = __nf_conncount_add(net, skb, l3num, list);\nnet/netfilter/nf_conncount.c-286-\tspin_unlock_bh(\u0026list-\u003elist_lock);\n--\nnet/netfilter/nf_conncount.c=531=count_tree(struct net *net,\n--\nnet/netfilter/nf_conncount.c-580-\t/* same source network -\u003e be counted! */\nnet/netfilter/nf_conncount.c:581:\tret = __nf_conncount_add(net, skb, l3num, \u0026rbconn-\u003elist);\nnet/netfilter/nf_conncount.c-582-\tspin_unlock_bh(\u0026rbconn-\u003elist.list_lock);\n"
}

21/2 2026/06/23 22:42 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 20738
							output: 33
							thoughts: 30
						

Thoughts:
Okay, here's my interpretation of those thoughts, framed as a first-person summary, keeping in mind my expertise:

**My Line of Inquiry: Network Connection Tracking**

Right, let's zero in. Focusing on `__nf_conncount_add` seems like a good starting point. That function is likely involved in the core connection tracking mechanisms within the Netfilter framework – a critical area for analyzing connection state and performance. Now, I should probably check the relation that it has with other parts of the netfilter subsystem. Next up, I want to take a look at `__nf_ct_expect_check`. I'm curious if this function is related somehow. It's likely involved in expectation management, perhaps dealing with related connections or connection tracking of protocols that require multiple streams or interactions. Examining how these two functions interact should shed some light on the overall tracking process and potentially reveal potential bottlenecks or areas for optimization within the connection tracking module.



22/2 2026/06/23 22:42 tool grepper
0m Args:
{
  "Expression": "__nf_ct_expect_check",
  "PathPrefix": "net/netfilter/"
}

Results:
{
  "Output": "net/netfilter/nf_conntrack_expect.c=438=static void evict_oldest_expect(struct nf_conn_help *master_help,\n--\nnet/netfilter/nf_conntrack_expect.c-459-\nnet/netfilter/nf_conntrack_expect.c:460:static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect,\nnet/netfilter/nf_conntrack_expect.c-461-\t\t\t\t       struct nf_conn_help *master_help,\n--\nnet/netfilter/nf_conntrack_expect.c=519=int nf_ct_expect_related_report(struct nf_conntrack_expect *expect,\n--\nnet/netfilter/nf_conntrack_expect.c-531-\nnet/netfilter/nf_conntrack_expect.c:532:\tret = __nf_ct_expect_check(expect, master_help, flags);\nnet/netfilter/nf_conntrack_expect.c-533-\tif (ret \u003c 0)\n"
}

23/2 2026/06/23 22:42 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 21284
							output: 35
							thoughts: 33
						

Thoughts:
Okay, here's my take on those thoughts, framed as a first-person summary, keeping in mind my expertise:

**My Line of Inquiry: Expectation Checks and Connection Tracking Helpers**

Right, so I see a promising lead with `__nf_ct_expect_check`. That's a solid function to keep in mind, a likely key piece in the connection tracking puzzle. It's a good place to start my investigation.

But I need to broaden the scope a bit. What's the wider context? Given that expectations are a piece of the larger picture, I should probably understand how helpers are registered. So, let's also delve into `__nf_conntrack_helper_register`. That seems like the right next step, as it likely defines the mechanisms for setting up and enabling these helpers. Understanding the registration process will give me a better grasp of where expectations fit in, and how to potentially influence or work with them. My goal, as always, is to understand the control flow and potential interaction points.



24/2 2026/06/23 22:42 tool grepper
0m Args:
{
  "Expression": "__nf_conntrack_helper_register",
  "PathPrefix": "net/netfilter/"
}

Results:
{
  "Output": "net/netfilter/nf_conntrack_helper.c=362=EXPORT_SYMBOL_GPL(nf_ct_helper_log);\nnet/netfilter/nf_conntrack_helper.c-363-\nnet/netfilter/nf_conntrack_helper.c:364:int __nf_conntrack_helper_register(struct nf_conntrack_helper *me)\nnet/netfilter/nf_conntrack_helper.c-365-{\n--\nnet/netfilter/nf_conntrack_helper.c-414-}\nnet/netfilter/nf_conntrack_helper.c:415:EXPORT_SYMBOL_GPL(__nf_conntrack_helper_register);\nnet/netfilter/nf_conntrack_helper.c-416-\nnet/netfilter/nf_conntrack_helper.c=417=int nf_conntrack_helper_register(struct nf_conntrack_helper *me,\n--\nnet/netfilter/nf_conntrack_helper.c-429-\nnet/netfilter/nf_conntrack_helper.c:430:\terr = __nf_conntrack_helper_register(new_helper);\nnet/netfilter/nf_conntrack_helper.c-431-\tif (err \u003c 0)\n--\nnet/netfilter/nf_conntrack_helper.c=519=int nf_conntrack_helpers_register(struct nf_conntrack_helper *helper,\n--\nnet/netfilter/nf_conntrack_helper.c-535-\nnet/netfilter/nf_conntrack_helper.c:536:\t\terr = __nf_conntrack_helper_register(new_helper);\nnet/netfilter/nf_conntrack_helper.c-537-\t\tif (err \u003c 0) {\n--\nnet/netfilter/nfnetlink_cthelper.c=220=nfnl_cthelper_create(const struct nlattr * const tb[],\n--\nnet/netfilter/nfnetlink_cthelper.c-280-\nnet/netfilter/nfnetlink_cthelper.c:281:\tret = __nf_conntrack_helper_register(helper);\nnet/netfilter/nfnetlink_cthelper.c-282-\tif (ret \u003c 0)\n"
}

25/2 2026/06/23 22:42 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 22161
							output: 32
							thoughts: 32
						

Thoughts:
Here's my take on those thoughts, from an expert's perspective:

**Diving into Connection Tracking Helpers**

Okay, so I'm thinking, `__nf_conntrack_helper_register` is a really solid starting point here. That function is the key to hooking up new connection tracking helpers, so understanding its role and how it's used is definitely crucial.

From there, I'll need to look at `ctnetlink_change_helper` next. This makes sense; it's the netlink interface that userspace would likely use to modify or register connection tracking helpers, so I bet that's where the registration process ultimately gets initiated. I want to see how these two pieces work in tandem. Let's see how the kernel handles the registration requests from userspace.



26/2 2026/06/23 22:42 tool grepper
0m Args:
{
  "Expression": "ctnetlink_change_helper",
  "PathPrefix": "net/netfilter/"
}

Results:
{
  "Output": "net/netfilter/nf_conntrack_netlink.c=1904=ctnetlink_setup_nat(struct nf_conn *ct, const struct nlattr * const cda[])\n--\nnet/netfilter/nf_conntrack_netlink.c-1925-\nnet/netfilter/nf_conntrack_netlink.c:1926:static int ctnetlink_change_helper(struct nf_conn *ct,\nnet/netfilter/nf_conntrack_netlink.c-1927-\t\t\t\t   const struct nlattr * const cda[])\n--\nnet/netfilter/nf_conntrack_netlink.c=2162=ctnetlink_change_conntrack(struct nf_conn *ct,\n--\nnet/netfilter/nf_conntrack_netlink.c-2171-\tif (cda[CTA_HELP]) {\nnet/netfilter/nf_conntrack_netlink.c:2172:\t\terr = ctnetlink_change_helper(ct, cda);\nnet/netfilter/nf_conntrack_netlink.c-2173-\t\tif (err \u003c 0)\n--\nnet/netfilter/nf_conntrack_netlink.c=2793=ctnetlink_glue_parse_ct(const struct nlattr *cda[], struct nf_conn *ct)\n--\nnet/netfilter/nf_conntrack_netlink.c-2807-\tif (cda[CTA_HELP]) {\nnet/netfilter/nf_conntrack_netlink.c:2808:\t\terr = ctnetlink_change_helper(ct, cda);\nnet/netfilter/nf_conntrack_netlink.c-2809-\t\tif (err \u003c 0)\n"
}

27/2 2026/06/23 22:42 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 22845
							output: 32
							thoughts: 29
						

Thoughts:
Here's a summary of my current thought process, as if I were analyzing this code:

**Analyzing `ctnetlink` Focus**

Okay, so `ctnetlink_change_helper` seems like a solid entry point for my current investigation. That's where I should focus initially. Now, let's drill down into what that function is doing. I need to understand its role in the overall process of... whatever it is `ctnetlink` is managing.

To get a better grip, I want to pivot and explore where expectation allocation is done, which is why I want to check `ctnetlink_alloc_expect`. I'm going to follow the trail of function calls and relevant data structures. This seems like it will be a good piece of the puzzle to follow next.



28/2 2026/06/23 22:42 tool grepper
0m Args:
{
  "Expression": "ctnetlink_alloc_expect",
  "PathPrefix": "net/netfilter/"
}

Results:
{
  "Output": "net/netfilter/nf_conntrack_netlink.c=2630=static struct nf_conntrack_expect *\nnet/netfilter/nf_conntrack_netlink.c:2631:ctnetlink_alloc_expect(const struct nlattr *const cda[], struct nf_conn *ct,\nnet/netfilter/nf_conntrack_netlink.c-2632-\t\t       const struct nf_conntrack_helper *assign_helper,\n--\nnet/netfilter/nf_conntrack_netlink.c=2856=ctnetlink_glue_attach_expect(const struct nlattr *attr, struct nf_conn *ct,\n--\nnet/netfilter/nf_conntrack_netlink.c-2887-\nnet/netfilter/nf_conntrack_netlink.c:2888:\texp = ctnetlink_alloc_expect((const struct nlattr * const *)cda, ct,\nnet/netfilter/nf_conntrack_netlink.c-2889-\t\t\t\t     assign_helper, \u0026tuple, \u0026mask);\n--\nnet/netfilter/nf_conntrack_netlink.c=3519=static struct nf_conntrack_expect *\nnet/netfilter/nf_conntrack_netlink.c:3520:ctnetlink_alloc_expect(const struct nlattr * const cda[], struct nf_conn *ct,\nnet/netfilter/nf_conntrack_netlink.c-3521-\t\t       const struct nf_conntrack_helper *assign_helper,\n--\nnet/netfilter/nf_conntrack_netlink.c=3600=ctnetlink_create_expect(struct net *net,\n--\nnet/netfilter/nf_conntrack_netlink.c-3631-\trcu_read_lock();\nnet/netfilter/nf_conntrack_netlink.c:3632:\texp = ctnetlink_alloc_expect(cda, ct, NULL, \u0026tuple, \u0026mask);\nnet/netfilter/nf_conntrack_netlink.c-3633-\tif (IS_ERR(exp)) {\n"
}

29/2 2026/06/23 22:42 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 23617
							output: 32
							thoughts: 29
						

Thoughts:
Here's a summary of my thought process, as requested:

**Navigating the Netfilter Landscape**

Okay, so I'm honing in on this kernel netlink code. `ctnetlink_alloc_expect` – that feels like a good, focused spot to really dig in. I need to understand the connection tracking and expectation management. That function call seems like a key piece.

Right, so where's the registration? Now, let's see, that `nf_nat_register_fn` call... let's check that registration function... I'm going to follow the path from there. I want to see how that function works with this netlink allocation piece. It will be helpful to see the interaction between NAT and connection tracking. Hopefully this will shed some light on the overall structure.



30/2 2026/06/23 22:42 tool grepper
0m Args:
{
  "Expression": "nf_nat_register_fn",
  "PathPrefix": "net/netfilter/"
}

Results:
{
  "Output": "net/netfilter/nf_nat_core.c=1169=static struct nf_ct_helper_expectfn follow_master_nat = {\n--\nnet/netfilter/nf_nat_core.c-1173-\nnet/netfilter/nf_nat_core.c:1174:int nf_nat_register_fn(struct net *net, u8 pf, const struct nf_hook_ops *ops,\nnet/netfilter/nf_nat_core.c-1175-\t\t       const struct nf_hook_ops *orig_nat_ops, unsigned int ops_count)\n--\nnet/netfilter/nf_nat_proto.c=797=int nf_nat_ipv4_register_fn(struct net *net, const struct nf_hook_ops *ops)\nnet/netfilter/nf_nat_proto.c-798-{\nnet/netfilter/nf_nat_proto.c:799:\treturn nf_nat_register_fn(net, ops-\u003epf, ops, nf_nat_ipv4_ops,\nnet/netfilter/nf_nat_proto.c-800-\t\t\t\t  ARRAY_SIZE(nf_nat_ipv4_ops));\n--\nnet/netfilter/nf_nat_proto.c=1058=int nf_nat_ipv6_register_fn(struct net *net, const struct nf_hook_ops *ops)\nnet/netfilter/nf_nat_proto.c-1059-{\nnet/netfilter/nf_nat_proto.c:1060:\treturn nf_nat_register_fn(net, ops-\u003epf, ops, nf_nat_ipv6_ops,\nnet/netfilter/nf_nat_proto.c-1061-\t\t\t\t  ARRAY_SIZE(nf_nat_ipv6_ops));\n--\nnet/netfilter/nf_nat_proto.c=1073=int nf_nat_inet_register_fn(struct net *net, const struct nf_hook_ops *ops)\n--\nnet/netfilter/nf_nat_proto.c-1079-\nnet/netfilter/nf_nat_proto.c:1080:\tret = nf_nat_register_fn(net, NFPROTO_IPV6, ops, nf_nat_ipv6_ops,\nnet/netfilter/nf_nat_proto.c-1081-\t\t\t\t ARRAY_SIZE(nf_nat_ipv6_ops));\n--\nnet/netfilter/nf_nat_proto.c-1084-\nnet/netfilter/nf_nat_proto.c:1085:\tret = nf_nat_register_fn(net, NFPROTO_IPV4, ops, nf_nat_ipv4_ops,\nnet/netfilter/nf_nat_proto.c-1086-\t\t\t\t ARRAY_SIZE(nf_nat_ipv4_ops));\n"
}

31/2 2026/06/23 22:42 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 24548
							output: 32
							thoughts: 29
						

Thoughts:
Here's my take on those thoughts:

**Analyzing Kernel Network Function Registration**

Okay, so `nf_nat_register_fn` seems like a pretty important registration function to zero in on. It's often the entry point for understanding how network address translation (NAT) modules are integrated into the Netfilter framework, right? And when I think about that, I’m immediately drawn to the expectation setup, which will probably be handled in the NAT helper with the initialization of the NAT Connection Tracking entry, so let's dig into `nf_ct_expect_init`. That'll likely show how the system preps itself to handle expected connections related to the NAT rules. I'm guessing that's where I can start to understand the lifecycle of a NAT'd connection within the kernel.



32/2 2026/06/23 22:42 tool grepper
0m Args:
{
  "Expression": "nf_ct_expect_init",
  "PathPrefix": "net/netfilter/"
}

Results:
{
  "Output": "net/netfilter/ipvs/ip_vs_nfct.c=210=void ip_vs_nfct_expect_related(struct sk_buff *skb, struct nf_conn *ct,\n--\nnet/netfilter/ipvs/ip_vs_nfct.c-222-\nnet/netfilter/ipvs/ip_vs_nfct.c:223:\tnf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),\nnet/netfilter/ipvs/ip_vs_nfct.c-224-\t\t\tfrom_rs ? \u0026cp-\u003edaddr : \u0026cp-\u003ecaddr,\n--\nnet/netfilter/nf_conntrack_amanda.c=83=static int amanda_help(struct sk_buff *skb,\n--\nnet/netfilter/nf_conntrack_amanda.c-146-\t\ttuple = \u0026ct-\u003etuplehash[IP_CT_DIR_ORIGINAL].tuple;\nnet/netfilter/nf_conntrack_amanda.c:147:\t\tnf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,\nnet/netfilter/nf_conntrack_amanda.c-148-\t\t\t\t  nf_ct_l3num(ct),\n--\nnet/netfilter/nf_conntrack_expect.c=318=EXPORT_SYMBOL_GPL(nf_ct_expect_alloc);\n--\nnet/netfilter/nf_conntrack_expect.c-323- */\nnet/netfilter/nf_conntrack_expect.c:324:void nf_ct_expect_init(struct nf_conntrack_expect *exp, unsigned int class,\nnet/netfilter/nf_conntrack_expect.c-325-\t\t       u_int8_t family,\n--\nnet/netfilter/nf_conntrack_expect.c-395-}\nnet/netfilter/nf_conntrack_expect.c:396:EXPORT_SYMBOL_GPL(nf_ct_expect_init);\nnet/netfilter/nf_conntrack_expect.c-397-\n--\nnet/netfilter/nf_conntrack_ftp.c=366=static int help(struct sk_buff *skb,\n--\nnet/netfilter/nf_conntrack_ftp.c-514-\nnet/netfilter/nf_conntrack_ftp.c:515:\tnf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, cmd.l3num,\nnet/netfilter/nf_conntrack_ftp.c-516-\t\t\t  \u0026ct-\u003etuplehash[!dir].tuple.src.u3, daddr,\n--\nnet/netfilter/nf_conntrack_h323_main.c=209=static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,\n--\nnet/netfilter/nf_conntrack_h323_main.c-236-\t\treturn -1;\nnet/netfilter/nf_conntrack_h323_main.c:237:\tnf_ct_expect_init(rtp_exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),\nnet/netfilter/nf_conntrack_h323_main.c-238-\t\t\t  \u0026ct-\u003etuplehash[!dir].tuple.src.u3,\n--\nnet/netfilter/nf_conntrack_h323_main.c-246-\t}\nnet/netfilter/nf_conntrack_h323_main.c:247:\tnf_ct_expect_init(rtcp_exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),\nnet/netfilter/nf_conntrack_h323_main.c-248-\t\t\t  \u0026ct-\u003etuplehash[!dir].tuple.src.u3,\n--\nnet/netfilter/nf_conntrack_h323_main.c=283=static int expect_t120(struct sk_buff *skb,\n--\nnet/netfilter/nf_conntrack_h323_main.c-305-\t\treturn -1;\nnet/netfilter/nf_conntrack_h323_main.c:306:\tnf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),\nnet/netfilter/nf_conntrack_h323_main.c-307-\t\t\t  \u0026ct-\u003etuplehash[!dir].tuple.src.u3,\n--\nnet/netfilter/nf_conntrack_h323_main.c=618=static int expect_h245(struct sk_buff *skb, struct nf_conn *ct,\n--\nnet/netfilter/nf_conntrack_h323_main.c-638-\t\treturn -1;\nnet/netfilter/nf_conntrack_h323_main.c:639:\tnf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),\nnet/netfilter/nf_conntrack_h323_main.c-640-\t\t\t  \u0026ct-\u003etuplehash[!dir].tuple.src.u3,\n--\nnet/netfilter/nf_conntrack_h323_main.c=735=static int expect_callforwarding(struct sk_buff *skb,\n--\nnet/netfilter/nf_conntrack_h323_main.c-766-\t\treturn -1;\nnet/netfilter/nf_conntrack_h323_main.c:767:\tnf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),\nnet/netfilter/nf_conntrack_h323_main.c-768-\t\t\t  \u0026ct-\u003etuplehash[!dir].tuple.src.u3, \u0026addr,\n--\nnet/netfilter/nf_conntrack_h323_main.c=1183=static int expect_q931(struct sk_buff *skb, struct nf_conn *ct,\n--\nnet/netfilter/nf_conntrack_h323_main.c-1213-\t\treturn -1;\nnet/netfilter/nf_conntrack_h323_main.c:1214:\tnf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),\nnet/netfilter/nf_conntrack_h323_main.c-1215-\t\t\t  gkrouted_only ? /* only accept calls from GK? */\n--\nnet/netfilter/nf_conntrack_h323_main.c=1263=static int process_gcf(struct sk_buff *skb, struct nf_conn *ct,\n--\nnet/netfilter/nf_conntrack_h323_main.c-1290-\t\treturn -1;\nnet/netfilter/nf_conntrack_h323_main.c:1291:\tnf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),\nnet/netfilter/nf_conntrack_h323_main.c-1292-\t\t\t  \u0026ct-\u003etuplehash[!dir].tuple.src.u3, \u0026addr,\n--\nnet/netfilter/nf_conntrack_h323_main.c=1486=static int process_acf(struct sk_buff *skb, struct nf_conn *ct,\n--\nnet/netfilter/nf_conntrack_h323_main.c-1518-\t\treturn -1;\nnet/netfilter/nf_conntrack_h323_main.c:1519:\tnf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),\nnet/netfilter/nf_conntrack_h323_main.c-1520-\t\t\t  \u0026ct-\u003etuplehash[!dir].tuple.src.u3, \u0026addr,\n--\nnet/netfilter/nf_conntrack_h323_main.c=1553=static int process_lcf(struct sk_buff *skb, struct nf_conn *ct,\n--\nnet/netfilter/nf_conntrack_h323_main.c-1572-\t\treturn -1;\nnet/netfilter/nf_conntrack_h323_main.c:1573:\tnf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),\nnet/netfilter/nf_conntrack_h323_main.c-1574-\t\t\t  \u0026ct-\u003etuplehash[!dir].tuple.src.u3, \u0026addr,\n--\nnet/netfilter/nf_conntrack_irc.c=102=static int help(struct sk_buff *skb, unsigned int protoff,\n--\nnet/netfilter/nf_conntrack_irc.c-231-\t\t\tport = htons(dcc_port);\nnet/netfilter/nf_conntrack_irc.c:232:\t\t\tnf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,\nnet/netfilter/nf_conntrack_irc.c-233-\t\t\t\t\t  tuple-\u003esrc.l3num,\n--\nnet/netfilter/nf_conntrack_pptp.c=128=static int exp_gre(struct nf_conn *ct, __be16 callid, __be16 peer_callid)\n--\nnet/netfilter/nf_conntrack_pptp.c-144-\tdir = IP_CT_DIR_ORIGINAL;\nnet/netfilter/nf_conntrack_pptp.c:145:\tnf_ct_expect_init(exp_orig, NF_CT_EXPECT_CLASS_DEFAULT,\nnet/netfilter/nf_conntrack_pptp.c-146-\t\t\t  nf_ct_l3num(ct),\n--\nnet/netfilter/nf_conntrack_pptp.c-153-\tdir = IP_CT_DIR_REPLY;\nnet/netfilter/nf_conntrack_pptp.c:154:\tnf_ct_expect_init(exp_reply, NF_CT_EXPECT_CLASS_DEFAULT,\nnet/netfilter/nf_conntrack_pptp.c-155-\t\t\t  nf_ct_l3num(ct),\n--\nnet/netfilter/nf_conntrack_sane.c=58=static int help(struct sk_buff *skb,\n--\nnet/netfilter/nf_conntrack_sane.c-154-\ttuple = \u0026ct-\u003etuplehash[IP_CT_DIR_ORIGINAL].tuple;\nnet/netfilter/nf_conntrack_sane.c:155:\tnf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),\nnet/netfilter/nf_conntrack_sane.c-156-\t\t\t  \u0026tuple-\u003esrc.u3, \u0026tuple-\u003edst.u3,\n--\nnet/netfilter/nf_conntrack_sip.c=929=static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int protoff,\n--\nnet/netfilter/nf_conntrack_sip.c-1048-\t\tgoto err1;\nnet/netfilter/nf_conntrack_sip.c:1049:\tnf_ct_expect_init(rtp_exp, class, nf_ct_l3num(ct), saddr, daddr,\nnet/netfilter/nf_conntrack_sip.c-1050-\t\t\t  IPPROTO_UDP, NULL, \u0026rtp_port);\n--\nnet/netfilter/nf_conntrack_sip.c-1054-\t\tgoto err2;\nnet/netfilter/nf_conntrack_sip.c:1055:\tnf_ct_expect_init(rtcp_exp, class, nf_ct_l3num(ct), saddr, daddr,\nnet/netfilter/nf_conntrack_sip.c-1056-\t\t\t  IPPROTO_UDP, NULL, \u0026rtcp_port);\n--\nnet/netfilter/nf_conntrack_sip.c=1326=static int process_register_request(struct sk_buff *skb, unsigned int protoff,\n--\nnet/netfilter/nf_conntrack_sip.c-1411-\nnet/netfilter/nf_conntrack_sip.c:1412:\tnf_ct_expect_init(exp, SIP_EXPECT_SIGNALLING, nf_ct_l3num(ct),\nnet/netfilter/nf_conntrack_sip.c-1413-\t\t\t  saddr, \u0026daddr, proto, NULL, \u0026port);\n--\nnet/netfilter/nf_conntrack_tftp.c=38=static int tftp_help(struct sk_buff *skb,\n--\nnet/netfilter/nf_conntrack_tftp.c-67-\t\ttuple = \u0026ct-\u003etuplehash[IP_CT_DIR_REPLY].tuple;\nnet/netfilter/nf_conntrack_tftp.c:68:\t\tnf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,\nnet/netfilter/nf_conntrack_tftp.c-69-\t\t\t\t  nf_ct_l3num(ct),\n--\nnet/netfilter/nft_ct.c=1300=static void nft_ct_expect_obj_eval(struct nft_object *obj,\n--\nnet/netfilter/nft_ct.c-1338-\t}\nnet/netfilter/nft_ct.c:1339:\tnf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, l3num,\nnet/netfilter/nft_ct.c-1340-\t\t          \u0026ct-\u003etuplehash[!dir].tuple.src.u3,\n"
}

33/2 2026/06/23 22:42 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 28355
							output: 30
							thoughts: 793
						

Thoughts:
**My Analysis of Reachability and Dependencies**

Okay, so I'm focusing my attention. `nf_ct_expect_init` is called all over the place, but the real meat is in `nft_ct_expect_obj_eval` since that's the caller that got the recent modifications. Let's see... I've got a list of symbols I need to check for reachability: `__nf_conncount_add`, `__nf_ct_expect_check`, `__nf_conntrack_helper_register`, `ctnetlink_change_helper`, `ctnetlink_alloc_expect`, `nf_flow_ip4_tunnel_proto`, `nft_target_bridge_validate`, `nft_ct_expect_obj_init`, `nft_ct_expect_obj_eval`, `nft_synproxy_eval_v4`, and `nft_synproxy_eval_v6`.

Alright, first up, `nf_flow_ip4_tunnel_proto`.  Yep, it's called by `nf_flow_skb_encap_protocol`, which in turn is called by `nf_flow_offload_ip_hook` and `nf_flow_offload_ipv6_hook`.  Good, that's reachable.

Next, `nft_target_bridge_validate`. Looks like it's used in `nft_target_select_ops` when the `family` is `NFPROTO_BRIDGE`. Perfect.

Now, `nft_ct_expect_obj_init`.  Yep, that's used in `nft_ct_expect_obj_ops`.  Makes sense.

How about `nft_synproxy_eval_v4`?  It's called by `nft_synproxy_do_eval`, which is in turn called by `nft_synproxy_eval`.  Got it.

`__nf_conncount_add`?  Reachable - called by `nf_conncount_add_skb` and `count_tree`.

`__nf_ct_expect_check`?  Yes, called by `nf_ct_expect_related_report`.

`__nf_conntrack_helper_register`?  Also reachable, called by `nf_conntrack_helper_register`, `nf_conntrack_helpers_register` and `nfnl_cthelper_create`.

Moving on to `ctnetlink_change_helper`. It's called by `ctnetlink_change_conntrack` and `ctnetlink_glue_parse_ct`. That's good.

And lastly, `ctnetlink_alloc_expect`. That's called by `ctnetlink_glue_attach_expect` and `ctnetlink_create_expect`. Okay, all the symbols are reachable!

Now, let's look at the config options. I've got `NETFILTER_CONNCOUNT`, `NF_CONNTRACK`, `NF_CT_NETLINK`, `NF_FLOW_TABLE`, `NFT_COMPAT`, `NFT_CT`, and `NFT_SYNPROXY`.

Just making sure, for `NF_CONNTRACK`... am I missing anything? No, just `NF_CONNTRACK` is sufficient.

Okay, checking dependencies. `NFT_COMPAT` depends on `NETFILTER_XTABLES`. Makes sense. `NFT_CT` needs `NF_CONNTRACK`.  And `NFT_SYNPROXY` needs both `NF_CONNTRACK` *and* `NETFILTER_SYNPROXY`. Right, I'll add `NETFILTER_SYNPROXY` to the list. That's all I need for now.



34/2 2026/06/23 22:42 tool grepper
0m Args:
{
  "Expression": "NETFILTER_SYNPROXY",
  "PathPrefix": "net/netfilter/"
}

Results:
{
  "Output": "net/netfilter/Kconfig=447=config NF_NAT_OVS\n--\nnet/netfilter/Kconfig-449-\nnet/netfilter/Kconfig:450:config NETFILTER_SYNPROXY\nnet/netfilter/Kconfig-451-\ttristate\n--\nnet/netfilter/Kconfig=649=config NFT_SYNPROXY\n--\nnet/netfilter/Kconfig-651-\tdepends on NF_CONNTRACK \u0026\u0026 NETFILTER_ADVANCED\nnet/netfilter/Kconfig:652:\tselect NETFILTER_SYNPROXY\nnet/netfilter/Kconfig-653-\tselect SYN_COOKIES\n--\nnet/netfilter/Makefile=76=obj-$(CONFIG_NF_NAT_TFTP) += nf_nat_tftp.o\n--\nnet/netfilter/Makefile-78-# SYNPROXY\nnet/netfilter/Makefile:79:obj-$(CONFIG_NETFILTER_SYNPROXY) += nf_synproxy_core.o\nnet/netfilter/Makefile-80-\n--\nnet/netfilter/nf_conntrack_extend.c=30=static const u8 nf_ct_ext_type_len[NF_CT_EXT_NUM] = {\n--\nnet/netfilter/nf_conntrack_extend.c-48-#endif\nnet/netfilter/nf_conntrack_extend.c:49:#if IS_ENABLED(CONFIG_NETFILTER_SYNPROXY)\nnet/netfilter/nf_conntrack_extend.c-50-\t[NF_CT_EXT_SYNPROXY] = sizeof(struct nf_conn_synproxy),\n--\nnet/netfilter/nf_conntrack_extend.c=57=static __always_inline unsigned int total_extension_size(void)\n--\nnet/netfilter/nf_conntrack_extend.c-80-#endif\nnet/netfilter/nf_conntrack_extend.c:81:#if IS_ENABLED(CONFIG_NETFILTER_SYNPROXY)\nnet/netfilter/nf_conntrack_extend.c-82-\t\t+ sizeof(struct nf_conn_synproxy)\n"
}

35/2 2026/06/23 22:42 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 30498
							output: 299
							thoughts: 298
						

Thoughts:
**My Fuzzing Strategy for Netfilter**

Okay, so I see that `NETFILTER_SYNPROXY` is implicitly selected by `NFT_SYNPROXY`, which simplifies things—no need to explicitly target it. Now, let's break down the implications. This patch series is touching critical netfilter components: connection tracking, flow tables, and nftables integration. This touches core functions like connection counting, expectation checks, helper registration, and netlink handling. I'm also seeing modifications to bridge target validation within `nft_compat` and some adjustments to timeout handling within `nft_ct`. All of these changes have a clear path from userspace via netlink, or by processing actual network packets. This screams fuzzing targets.

Now, let's refine the symbol list for the fuzzing. I don't want to choose generic functions that are also hot paths. I've got a much more focused list now:

*   `__nf_conncount_add`
*   `__nf_ct_expect_check`
*   `__nf_conntrack_helper_register`
*   `ctnetlink_change_helper`
*   `ctnetlink_alloc_expect`
*   `nf_flow_ip4_tunnel_proto`
*   `nft_target_bridge_validate`
*   `nft_ct_expect_obj_init`
*   `nft_ct_expect_obj_eval`
*   `nft_synproxy_eval_v4`
*   `nft_synproxy_eval_v6`

These are highly relevant to the introduced features and not overly generic. I think this list is solid and focused for achieving the fuzzing objective.

Alright, let's call `set-results`.



36/2 2026/06/23 22:42 tool set-results
0m Args:
{
  "EnableConfigs": [
    "NETFILTER_CONNCOUNT",
    "NF_CONNTRACK",
    "NF_CT_NETLINK",
    "NF_FLOW_TABLE",
    "NFT_COMPAT",
    "NFT_CT",
    "NFT_SYNPROXY"
  ],
  "FocusSymbols": [
    "__nf_conncount_add",
    "__nf_ct_expect_check",
    "__nf_conntrack_helper_register",
    "ctnetlink_change_helper",
    "ctnetlink_alloc_expect",
    "nf_flow_ip4_tunnel_proto",
    "nft_target_bridge_validate",
    "nft_ct_expect_obj_init",
    "nft_ct_expect_obj_eval",
    "nft_synproxy_eval_v4",
    "nft_synproxy_eval_v6"
  ],
  "Reasoning": "The patch series makes functional changes to netfilter, including connection tracking, flow tables, and nftables compatibility. It modifies the logic for connection counting, expectation checking, helper registration, and netlink handling. It also adds a new validation function for bridge targets in nft_compat and fixes timeout handling in nft_ct. These changes affect core netfilter functionality and are reachable from userspace via netlink or by processing network packets, making them suitable for fuzzing.",
  "WorthFuzzing": true
}

Results:
{
  "EnableConfigs": [
    "NETFILTER_CONNCOUNT",
    "NF_CONNTRACK",
    "NF_CT_NETLINK",
    "NF_FLOW_TABLE",
    "NFT_COMPAT",
    "NFT_CT",
    "NFT_SYNPROXY"
  ],
  "FocusSymbols": [
    "__nf_conncount_add",
    "__nf_ct_expect_check",
    "__nf_conntrack_helper_register",
    "ctnetlink_change_helper",
    "ctnetlink_alloc_expect",
    "nf_flow_ip4_tunnel_proto",
    "nft_target_bridge_validate",
    "nft_ct_expect_obj_init",
    "nft_ct_expect_obj_eval",
    "nft_synproxy_eval_v4",
    "nft_synproxy_eval_v6"
  ],
  "Reasoning": "The patch series makes functional changes to netfilter, including connection tracking, flow tables, and nftables compatibility. It modifies the logic for connection counting, expectation checking, helper registration, and netlink handling. It also adds a new validation function for bridge targets in nft_compat and fixes timeout handling in nft_ct. These changes affect core netfilter functionality and are reachable from userspace via netlink or by processing network packets, making them suitable for fuzzing.",
  "WorthFuzzing": true
}

LLM Calls Summary:
Total Calls Total Tokens Avg Tokens Total Duration (Seconds) Avg Duration (Seconds)
Tool Calls Summary:
Total Calls Total Duration (Seconds) Avg Duration (Seconds)