| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/07/07 16:30 | flow | patch-triage |
1mArgs:null Results: {
"EnableConfigs": [
"NF_FLOW_TABLE",
"NF_FLOW_TABLE_INET",
"NFT_FLOW_OFFLOAD",
"BRIDGE",
"BRIDGE_VLAN_FILTERING"
],
"FocusSymbols": [
"dev_fill_bridge_path",
"flow_offload_bridge_init",
"nft_dev_fill_bridge_path",
"nf_flow_rule_bridge",
"br_fill_forward_path",
"br_vlan_fill_forward_path_pvid"
],
"Reasoning": "The patch introduces bridge support for netfilter flow offload. It adds new functions to handle bridge paths in flow offload and modifies existing bridge forward path functions. This is a functional change in the core networking and netfilter subsystems that is reachable via nftables and bridge configuration, making it a good target for fuzzing.",
"WorthFuzzing": true
} |
| 1/1 | 2026/07/07 16:30 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 3205a525ad0cd6d4410da0c3915d3e3cadb15dee\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Tue Jul 7 16:30:22 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/include/linux/netdevice.h b/include/linux/netdevice.h\nindex 9981d637f8b546..fdee4465d61261 100644\n--- a/include/linux/netdevice.h\n+++ b/include/linux/netdevice.h\n@@ -3420,6 +3420,8 @@ void dev_remove_offload(struct packet_offload *po);\n \n int dev_get_iflink(const struct net_device *dev);\n int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb);\n+int dev_fill_bridge_path(struct net_device_path_ctx *ctx,\n+\t\t\t struct net_device_path_stack *stack);\n int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,\n \t\t\t struct net_device_path_stack *stack);\n struct net_device *dev_get_by_name(struct net *net, const char *name);\ndiff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h\nindex 7b23b245a5a86a..a109eda5250c79 100644\n--- a/include/net/netfilter/nf_flow_table.h\n+++ b/include/net/netfilter/nf_flow_table.h\n@@ -305,6 +305,11 @@ nf_flow_table_offload_del_cb(struct nf_flowtable *flow_table,\n void flow_offload_route_init(struct flow_offload *flow,\n \t\t\t struct nf_flow_route *route);\n \n+int flow_offload_bridge_init(struct flow_offload *flow,\n+\t\t\t const struct nft_pktinfo *pkt,\n+\t\t\t enum ip_conntrack_dir dir,\n+\t\t\t struct nft_flowtable *ft);\n+\n int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow);\n void flow_offload_refresh(struct nf_flowtable *flow_table,\n \t\t\t struct flow_offload *flow, bool force);\n@@ -368,6 +373,9 @@ void nf_flow_table_offload_flush_cleanup(struct nf_flowtable *flowtable);\n int nf_flow_table_offload_setup(struct nf_flowtable *flowtable,\n \t\t\t\tstruct net_device *dev,\n \t\t\t\tenum flow_block_command cmd);\n+int nf_flow_rule_bridge(struct net *net, struct flow_offload *flow,\n+\t\t\tenum flow_offload_tuple_dir dir,\n+\t\t\tstruct nf_flow_rule *flow_rule);\n int nf_flow_rule_route_ipv4(struct net *net, struct flow_offload *flow,\n \t\t\t enum flow_offload_tuple_dir dir,\n \t\t\t struct nf_flow_rule *flow_rule);\ndiff --git a/net/bridge/br_device.c b/net/bridge/br_device.c\nindex e7f343ab22d379..89f4525a7279d6 100644\n--- a/net/bridge/br_device.c\n+++ b/net/bridge/br_device.c\n@@ -385,16 +385,25 @@ static int br_del_slave(struct net_device *dev, struct net_device *slave_dev)\n static int br_fill_forward_path(struct net_device_path_ctx *ctx,\n \t\t\t\tstruct net_device_path *path)\n {\n+\tstruct net_bridge_port *src, *dst;\n \tstruct net_bridge_fdb_entry *f;\n-\tstruct net_bridge_port *dst;\n \tstruct net_bridge *br;\n \n-\tif (netif_is_bridge_port(ctx-\u003edev))\n-\t\treturn -1;\n+\tif (netif_is_bridge_port(ctx-\u003edev)) {\n+\t\tstruct net_device *br_dev;\n+\n+\t\tbr_dev = netdev_master_upper_dev_get_rcu((struct net_device *)ctx-\u003edev);\n+\t\tif (!br_dev)\n+\t\t\treturn -1;\n \n-\tbr = netdev_priv(ctx-\u003edev);\n+\t\tsrc = br_port_get_rcu(ctx-\u003edev);\n+\t\tbr = netdev_priv(br_dev);\n+\t} else {\n+\t\tsrc = NULL;\n+\t\tbr = netdev_priv(ctx-\u003edev);\n+\t}\n \n-\tbr_vlan_fill_forward_path_pvid(br, ctx, path);\n+\tbr_vlan_fill_forward_path_pvid(br, src, ctx, path);\n \n \tf = br_fdb_find_rcu(br, ctx-\u003edaddr, path-\u003ebridge.vlan_id);\n \tif (!f)\ndiff --git a/net/bridge/br_private.h b/net/bridge/br_private.h\nindex d55ea9516e3e36..00f5b72ff42dea 100644\n--- a/net/bridge/br_private.h\n+++ b/net/bridge/br_private.h\n@@ -1630,6 +1630,7 @@ bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr,\n \t\t\t const struct net_bridge_vlan *range_end);\n \n void br_vlan_fill_forward_path_pvid(struct net_bridge *br,\n+\t\t\t\t struct net_bridge_port *p,\n \t\t\t\t struct net_device_path_ctx *ctx,\n \t\t\t\t struct net_device_path *path);\n int br_vlan_fill_forward_path_mode(struct net_bridge *br,\n@@ -1799,6 +1800,7 @@ static inline int nbp_get_num_vlan_infos(struct net_bridge_port *p,\n }\n \n static inline void br_vlan_fill_forward_path_pvid(struct net_bridge *br,\n+\t\t\t\t\t\t struct net_bridge_port *p,\n \t\t\t\t\t\t struct net_device_path_ctx *ctx,\n \t\t\t\t\t\t struct net_device_path *path)\n {\ndiff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c\nindex 5560afcaaca327..71531499bc7356 100644\n--- a/net/bridge/br_vlan.c\n+++ b/net/bridge/br_vlan.c\n@@ -1450,6 +1450,7 @@ int br_vlan_get_pvid_rcu(const struct net_device *dev, u16 *p_pvid)\n EXPORT_SYMBOL_GPL(br_vlan_get_pvid_rcu);\n \n void br_vlan_fill_forward_path_pvid(struct net_bridge *br,\n+\t\t\t\t struct net_bridge_port *p,\n \t\t\t\t struct net_device_path_ctx *ctx,\n \t\t\t\t struct net_device_path *path)\n {\n@@ -1462,7 +1463,10 @@ void br_vlan_fill_forward_path_pvid(struct net_bridge *br,\n \tif (!br_opt_get(br, BROPT_VLAN_ENABLED))\n \t\treturn;\n \n-\tvg = br_vlan_group_rcu(br);\n+\tif (p)\n+\t\tvg = nbp_vlan_group_rcu(p);\n+\telse\n+\t\tvg = br_vlan_group_rcu(br);\n \n \tif (idx \u003e= 0 \u0026\u0026\n \t ctx-\u003evlan[idx].proto == br-\u003evlan_proto) {\ndiff --git a/net/core/dev.c b/net/core/dev.c\nindex 4b3d5cfdf6e00f..f6685c1e478601 100644\n--- a/net/core/dev.c\n+++ b/net/core/dev.c\n@@ -750,44 +750,84 @@ static struct net_device_path *dev_fwd_path(struct net_device_path_stack *stack)\n \treturn \u0026stack-\u003epath[k];\n }\n \n-int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,\n-\t\t\t struct net_device_path_stack *stack)\n+static int dev_fill_forward_path_common(struct net_device_path_ctx *ctx,\n+\t\t\t\t\tstruct net_device_path_stack *stack)\n {\n \tconst struct net_device *last_dev;\n-\tstruct net_device_path_ctx ctx = {\n-\t\t.dev\t= dev,\n-\t};\n \tstruct net_device_path *path;\n \tint ret = 0;\n \n-\tmemcpy(ctx.daddr, daddr, sizeof(ctx.daddr));\n-\tstack-\u003enum_paths = 0;\n-\twhile (ctx.dev \u0026\u0026 ctx.dev-\u003enetdev_ops-\u003endo_fill_forward_path) {\n-\t\tlast_dev = ctx.dev;\n+\twhile (ctx-\u003edev \u0026\u0026 ctx-\u003edev-\u003enetdev_ops-\u003endo_fill_forward_path) {\n+\t\tlast_dev = ctx-\u003edev;\n \t\tpath = dev_fwd_path(stack);\n \t\tif (!path)\n \t\t\treturn -1;\n \n \t\tmemset(path, 0, sizeof(struct net_device_path));\n-\t\tret = ctx.dev-\u003enetdev_ops-\u003endo_fill_forward_path(\u0026ctx, path);\n+\t\tret = ctx-\u003edev-\u003enetdev_ops-\u003endo_fill_forward_path(ctx, path);\n \t\tif (ret \u003c 0)\n \t\t\treturn -1;\n \n-\t\tif (WARN_ON_ONCE(last_dev == ctx.dev))\n+\t\tif (WARN_ON_ONCE(last_dev == ctx-\u003edev))\n \t\t\treturn -1;\n \t}\n \n-\tif (!ctx.dev)\n+\tif (!ctx-\u003edev)\n \t\treturn ret;\n \n \tpath = dev_fwd_path(stack);\n \tif (!path)\n \t\treturn -1;\n \tpath-\u003etype = DEV_PATH_ETHERNET;\n-\tpath-\u003edev = ctx.dev;\n+\tpath-\u003edev = ctx-\u003edev;\n \n \treturn ret;\n }\n+\n+int dev_fill_bridge_path(struct net_device_path_ctx *ctx,\n+\t\t\t struct net_device_path_stack *stack)\n+{\n+\tconst struct net_device *last_dev, *br_dev;\n+\tstruct net_device_path *path;\n+\n+\tstack-\u003enum_paths = 0;\n+\n+\tif (!ctx-\u003edev || !netif_is_bridge_port(ctx-\u003edev))\n+\t\treturn -1;\n+\n+\tbr_dev = netdev_master_upper_dev_get_rcu((struct net_device *)ctx-\u003edev);\n+\tif (!br_dev || !br_dev-\u003enetdev_ops-\u003endo_fill_forward_path)\n+\t\treturn -1;\n+\n+\tlast_dev = ctx-\u003edev;\n+\tpath = dev_fwd_path(stack);\n+\tif (!path)\n+\t\treturn -1;\n+\n+\tmemset(path, 0, sizeof(struct net_device_path));\n+\tif (br_dev-\u003enetdev_ops-\u003endo_fill_forward_path(ctx, path) \u003c 0)\n+\t\treturn -1;\n+\n+\tif (!ctx-\u003edev || WARN_ON_ONCE(last_dev == ctx-\u003edev))\n+\t\treturn -1;\n+\n+\treturn dev_fill_forward_path_common(ctx, stack);\n+}\n+EXPORT_SYMBOL_GPL(dev_fill_bridge_path);\n+\n+int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,\n+\t\t\t struct net_device_path_stack *stack)\n+{\n+\tstruct net_device_path_ctx ctx = {\n+\t\t.dev\t= dev,\n+\t};\n+\n+\tmemcpy(ctx.daddr, daddr, sizeof(ctx.daddr));\n+\n+\tstack-\u003enum_paths = 0;\n+\n+\treturn dev_fill_forward_path_common(\u0026ctx, stack);\n+}\n EXPORT_SYMBOL_GPL(dev_fill_forward_path);\n \n /* must be called under rcu_read_lock(), as we dont take a reference */\ndiff --git a/net/netfilter/nf_flow_table_inet.c b/net/netfilter/nf_flow_table_inet.c\nindex b0f19917193241..80b238196f29b3 100644\n--- a/net/netfilter/nf_flow_table_inet.c\n+++ b/net/netfilter/nf_flow_table_inet.c\n@@ -65,6 +65,16 @@ static int nf_flow_rule_route_inet(struct net *net,\n \treturn err;\n }\n \n+static struct nf_flowtable_type flowtable_bridge = {\n+\t.family\t\t= NFPROTO_BRIDGE,\n+\t.init\t\t= nf_flow_table_init,\n+\t.setup\t\t= nf_flow_table_offload_setup,\n+\t.action\t\t= nf_flow_rule_bridge,\n+\t.free\t\t= nf_flow_table_free,\n+\t.hook\t\t= nf_flow_offload_inet_hook,\n+\t.owner\t\t= THIS_MODULE,\n+};\n+\n static struct nf_flowtable_type flowtable_inet = {\n \t.family\t\t= NFPROTO_INET,\n \t.init\t\t= nf_flow_table_init,\n@@ -97,6 +107,7 @@ static struct nf_flowtable_type flowtable_ipv6 = {\n \n static int __init nf_flow_inet_module_init(void)\n {\n+\tnft_register_flowtable_type(\u0026flowtable_bridge);\n \tnft_register_flowtable_type(\u0026flowtable_ipv4);\n \tnft_register_flowtable_type(\u0026flowtable_ipv6);\n \tnft_register_flowtable_type(\u0026flowtable_inet);\n@@ -109,6 +120,7 @@ static void __exit nf_flow_inet_module_exit(void)\n \tnft_unregister_flowtable_type(\u0026flowtable_inet);\n \tnft_unregister_flowtable_type(\u0026flowtable_ipv6);\n \tnft_unregister_flowtable_type(\u0026flowtable_ipv4);\n+\tnft_unregister_flowtable_type(\u0026flowtable_bridge);\n }\n \n module_init(nf_flow_inet_module_init);\n@@ -118,5 +130,6 @@ MODULE_LICENSE(\"GPL\");\n MODULE_AUTHOR(\"Pablo Neira Ayuso \u003cpablo@netfilter.org\u003e\");\n MODULE_ALIAS_NF_FLOWTABLE(AF_INET);\n MODULE_ALIAS_NF_FLOWTABLE(AF_INET6);\n+MODULE_ALIAS_NF_FLOWTABLE(AF_BRIDGE);\n MODULE_ALIAS_NF_FLOWTABLE(1); /* NFPROTO_INET */\n MODULE_DESCRIPTION(\"Netfilter flow table mixed IPv4/IPv6 module\");\ndiff --git a/net/netfilter/nf_flow_table_offload.c b/net/netfilter/nf_flow_table_offload.c\nindex 002ec15d988bdb..5566ebda7b7d30 100644\n--- a/net/netfilter/nf_flow_table_offload.c\n+++ b/net/netfilter/nf_flow_table_offload.c\n@@ -740,6 +740,19 @@ nf_flow_rule_route_common(struct net *net, const struct flow_offload *flow,\n \treturn 0;\n }\n \n+int nf_flow_rule_bridge(struct net *net, struct flow_offload *flow,\n+\t\t\tenum flow_offload_tuple_dir dir,\n+\t\t\tstruct nf_flow_rule *flow_rule)\n+{\n+\tif (nf_flow_rule_route_common(net, flow, dir, flow_rule) \u003c 0)\n+\t\treturn -1;\n+\n+\tflow_offload_redirect(net, flow, dir, flow_rule);\n+\n+\treturn 0;\n+}\n+EXPORT_SYMBOL_GPL(nf_flow_rule_bridge);\n+\n int nf_flow_rule_route_ipv4(struct net *net, struct flow_offload *flow,\n \t\t\t enum flow_offload_tuple_dir dir,\n \t\t\t struct nf_flow_rule *flow_rule)\ndiff --git a/net/netfilter/nf_flow_table_path.c b/net/netfilter/nf_flow_table_path.c\nindex 98c03b487f5211..2deb8e4d5328b3 100644\n--- a/net/netfilter/nf_flow_table_path.c\n+++ b/net/netfilter/nf_flow_table_path.c\n@@ -1,6 +1,7 @@\n // SPDX-License-Identifier: GPL-2.0-only\n #include \u003clinux/kernel.h\u003e\n #include \u003clinux/module.h\u003e\n+#include \u003clinux/if_vlan.h\u003e\n #include \u003clinux/init.h\u003e\n #include \u003clinux/etherdevice.h\u003e\n #include \u003clinux/netlink.h\u003e\n@@ -350,3 +351,128 @@ int nft_flow_route(const struct nft_pktinfo *pkt, const struct nf_conn *ct,\n \treturn -ENOENT;\n }\n EXPORT_SYMBOL_GPL(nft_flow_route);\n+\n+static int nft_dev_fill_bridge_path(struct flow_offload *flow,\n+\t\t\t\t struct nft_flowtable *ft,\n+\t\t\t\t enum ip_conntrack_dir dir,\n+\t\t\t\t const struct net_device *src_dev,\n+\t\t\t\t const struct net_device *dst_dev,\n+\t\t\t\t unsigned char *src_ha,\n+\t\t\t\t unsigned char *dst_ha)\n+{\n+\tstruct flow_offload_tuple_rhash *th = flow-\u003etuplehash;\n+\tstruct net_device_path_ctx ctx = {};\n+\tstruct net_device_path_stack stack;\n+\tstruct nft_forward_info info = {};\n+\tint i, j = 0;\n+\n+\tfor (i = th[dir].tuple.encap_num - 1; i \u003e= 0 ; i--) {\n+\t\tif (info.num_encaps \u003e= NF_FLOW_TABLE_ENCAP_MAX)\n+\t\t\treturn -1;\n+\n+\t\tif (th[dir].tuple.in_vlan_ingress \u0026 BIT(i))\n+\t\t\tcontinue;\n+\n+\t\tinfo.encap[info.num_encaps].id = th[dir].tuple.encap[i].id;\n+\t\tinfo.encap[info.num_encaps].proto = th[dir].tuple.encap[i].proto;\n+\t\tinfo.num_encaps++;\n+\n+\t\tif (th[dir].tuple.encap[i].proto == htons(ETH_P_PPP_SES))\n+\t\t\tcontinue;\n+\n+\t\tif (ctx.num_vlans \u003e= NET_DEVICE_PATH_VLAN_MAX)\n+\t\t\treturn -1;\n+\t\tctx.vlan[ctx.num_vlans].id = th[dir].tuple.encap[i].id;\n+\t\tctx.vlan[ctx.num_vlans].proto = th[dir].tuple.encap[i].proto;\n+\t\tctx.num_vlans++;\n+\t}\n+\tctx.dev = src_dev;\n+\tether_addr_copy(ctx.daddr, dst_ha);\n+\n+\tif (dev_fill_bridge_path(\u0026ctx, \u0026stack) \u003c 0)\n+\t\treturn -1;\n+\n+\tnft_dev_path_info(\u0026stack, \u0026info, dst_ha, \u0026ft-\u003edata);\n+\n+\tif (!info.indev || info.indev != dst_dev)\n+\t\treturn -1;\n+\n+\tth[!dir].tuple.iifidx = info.indev-\u003eifindex;\n+\tfor (i = info.num_encaps - 1; i \u003e= 0; i--) {\n+\t\tth[!dir].tuple.encap[j].id = info.encap[i].id;\n+\t\tth[!dir].tuple.encap[j].proto = info.encap[i].proto;\n+\t\tif (info.ingress_vlans \u0026 BIT(i))\n+\t\t\tth[!dir].tuple.in_vlan_ingress |= BIT(j);\n+\t\tj++;\n+\t}\n+\tth[!dir].tuple.encap_num = info.num_encaps;\n+\n+\tth[dir].tuple.mtu = dst_dev-\u003emtu;\n+\tether_addr_copy(th[dir].tuple.out.h_source, src_ha);\n+\tether_addr_copy(th[dir].tuple.out.h_dest, dst_ha);\n+\tth[dir].tuple.out.ifidx = info.outdev-\u003eifindex;\n+\tth[dir].tuple.xmit_type = FLOW_OFFLOAD_XMIT_DIRECT;\n+\n+\treturn 0;\n+}\n+\n+int flow_offload_bridge_init(struct flow_offload *flow,\n+\t\t\t const struct nft_pktinfo *pkt,\n+\t\t\t enum ip_conntrack_dir dir,\n+\t\t\t struct nft_flowtable *ft)\n+{\n+\tconst struct net_device *in_dev, *out_dev;\n+\tstruct ethhdr *eth = eth_hdr(pkt-\u003eskb);\n+\tstruct flow_offload_tuple *tuple;\n+\tint err, i = 0;\n+\n+\tin_dev = nft_in(pkt);\n+\tif (!in_dev || !nft_flowtable_find_dev(in_dev, ft))\n+\t\treturn -1;\n+\n+\tout_dev = nft_out(pkt);\n+\tif (!out_dev || !nft_flowtable_find_dev(out_dev, ft))\n+\t\treturn -1;\n+\n+\ttuple = \u0026flow-\u003etuplehash[!dir].tuple;\n+\n+\tif (skb_vlan_tag_present(pkt-\u003eskb)) {\n+\t\ttuple-\u003eencap[i].id = skb_vlan_tag_get(pkt-\u003eskb);\n+\t\ttuple-\u003eencap[i].proto = pkt-\u003eskb-\u003evlan_proto;\n+\t\ti++;\n+\t}\n+\n+\tswitch (eth_hdr(pkt-\u003eskb)-\u003eh_proto) {\n+\tcase htons(ETH_P_8021Q): {\n+\t\tstruct vlan_hdr *vhdr = (struct vlan_hdr *)(skb_mac_header(pkt-\u003eskb)\n+\t\t\t\t\t + sizeof(struct ethhdr));\n+\t\ttuple-\u003eencap[i].id = ntohs(vhdr-\u003eh_vlan_TCI);\n+\t\ttuple-\u003eencap[i].proto = htons(ETH_P_8021Q);\n+\t\ti++;\n+\t\tbreak;\n+\t}\n+\tcase htons(ETH_P_PPP_SES): {\n+\t\tstruct pppoe_hdr *phdr = (struct pppoe_hdr *)(skb_mac_header(pkt-\u003eskb)\n+\t\t\t\t\t + sizeof(struct ethhdr));\n+\n+\t\ttuple-\u003eencap[i].id = ntohs(phdr-\u003esid);\n+\t\ttuple-\u003eencap[i].proto = htons(ETH_P_PPP_SES);\n+\t\ti++;\n+\t\tbreak;\n+\t}\n+\t}\n+\ttuple-\u003eencap_num = i;\n+\n+\terr = nft_dev_fill_bridge_path(flow, ft, !dir, out_dev, in_dev,\n+\t\t\t\t eth-\u003eh_dest, eth-\u003eh_source);\n+\tif (err \u003c 0)\n+\t\treturn err;\n+\n+\terr = nft_dev_fill_bridge_path(flow, ft, dir, in_dev, out_dev,\n+\t\t\t\t eth-\u003eh_source, eth-\u003eh_dest);\n+\tif (err \u003c 0)\n+\t\treturn err;\n+\n+\treturn 0;\n+}\n+EXPORT_SYMBOL_GPL(flow_offload_bridge_init);\ndiff --git a/net/netfilter/nft_flow_offload.c b/net/netfilter/nft_flow_offload.c\nindex 32b4281038dd35..1a5eef46f922d0 100644\n--- a/net/netfilter/nft_flow_offload.c\n+++ b/net/netfilter/nft_flow_offload.c\n@@ -53,13 +53,14 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,\n {\n \tstruct nft_flow_offload *priv = nft_expr_priv(expr);\n \tstruct nf_flowtable *flowtable = \u0026priv-\u003eflowtable-\u003edata;\n+\tbool routing = flowtable-\u003etype-\u003efamily != NFPROTO_BRIDGE;\n \tstruct tcphdr _tcph, *tcph = NULL;\n \tstruct nf_flow_route route = {};\n \tenum ip_conntrack_info ctinfo;\n \tstruct flow_offload *flow;\n \tenum ip_conntrack_dir dir;\n \tstruct nf_conn *ct;\n-\tint ret;\n+\tint ret, thoff;\n \n \tif (nft_flow_offload_skip(pkt-\u003eskb, nft_pf(pkt)))\n \t\tgoto out;\n@@ -70,8 +71,11 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,\n \n \tswitch (ct-\u003etuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum) {\n \tcase IPPROTO_TCP:\n-\t\ttcph = skb_header_pointer(pkt-\u003eskb, nft_thoff(pkt),\n-\t\t\t\t\t sizeof(_tcph), \u0026_tcph);\n+\t\tthoff = nft_thoff(pkt);\n+\t\tif (thoff == 0)\n+\t\t\tgoto out;\n+\t\ttcph = skb_header_pointer(pkt-\u003eskb, thoff, sizeof(_tcph),\n+\t\t\t\t\t \u0026_tcph);\n \t\tif (unlikely(!tcph || tcph-\u003efin || tcph-\u003erst ||\n \t\t\t !nf_conntrack_tcp_established(ct)))\n \t\t\tgoto out;\n@@ -106,14 +110,21 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,\n \t\tgoto out;\n \n \tdir = CTINFO2DIR(ctinfo);\n-\tif (nft_flow_route(pkt, ct, \u0026route, dir, priv-\u003eflowtable) \u003c 0)\n-\t\tgoto err_flow_route;\n+\tif (routing) {\n+\t\tif (nft_flow_route(pkt, ct, \u0026route, dir, priv-\u003eflowtable) \u003c 0)\n+\t\t\tgoto err_flow_route;\n+\t}\n \n \tflow = flow_offload_alloc(ct);\n \tif (!flow)\n \t\tgoto err_flow_alloc;\n \n-\tflow_offload_route_init(flow, \u0026route);\n+\tif (routing)\n+\t\tflow_offload_route_init(flow, \u0026route);\n+\telse\n+\t\tif (flow_offload_bridge_init(flow, pkt, dir, priv-\u003eflowtable) \u003c 0)\n+\t\t\tgoto err_flow_add;\n+\n \tif (tcph)\n \t\tflow_offload_ct_tcp(ct);\n \n@@ -127,8 +138,10 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,\n err_flow_add:\n \tflow_offload_free(flow);\n err_flow_alloc:\n-\tdst_release(route.tuple[dir].dst);\n-\tdst_release(route.tuple[!dir].dst);\n+\tif (routing) {\n+\t\tdst_release(route.tuple[dir].dst);\n+\t\tdst_release(route.tuple[!dir].dst);\n+\t}\n err_flow_route:\n \tclear_bit(IPS_OFFLOAD_BIT, \u0026ct-\u003estatus);\n out:\n@@ -142,7 +155,8 @@ static int nft_flow_offload_validate(const struct nft_ctx *ctx,\n \n \tif (ctx-\u003efamily != NFPROTO_IPV4 \u0026\u0026\n \t ctx-\u003efamily != NFPROTO_IPV6 \u0026\u0026\n-\t ctx-\u003efamily != NFPROTO_INET)\n+\t ctx-\u003efamily != NFPROTO_INET \u0026\u0026\n+\t ctx-\u003efamily != NFPROTO_BRIDGE)\n \t\treturn -EOPNOTSUPP;\n \n \treturn nft_chain_validate_hooks(ctx-\u003echain, hook_mask);\n"
} |
| 2/1 | 2026/07/07 16:30 | agent | patch-evaluator |
1mModel:gemini-3.1-pro-preview Args: null Results: {
"EnableConfigs": [
"NF_FLOW_TABLE",
"NF_FLOW_TABLE_INET",
"NFT_FLOW_OFFLOAD",
"BRIDGE",
"BRIDGE_VLAN_FILTERING"
],
"FocusSymbols": [
"dev_fill_bridge_path",
"flow_offload_bridge_init",
"nft_dev_fill_bridge_path",
"nf_flow_rule_bridge",
"br_fill_forward_path",
"br_vlan_fill_forward_path_pvid"
],
"Reasoning": "The patch introduces bridge support for netfilter flow offload. It adds new functions to handle bridge paths in flow offload and modifies existing bridge forward path functions. This is a functional change in the core networking and netfilter subsystems that is reachable via nftables and bridge configuration, making it a good target 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 3205a525ad0cd6d4410da0c3915d3e3cadb15dee
Author: syz-cluster <triage@syzkaller.com>
Date: Tue Jul 7 16:30:22 2026 +0000
syz-cluster: applied patch under review
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 9981d637f8b546..fdee4465d61261 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -3420,6 +3420,8 @@ void dev_remove_offload(struct packet_offload *po);
int dev_get_iflink(const struct net_device *dev);
int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb);
+int dev_fill_bridge_path(struct net_device_path_ctx *ctx,
+ struct net_device_path_stack *stack);
int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
struct net_device_path_stack *stack);
struct net_device *dev_get_by_name(struct net *net, const char *name);
diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
index 7b23b245a5a86a..a109eda5250c79 100644
--- a/include/net/netfilter/nf_flow_table.h
+++ b/include/net/netfilter/nf_flow_table.h
@@ -305,6 +305,11 @@ nf_flow_table_offload_del_cb(struct nf_flowtable *flow_table,
void flow_offload_route_init(struct flow_offload *flow,
struct nf_flow_route *route);
+int flow_offload_bridge_init(struct flow_offload *flow,
+ const struct nft_pktinfo *pkt,
+ enum ip_conntrack_dir dir,
+ struct nft_flowtable *ft);
+
int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow);
void flow_offload_refresh(struct nf_flowtable *flow_table,
struct flow_offload *flow, bool force);
@@ -368,6 +373,9 @@ void nf_flow_table_offload_flush_cleanup(struct nf_flowtable *flowtable);
int nf_flow_table_offload_setup(struct nf_flowtable *flowtable,
struct net_device *dev,
enum flow_block_command cmd);
+int nf_flow_rule_bridge(struct net *net, struct flow_offload *flow,
+ enum flow_offload_tuple_dir dir,
+ struct nf_flow_rule *flow_rule);
int nf_flow_rule_route_ipv4(struct net *net, struct flow_offload *flow,
enum flow_offload_tuple_dir dir,
struct nf_flow_rule *flow_rule);
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index e7f343ab22d379..89f4525a7279d6 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -385,16 +385,25 @@ static int br_del_slave(struct net_device *dev, struct net_device *slave_dev)
static int br_fill_forward_path(struct net_device_path_ctx *ctx,
struct net_device_path *path)
{
+ struct net_bridge_port *src, *dst;
struct net_bridge_fdb_entry *f;
- struct net_bridge_port *dst;
struct net_bridge *br;
- if (netif_is_bridge_port(ctx->dev))
- return -1;
+ if (netif_is_bridge_port(ctx->dev)) {
+ struct net_device *br_dev;
+
+ br_dev = netdev_master_upper_dev_get_rcu((struct net_device *)ctx->dev);
+ if (!br_dev)
+ return -1;
- br = netdev_priv(ctx->dev);
+ src = br_port_get_rcu(ctx->dev);
+ br = netdev_priv(br_dev);
+ } else {
+ src = NULL;
+ br = netdev_priv(ctx->dev);
+ }
- br_vlan_fill_forward_path_pvid(br, ctx, path);
+ br_vlan_fill_forward_path_pvid(br, src, ctx, path);
f = br_fdb_find_rcu(br, ctx->daddr, path->bridge.vlan_id);
if (!f)
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index d55ea9516e3e36..00f5b72ff42dea 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -1630,6 +1630,7 @@ bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr,
const struct net_bridge_vlan *range_end);
void br_vlan_fill_forward_path_pvid(struct net_bridge *br,
+ struct net_bridge_port *p,
struct net_device_path_ctx *ctx,
struct net_device_path *path);
int br_vlan_fill_forward_path_mode(struct net_bridge *br,
@@ -1799,6 +1800,7 @@ static inline int nbp_get_num_vlan_infos(struct net_bridge_port *p,
}
static inline void br_vlan_fill_forward_path_pvid(struct net_bridge *br,
+ struct net_bridge_port *p,
struct net_device_path_ctx *ctx,
struct net_device_path *path)
{
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index 5560afcaaca327..71531499bc7356 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -1450,6 +1450,7 @@ int br_vlan_get_pvid_rcu(const struct net_device *dev, u16 *p_pvid)
EXPORT_SYMBOL_GPL(br_vlan_get_pvid_rcu);
void br_vlan_fill_forward_path_pvid(struct net_bridge *br,
+ struct net_bridge_port *p,
struct net_device_path_ctx *ctx,
struct net_device_path *path)
{
@@ -1462,7 +1463,10 @@ void br_vlan_fill_forward_path_pvid(struct net_bridge *br,
if (!br_opt_get(br, BROPT_VLAN_ENABLED))
return;
- vg = br_vlan_group_rcu(br);
+ if (p)
+ vg = nbp_vlan_group_rcu(p);
+ else
+ vg = br_vlan_group_rcu(br);
if (idx >= 0 &&
ctx->vlan[idx].proto == br->vlan_proto) {
diff --git a/net/core/dev.c b/net/core/dev.c
index 4b3d5cfdf6e00f..f6685c1e478601 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -750,44 +750,84 @@ static struct net_device_path *dev_fwd_path(struct net_device_path_stack *stack)
return &stack->path[k];
}
-int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
- struct net_device_path_stack *stack)
+static int dev_fill_forward_path_common(struct net_device_path_ctx *ctx,
+ struct net_device_path_stack *stack)
{
const struct net_device *last_dev;
- struct net_device_path_ctx ctx = {
- .dev = dev,
- };
struct net_device_path *path;
int ret = 0;
- memcpy(ctx.daddr, daddr, sizeof(ctx.daddr));
- stack->num_paths = 0;
- while (ctx.dev && ctx.dev->netdev_ops->ndo_fill_forward_path) {
- last_dev = ctx.dev;
+ while (ctx->dev && ctx->dev->netdev_ops->ndo_fill_forward_path) {
+ last_dev = ctx->dev;
path = dev_fwd_path(stack);
if (!path)
return -1;
memset(path, 0, sizeof(struct net_device_path));
- ret = ctx.dev->netdev_ops->ndo_fill_forward_path(&ctx, path);
+ ret = ctx->dev->netdev_ops->ndo_fill_forward_path(ctx, path);
if (ret < 0)
return -1;
- if (WARN_ON_ONCE(last_dev == ctx.dev))
+ if (WARN_ON_ONCE(last_dev == ctx->dev))
return -1;
}
- if (!ctx.dev)
+ if (!ctx->dev)
return ret;
path = dev_fwd_path(stack);
if (!path)
return -1;
path->type = DEV_PATH_ETHERNET;
- path->dev = ctx.dev;
+ path->dev = ctx->dev;
return ret;
}
+
+int dev_fill_bridge_path(struct net_device_path_ctx *ctx,
+ struct net_device_path_stack *stack)
+{
+ const struct net_device *last_dev, *br_dev;
+ struct net_device_path *path;
+
+ stack->num_paths = 0;
+
+ if (!ctx->dev || !netif_is_bridge_port(ctx->dev))
+ return -1;
+
+ br_dev = netdev_master_upper_dev_get_rcu((struct net_device *)ctx->dev);
+ if (!br_dev || !br_dev->netdev_ops->ndo_fill_forward_path)
+ return -1;
+
+ last_dev = ctx->dev;
+ path = dev_fwd_path(stack);
+ if (!path)
+ return -1;
+
+ memset(path, 0, sizeof(struct net_device_path));
+ if (br_dev->netdev_ops->ndo_fill_forward_path(ctx, path) < 0)
+ return -1;
+
+ if (!ctx->dev || WARN_ON_ONCE(last_dev == ctx->dev))
+ return -1;
+
+ return dev_fill_forward_path_common(ctx, stack);
+}
+EXPORT_SYMBOL_GPL(dev_fill_bridge_path);
+
+int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
+ struct net_device_path_stack *stack)
+{
+ struct net_device_path_ctx ctx = {
+ .dev = dev,
+ };
+
+ memcpy(ctx.daddr, daddr, sizeof(ctx.daddr));
+
+ stack->num_paths = 0;
+
+ return dev_fill_forward_path_common(&ctx, stack);
+}
EXPORT_SYMBOL_GPL(dev_fill_forward_path);
/* must be called under rcu_read_lock(), as we dont take a reference */
diff --git a/net/netfilter/nf_flow_table_inet.c b/net/netfilter/nf_flow_table_inet.c
index b0f19917193241..80b238196f29b3 100644
--- a/net/netfilter/nf_flow_table_inet.c
+++ b/net/netfilter/nf_flow_table_inet.c
@@ -65,6 +65,16 @@ static int nf_flow_rule_route_inet(struct net *net,
return err;
}
+static struct nf_flowtable_type flowtable_bridge = {
+ .family = NFPROTO_BRIDGE,
+ .init = nf_flow_table_init,
+ .setup = nf_flow_table_offload_setup,
+ .action = nf_flow_rule_bridge,
+ .free = nf_flow_table_free,
+ .hook = nf_flow_offload_inet_hook,
+ .owner = THIS_MODULE,
+};
+
static struct nf_flowtable_type flowtable_inet = {
.family = NFPROTO_INET,
.init = nf_flow_table_init,
@@ -97,6 +107,7 @@ static struct nf_flowtable_type flowtable_ipv6 = {
static int __init nf_flow_inet_module_init(void)
{
+ nft_register_flowtable_type(&flowtable_bridge);
nft_register_flowtable_type(&flowtable_ipv4);
nft_register_flowtable_type(&flowtable_ipv6);
nft_register_flowtable_type(&flowtable_inet);
@@ -109,6 +120,7 @@ static void __exit nf_flow_inet_module_exit(void)
nft_unregister_flowtable_type(&flowtable_inet);
nft_unregister_flowtable_type(&flowtable_ipv6);
nft_unregister_flowtable_type(&flowtable_ipv4);
+ nft_unregister_flowtable_type(&flowtable_bridge);
}
module_init(nf_flow_inet_module_init);
@@ -118,5 +130,6 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
MODULE_ALIAS_NF_FLOWTABLE(AF_INET);
MODULE_ALIAS_NF_FLOWTABLE(AF_INET6);
+MODULE_ALIAS_NF_FLOWTABLE(AF_BRIDGE);
MODULE_ALIAS_NF_FLOWTABLE(1); /* NFPROTO_INET */
MODULE_DESCRIPTION("Netfilter flow table mixed IPv4/IPv6 module");
diff --git a/net/netfilter/nf_flow_table_offload.c b/net/netfilter/nf_flow_table_offload.c
index 002ec15d988bdb..5566ebda7b7d30 100644
--- a/net/netfilter/nf_flow_table_offload.c
+++ b/net/netfilter/nf_flow_table_offload.c
@@ -740,6 +740,19 @@ nf_flow_rule_route_common(struct net *net, const struct flow_offload *flow,
return 0;
}
+int nf_flow_rule_bridge(struct net *net, struct flow_offload *flow,
+ enum flow_offload_tuple_dir dir,
+ struct nf_flow_rule *flow_rule)
+{
+ if (nf_flow_rule_route_common(net, flow, dir, flow_rule) < 0)
+ return -1;
+
+ flow_offload_redirect(net, flow, dir, flow_rule);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(nf_flow_rule_bridge);
+
int nf_flow_rule_route_ipv4(struct net *net, struct flow_offload *flow,
enum flow_offload_tuple_dir dir,
struct nf_flow_rule *flow_rule)
diff --git a/net/netfilter/nf_flow_table_path.c b/net/netfilter/nf_flow_table_path.c
index 98c03b487f5211..2deb8e4d5328b3 100644
--- a/net/netfilter/nf_flow_table_path.c
+++ b/net/netfilter/nf_flow_table_path.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/if_vlan.h>
#include <linux/init.h>
#include <linux/etherdevice.h>
#include <linux/netlink.h>
@@ -350,3 +351,128 @@ int nft_flow_route(const struct nft_pktinfo *pkt, const struct nf_conn *ct,
return -ENOENT;
}
EXPORT_SYMBOL_GPL(nft_flow_route);
+
+static int nft_dev_fill_bridge_path(struct flow_offload *flow,
+ struct nft_flowtable *ft,
+ enum ip_conntrack_dir dir,
+ const struct net_device *src_dev,
+ const struct net_device *dst_dev,
+ unsigned char *src_ha,
+ unsigned char *dst_ha)
+{
+ struct flow_offload_tuple_rhash *th = flow->tuplehash;
+ struct net_device_path_ctx ctx = {};
+ struct net_device_path_stack stack;
+ struct nft_forward_info info = {};
+ int i, j = 0;
+
+ for (i = th[dir].tuple.encap_num - 1; i >= 0 ; i--) {
+ if (info.num_encaps >= NF_FLOW_TABLE_ENCAP_MAX)
+ return -1;
+
+ if (th[dir].tuple.in_vlan_ingress & BIT(i))
+ continue;
+
+ info.encap[info.num_encaps].id = th[dir].tuple.encap[i].id;
+ info.encap[info.num_encaps].proto = th[dir].tuple.encap[i].proto;
+ info.num_encaps++;
+
+ if (th[dir].tuple.encap[i].proto == htons(ETH_P_PPP_SES))
+ continue;
+
+ if (ctx.num_vlans >= NET_DEVICE_PATH_VLAN_MAX)
+ return -1;
+ ctx.vlan[ctx.num_vlans].id = th[dir].tuple.encap[i].id;
+ ctx.vlan[ctx.num_vlans].proto = th[dir].tuple.encap[i].proto;
+ ctx.num_vlans++;
+ }
+ ctx.dev = src_dev;
+ ether_addr_copy(ctx.daddr, dst_ha);
+
+ if (dev_fill_bridge_path(&ctx, &stack) < 0)
+ return -1;
+
+ nft_dev_path_info(&stack, &info, dst_ha, &ft->data);
+
+ if (!info.indev || info.indev != dst_dev)
+ return -1;
+
+ th[!dir].tuple.iifidx = info.indev->ifindex;
+ for (i = info.num_encaps - 1; i >= 0; i--) {
+ th[!dir].tuple.encap[j].id = info.encap[i].id;
+ th[!dir].tuple.encap[j].proto = info.encap[i].proto;
+ if (info.ingress_vlans & BIT(i))
+ th[!dir].tuple.in_vlan_ingress |= BIT(j);
+ j++;
+ }
+ th[!dir].tuple.encap_num = info.num_encaps;
+
+ th[dir].tuple.mtu = dst_dev->mtu;
+ ether_addr_copy(th[dir].tuple.out.h_source, src_ha);
+ ether_addr_copy(th[dir].tuple.out.h_dest, dst_ha);
+ th[dir].tuple.out.ifidx = info.outdev->ifindex;
+ th[dir].tuple.xmit_type = FLOW_OFFLOAD_XMIT_DIRECT;
+
+ return 0;
+}
+
+int flow_offload_bridge_init(struct flow_offload *flow,
+ const struct nft_pktinfo *pkt,
+ enum ip_conntrack_dir dir,
+ struct nft_flowtable *ft)
+{
+ const struct net_device *in_dev, *out_dev;
+ struct ethhdr *eth = eth_hdr(pkt->skb);
+ struct flow_offload_tuple *tuple;
+ int err, i = 0;
+
+ in_dev = nft_in(pkt);
+ if (!in_dev || !nft_flowtable_find_dev(in_dev, ft))
+ return -1;
+
+ out_dev = nft_out(pkt);
+ if (!out_dev || !nft_flowtable_find_dev(out_dev, ft))
+ return -1;
+
+ tuple = &flow->tuplehash[!dir].tuple;
+
+ if (skb_vlan_tag_present(pkt->skb)) {
+ tuple->encap[i].id = skb_vlan_tag_get(pkt->skb);
+ tuple->encap[i].proto = pkt->skb->vlan_proto;
+ i++;
+ }
+
+ switch (eth_hdr(pkt->skb)->h_proto) {
+ case htons(ETH_P_8021Q): {
+ struct vlan_hdr *vhdr = (struct vlan_hdr *)(skb_mac_header(pkt->skb)
+ + sizeof(struct ethhdr));
+ tuple->encap[i].id = ntohs(vhdr->h_vlan_TCI);
+ tuple->encap[i].proto = htons(ETH_P_8021Q);
+ i++;
+ break;
+ }
+ case htons(ETH_P_PPP_SES): {
+ struct pppoe_hdr *phdr = (struct pppoe_hdr *)(skb_mac_header(pkt->skb)
+ + sizeof(struct ethhdr));
+
+ tuple->encap[i].id = ntohs(phdr->sid);
+ tuple->encap[i].proto = htons(ETH_P_PPP_SES);
+ i++;
+ break;
+ }
+ }
+ tuple->encap_num = i;
+
+ err = nft_dev_fill_bridge_path(flow, ft, !dir, out_dev, in_dev,
+ eth->h_dest, eth->h_source);
+ if (err < 0)
+ return err;
+
+ err = nft_dev_fill_bridge_path(flow, ft, dir, in_dev, out_dev,
+ eth->h_source, eth->h_dest);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(flow_offload_bridge_init);
diff --git a/net/netfilter/nft_flow_offload.c b/net/netfilter/nft_flow_offload.c
index 32b4281038dd35..1a5eef46f922d0 100644
--- a/net/netfilter/nft_flow_offload.c
+++ b/net/netfilter/nft_flow_offload.c
@@ -53,13 +53,14 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
{
struct nft_flow_offload *priv = nft_expr_priv(expr);
struct nf_flowtable *flowtable = &priv->flowtable->data;
+ bool routing = flowtable->type->family != NFPROTO_BRIDGE;
struct tcphdr _tcph, *tcph = NULL;
struct nf_flow_route route = {};
enum ip_conntrack_info ctinfo;
struct flow_offload *flow;
enum ip_conntrack_dir dir;
struct nf_conn *ct;
- int ret;
+ int ret, thoff;
if (nft_flow_offload_skip(pkt->skb, nft_pf(pkt)))
goto out;
@@ -70,8 +71,11 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
switch (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum) {
case IPPROTO_TCP:
- tcph = skb_header_pointer(pkt->skb, nft_thoff(pkt),
- sizeof(_tcph), &_tcph);
+ thoff = nft_thoff(pkt);
+ if (thoff == 0)
+ goto out;
+ tcph = skb_header_pointer(pkt->skb, thoff, sizeof(_tcph),
+ &_tcph);
if (unlikely(!tcph || tcph->fin || tcph->rst ||
!nf_conntrack_tcp_established(ct)))
goto out;
@@ -106,14 +110,21 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
goto out;
dir = CTINFO2DIR(ctinfo);
- if (nft_flow_route(pkt, ct, &route, dir, priv->flowtable) < 0)
- goto err_flow_route;
+ if (routing) {
+ if (nft_flow_route(pkt, ct, &route, dir, priv->flowtable) < 0)
+ goto err_flow_route;
+ }
flow = flow_offload_alloc(ct);
if (!flow)
goto err_flow_alloc;
- flow_offload_route_init(flow, &route);
+ if (routing)
+ flow_offload_route_init(flow, &route);
+ else
+ if (flow_offload_bridge_init(flow, pkt, dir, priv->flowtable) < 0)
+ goto err_flow_add;
+
if (tcph)
flow_offload_ct_tcp(ct);
@@ -127,8 +138,10 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
err_flow_add:
flow_offload_free(flow);
err_flow_alloc:
- dst_release(route.tuple[dir].dst);
- dst_release(route.tuple[!dir].dst);
+ if (routing) {
+ dst_release(route.tuple[dir].dst);
+ dst_release(route.tuple[!dir].dst);
+ }
err_flow_route:
clear_bit(IPS_OFFLOAD_BIT, &ct->status);
out:
@@ -142,7 +155,8 @@ static int nft_flow_offload_validate(const struct nft_ctx *ctx,
if (ctx->family != NFPROTO_IPV4 &&
ctx->family != NFPROTO_IPV6 &&
- ctx->family != NFPROTO_INET)
+ ctx->family != NFPROTO_INET &&
+ ctx->family != NFPROTO_BRIDGE)
return -EOPNOTSUPP;
return nft_chain_validate_hooks(ctx->chain, hook_mask);
|
| 3/2 | 2026/07/07 16:30 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 8859 output: 34 thoughts: 380 Thoughts: **Fuzzing Target Identification: Bridge Netfilter Flow Offload Patch** Okay, so I've got this patch series in front of me, and my immediate concern is whether it introduces functional changes to the kernel that necessitate fuzzing. Seems like it's adding bridge support for netfilter flow offload, which definitely sounds like a potential target. Let's dig in. The patch touches a few key areas. I see `dev_fill_bridge_path` in `net/core/dev.c`, which always warrants a look, and `br_fill_forward_path` in `net/bridge/br_device.c` gets modified. Then, we have `flow_offload_bridge_init` and `nf_flow_rule_bridge` in the netfilter side, specifically `net/netfilter/nf_flow_table_path.c` and `net/netfilter/nf_flow_table_offload.c` respectively. It also registers `flowtable_bridge` in `net/netfilter/nf_flow_table_inet.c`. Finally `nft_flow_offload_eval` in `net/netfilter/nft_flow_offload.c` is being modified to handle `NFPROTO_BRIDGE`. Yes, this is a clear functional change. I need to pinpoint the kernel functions to prioritize for fuzzing. Looks like: * `dev_fill_bridge_path` * `flow_offload_bridge_init` * `nft_dev_fill_bridge_path` (statically defined) * `nf_flow_rule_bridge` I need to make sure I understand the relevant Kconfig options to determine if these functions are compiled in various configurations. I know the code is spread across multiple files: * `dev_fill_bridge_path` lives in `net/core/dev.c` * `flow_offload_bridge_init` lives in `net/netfilter/nf_flow_table_path.c` * `nf_flow_rule_bridge` lives in `net/netfilter/nf_flow_table_offload.c` * `flowtable_bridge` lives in `net/netfilter/nf_flow_table_inet.c` Time to whip out `grepper` and see what Kconfig options are controlling this. That's the next step to ensure I can build a fuzzer that's relevant to the widest set of kernel configurations. |
| 4/2 | 2026/07/07 16:30 | tool | grepper |
0mArgs:{
"Expression": "nf_flow_table_path\\.o",
"PathPrefix": "net/netfilter/"
}Results: {
"Output": "net/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 \\\nnet/netfilter/Makefile-145-\t\t\t\t nf_flow_table_offload.o nf_flow_table_xdp.o\n"
} |
| 5/2 | 2026/07/07 16:30 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 9928 output: 32 thoughts: 20 Thoughts: Okay, let's dive into this. Here's my thought process on this: **Investigating the `nf_flow_table` in the Netfilter Build Process** Right, so I need to understand something about the `nf_flow_table` module and where it fits in the Netfilter framework. The logical first step, given my familiarity with kernel development, is to check the `Makefile`. That's where all the build instructions reside. It'll tell me how `nf_flow_table` is compiled, linked, and possibly what dependencies it has. Specifically, I'll go directly to the `net/netfilter/` directory and see what's in its Makefile. That should give me a solid starting point for understanding how this particular component is integrated into the larger Netfilter ecosystem. Knowing the build process will illuminate its dependencies, potential build flags, and overall role within the Netfilter architecture. Time to check that Makefile! |
| 6/2 | 2026/07/07 16:30 | tool | grepper |
0mArgs:{
"Expression": "nf_flow_table-objs",
"PathPrefix": "net/netfilter/"
}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/07/07 16:30 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 10286 output: 34 thoughts: 28 Thoughts: Okay, here's my interpretation of those thoughts, presented as my own mental process, given my expertise: **Examining the Flow Table Configuration** Alright, let's see, the current state of the code points to the mandatory requirement of `CONFIG_NF_FLOW_TABLE`. That's the core, the foundational setting. No surprises there. But, I need to dig a little deeper than just that. My immediate thought is, what about `nf_flow_table_inet.o`? Is it also necessary? The dependency tree is important to understand. I need to figure out the interplay between the configuration option and the associated modules. I'll need to figure out if it's implicitly built with that, or if it requires its own explicit call, or it may need other options. Time to analyze the build system more closely. |
| 8/2 | 2026/07/07 16:30 | tool | grepper |
0mArgs:{
"Expression": "nf_flow_table_inet\\.o",
"PathPrefix": "net/netfilter/"
}Results: {
"Output": "net/netfilter/Makefile=151=endif\nnet/netfilter/Makefile-152-\nnet/netfilter/Makefile:153:obj-$(CONFIG_NF_FLOW_TABLE_INET) += nf_flow_table_inet.o\nnet/netfilter/Makefile-154-\n"
} |
| 9/2 | 2026/07/07 16:30 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 10609 output: 33 thoughts: 29 Thoughts: Okay, here's my interpretation of those thoughts, tailored for an expert audience, presented in the first person: **Kernel Configuration Dependencies** Alright, let me see... it looks like I need to ensure that `CONFIG_NF_FLOW_TABLE_INET` is enabled. That's a given, I understand its implications within the netfilter framework. Now, the next question that's jumping to my mind is about `nft_flow_offload.o`. Is this module's inclusion also essential or tied to specific features I am using? I need to clarify the relationship between the flow table and the offload component; do they both need to be present and available in the kernel for things to function properly? Let's check the kernel documentation to verify. |
| 10/2 | 2026/07/07 16:30 | tool | grepper |
0mArgs:{
"Expression": "nft_flow_offload\\.o",
"PathPrefix": "net/netfilter/"
}Results: {
"Output": "net/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\nnet/netfilter/Makefile-114-obj-$(CONFIG_NFT_LIMIT)\t\t+= nft_limit.o\n"
} |
| 11/2 | 2026/07/07 16:30 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 10933 output: 29 thoughts: 43 Thoughts: Okay, here's my take on those thoughts, framed from my perspective, as if I'm working through this myself: **Investigating NFTables Flow Offload Dependencies in Bridge Code** Alright, the system's telling me that `CONFIG_NFT_FLOW_OFFLOAD` is a necessary component here. Time to get my hands dirty and understand exactly how this interacts with the bridge code. My first instinct, given the context, is to delve into `net/bridge/br_device.c` and `net/bridge/br_vlan.c`. These seem like the logical starting points; they're the core of the bridge functionality and VLAN handling respectively, so they're the most likely places to find the integration, or lack thereof, with nftables offload. I need to figure out the specific locations in the source code to get a deeper understanding. I need to know where the hooks are, or whether there needs to be a hook added. |
| 12/2 | 2026/07/07 16:30 | tool | grepper |
0mArgs:{
"Expression": "br_device\\.o",
"PathPrefix": "net/bridge/"
}Results: {
"Output": "net/bridge/Makefile=6=obj-$(CONFIG_BRIDGE) += bridge.o\nnet/bridge/Makefile-7-\nnet/bridge/Makefile:8:bridge-y\t:= br.o br_device.o br_fdb.o br_forward.o br_if.o br_input.o \\\nnet/bridge/Makefile-9-\t\t\tbr_ioctl.o br_stp.o br_stp_bpdu.o \\\n"
} |
| 13/2 | 2026/07/07 16:30 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 11321 output: 30 thoughts: 21 Thoughts: Here's my thought process, as if I were considering this issue: **Delving into the Bridge Configuration** Okay, so I see that `CONFIG_BRIDGE` is a fundamental requirement here. That's hardly surprising, we're dealing with bridging after all. The core functionality hinges on that configuration option being enabled. Now, what about the interactions with `br_vlan.c`? I need to consider how this module integrates with the broader bridging framework. Is it a core component? A supporting module? Are there specific dependencies or potential conflicts I should be aware of? This needs further investigation to understand its role in this system. |
| 14/2 | 2026/07/07 16:31 | tool | grepper |
0mArgs:{
"Expression": "br_vlan\\.o",
"PathPrefix": "net/bridge/"
}Results: {
"Output": "net/bridge/Makefile=21=bridge-$(CONFIG_BRIDGE_IGMP_SNOOPING) += br_multicast.o br_mdb.o br_multicast_eht.o\nnet/bridge/Makefile-22-\nnet/bridge/Makefile:23:bridge-$(CONFIG_BRIDGE_VLAN_FILTERING) += br_vlan.o br_vlan_tunnel.o br_vlan_options.o br_mst.o\nnet/bridge/Makefile-24-\n"
} |
| 15/2 | 2026/07/07 16:31 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 11636 output: 34 thoughts: 39 Thoughts: Okay, here's my take on those thoughts, framed as an expert's internal monologue: **Bridged VLAN Filtering - Digging Deeper** Right, `CONFIG_BRIDGE_VLAN_FILTERING` is definitely a prerequisite here. That's the baseline. Now, I need to understand *how* it's working under the hood, particularly how the kernel determines if a packet should be bridged when VLAN filtering is enabled. My instincts tell me the core logic likely resides in something like the device path handling. I need to understand the mechanism. Let's dive into `dev_fill_bridge_path` within `net/core/dev.c`. That function name suggests it’s responsible for establishing the path a packet takes through the bridging infrastructure based on the device information, which is exactly what I'm looking for. Let's see how that path-building interacts with VLAN filtering enabled. This should expose the crucial decision points and filtering rules. I need to quickly ascertain how the VLAN tag is considered during path determination and whether it’s used in filtering packets destined for the bridge. |
| 16/2 | 2026/07/07 16:31 | tool | grepper |
0mArgs:{
"Expression": "dev_fill_bridge_path",
"PathPrefix": "net/core/dev.c"
}Results: {
"Output": "net/core/dev.c=753=static int dev_fill_forward_path_common(struct net_device_path_ctx *ctx,\n--\nnet/core/dev.c-786-\nnet/core/dev.c:787:int dev_fill_bridge_path(struct net_device_path_ctx *ctx,\nnet/core/dev.c-788-\t\t\t struct net_device_path_stack *stack)\n--\nnet/core/dev.c-815-}\nnet/core/dev.c:816:EXPORT_SYMBOL_GPL(dev_fill_bridge_path);\nnet/core/dev.c-817-\n"
} |
| 17/2 | 2026/07/07 16:31 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 12117 output: 42 thoughts: 31 Thoughts: Here's my take on those thoughts, tailored for an expert audience: **Diving into Flow Offload Initialization** Okay, so I'm thinking, where does the magic really begin for the flow offload bridge functionality? I need to get to the root of how this thing gets initialized. My gut tells me that `flow_offload_bridge_init` is the function to examine. Specifically, that function should be in the `net/netfilter/nf_flow_table_path.c` file. Time to dig in there and see how the bridge-specific configurations and resources are setup for the flow offload feature. Let's see how the different components are hooked together. |
| 18/2 | 2026/07/07 16:31 | tool | grepper |
0mArgs:{
"Expression": "flow_offload_bridge_init",
"PathPrefix": "net/netfilter/nf_flow_table_path.c"
}Results: {
"Output": "net/netfilter/nf_flow_table_path.c=355=static int nft_dev_fill_bridge_path(struct flow_offload *flow,\n--\nnet/netfilter/nf_flow_table_path.c-418-\nnet/netfilter/nf_flow_table_path.c:419:int flow_offload_bridge_init(struct flow_offload *flow,\nnet/netfilter/nf_flow_table_path.c-420-\t\t\t const struct nft_pktinfo *pkt,\n--\nnet/netfilter/nf_flow_table_path.c-477-}\nnet/netfilter/nf_flow_table_path.c:478:EXPORT_SYMBOL_GPL(flow_offload_bridge_init);\n"
} |
| 19/2 | 2026/07/07 16:31 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 12537 output: 42 thoughts: 31 Thoughts: Okay, let's dive into this. Here's how I'd approach that kernel code, thinking out loud: **Diving into nf_flow_rule_bridge** Alright, time to crack open `nf_flow_rule_bridge` in `net/netfilter/nf_flow_table_offload.c`. I need to understand this module's role in the offload path. Since it's bridge-related, I'm expecting to see how flow table entries are handled when a packet traverses a bridge. Specifically, I want to get a good handle on how the code interacts with the underlying hardware offload capabilities. I'll be looking for key functions that manage rule creation, matching, and eviction within the context of a bridged environment. I'll be paying close attention to any interaction with the bridge netdevice structure, and what happens when the packets get forwarded through the flow table. I'm looking for where and how the bridge-specific information (like VLAN IDs or MAC addresses) is incorporated into the flow key and rule matching process. I need to be ready to trace how the packets are getting punted to the appropriate interface. I'm going to watch the data path closely. Are there any specific hooks or callbacks to the bridge driver itself? If so, I need to understand what those callbacks are doing and where they're invoked. Any interactions with the hardware offload API are critical here, and I'll need to confirm what the relationship between the hardware and the software is, and how it is enforced. Finally, let's find the places where the code interacts with the hardware, maybe the device drivers' functions and data structures. |
| 20/2 | 2026/07/07 16:31 | tool | grepper |
0mArgs:{
"Expression": "nf_flow_rule_bridge",
"PathPrefix": "net/netfilter/nf_flow_table_offload.c"
}Results: {
"Output": "net/netfilter/nf_flow_table_offload.c=683=nf_flow_rule_route_common(struct net *net, const struct flow_offload *flow,\n--\nnet/netfilter/nf_flow_table_offload.c-742-\nnet/netfilter/nf_flow_table_offload.c:743:int nf_flow_rule_bridge(struct net *net, struct flow_offload *flow,\nnet/netfilter/nf_flow_table_offload.c-744-\t\t\tenum flow_offload_tuple_dir dir,\n--\nnet/netfilter/nf_flow_table_offload.c-753-}\nnet/netfilter/nf_flow_table_offload.c:754:EXPORT_SYMBOL_GPL(nf_flow_rule_bridge);\nnet/netfilter/nf_flow_table_offload.c-755-\n"
} |
| 21/2 | 2026/07/07 16:31 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 13195 output: 35 thoughts: 280 Thoughts: **Fuzzing Target Identification** Okay, so I'm honing in on specific functions for fuzzing this networking code. My initial target list is: `dev_fill_bridge_path`, `flow_offload_bridge_init`, `nf_flow_rule_bridge`, and `nft_dev_fill_bridge_path`. I'm also including `br_fill_forward_path` and `br_vlan_fill_forward_path_pvid` because I know these were recently modified, increasing the likelihood of interesting behavior. I'm quickly cross-referencing these functions to their respective files to ensure my understanding is accurate. `nft_dev_fill_bridge_path` is definitely in `net/netfilter/nf_flow_table_path.c`, just as I thought. I can confirm `br_fill_forward_path` resides in `net/bridge/br_device.c` and `br_vlan_fill_forward_path_pvid` in `net/bridge/br_vlan.c`. All checks are good. Now, for the configurations, I want to make sure I have these in place when testing: `NF_FLOW_TABLE`, `NF_FLOW_TABLE_INET`, `NFT_FLOW_OFFLOAD`, `BRIDGE`, and `BRIDGE_VLAN_FILTERING`. I should also double-check the dependencies of `NF_FLOW_TABLE_INET` to be absolutely certain I haven't missed anything critical. |
| 22/2 | 2026/07/07 16:31 | tool | grepper |
0mArgs:{
"Expression": "config NF_FLOW_TABLE_INET",
"PathPrefix": "net/netfilter/Kconfig"
}Results: {
"Output": "net/netfilter/Kconfig=701=endif # NF_TABLES\nnet/netfilter/Kconfig-702-\nnet/netfilter/Kconfig:703:config NF_FLOW_TABLE_INET\nnet/netfilter/Kconfig-704-\ttristate \"Netfilter flow table mixed IPv4/IPv6 module\"\n"
} |
| 23/2 | 2026/07/07 16:31 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 13926 output: 34 thoughts: 14 Thoughts: Okay, let's dive into this. Here's my thought process on this task: **Dependencies Check for `NFT_FLOW_OFFLOAD`** Right, so `NFT_FLOW_OFFLOAD`. That's a key feature, and before I start doing anything else, I need to make sure all the underlying pieces are in place. No sense wasting time debugging a build later if I can proactively identify any missing links. This means a thorough check of all dependencies is absolutely critical. I need to know exactly what other modules, libraries, or system components `NFT_FLOW_OFFLOAD` relies on to function correctly. This isn't just about compiling; it's about runtime behavior and ensuring everything plays nicely together. I'll need to go through the code, documentation, and maybe even some system configurations to get a complete picture. Let's get to it. |
| 24/2 | 2026/07/07 16:31 | tool | grepper |
0mArgs:{
"Expression": "config NFT_FLOW_OFFLOAD",
"PathPrefix": "net/netfilter/Kconfig"
}Results: {
"Output": "net/netfilter/Kconfig=498=config NFT_EXTHDR_DCCP\n--\nnet/netfilter/Kconfig-503-\nnet/netfilter/Kconfig:504:config NFT_FLOW_OFFLOAD\nnet/netfilter/Kconfig-505-\tdepends on NF_CONNTRACK \u0026\u0026 NF_FLOW_TABLE\n"
} |
| 25/2 | 2026/07/07 16:31 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 14251 output: 33 thoughts: 13 Thoughts: Here's my take on those thoughts, tailored for an expert audience: **NF_FLOW_TABLE Dependency Deep Dive** Okay, so I need to get a handle on the `NF_FLOW_TABLE`. Before I go any further down this rabbit hole, I need to map out its dependencies. It's too easy to make a change here and break something upstream or downstream without a full understanding. Let's see… what other kernel subsystems rely on this? Are we talking about core networking components, perhaps netfilter modules? Are there any obvious user-space interfaces that are linked to this table? I need to look for related data structures, function calls, and any potential locking mechanisms. The goal is to fully understand the impact of any changes I might make. I'm thinking I'll start with a `grep` through the kernel source to find references and then move to cross-referencing this with netfilter internals. Gotta be methodical about this. |
| 26/2 | 2026/07/07 16:31 | tool | grepper |
0mArgs:{
"Expression": "config NF_FLOW_TABLE",
"PathPrefix": "net/netfilter/Kconfig"
}Results: {
"Output": "net/netfilter/Kconfig=701=endif # NF_TABLES\nnet/netfilter/Kconfig-702-\nnet/netfilter/Kconfig:703:config NF_FLOW_TABLE_INET\nnet/netfilter/Kconfig-704-\ttristate \"Netfilter flow table mixed IPv4/IPv6 module\"\n--\nnet/netfilter/Kconfig-710-\nnet/netfilter/Kconfig:711:config NF_FLOW_TABLE\nnet/netfilter/Kconfig-712-\ttristate \"Netfilter flow table module\"\n--\nnet/netfilter/Kconfig-720-\nnet/netfilter/Kconfig:721:config NF_FLOW_TABLE_PROCFS\nnet/netfilter/Kconfig-722-\tbool \"Supply flow table statistics in procfs\"\n"
} |
| 27/2 | 2026/07/07 16:31 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 14712 output: 34 thoughts: 55 Thoughts: Okay, here's my take on those initial thoughts, framed as a concise summary for an expert like myself: **Initial Netfilter Configuration Exploration** Right, so I'm initially zeroing in on the netfilter configuration. I'm noting the presence of `NF_FLOW_TABLE`, `NF_FLOW_TABLE_INET`, and `NFT_FLOW_OFFLOAD` within the `net/netfilter/Kconfig` file. That's a good starting point for understanding flow table and offload capabilities within the kernel. My immediate next step will be to quickly vet the dependencies of `BRIDGE_VLAN_FILTERING`. Gotta make sure everything lines up logically there. |
| 28/2 | 2026/07/07 16:31 | tool | grepper |
0mArgs:{
"Expression": "config BRIDGE_VLAN_FILTERING",
"PathPrefix": "net/bridge/Kconfig"
}Results: {
"Output": "net/bridge/Kconfig=36=config BRIDGE_IGMP_SNOOPING\n--\nnet/bridge/Kconfig-49-\nnet/bridge/Kconfig:50:config BRIDGE_VLAN_FILTERING\nnet/bridge/Kconfig-51-\tbool \"VLAN filtering\"\n"
} |
| 29/2 | 2026/07/07 16:31 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 15027 output: 28 thoughts: 9 Thoughts: Okay, let's dive into this. Here's my thought process summarized, assuming I'm already deep in the weeds and thinking along these lines: **Checking `BRIDGE` Dependencies** Alright, time to get a grip on the current state of things. First order of business: I need to quickly assess the landscape of dependencies related to the `BRIDGE` system. This is crucial for understanding potential impacts, identifying any lurking conflicts, or pinpointing areas where we might be vulnerable to upstream changes. I want to make sure the core foundations are solid. I need to know where we stand, specifically with the `BRIDGE` system before I move on. What does the dependency tree look like? Are we relying on any libraries that are known pain points, or that are about to reach end-of-life? A quick dependency audit is my starting point here. Let's dig in and see what we have. |
| 30/2 | 2026/07/07 16:31 | tool | grepper |
0mArgs:{
"Expression": "config BRIDGE",
"PathPrefix": "net/bridge/Kconfig"
}Results: {
"Output": "net/bridge/Kconfig-5-\nnet/bridge/Kconfig:6:config BRIDGE\nnet/bridge/Kconfig-7-\ttristate \"802.1d Ethernet Bridging\"\n--\nnet/bridge/Kconfig-35-\nnet/bridge/Kconfig:36:config BRIDGE_IGMP_SNOOPING\nnet/bridge/Kconfig-37-\tbool \"IGMP/MLD snooping\"\n--\nnet/bridge/Kconfig-49-\nnet/bridge/Kconfig:50:config BRIDGE_VLAN_FILTERING\nnet/bridge/Kconfig-51-\tbool \"VLAN filtering\"\n--\nnet/bridge/Kconfig-63-\nnet/bridge/Kconfig:64:config BRIDGE_MRP\nnet/bridge/Kconfig-65-\tbool \"MRP protocol\"\n--\nnet/bridge/Kconfig-75-\nnet/bridge/Kconfig:76:config BRIDGE_CFM\nnet/bridge/Kconfig-77-\tbool \"CFM protocol\"\n"
} |
| 31/2 | 2026/07/07 16:31 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 15509 output: 203 thoughts: 526 Thoughts: **Analysis of Bridge Support for Netfilter Flow Offload** Okay, so I'm looking at this patch and it's dealing with bridge support for netfilter flow offload, which is interesting. I see that `BRIDGE` and `BRIDGE_VLAN_FILTERING` are defined within `net/bridge/Kconfig`, that's a good starting point. I need to understand the new functionalities and integration with the existing structure. My primary focus is on these functions: `dev_fill_bridge_path`, `flow_offload_bridge_init`, `nf_flow_rule_bridge`, `br_fill_forward_path`, and `br_vlan_fill_forward_path_pvid`. Let's verify that `nft_dev_fill_bridge_path` is indeed a static function; ah, yes, it is. It's probably best to include it within the context. Now, let's trace the reachability of these functions. `dev_fill_bridge_path` is exported and called by `nft_dev_fill_bridge_path`. Then, `nft_dev_fill_bridge_path` is called by `flow_offload_bridge_init`. Finally, `flow_offload_bridge_init` is invoked by `nft_flow_offload_eval` specifically when the routing functionality is disabled, or rather, when `flowtable->type->family == NFPROTO_BRIDGE`. `nft_flow_offload_eval` is the evaluation function for the `nft_flow_offload` expression, which is used within nftables. So, the code is reachable, and it's functional. That means it is a good target for fuzzing. It's a key part of the bridge-netfilter interaction and can be tested. Let's prepare the output. The fuzzing target is definitely worthwhile. Here are the key functions I'm targeting: * `dev_fill_bridge_path` * `flow_offload_bridge_init` * `nft_dev_fill_bridge_path` * `nf_flow_rule_bridge` * `br_fill_forward_path` * `br_vlan_fill_forward_path_pvid` And here are the necessary configurations to enable: * `NF_FLOW_TABLE` * `NF_FLOW_TABLE_INET` * `NFT_FLOW_OFFLOAD` * `BRIDGE` * `BRIDGE_VLAN_FILTERING` My reasoning is that the patch introduces fundamental changes to how bridge traffic interacts with netfilter's flow offload capabilities. This is achieved by implementing new functions to handle bridge paths within the flow offload framework, coupled with modifications to existing bridge forwarding path functions. Given this level of core networking and netfilter subsystem modifications, combined with its direct accessibility via nftables and relevant bridge configurations, this makes it an excellent target for thorough fuzzing. |
| 32/2 | 2026/07/07 16:31 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"NF_FLOW_TABLE",
"NF_FLOW_TABLE_INET",
"NFT_FLOW_OFFLOAD",
"BRIDGE",
"BRIDGE_VLAN_FILTERING"
],
"FocusSymbols": [
"dev_fill_bridge_path",
"flow_offload_bridge_init",
"nft_dev_fill_bridge_path",
"nf_flow_rule_bridge",
"br_fill_forward_path",
"br_vlan_fill_forward_path_pvid"
],
"Reasoning": "The patch introduces bridge support for netfilter flow offload. It adds new functions to handle bridge paths in flow offload and modifies existing bridge forward path functions. This is a functional change in the core networking and netfilter subsystems that is reachable via nftables and bridge configuration, making it a good target for fuzzing.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"NF_FLOW_TABLE",
"NF_FLOW_TABLE_INET",
"NFT_FLOW_OFFLOAD",
"BRIDGE",
"BRIDGE_VLAN_FILTERING"
],
"FocusSymbols": [
"dev_fill_bridge_path",
"flow_offload_bridge_init",
"nft_dev_fill_bridge_path",
"nf_flow_rule_bridge",
"br_fill_forward_path",
"br_vlan_fill_forward_path_pvid"
],
"Reasoning": "The patch introduces bridge support for netfilter flow offload. It adds new functions to handle bridge paths in flow offload and modifies existing bridge forward path functions. This is a functional change in the core networking and netfilter subsystems that is reachable via nftables and bridge configuration, making it a good target for fuzzing.",
"WorthFuzzing": true
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|