AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/08/31 12:17 flow patch-triage
3m Args:
null

Results:
{
  "EnableConfigs": [
    "BRIDGE",
    "BRIDGE_CFM",
    "BRIDGE_MRP"
  ],
  "FocusSymbols": [
    "br_cfm_frame_rx",
    "br_mrp_process",
    "br_cfm_mep_create",
    "br_cfm_mep_delete",
    "br_mrp_add",
    "br_mrp_del"
  ],
  "KMSANReasoning": "The patch refactors the bridge subsystem's CFM (Connectivity Fault Management) and MRP (Media Redundancy Protocol) frame dispatch mechanism by replacing the dynamic frame-type linked list (`frame_type_list`) with bit flags in the existing bridge options bitmask (`BROPT_CFM_ENABLED` and `BROPT_MRP_ENABLED`). \n\nNo new structures, allocations, or data buffers are created or exported to user space. The logic relies on already-allocated and initialized bridge structures (`struct net_bridge`), toggling and checking existing bit flags. No uninitialized memory is read, branched on, or leaked to userspace. Standard KASAN/sanitizer configurations are sufficient to catch any regression. Dedicated KMSAN fuzzing is not required.",
  "NeedsKMSAN": false,
  "Reasoning": "The patch refactors the bridge frame handling logic for CFM (802.1Q CFM) and MRP protocols by replacing the dynamic frame_type_list with bridge option flags (BROPT_CFM_ENABLED and BROPT_MRP_ENABLED) and direct calls to br_cfm_frame_rx and br_mrp_process. It modifies both the frame receive path and the netlink-triggered instance creation/deletion paths. This affects core bridge networking logic and is reachable in standard virtual environments without specialized hardware.",
  "WorthFuzzing": true
}

1/1 2026/08/31 12:17 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit f282a61829a6be7f51ca9ea76d0c68731ce2d37b\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Mon Aug 31 12:17:23 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/net/bridge/br_cfm.c b/net/bridge/br_cfm.c\nindex dea56fffa1c19..9dcc97d63a6fc 100644\n--- a/net/bridge/br_cfm.c\n+++ b/net/bridge/br_cfm.c\n@@ -367,7 +367,7 @@ static u32 ccm_tlv_extract(struct sk_buff *skb, u32 index,\n }\n \n /* note: already called with rcu_read_lock */\n-static int br_cfm_frame_rx(struct net_bridge_port *port, struct sk_buff *skb)\n+int br_cfm_frame_rx(struct net_bridge_port *port, struct sk_buff *skb)\n {\n \tu32 mdlevel, interval, size, index, max;\n \tconst struct br_cfm_common_hdr *hdr;\n@@ -489,11 +489,6 @@ static int br_cfm_frame_rx(struct net_bridge_port *port, struct sk_buff *skb)\n \treturn 1;\n }\n \n-static struct br_frame_type cfm_frame_type __read_mostly = {\n-\t.type = cpu_to_be16(ETH_P_CFM),\n-\t.frame_handler = br_cfm_frame_rx,\n-};\n-\n int br_cfm_mep_create(struct net_bridge *br,\n \t\t      const u32 instance,\n \t\t      struct br_cfm_mep_create *const create,\n@@ -559,7 +554,7 @@ int br_cfm_mep_create(struct net_bridge *br,\n \tINIT_DELAYED_WORK(\u0026mep-\u003eccm_tx_dwork, ccm_tx_work_expired);\n \n \tif (hlist_empty(\u0026br-\u003emep_list))\n-\t\tbr_add_frame(br, \u0026cfm_frame_type);\n+\t\tbr_opt_toggle(br, BROPT_CFM_ENABLED, true);\n \n \thlist_add_tail_rcu(\u0026mep-\u003ehead, \u0026br-\u003emep_list);\n \n@@ -588,7 +583,7 @@ static void mep_delete_implementation(struct net_bridge *br,\n \tkfree_rcu(mep, rcu);\n \n \tif (hlist_empty(\u0026br-\u003emep_list))\n-\t\tbr_del_frame(br, \u0026cfm_frame_type);\n+\t\tbr_opt_toggle(br, BROPT_CFM_ENABLED, false);\n }\n \n int br_cfm_mep_delete(struct net_bridge *br,\ndiff --git a/net/bridge/br_device.c b/net/bridge/br_device.c\nindex ff55dab736326..e01c44a90d84b 100644\n--- a/net/bridge/br_device.c\n+++ b/net/bridge/br_device.c\n@@ -503,7 +503,6 @@ void br_dev_setup(struct net_device *dev)\n \tspin_lock_init(\u0026br-\u003elock);\n \tINIT_LIST_HEAD(\u0026br-\u003eport_list);\n \tINIT_HLIST_HEAD(\u0026br-\u003efdb_list);\n-\tINIT_HLIST_HEAD(\u0026br-\u003eframe_type_list);\n #if IS_ENABLED(CONFIG_BRIDGE_MRP)\n \tINIT_HLIST_HEAD(\u0026br-\u003emrp_list);\n #endif\ndiff --git a/net/bridge/br_input.c b/net/bridge/br_input.c\nindex d87a5f9fa92b7..72892e5b40439 100644\n--- a/net/bridge/br_input.c\n+++ b/net/bridge/br_input.c\n@@ -317,20 +317,33 @@ static int nf_hook_bridge_pre(struct sk_buff *skb, struct sk_buff **pskb)\n \treturn RX_HANDLER_CONSUMED;\n }\n \n+#if IS_ENABLED(CONFIG_BRIDGE_CFM) || IS_ENABLED(CONFIG_BRIDGE_MRP)\n+/* CFM/MRP are uncommon; test both enable bits together first. */\n+#define BR_CFM_MRP_OPTS \\\n+\t((IS_ENABLED(CONFIG_BRIDGE_CFM) ? BIT(BROPT_CFM_ENABLED) : 0UL) | \\\n+\t (IS_ENABLED(CONFIG_BRIDGE_MRP) ? BIT(BROPT_MRP_ENABLED) : 0UL))\n+\n /* Return 0 if the frame was not processed otherwise 1\n  * note: already called with rcu_read_lock\n  */\n static int br_process_frame_type(struct net_bridge_port *p,\n \t\t\t\t struct sk_buff *skb)\n {\n-\tstruct br_frame_type *tmp;\n-\n-\thlist_for_each_entry_rcu(tmp, \u0026p-\u003ebr-\u003eframe_type_list, list)\n-\t\tif (unlikely(tmp-\u003etype == skb-\u003eprotocol))\n-\t\t\treturn tmp-\u003eframe_handler(p, skb);\n+\tstruct net_bridge *br = p-\u003ebr;\n \n+#if IS_ENABLED(CONFIG_BRIDGE_CFM)\n+\tif (skb-\u003eprotocol == htons(ETH_P_CFM) \u0026\u0026\n+\t    br_opt_get(br, BROPT_CFM_ENABLED))\n+\t\treturn br_cfm_frame_rx(p, skb);\n+#endif\n+#if IS_ENABLED(CONFIG_BRIDGE_MRP)\n+\tif (skb-\u003eprotocol == htons(ETH_P_MRP) \u0026\u0026\n+\t    br_opt_get(br, BROPT_MRP_ENABLED))\n+\t\treturn br_mrp_process(p, skb);\n+#endif\n \treturn 0;\n }\n+#endif\n \n /*\n  * Return NULL if skb is handled\n@@ -425,8 +438,11 @@ static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)\n \t\t}\n \t}\n \n-\tif (unlikely(br_process_frame_type(p, skb)))\n+#if IS_ENABLED(CONFIG_BRIDGE_CFM) || IS_ENABLED(CONFIG_BRIDGE_MRP)\n+\tif (unlikely((p-\u003ebr-\u003eoptions \u0026 BR_CFM_MRP_OPTS) \u0026\u0026\n+\t\t     br_process_frame_type(p, skb)))\n \t\treturn RX_HANDLER_PASS;\n+#endif\n \n forward:\n \tif (br_mst_is_enabled(p))\n@@ -467,19 +483,3 @@ rx_handler_func_t *br_get_rx_handler(const struct net_device *dev)\n \n \treturn br_handle_frame;\n }\n-\n-void br_add_frame(struct net_bridge *br, struct br_frame_type *ft)\n-{\n-\thlist_add_head_rcu(\u0026ft-\u003elist, \u0026br-\u003eframe_type_list);\n-}\n-\n-void br_del_frame(struct net_bridge *br, struct br_frame_type *ft)\n-{\n-\tstruct br_frame_type *tmp;\n-\n-\thlist_for_each_entry(tmp, \u0026br-\u003eframe_type_list, list)\n-\t\tif (ft == tmp) {\n-\t\t\thlist_del_rcu(\u0026ft-\u003elist);\n-\t\t\treturn;\n-\t\t}\n-}\ndiff --git a/net/bridge/br_mrp.c b/net/bridge/br_mrp.c\nindex ef16d07039241..dce6efa96c4c6 100644\n--- a/net/bridge/br_mrp.c\n+++ b/net/bridge/br_mrp.c\n@@ -6,13 +6,6 @@\n static const u8 mrp_test_dmac[ETH_ALEN] = { 0x1, 0x15, 0x4e, 0x0, 0x0, 0x1 };\n static const u8 mrp_in_test_dmac[ETH_ALEN] = { 0x1, 0x15, 0x4e, 0x0, 0x0, 0x3 };\n \n-static int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb);\n-\n-static struct br_frame_type mrp_frame_type __read_mostly = {\n-\t.type = cpu_to_be16(ETH_P_MRP),\n-\t.frame_handler = br_mrp_process,\n-};\n-\n static bool br_mrp_is_ring_port(struct net_bridge_port *p_port,\n \t\t\t\tstruct net_bridge_port *s_port,\n \t\t\t\tstruct net_bridge_port *port)\n@@ -486,7 +479,7 @@ static void br_mrp_del_impl(struct net_bridge *br, struct br_mrp *mrp)\n \tkfree_rcu(mrp, rcu);\n \n \tif (hlist_empty(\u0026br-\u003emrp_list))\n-\t\tbr_del_frame(br, \u0026mrp_frame_type);\n+\t\tbr_opt_toggle(br, BROPT_MRP_ENABLED, false);\n }\n \n /* Adds a new MRP instance.\n@@ -536,7 +529,7 @@ int br_mrp_add(struct net_bridge *br, struct br_mrp_instance *instance)\n \trcu_assign_pointer(mrp-\u003es_port, p);\n \n \tif (hlist_empty(\u0026br-\u003emrp_list))\n-\t\tbr_add_frame(br, \u0026mrp_frame_type);\n+\t\tbr_opt_toggle(br, BROPT_MRP_ENABLED, true);\n \n \tINIT_DELAYED_WORK(\u0026mrp-\u003etest_work, br_mrp_test_work_expired);\n \tINIT_DELAYED_WORK(\u0026mrp-\u003ein_test_work, br_mrp_in_test_work_expired);\n@@ -1241,7 +1234,7 @@ static int br_mrp_rcv(struct net_bridge_port *p,\n  * normal forwarding.\n  * note: already called with rcu_read_lock\n  */\n-static int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb)\n+int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb)\n {\n \t/* If there is no MRP instance do normal forwarding */\n \tif (likely(!test_bit(BR_MRP_AWARE_BIT, \u0026p-\u003eflags)))\ndiff --git a/net/bridge/br_private.h b/net/bridge/br_private.h\nindex d337b1cfb980d..afe7c0b4f8fa7 100644\n--- a/net/bridge/br_private.h\n+++ b/net/bridge/br_private.h\n@@ -495,12 +495,13 @@ enum net_bridge_opts {\n \tBROPT_MST_ENABLED,\n \tBROPT_MDB_OFFLOAD_FAIL_NOTIFICATION,\n \tBROPT_FDB_LOCAL_VLAN_0,\n+\tBROPT_CFM_ENABLED,\n+\tBROPT_MRP_ENABLED,\n };\n \n struct net_bridge {\n \tspinlock_t\t\t\tlock;\n \tspinlock_t\t\t\thash_lock;\n-\tstruct hlist_head\t\tframe_type_list;\n \tstruct net_device\t\t*dev;\n \tunsigned long\t\t\toptions;\n \t/* These fields are accessed on each packet */\n@@ -932,16 +933,6 @@ int nbp_backup_change(struct net_bridge_port *p, struct net_device *backup_dev);\n int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb);\n rx_handler_func_t *br_get_rx_handler(const struct net_device *dev);\n \n-struct br_frame_type {\n-\t__be16\t\t\ttype;\n-\tint\t\t\t(*frame_handler)(struct net_bridge_port *port,\n-\t\t\t\t\t\t struct sk_buff *skb);\n-\tstruct hlist_node\tlist;\n-};\n-\n-void br_add_frame(struct net_bridge *br, struct br_frame_type *ft);\n-void br_del_frame(struct net_bridge *br, struct br_frame_type *ft);\n-\n static inline bool br_rx_handler_check_rcu(const struct net_device *dev)\n {\n \treturn rcu_dereference(dev-\u003erx_handler) == br_get_rx_handler(dev);\n@@ -2080,6 +2071,7 @@ int br_mrp_parse(struct net_bridge *br, struct net_bridge_port *p,\n bool br_mrp_enabled(struct net_bridge *br);\n void br_mrp_port_del(struct net_bridge *br, struct net_bridge_port *p);\n int br_mrp_fill_info(struct sk_buff *skb, struct net_bridge *br);\n+int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb);\n #else\n static inline int br_mrp_parse(struct net_bridge *br, struct net_bridge_port *p,\n \t\t\t       struct nlattr *attr, int cmd,\n@@ -2111,6 +2103,7 @@ int br_cfm_parse(struct net_bridge *br, struct net_bridge_port *p,\n \t\t struct nlattr *attr, int cmd, struct netlink_ext_ack *extack);\n bool br_cfm_created(struct net_bridge *br);\n void br_cfm_port_del(struct net_bridge *br, struct net_bridge_port *p);\n+int br_cfm_frame_rx(struct net_bridge_port *port, struct sk_buff *skb);\n int br_cfm_config_fill_info(struct sk_buff *skb, struct net_bridge *br);\n int br_cfm_status_fill_info(struct sk_buff *skb,\n \t\t\t    struct net_bridge *br,\n"
}

2/1 2026/08/31 12:17 agent patch-evaluator
2m Model:
core

Args:
null

Results:
{
  "EnableConfigs": [
    "BRIDGE",
    "BRIDGE_CFM",
    "BRIDGE_MRP"
  ],
  "FocusSymbols": [
    "br_cfm_frame_rx",
    "br_mrp_process",
    "br_cfm_mep_create",
    "br_cfm_mep_delete",
    "br_mrp_add",
    "br_mrp_del"
  ],
  "Reasoning": "The patch refactors the bridge frame handling logic for CFM (802.1Q CFM) and MRP protocols by replacing the dynamic frame_type_list with bridge option flags (BROPT_CFM_ENABLED and BROPT_MRP_ENABLED) and direct calls to br_cfm_frame_rx and br_mrp_process. It modifies both the frame receive path and the netlink-triggered instance creation/deletion paths. This affects core bridge networking logic and is reachable in standard virtual environments without specialized hardware.",
  "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).
- Code in vendor-specific PCIe switch, SmartNIC, or GPU drivers (e.g., mlxsw, pds_core, qed,
  ionic, amdgpu) that require physical PCIe hardware cards not emulated in standard QEMU.
- Driver .remove, .shutdown, or pci_unregister_driver teardown callbacks (e.g., igb_remove)
  that are executed only during PCI hot-unplug or sysfs driver unbind operations.

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.
   Prefer non-static, non-inlined API entrypoint functions over internal static helper functions
   (which are inlined by the compiler and do not have distinct symbol addresses).
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.
   Also check "depends on" lines in Kconfig to include any non-standard parent subsystem configs
   needed for Kbuild to compile the code statically into vmlinux. 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 f282a61829a6be7f51ca9ea76d0c68731ce2d37b
Author: syz-cluster <triage@syzkaller.com>
Date:   Mon Aug 31 12:17:23 2026 +0000

    syz-cluster: applied patch under review

diff --git a/net/bridge/br_cfm.c b/net/bridge/br_cfm.c
index dea56fffa1c19..9dcc97d63a6fc 100644
--- a/net/bridge/br_cfm.c
+++ b/net/bridge/br_cfm.c
@@ -367,7 +367,7 @@ static u32 ccm_tlv_extract(struct sk_buff *skb, u32 index,
 }
 
 /* note: already called with rcu_read_lock */
-static int br_cfm_frame_rx(struct net_bridge_port *port, struct sk_buff *skb)
+int br_cfm_frame_rx(struct net_bridge_port *port, struct sk_buff *skb)
 {
 	u32 mdlevel, interval, size, index, max;
 	const struct br_cfm_common_hdr *hdr;
@@ -489,11 +489,6 @@ static int br_cfm_frame_rx(struct net_bridge_port *port, struct sk_buff *skb)
 	return 1;
 }
 
-static struct br_frame_type cfm_frame_type __read_mostly = {
-	.type = cpu_to_be16(ETH_P_CFM),
-	.frame_handler = br_cfm_frame_rx,
-};
-
 int br_cfm_mep_create(struct net_bridge *br,
 		      const u32 instance,
 		      struct br_cfm_mep_create *const create,
@@ -559,7 +554,7 @@ int br_cfm_mep_create(struct net_bridge *br,
 	INIT_DELAYED_WORK(&mep->ccm_tx_dwork, ccm_tx_work_expired);
 
 	if (hlist_empty(&br->mep_list))
-		br_add_frame(br, &cfm_frame_type);
+		br_opt_toggle(br, BROPT_CFM_ENABLED, true);
 
 	hlist_add_tail_rcu(&mep->head, &br->mep_list);
 
@@ -588,7 +583,7 @@ static void mep_delete_implementation(struct net_bridge *br,
 	kfree_rcu(mep, rcu);
 
 	if (hlist_empty(&br->mep_list))
-		br_del_frame(br, &cfm_frame_type);
+		br_opt_toggle(br, BROPT_CFM_ENABLED, false);
 }
 
 int br_cfm_mep_delete(struct net_bridge *br,
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index ff55dab736326..e01c44a90d84b 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -503,7 +503,6 @@ void br_dev_setup(struct net_device *dev)
 	spin_lock_init(&br->lock);
 	INIT_LIST_HEAD(&br->port_list);
 	INIT_HLIST_HEAD(&br->fdb_list);
-	INIT_HLIST_HEAD(&br->frame_type_list);
 #if IS_ENABLED(CONFIG_BRIDGE_MRP)
 	INIT_HLIST_HEAD(&br->mrp_list);
 #endif
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index d87a5f9fa92b7..72892e5b40439 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -317,20 +317,33 @@ static int nf_hook_bridge_pre(struct sk_buff *skb, struct sk_buff **pskb)
 	return RX_HANDLER_CONSUMED;
 }
 
+#if IS_ENABLED(CONFIG_BRIDGE_CFM) || IS_ENABLED(CONFIG_BRIDGE_MRP)
+/* CFM/MRP are uncommon; test both enable bits together first. */
+#define BR_CFM_MRP_OPTS \
+	((IS_ENABLED(CONFIG_BRIDGE_CFM) ? BIT(BROPT_CFM_ENABLED) : 0UL) | \
+	 (IS_ENABLED(CONFIG_BRIDGE_MRP) ? BIT(BROPT_MRP_ENABLED) : 0UL))
+
 /* Return 0 if the frame was not processed otherwise 1
  * note: already called with rcu_read_lock
  */
 static int br_process_frame_type(struct net_bridge_port *p,
 				 struct sk_buff *skb)
 {
-	struct br_frame_type *tmp;
-
-	hlist_for_each_entry_rcu(tmp, &p->br->frame_type_list, list)
-		if (unlikely(tmp->type == skb->protocol))
-			return tmp->frame_handler(p, skb);
+	struct net_bridge *br = p->br;
 
+#if IS_ENABLED(CONFIG_BRIDGE_CFM)
+	if (skb->protocol == htons(ETH_P_CFM) &&
+	    br_opt_get(br, BROPT_CFM_ENABLED))
+		return br_cfm_frame_rx(p, skb);
+#endif
+#if IS_ENABLED(CONFIG_BRIDGE_MRP)
+	if (skb->protocol == htons(ETH_P_MRP) &&
+	    br_opt_get(br, BROPT_MRP_ENABLED))
+		return br_mrp_process(p, skb);
+#endif
 	return 0;
 }
+#endif
 
 /*
  * Return NULL if skb is handled
@@ -425,8 +438,11 @@ static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
 		}
 	}
 
-	if (unlikely(br_process_frame_type(p, skb)))
+#if IS_ENABLED(CONFIG_BRIDGE_CFM) || IS_ENABLED(CONFIG_BRIDGE_MRP)
+	if (unlikely((p->br->options & BR_CFM_MRP_OPTS) &&
+		     br_process_frame_type(p, skb)))
 		return RX_HANDLER_PASS;
+#endif
 
 forward:
 	if (br_mst_is_enabled(p))
@@ -467,19 +483,3 @@ rx_handler_func_t *br_get_rx_handler(const struct net_device *dev)
 
 	return br_handle_frame;
 }
-
-void br_add_frame(struct net_bridge *br, struct br_frame_type *ft)
-{
-	hlist_add_head_rcu(&ft->list, &br->frame_type_list);
-}
-
-void br_del_frame(struct net_bridge *br, struct br_frame_type *ft)
-{
-	struct br_frame_type *tmp;
-
-	hlist_for_each_entry(tmp, &br->frame_type_list, list)
-		if (ft == tmp) {
-			hlist_del_rcu(&ft->list);
-			return;
-		}
-}
diff --git a/net/bridge/br_mrp.c b/net/bridge/br_mrp.c
index ef16d07039241..dce6efa96c4c6 100644
--- a/net/bridge/br_mrp.c
+++ b/net/bridge/br_mrp.c
@@ -6,13 +6,6 @@
 static const u8 mrp_test_dmac[ETH_ALEN] = { 0x1, 0x15, 0x4e, 0x0, 0x0, 0x1 };
 static const u8 mrp_in_test_dmac[ETH_ALEN] = { 0x1, 0x15, 0x4e, 0x0, 0x0, 0x3 };
 
-static int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb);
-
-static struct br_frame_type mrp_frame_type __read_mostly = {
-	.type = cpu_to_be16(ETH_P_MRP),
-	.frame_handler = br_mrp_process,
-};
-
 static bool br_mrp_is_ring_port(struct net_bridge_port *p_port,
 				struct net_bridge_port *s_port,
 				struct net_bridge_port *port)
@@ -486,7 +479,7 @@ static void br_mrp_del_impl(struct net_bridge *br, struct br_mrp *mrp)
 	kfree_rcu(mrp, rcu);
 
 	if (hlist_empty(&br->mrp_list))
-		br_del_frame(br, &mrp_frame_type);
+		br_opt_toggle(br, BROPT_MRP_ENABLED, false);
 }
 
 /* Adds a new MRP instance.
@@ -536,7 +529,7 @@ int br_mrp_add(struct net_bridge *br, struct br_mrp_instance *instance)
 	rcu_assign_pointer(mrp->s_port, p);
 
 	if (hlist_empty(&br->mrp_list))
-		br_add_frame(br, &mrp_frame_type);
+		br_opt_toggle(br, BROPT_MRP_ENABLED, true);
 
 	INIT_DELAYED_WORK(&mrp->test_work, br_mrp_test_work_expired);
 	INIT_DELAYED_WORK(&mrp->in_test_work, br_mrp_in_test_work_expired);
@@ -1241,7 +1234,7 @@ static int br_mrp_rcv(struct net_bridge_port *p,
  * normal forwarding.
  * note: already called with rcu_read_lock
  */
-static int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb)
+int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb)
 {
 	/* If there is no MRP instance do normal forwarding */
 	if (likely(!test_bit(BR_MRP_AWARE_BIT, &p->flags)))
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index d337b1cfb980d..afe7c0b4f8fa7 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -495,12 +495,13 @@ enum net_bridge_opts {
 	BROPT_MST_ENABLED,
 	BROPT_MDB_OFFLOAD_FAIL_NOTIFICATION,
 	BROPT_FDB_LOCAL_VLAN_0,
+	BROPT_CFM_ENABLED,
+	BROPT_MRP_ENABLED,
 };
 
 struct net_bridge {
 	spinlock_t			lock;
 	spinlock_t			hash_lock;
-	struct hlist_head		frame_type_list;
 	struct net_device		*dev;
 	unsigned long			options;
 	/* These fields are accessed on each packet */
@@ -932,16 +933,6 @@ int nbp_backup_change(struct net_bridge_port *p, struct net_device *backup_dev);
 int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb);
 rx_handler_func_t *br_get_rx_handler(const struct net_device *dev);
 
-struct br_frame_type {
-	__be16			type;
-	int			(*frame_handler)(struct net_bridge_port *port,
-						 struct sk_buff *skb);
-	struct hlist_node	list;
-};
-
-void br_add_frame(struct net_bridge *br, struct br_frame_type *ft);
-void br_del_frame(struct net_bridge *br, struct br_frame_type *ft);
-
 static inline bool br_rx_handler_check_rcu(const struct net_device *dev)
 {
 	return rcu_dereference(dev->rx_handler) == br_get_rx_handler(dev);
@@ -2080,6 +2071,7 @@ int br_mrp_parse(struct net_bridge *br, struct net_bridge_port *p,
 bool br_mrp_enabled(struct net_bridge *br);
 void br_mrp_port_del(struct net_bridge *br, struct net_bridge_port *p);
 int br_mrp_fill_info(struct sk_buff *skb, struct net_bridge *br);
+int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb);
 #else
 static inline int br_mrp_parse(struct net_bridge *br, struct net_bridge_port *p,
 			       struct nlattr *attr, int cmd,
@@ -2111,6 +2103,7 @@ int br_cfm_parse(struct net_bridge *br, struct net_bridge_port *p,
 		 struct nlattr *attr, int cmd, struct netlink_ext_ack *extack);
 bool br_cfm_created(struct net_bridge *br);
 void br_cfm_port_del(struct net_bridge *br, struct net_bridge_port *p);
+int br_cfm_frame_rx(struct net_bridge_port *port, struct sk_buff *skb);
 int br_cfm_config_fill_info(struct sk_buff *skb, struct net_bridge *br);
 int br_cfm_status_fill_info(struct sk_buff *skb,
 			    struct net_bridge *br,

3/2 2026/08/31 12:17 llm patch-evaluator
0m Model:
gemini-3.7-flash

Args:
null

Results:
null

Tokens:
							input: 5416
							output: 28
							thoughts: 291
						

Thoughts:
**Analyzing the Bridge Patch for Fuzzing Potential**

Okay, let's dive into this patch and figure out the best approach for fuzzing. My immediate thought is to determine if this change to the bridge code in the kernel is even worth the effort. We need to assess the attack surface and potential for interesting bugs. I can see the patch touches a few files within `net/bridge`: `br_cfm.c`, `br_device.c`, `br_input.c`, `br_mrp.c`, and `br_private.h`.

Now, let's understand the core of the change. It looks like they're optimizing the frame handling. Instead of iterating through a linked list of `struct br_frame_type` objects when processing frames in the fast rx path (`br_handle_frame()` -> `br_process_frame_type()`), they're ditching the dynamic list lookup. They've replaced it with direct checks of bridge option flags (`BROPT_CFM_ENABLED` and `BROPT_MRP_ENABLED`) within `br_process_frame_type()`. Furthermore, it seems they've removed `br_add_frame` and `br_del_frame`, the `frame_type_list` from the `struct net_bridge`, and now call `br_cfm_frame_rx` and `br_mrp_process` directly if the respective flags are enabled. This looks interesting from a security perspective, we now have control flow based on bridge flags.

This flag-based approach is potentially more efficient but could introduce subtle vulnerabilities if not handled carefully. I need to keep in mind the potential for flag races and off-by-one errors in their implementation.

Next up, I should verify the Kconfig dependencies in `net/bridge/Kconfig`. We must understand the build environment to ensure that this patch is even enabled in the configurations we're targeting for fuzzing.



4/2 2026/08/31 12:17 tool grepper
0m Args:
{
  "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"
}

5/2 2026/08/31 12:17 llm patch-evaluator
0m Model:
gemini-3.7-flash

Args:
null

Results:
null

Tokens:
							input: 6402
							output: 32
							thoughts: 20
						

Thoughts:
Here's my take on the `net/bridge/Kconfig` thought process, delivered as a first-person summary, keeping in mind my expert perspective:

**Delving into the Bridge Configuration**

Okay, time to dive into the core configuration settings for the Linux bridging code. I need to refresh my memory on what options are available and how they're structured, specifically focusing on the first 90 lines of `net/bridge/Kconfig`. This should cover the basic features, dependencies, and perhaps some default behavior declarations. I anticipate this will set the stage for understanding the more nuanced aspects further down the file. I'll be looking for the fundamental building blocks - the core enable/disable switches for the bridge itself, maybe some essential hardware acceleration features (if present), and any dependencies on other kernel subsystems. I also want to identify any default settings that might significantly influence how a bridge operates out-of-the-box. This will help me understand the default behavior of the module.



6/2 2026/08/31 12:17 tool read-file
0m Args:
{
  "File": "net/bridge/Kconfig",
  "FirstLine": 1,
  "LineCount": 90
}

Results:
{
  "Contents": "   1:\t# SPDX-License-Identifier: GPL-2.0-only\n   2:\t#\n   3:\t# 802.1d Ethernet Bridging\n   4:\t#\n   5:\t\n   6:\tconfig BRIDGE\n   7:\t\ttristate \"802.1d Ethernet Bridging\"\n   8:\t\tselect LLC\n   9:\t\tselect STP\n  10:\t\thelp\n  11:\t\t  If you say Y here, then your Linux box will be able to act as an\n  12:\t\t  Ethernet bridge, which means that the different Ethernet segments it\n  13:\t\t  is connected to will appear as one Ethernet to the participants.\n  14:\t\t  Several such bridges can work together to create even larger\n  15:\t\t  networks of Ethernets using the IEEE 802.1 spanning tree algorithm.\n  16:\t\t  As this is a standard, Linux bridges will cooperate properly with\n  17:\t\t  other third party bridge products.\n  18:\t\n  19:\t\t  In order to use the Ethernet bridge, you'll need the bridge\n  20:\t\t  configuration tools; see \u003cfile:Documentation/networking/bridge.rst\u003e\n  21:\t\t  for location. Please read the Bridge mini-HOWTO for more\n  22:\t\t  information.\n  23:\t\n  24:\t\t  If you enable iptables support along with the bridge support then you\n  25:\t\t  turn your bridge into a bridging IP firewall.\n  26:\t\t  iptables will then see the IP packets being bridged, so you need to\n  27:\t\t  take this into account when setting up your firewall rules.\n  28:\t\t  Enabling arptables support when bridging will let arptables see\n  29:\t\t  bridged ARP traffic in the arptables FORWARD chain.\n  30:\t\n  31:\t\t  To compile this code as a module, choose M here: the module\n  32:\t\t  will be called bridge.\n  33:\t\n  34:\t\t  If unsure, say N.\n  35:\t\n  36:\tconfig BRIDGE_IGMP_SNOOPING\n  37:\t\tbool \"IGMP/MLD snooping\"\n  38:\t\tdepends on BRIDGE\n  39:\t\tdepends on INET\n  40:\t\tdefault y\n  41:\t\thelp\n  42:\t\t  If you say Y here, then the Ethernet bridge will be able selectively\n  43:\t\t  forward multicast traffic based on IGMP/MLD traffic received from\n  44:\t\t  each port.\n  45:\t\n  46:\t\t  Say N to exclude this support and reduce the binary size.\n  47:\t\n  48:\t\t  If unsure, say Y.\n  49:\t\n  50:\tconfig BRIDGE_VLAN_FILTERING\n  51:\t\tbool \"VLAN filtering\"\n  52:\t\tdepends on BRIDGE\n  53:\t\tdepends on VLAN_8021Q\n  54:\t\tdefault n\n  55:\t\thelp\n  56:\t\t  If you say Y here, then the Ethernet bridge will be able selectively\n  57:\t\t  receive and forward traffic based on VLAN information in the packet\n  58:\t\t  any VLAN information configured on the bridge port or bridge device.\n  59:\t\n  60:\t\t  Say N to exclude this support and reduce the binary size.\n  61:\t\n  62:\t\t  If unsure, say Y.\n  63:\t\n  64:\tconfig BRIDGE_MRP\n  65:\t\tbool \"MRP protocol\"\n  66:\t\tdepends on BRIDGE\n  67:\t\tdefault n\n  68:\t\thelp\n  69:\t\t  If you say Y here, then the Ethernet bridge will be able to run MRP\n  70:\t\t  protocol to detect loops\n  71:\t\n  72:\t\t  Say N to exclude this support and reduce the binary size.\n  73:\t\n  74:\t\t  If unsure, say N.\n  75:\t\n  76:\tconfig BRIDGE_CFM\n  77:\t\tbool \"CFM protocol\"\n  78:\t\tdepends on BRIDGE\n  79:\t\thelp\n  80:\t\t  If you say Y here, then the Ethernet bridge will be able to run CFM\n  81:\t\t  protocol according to 802.1Q section 12.14\n  82:\t\n  83:\t\t  Say N to exclude this support and reduce the binary size.\n  84:\t\n  85:\t\t  If unsure, say N.\n"
}

7/2 2026/08/31 12:17 llm patch-evaluator
0m Model:
gemini-3.7-flash

Args:
null

Results:
null

Tokens:
							input: 7772
							output: 31
							thoughts: 578
						

Thoughts:
**Initial Assessment of Bridge Code Vulnerability**

Okay, let's dive into this. My initial thought is to investigate the bridge code, specifically the integration of BRIDGE\_MRP and BRIDGE\_CFM, to see if we can trigger something interesting. I want to check how these features are compiled in, which boils down to looking at `CONFIG_BRIDGE`, `CONFIG_BRIDGE_MRP`, and `CONFIG_BRIDGE_CFM`. Is it going to be worth the effort to fuzz this? Absolutely, this is core network bridge frame processing and configuration logic, including CFM (Connectivity Fault Management) and MRP (Media Redundancy Protocol).

I see that `br_handle_frame`, the bridge RX handler, directly calls `br_process_frame_type`, which now incorporates `BROPT_CFM_ENABLED` and `BROPT_MRP_ENABLED` option bits. This is a good starting point. I also note modifications to `br_cfm_mep_create`, `br_cfm_mep_delete`, `br_mrp_add`, and `br_mrp_del_impl`.

The key here is that these protocols and their frame handling are accessible through bridge netlink configuration (rtnetlink / bridge netlink) and network packet transmission/reception (tun/tap, veth, raw sockets, etc.) in a standard Linux environment like QEMU. No special hardware required – that makes this even more attractive as a target.

Now, let's identify the specific functions to focus on. I'm noting the functions that were either changed or exported from static scope: specifically `br_cfm_frame_rx`, `br_mrp_process` (both were static before), `br_cfm_mep_create`, `br_cfm_mep_delete`, and `br_mrp_add`. Although `br_handle_frame` is on that list, I'm more interested in the non-hot-path kernel functions: `br_cfm_frame_rx`, `br_mrp_process`, `br_cfm_mep_create`, `br_cfm_mep_delete`, and `br_mrp_add`.

Okay, double-checking… I see that `br_cfm_frame_rx` is now an `int br_cfm_frame_rx(struct net_bridge_port *port, struct sk_buff *skb)` in `net/bridge/br_cfm.c`, and `br_mrp_process` is `int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb)` in `net/bridge/br_mrp.c`. Good. Next, I need to trace where `br_cfm_mep_create`, `br_cfm_mep_delete`, and `br_mrp_add` are actually called from, so I can understand the call paths.



8/2 2026/08/31 12:18 tool grepper
0m Args:
{
  "Expression": "br_cfm_mep_create",
  "PathPrefix": "net/bridge"
}

Results:
{
  "Output": "net/bridge/br_cfm.c=370=int br_cfm_frame_rx(struct net_bridge_port *port, struct sk_buff *skb)\n--\nnet/bridge/br_cfm.c-491-\nnet/bridge/br_cfm.c:492:int br_cfm_mep_create(struct net_bridge *br,\nnet/bridge/br_cfm.c-493-\t\t      const u32 instance,\nnet/bridge/br_cfm.c:494:\t\t      struct br_cfm_mep_create *const create,\nnet/bridge/br_cfm.c-495-\t\t      struct netlink_ext_ack *extack)\n--\nnet/bridge/br_cfm_netlink.c=8=static const struct nla_policy\nnet/bridge/br_cfm_netlink.c:9:br_cfm_mep_create_policy[IFLA_BRIDGE_CFM_MEP_CREATE_MAX + 1] = {\nnet/bridge/br_cfm_netlink.c-10-\t[IFLA_BRIDGE_CFM_MEP_CREATE_UNSPEC]\t= { .type = NLA_REJECT },\n--\nnet/bridge/br_cfm_netlink.c=72=br_cfm_policy[IFLA_BRIDGE_CFM_MAX + 1] = {\n--\nnet/bridge/br_cfm_netlink.c-74-\t[IFLA_BRIDGE_CFM_MEP_CREATE]\t\t=\nnet/bridge/br_cfm_netlink.c:75:\t\t\t\tNLA_POLICY_NESTED(br_cfm_mep_create_policy),\nnet/bridge/br_cfm_netlink.c-76-\t[IFLA_BRIDGE_CFM_MEP_DELETE]\t\t=\n--\nnet/bridge/br_cfm_netlink.c=92=static int br_mep_create_parse(struct net_bridge *br, struct nlattr *attr,\n--\nnet/bridge/br_cfm_netlink.c-95-\tstruct nlattr *tb[IFLA_BRIDGE_CFM_MEP_CREATE_MAX + 1];\nnet/bridge/br_cfm_netlink.c:96:\tstruct br_cfm_mep_create create;\nnet/bridge/br_cfm_netlink.c-97-\tu32 instance;\n--\nnet/bridge/br_cfm_netlink.c-100-\terr = nla_parse_nested(tb, IFLA_BRIDGE_CFM_MEP_CREATE_MAX, attr,\nnet/bridge/br_cfm_netlink.c:101:\t\t\t       br_cfm_mep_create_policy, extack);\nnet/bridge/br_cfm_netlink.c-102-\tif (err)\n--\nnet/bridge/br_cfm_netlink.c-128-\nnet/bridge/br_cfm_netlink.c:129:\treturn br_cfm_mep_create(br, instance, \u0026create, extack);\nnet/bridge/br_cfm_netlink.c-130-}\n--\nnet/bridge/br_private_cfm.h-8-\nnet/bridge/br_private_cfm.h:9:struct br_cfm_mep_create {\nnet/bridge/br_private_cfm.h-10-\tenum br_cfm_domain domain; /* Domain for this MEP */\n--\nnet/bridge/br_private_cfm.h-14-\nnet/bridge/br_private_cfm.h:15:int br_cfm_mep_create(struct net_bridge *br,\nnet/bridge/br_private_cfm.h-16-\t\t      const u32 instance,\nnet/bridge/br_private_cfm.h:17:\t\t      struct br_cfm_mep_create *const create,\nnet/bridge/br_private_cfm.h-18-\t\t      struct netlink_ext_ack *extack);\n--\nnet/bridge/br_private_cfm.h=117=struct br_cfm_mep {\n--\nnet/bridge/br_private_cfm.h-120-\tu32\t\t\t\tinstance;\nnet/bridge/br_private_cfm.h:121:\tstruct br_cfm_mep_create\tcreate;\nnet/bridge/br_private_cfm.h-122-\tstruct br_cfm_mep_config\tconfig;\n"
}

9/2 2026/08/31 12:18 llm patch-evaluator
0m Model:
gemini-3.7-flash

Args:
null

Results:
null

Tokens:
							input: 10098
							output: 29
							thoughts: 15
						

Thoughts:
Here's my attempt at summarizing the thought process, tailored for an expert audience:

**Investigating Potential Weak Points**

Okay, so we're looking for vulnerabilities, and based on the recent findings, I need to expand my search. The usual suspects have already been scrutinized, so I'm thinking... let's not overlook `br_mrp_add`. It's a key function in [mention the relevant system/area this function is in], and given the nature of the previous issues, it's definitely within the scope of where we should be looking. My initial focus was [mention a previous area of focus, if any], but I have to be thorough. Let's see if this one also needs to be explored.



10/2 2026/08/31 12:18 tool grepper
0m Args:
{
  "Expression": "br_mrp_add",
  "PathPrefix": "net/bridge"
}

Results:
{
  "Output": "net/bridge/br_mrp.c=419=static void br_mrp_del_impl(struct net_bridge *br, struct br_mrp *mrp)\n--\nnet/bridge/br_mrp.c-487- */\nnet/bridge/br_mrp.c:488:int br_mrp_add(struct net_bridge *br, struct br_mrp_instance *instance)\nnet/bridge/br_mrp.c-489-{\n--\nnet/bridge/br_mrp_netlink.c=31=static int br_mrp_instance_parse(struct net_bridge *br, struct nlattr *attr,\n--\nnet/bridge/br_mrp_netlink.c-61-\tif (cmd == RTM_SETLINK)\nnet/bridge/br_mrp_netlink.c:62:\t\treturn br_mrp_add(br, \u0026inst);\nnet/bridge/br_mrp_netlink.c-63-\telse\n--\nnet/bridge/br_private_mrp.h=59=enum br_mrp_hw_support {\n--\nnet/bridge/br_private_mrp.h-65-/* br_mrp.c */\nnet/bridge/br_private_mrp.h:66:int br_mrp_add(struct net_bridge *br, struct br_mrp_instance *instance);\nnet/bridge/br_private_mrp.h-67-int br_mrp_del(struct net_bridge *br, struct br_mrp_instance *instance);\n"
}

11/2 2026/08/31 12:18 llm patch-evaluator
0m Model:
gemini-3.7-flash

Args:
null

Results:
null

Tokens:
							input: 10695
							output: 31
							thoughts: 23
						

Thoughts:
Here's my summary, as though I'm thinking through this process:

**Reviewing Deletion Processes**

Okay, time to get down to brass tacks. I need to take a quick look at the deletion processes, particularly as they relate to `br_cfm_mep_delete` and `br_mrp_del`. I want to make sure the removal of these objects is functioning properly, especially in conjunction with the other modules. I need to ensure there are no orphaned records, cascade deletions are working as expected, and that all related tables are being handled gracefully. Let me begin by checking the most recent logs, then I can run a few targeted queries to confirm the integrity of the database after a deletion is triggered. I need to make sure there are no unexpected side effects; this is a critical check.



12/2 2026/08/31 12:18 tool grepper
0m Args:
{
  "Expression": "br_cfm_mep_delete",
  "PathPrefix": "net/bridge"
}

Results:
{
  "Output": "net/bridge/br_cfm.c=564=static void mep_delete_implementation(struct net_bridge *br,\n--\nnet/bridge/br_cfm.c-588-\nnet/bridge/br_cfm.c:589:int br_cfm_mep_delete(struct net_bridge *br,\nnet/bridge/br_cfm.c-590-\t\t      const u32 instance,\n--\nnet/bridge/br_cfm_netlink.c=17=static const struct nla_policy\nnet/bridge/br_cfm_netlink.c:18:br_cfm_mep_delete_policy[IFLA_BRIDGE_CFM_MEP_DELETE_MAX + 1] = {\nnet/bridge/br_cfm_netlink.c-19-\t[IFLA_BRIDGE_CFM_MEP_DELETE_UNSPEC]\t= { .type = NLA_REJECT },\n--\nnet/bridge/br_cfm_netlink.c=72=br_cfm_policy[IFLA_BRIDGE_CFM_MAX + 1] = {\n--\nnet/bridge/br_cfm_netlink.c-76-\t[IFLA_BRIDGE_CFM_MEP_DELETE]\t\t=\nnet/bridge/br_cfm_netlink.c:77:\t\t\t\tNLA_POLICY_NESTED(br_cfm_mep_delete_policy),\nnet/bridge/br_cfm_netlink.c-78-\t[IFLA_BRIDGE_CFM_MEP_CONFIG]\t\t=\n--\nnet/bridge/br_cfm_netlink.c=132=static int br_mep_delete_parse(struct net_bridge *br, struct nlattr *attr,\n--\nnet/bridge/br_cfm_netlink.c-139-\terr = nla_parse_nested(tb, IFLA_BRIDGE_CFM_MEP_DELETE_MAX, attr,\nnet/bridge/br_cfm_netlink.c:140:\t\t\t       br_cfm_mep_delete_policy, extack);\nnet/bridge/br_cfm_netlink.c-141-\tif (err)\n--\nnet/bridge/br_cfm_netlink.c-151-\nnet/bridge/br_cfm_netlink.c:152:\treturn br_cfm_mep_delete(br, instance, extack);\nnet/bridge/br_cfm_netlink.c-153-}\n--\nnet/bridge/br_private_cfm.h=15=int br_cfm_mep_create(struct net_bridge *br,\n--\nnet/bridge/br_private_cfm.h-19-\nnet/bridge/br_private_cfm.h:20:int br_cfm_mep_delete(struct net_bridge *br,\nnet/bridge/br_private_cfm.h-21-\t\t      const u32 instance,\n"
}

13/2 2026/08/31 12:18 llm patch-evaluator
0m Model:
gemini-3.7-flash

Args:
null

Results:
null

Tokens:
							input: 11638
							output: 30
							thoughts: 12
						

Thoughts:
Okay, here's my summarized thought process, keeping in mind my expertise:

**Checking `br_mrp_del`**

Alright, time to dive in. My initial thought process, as an expert, immediately centers on the context. "Let's check `br_mrp_del`" - this implies a very specific area of concern. I'm already mentally running through the systems and data structures that `br_mrp_del` is likely associated with. Is it a table name? A stored procedure? A variable within a larger script or module? Knowing this will dramatically affect my approach.

I'm probably dealing with either a data issue, a code execution problem, or perhaps a performance bottleneck. The term "MRP" (Material Requirements Planning) is a strong indicator that I'm likely dealing with supply chain, manufacturing, or distribution processes. "Del" suggests deletion, removal, or perhaps delivery. Combining those, my mind is immediately working through the potential scenarios, something like:

*   **Data Integrity:** Is this related to deleting planned orders, deleting records of deliveries, or something similar? Are there constraints or triggers involved that might cause errors?
*   **Process Automation:** Is this a script that's supposed to handle these deletions automatically? If so, what's its history of success and failure? What are the potential consequences of a malfunction?
*   **Performance Impact:** Are we talking about large datasets? Could a poorly optimized delete operation be slowing down other crucial processes? Are there locks that might be an issue?

Before I start digging into any code or data, I need to know *what* I'm looking for specifically and what the goal is. This is all just an initial mental framework to structure the investigation. Let me determine the next steps I should take to gain greater context on the problem.



14/2 2026/08/31 12:18 tool grepper
0m Args:
{
  "Expression": "br_mrp_del\\(",
  "PathPrefix": "net/bridge"
}

Results:
{
  "Output": "net/bridge/br_mrp.c=553=void br_mrp_port_del(struct net_bridge *br, struct net_bridge_port *p)\n--\nnet/bridge/br_mrp.c-566- */\nnet/bridge/br_mrp.c:567:int br_mrp_del(struct net_bridge *br, struct br_mrp_instance *instance)\nnet/bridge/br_mrp.c-568-{\n--\nnet/bridge/br_mrp_netlink.c=31=static int br_mrp_instance_parse(struct net_bridge *br, struct nlattr *attr,\n--\nnet/bridge/br_mrp_netlink.c-63-\telse\nnet/bridge/br_mrp_netlink.c:64:\t\treturn br_mrp_del(br, \u0026inst);\nnet/bridge/br_mrp_netlink.c-65-\n--\nnet/bridge/br_private_mrp.h=66=int br_mrp_add(struct net_bridge *br, struct br_mrp_instance *instance);\nnet/bridge/br_private_mrp.h:67:int br_mrp_del(struct net_bridge *br, struct br_mrp_instance *instance);\nnet/bridge/br_private_mrp.h-68-int br_mrp_set_port_state(struct net_bridge_port *p,\n"
}

15/2 2026/08/31 12:18 llm patch-evaluator
0m Model:
gemini-3.7-flash

Args:
null

Results:
null

Tokens:
							input: 12434
							output: 31
							thoughts: 25
						

Thoughts:
Here's a summary of my thought process:

**Diving into the Bridge Makefile**

Okay, let's get down to brass tacks. I need to understand the build process and configuration dependencies for the networking bridge implementation. The best place to start, as always with these kinds of investigations, is the `Makefile` in the `net/bridge/` directory. That's the heart of how things are built in this module, it holds the secrets. I'll need to see precisely which source files are compiled, what compiler flags are used, and most critically, what configuration options influence the build process. I'm expecting to see dependencies on various kernel configuration symbols related to bridging functionality; things like VLAN support, STP, and the various bridge protocols. Understanding this Makefile will give me a solid foundation for further investigations.



16/2 2026/08/31 12:18 tool read-file
0m Args:
{
  "File": "net/bridge/Makefile",
  "FirstLine": 1,
  "LineCount": 40
}

Results:
{
  "Contents": "   1:\t# SPDX-License-Identifier: GPL-2.0\n   2:\t#\n   3:\t# Makefile for the IEEE 802.1d ethernet bridging layer.\n   4:\t#\n   5:\t\n   6:\tobj-$(CONFIG_BRIDGE) += bridge.o\n   7:\t\n   8:\tbridge-y\t:= br.o br_device.o br_fdb.o br_forward.o br_if.o br_input.o \\\n   9:\t\t\t\tbr_ioctl.o br_stp.o br_stp_bpdu.o \\\n  10:\t\t\t\tbr_stp_if.o br_stp_timer.o br_netlink.o \\\n  11:\t\t\t\tbr_netlink_tunnel.o br_arp_nd_proxy.o\n  12:\t\n  13:\tbridge-$(CONFIG_SYSFS) += br_sysfs_if.o br_sysfs_br.o\n  14:\t\n  15:\tbridge-$(subst m,y,$(CONFIG_BRIDGE_NETFILTER)) += br_nf_core.o\n  16:\t\n  17:\tbr_netfilter-y := br_netfilter_hooks.o\n  18:\tbr_netfilter-$(subst m,y,$(CONFIG_IPV6)) += br_netfilter_ipv6.o\n  19:\tobj-$(CONFIG_BRIDGE_NETFILTER) += br_netfilter.o\n  20:\t\n  21:\tbridge-$(CONFIG_BRIDGE_IGMP_SNOOPING) += br_multicast.o br_mdb.o br_multicast_eht.o\n  22:\t\n  23:\tbridge-$(CONFIG_BRIDGE_VLAN_FILTERING) += br_vlan.o br_vlan_tunnel.o br_vlan_options.o br_mst.o\n  24:\t\n  25:\tbridge-$(CONFIG_NET_SWITCHDEV) += br_switchdev.o\n  26:\t\n  27:\tobj-$(CONFIG_NETFILTER) += netfilter/\n  28:\t\n  29:\tbridge-$(CONFIG_BRIDGE_MRP)\t+= br_mrp_switchdev.o br_mrp.o br_mrp_netlink.o\n  30:\t\n  31:\tbridge-$(CONFIG_BRIDGE_CFM)\t+= br_cfm.o br_cfm_netlink.o\n  32:\t\n  33:\tifdef CONFIG_GCOV_PROFILE_NETFILTER\n  34:\tGCOV_PROFILE_br_nf_core.o := y\n  35:\tGCOV_PROFILE_br_netfilter_hooks.o := y\n  36:\tGCOV_PROFILE_br_netfilter_ipv6.o := y\n  37:\tendif\n"
}

17/2 2026/08/31 12:18 llm patch-evaluator
0m Model:
gemini-3.7-flash

Args:
null

Results:
null

Tokens:
							input: 13356
							output: 212
							thoughts: 877
						

Thoughts:
**Analyzing the Ethernet Bridge CFM and MRP Implementation**

Okay, let's dive into this. First, I need to verify the relevant configurations: `BRIDGE`, `BRIDGE_CFM`, and `BRIDGE_MRP`.  I'll quickly check Kconfig for dependencies; it looks like `BRIDGE_CFM` and `BRIDGE_MRP` both depend on `BRIDGE`, which makes sense because we need the basic bridging functionality first. `BRIDGE` itself is a tristate config enabling 802.1d Ethernet Bridging, and selects LLC and STP.

Now, let's see what the diff actually touches. I see files like `br_cfm.c`, `br_device.c`, `br_input.c`, `br_mrp.c`, and `br_private.h`.  This confirms that we're dealing with Connectivity Fault Management (CFM) and Media Redundancy Protocol (MRP) handling within the bridge. Specifically, it seems like the changes are about bridge device setup, packet input, and the creation/deletion of CFM MEPs and MRP instances.

Next, I'll identify the key symbols modified: `br_cfm_frame_rx`, `br_mrp_process`, `br_cfm_mep_create`, `br_cfm_mep_delete`, `br_mrp_add`, and `br_mrp_del`. I need to ensure they are the correct symbols, and that their visibility is correct. `br_cfm_frame_rx` and `br_mrp_process` are now non-static, which is interesting. It indicates they might be getting used outside of their original scope. The remaining are non-static as well.

I'll quickly scan for other modified functions. In `br_device.c`, there's `br_dev_setup` (initialization), which seems reasonable. In `br_input.c`, `br_process_frame_type` is static but `br_handle_frame` is present, along with the deletions of `br_add_frame` and `br_del_frame`. In `br_cfm.c`, `mep_delete_implementation` is static and called by `br_cfm_mep_delete` and `br_cfm_port_del`. In `br_mrp.c`, there's `br_mrp_del_impl`, static too, and called by `br_mrp_del` and `br_mrp_port_del`.

So, to summarize, the relevant symbols are: `br_cfm_frame_rx`, `br_mrp_process`, `br_cfm_mep_create`, `br_cfm_mep_delete`, `br_mrp_add`, and `br_mrp_del`.  The configurations we're tracking are: `BRIDGE`, `BRIDGE_CFM`, and `BRIDGE_MRP`.

Based on this, it seems the patch is optimizing Ethernet Bridge frame type handling for CFM and MRP.  Instead of dynamic management of `frame_type_list`, it's replacing it with direct flag checks (`BROPT_CFM_ENABLED` and `BROPT_MRP_ENABLED`) in the receive path (`br_handle_frame` / `br_process_frame_type`).  This is likely to improve performance. The code also exports `br_cfm_frame_rx` and `br_mrp_process`, and updates the instance creation/deletion paths. This change is certainly testable in standard virtualized environments and should be fuzzed as a matter of course.

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



18/2 2026/08/31 12:19 tool set-results
0m Args:
{
  "EnableConfigs": [
    "BRIDGE",
    "BRIDGE_CFM",
    "BRIDGE_MRP"
  ],
  "FocusSymbols": [
    "br_cfm_frame_rx",
    "br_mrp_process",
    "br_cfm_mep_create",
    "br_cfm_mep_delete",
    "br_mrp_add",
    "br_mrp_del"
  ],
  "Reasoning": "The patch refactors the bridge frame handling logic for CFM (802.1Q CFM) and MRP protocols by replacing the dynamic frame_type_list with bridge option flags (BROPT_CFM_ENABLED and BROPT_MRP_ENABLED) and direct calls to br_cfm_frame_rx and br_mrp_process. It modifies both the frame receive path and the netlink-triggered instance creation/deletion paths. This affects core bridge networking logic and is reachable in standard virtual environments without specialized hardware.",
  "WorthFuzzing": true
}

Results:
{
  "EnableConfigs": [
    "BRIDGE",
    "BRIDGE_CFM",
    "BRIDGE_MRP"
  ],
  "FocusSymbols": [
    "br_cfm_frame_rx",
    "br_mrp_process",
    "br_cfm_mep_create",
    "br_cfm_mep_delete",
    "br_mrp_add",
    "br_mrp_del"
  ],
  "Reasoning": "The patch refactors the bridge frame handling logic for CFM (802.1Q CFM) and MRP protocols by replacing the dynamic frame_type_list with bridge option flags (BROPT_CFM_ENABLED and BROPT_MRP_ENABLED) and direct calls to br_cfm_frame_rx and br_mrp_process. It modifies both the frame receive path and the netlink-triggered instance creation/deletion paths. This affects core bridge networking logic and is reachable in standard virtual environments without specialized hardware.",
  "WorthFuzzing": true
}

19/1 2026/08/31 12:19 action If
0m Args:
{
  "WorthFuzzing": true
}

Results:
null

20/2 2026/08/31 12:19 agent kmsan-evaluator
0m Model:
core

Args:
null

Results:
{
  "KMSANReasoning": "The patch refactors the bridge subsystem's CFM (Connectivity Fault Management) and MRP (Media Redundancy Protocol) frame dispatch mechanism by replacing the dynamic frame-type linked list (`frame_type_list`) with bit flags in the existing bridge options bitmask (`BROPT_CFM_ENABLED` and `BROPT_MRP_ENABLED`). \n\nNo new structures, allocations, or data buffers are created or exported to user space. The logic relies on already-allocated and initialized bridge structures (`struct net_bridge`), toggling and checking existing bit flags. No uninitialized memory is read, branched on, or leaked to userspace. Standard KASAN/sanitizer configurations are sufficient to catch any regression. Dedicated KMSAN fuzzing is not required.",
  "NeedsKMSAN": false
}

Instruction:
You are an expert Linux kernel security engineer specializing in kernel memory
error detectors (KASAN and KMSAN). Your job is to review the provided patch series and
determine if the code changes justify spawning a dedicated KMSAN (KernelMemorySanitizer)
fuzzing session in addition to standard KASAN fuzzing.

CRITICAL DISTINCTION BETWEEN KASAN AND KMSAN:
- Standard KASAN kernel builds (upstream-apparmor-kasan.config) already enable
  a comprehensive suite of debugging tools and sanitizers, including KASAN
  (out-of-bounds accesses, use-after-free, double free, invalid free), LOCKDEP
  (locking bugs and deadlocks), UB-sanitizers, and memory corruption checks.
- KMSAN (KernelMemorySanitizer) detects reads of UNINITIALIZED memory (stack, heap,
  or page allocations) and kernel-to-user memory info-leaks.

Rule: THERE IS NO SENSE IN RUNNING A KMSAN SESSION IF A BUG CAN BE CAUGHT BY KASAN,
LOCKDEP, OR OTHER STANDARD BUG DETECTORS.
A dedicated KMSAN fuzzing session incurs significant resource costs. You must ONLY
set NeedsKMSAN=true if the code changes introduce or expose UNINITIALIZED MEMORY risks
that are detected ONLY by KMSAN.

Look holistically at the patch series and surrounding code. Even if no direct
uninitialized field accesses or new buffer allocations are added in the diff itself,
a patch may alter control flow, bounds checking, or data length calculations in ways
that change how the rest of the code operates on existing buffers (e.g. allowing
uninitialized stack/heap memory to be read, copied to user space, or used in control
flow). Do not hesitate to use your code access tools to inspect the surrounding code,
called functions, and callers.

Set NeedsKMSAN=true ONLY IF the patch introduces or modifies:
1. Kernel structures sent to user space (via copy_to_user, put_user, netlink skb
   attributes, ioctl output arguments, socket options, or BPF buffers) where fields
   or structure padding might not be fully initialized/zeroed.
2. Conditional logic or branching that depends on potentially uninitialized variables
   or struct fields.
3. Allocation or initialization of complex data structures where uninitialized fields
   could be read later in reachable code paths.
4. Bounds checks, lengths, or logic in a way that allows surrounding code to access
   uninitialized bytes of existing buffers.

Set NeedsKMSAN=false IF:
- The code changes primarily risk out-of-bounds access, array overflows, NULL pointer
  dereferences, locking deadlocks, or use-after-free bugs (these are already caught
  by KASAN, LOCKDEP, or standard bug detectors).
- All stack/heap structures touched or introduced by the patch are fully zeroed
  or initialized (e.g. using = {0}, memset, kzalloc) before being read or copied.
- The patch does not introduce any risk of uninitialized memory usage or info-leaks.

Use your code access tools to inspect the surrounding code if necessary, then provide
detailed KMSANReasoning contrasting KASAN vs KMSAN applicability for this patch.
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 f282a61829a6be7f51ca9ea76d0c68731ce2d37b
Author: syz-cluster <triage@syzkaller.com>
Date:   Mon Aug 31 12:17:23 2026 +0000

    syz-cluster: applied patch under review

diff --git a/net/bridge/br_cfm.c b/net/bridge/br_cfm.c
index dea56fffa1c19..9dcc97d63a6fc 100644
--- a/net/bridge/br_cfm.c
+++ b/net/bridge/br_cfm.c
@@ -367,7 +367,7 @@ static u32 ccm_tlv_extract(struct sk_buff *skb, u32 index,
 }
 
 /* note: already called with rcu_read_lock */
-static int br_cfm_frame_rx(struct net_bridge_port *port, struct sk_buff *skb)
+int br_cfm_frame_rx(struct net_bridge_port *port, struct sk_buff *skb)
 {
 	u32 mdlevel, interval, size, index, max;
 	const struct br_cfm_common_hdr *hdr;
@@ -489,11 +489,6 @@ static int br_cfm_frame_rx(struct net_bridge_port *port, struct sk_buff *skb)
 	return 1;
 }
 
-static struct br_frame_type cfm_frame_type __read_mostly = {
-	.type = cpu_to_be16(ETH_P_CFM),
-	.frame_handler = br_cfm_frame_rx,
-};
-
 int br_cfm_mep_create(struct net_bridge *br,
 		      const u32 instance,
 		      struct br_cfm_mep_create *const create,
@@ -559,7 +554,7 @@ int br_cfm_mep_create(struct net_bridge *br,
 	INIT_DELAYED_WORK(&mep->ccm_tx_dwork, ccm_tx_work_expired);
 
 	if (hlist_empty(&br->mep_list))
-		br_add_frame(br, &cfm_frame_type);
+		br_opt_toggle(br, BROPT_CFM_ENABLED, true);
 
 	hlist_add_tail_rcu(&mep->head, &br->mep_list);
 
@@ -588,7 +583,7 @@ static void mep_delete_implementation(struct net_bridge *br,
 	kfree_rcu(mep, rcu);
 
 	if (hlist_empty(&br->mep_list))
-		br_del_frame(br, &cfm_frame_type);
+		br_opt_toggle(br, BROPT_CFM_ENABLED, false);
 }
 
 int br_cfm_mep_delete(struct net_bridge *br,
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index ff55dab736326..e01c44a90d84b 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -503,7 +503,6 @@ void br_dev_setup(struct net_device *dev)
 	spin_lock_init(&br->lock);
 	INIT_LIST_HEAD(&br->port_list);
 	INIT_HLIST_HEAD(&br->fdb_list);
-	INIT_HLIST_HEAD(&br->frame_type_list);
 #if IS_ENABLED(CONFIG_BRIDGE_MRP)
 	INIT_HLIST_HEAD(&br->mrp_list);
 #endif
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index d87a5f9fa92b7..72892e5b40439 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -317,20 +317,33 @@ static int nf_hook_bridge_pre(struct sk_buff *skb, struct sk_buff **pskb)
 	return RX_HANDLER_CONSUMED;
 }
 
+#if IS_ENABLED(CONFIG_BRIDGE_CFM) || IS_ENABLED(CONFIG_BRIDGE_MRP)
+/* CFM/MRP are uncommon; test both enable bits together first. */
+#define BR_CFM_MRP_OPTS \
+	((IS_ENABLED(CONFIG_BRIDGE_CFM) ? BIT(BROPT_CFM_ENABLED) : 0UL) | \
+	 (IS_ENABLED(CONFIG_BRIDGE_MRP) ? BIT(BROPT_MRP_ENABLED) : 0UL))
+
 /* Return 0 if the frame was not processed otherwise 1
  * note: already called with rcu_read_lock
  */
 static int br_process_frame_type(struct net_bridge_port *p,
 				 struct sk_buff *skb)
 {
-	struct br_frame_type *tmp;
-
-	hlist_for_each_entry_rcu(tmp, &p->br->frame_type_list, list)
-		if (unlikely(tmp->type == skb->protocol))
-			return tmp->frame_handler(p, skb);
+	struct net_bridge *br = p->br;
 
+#if IS_ENABLED(CONFIG_BRIDGE_CFM)
+	if (skb->protocol == htons(ETH_P_CFM) &&
+	    br_opt_get(br, BROPT_CFM_ENABLED))
+		return br_cfm_frame_rx(p, skb);
+#endif
+#if IS_ENABLED(CONFIG_BRIDGE_MRP)
+	if (skb->protocol == htons(ETH_P_MRP) &&
+	    br_opt_get(br, BROPT_MRP_ENABLED))
+		return br_mrp_process(p, skb);
+#endif
 	return 0;
 }
+#endif
 
 /*
  * Return NULL if skb is handled
@@ -425,8 +438,11 @@ static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
 		}
 	}
 
-	if (unlikely(br_process_frame_type(p, skb)))
+#if IS_ENABLED(CONFIG_BRIDGE_CFM) || IS_ENABLED(CONFIG_BRIDGE_MRP)
+	if (unlikely((p->br->options & BR_CFM_MRP_OPTS) &&
+		     br_process_frame_type(p, skb)))
 		return RX_HANDLER_PASS;
+#endif
 
 forward:
 	if (br_mst_is_enabled(p))
@@ -467,19 +483,3 @@ rx_handler_func_t *br_get_rx_handler(const struct net_device *dev)
 
 	return br_handle_frame;
 }
-
-void br_add_frame(struct net_bridge *br, struct br_frame_type *ft)
-{
-	hlist_add_head_rcu(&ft->list, &br->frame_type_list);
-}
-
-void br_del_frame(struct net_bridge *br, struct br_frame_type *ft)
-{
-	struct br_frame_type *tmp;
-
-	hlist_for_each_entry(tmp, &br->frame_type_list, list)
-		if (ft == tmp) {
-			hlist_del_rcu(&ft->list);
-			return;
-		}
-}
diff --git a/net/bridge/br_mrp.c b/net/bridge/br_mrp.c
index ef16d07039241..dce6efa96c4c6 100644
--- a/net/bridge/br_mrp.c
+++ b/net/bridge/br_mrp.c
@@ -6,13 +6,6 @@
 static const u8 mrp_test_dmac[ETH_ALEN] = { 0x1, 0x15, 0x4e, 0x0, 0x0, 0x1 };
 static const u8 mrp_in_test_dmac[ETH_ALEN] = { 0x1, 0x15, 0x4e, 0x0, 0x0, 0x3 };
 
-static int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb);
-
-static struct br_frame_type mrp_frame_type __read_mostly = {
-	.type = cpu_to_be16(ETH_P_MRP),
-	.frame_handler = br_mrp_process,
-};
-
 static bool br_mrp_is_ring_port(struct net_bridge_port *p_port,
 				struct net_bridge_port *s_port,
 				struct net_bridge_port *port)
@@ -486,7 +479,7 @@ static void br_mrp_del_impl(struct net_bridge *br, struct br_mrp *mrp)
 	kfree_rcu(mrp, rcu);
 
 	if (hlist_empty(&br->mrp_list))
-		br_del_frame(br, &mrp_frame_type);
+		br_opt_toggle(br, BROPT_MRP_ENABLED, false);
 }
 
 /* Adds a new MRP instance.
@@ -536,7 +529,7 @@ int br_mrp_add(struct net_bridge *br, struct br_mrp_instance *instance)
 	rcu_assign_pointer(mrp->s_port, p);
 
 	if (hlist_empty(&br->mrp_list))
-		br_add_frame(br, &mrp_frame_type);
+		br_opt_toggle(br, BROPT_MRP_ENABLED, true);
 
 	INIT_DELAYED_WORK(&mrp->test_work, br_mrp_test_work_expired);
 	INIT_DELAYED_WORK(&mrp->in_test_work, br_mrp_in_test_work_expired);
@@ -1241,7 +1234,7 @@ static int br_mrp_rcv(struct net_bridge_port *p,
  * normal forwarding.
  * note: already called with rcu_read_lock
  */
-static int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb)
+int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb)
 {
 	/* If there is no MRP instance do normal forwarding */
 	if (likely(!test_bit(BR_MRP_AWARE_BIT, &p->flags)))
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index d337b1cfb980d..afe7c0b4f8fa7 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -495,12 +495,13 @@ enum net_bridge_opts {
 	BROPT_MST_ENABLED,
 	BROPT_MDB_OFFLOAD_FAIL_NOTIFICATION,
 	BROPT_FDB_LOCAL_VLAN_0,
+	BROPT_CFM_ENABLED,
+	BROPT_MRP_ENABLED,
 };
 
 struct net_bridge {
 	spinlock_t			lock;
 	spinlock_t			hash_lock;
-	struct hlist_head		frame_type_list;
 	struct net_device		*dev;
 	unsigned long			options;
 	/* These fields are accessed on each packet */
@@ -932,16 +933,6 @@ int nbp_backup_change(struct net_bridge_port *p, struct net_device *backup_dev);
 int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb);
 rx_handler_func_t *br_get_rx_handler(const struct net_device *dev);
 
-struct br_frame_type {
-	__be16			type;
-	int			(*frame_handler)(struct net_bridge_port *port,
-						 struct sk_buff *skb);
-	struct hlist_node	list;
-};
-
-void br_add_frame(struct net_bridge *br, struct br_frame_type *ft);
-void br_del_frame(struct net_bridge *br, struct br_frame_type *ft);
-
 static inline bool br_rx_handler_check_rcu(const struct net_device *dev)
 {
 	return rcu_dereference(dev->rx_handler) == br_get_rx_handler(dev);
@@ -2080,6 +2071,7 @@ int br_mrp_parse(struct net_bridge *br, struct net_bridge_port *p,
 bool br_mrp_enabled(struct net_bridge *br);
 void br_mrp_port_del(struct net_bridge *br, struct net_bridge_port *p);
 int br_mrp_fill_info(struct sk_buff *skb, struct net_bridge *br);
+int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb);
 #else
 static inline int br_mrp_parse(struct net_bridge *br, struct net_bridge_port *p,
 			       struct nlattr *attr, int cmd,
@@ -2111,6 +2103,7 @@ int br_cfm_parse(struct net_bridge *br, struct net_bridge_port *p,
 		 struct nlattr *attr, int cmd, struct netlink_ext_ack *extack);
 bool br_cfm_created(struct net_bridge *br);
 void br_cfm_port_del(struct net_bridge *br, struct net_bridge_port *p);
+int br_cfm_frame_rx(struct net_bridge_port *port, struct sk_buff *skb);
 int br_cfm_config_fill_info(struct sk_buff *skb, struct net_bridge *br);
 int br_cfm_status_fill_info(struct sk_buff *skb,
 			    struct net_bridge *br,

21/3 2026/08/31 12:19 llm kmsan-evaluator
0m Model:
gemini-3.7-flash

Args:
null

Results:
null

Tokens:
							input: 5413
							output: 27
							thoughts: 962
						

Thoughts:
**Refactoring CFM/MRP Frame Handling in the Bridge**

Okay, so I'm looking at this patch and it's a significant refactoring of how CFM (Connectivity Fault Management) and MRP (Multiple Registration Protocol) frame handlers are managed within the bridge code (`net/bridge/`).  Previously, we were using a linked list (`frame_type_list`) on the `net_bridge` struct to dynamically register these frame types via `br_add_frame` and `br_del_frame` using `cfm_frame_type` and `mrp_frame_type` structs.  Now, the approach is being simplified and optimized.

The key change is the introduction of bit flags within `net_bridge->options`: `BROPT_CFM_ENABLED` and `BROPT_MRP_ENABLED`. Instead of the linked list, `br_process_frame_type` is now the core. This function directly checks these option bits to determine whether to call the appropriate handlers: `br_cfm_frame_rx` or `br_mrp_process`. The `frame_type_list` and the `struct br_frame_type` are being removed altogether, streamlining the code. In `br_handle_frame`, it checks `(p->br->options & BR_CFM_MRP_OPTS) && br_process_frame_type(p, skb)`.

Let's break down the individual files:

*   In `br_cfm.c`, `br_cfm_frame_rx` is no longer `static`. The `cfm_frame_type` struct is gone. The registration and de-registration of CFM functionality is now handled with `br_opt_toggle(br, BROPT_CFM_ENABLED, true/false)` instead of `br_add_frame` and `br_del_frame`.
*   `br_device.c` sees the removal of `INIT_HLIST_HEAD(&br->frame_type_list);` since the list is no longer required.
*   In `br_input.c`, we've got the definition for `BR_CFM_MRP_OPTS` as a bitmask. The `br_process_frame_type` function is now crucial, checking for the correct Ethernet protocol types (`ETH_P_CFM` and `ETH_P_MRP`) and the corresponding option flags before calling the specific handler.  Again, `br_add_frame` and `br_del_frame` are removed.
*   `br_mrp.c` mirrors these changes. The `mrp_frame_type` is removed, and registration is done via `br_opt_toggle` as well. `br_mrp_process` is made non-static.
*   Lastly, in `br_private.h`, we have the new option flags added to `enum net_bridge_opts`, and the removal of the old data structures. The relevant function declarations are added.

Now, a quick, but important, security audit. I need to make sure this doesn't open any vulnerabilities.

*   No kernel-to-user information leaks are introduced; it's all about packet reception processing and internal option flags.
*   There's no uninitialized memory being read. The `br->options` struct member is part of `struct net_bridge` and initialized via `kzalloc`.
*   We're not passing uninitialized data anywhere.
*   No conditional branches rely on uninitialized data.
*   The memory allocation and handling don't seem to introduce uninitialized byte issues.

I'll quickly double-check the `br_opt_toggle` and `br_opt_get` functions to make sure they're working as expected, but this looks like a well-structured and potentially more efficient approach to managing these frame handlers.



22/3 2026/08/31 12:20 tool grepper
0m Args:
{
  "Expression": "br_opt_",
  "PathPrefix": "net/bridge"
}

Results:
{
  "Output": "\nFull output is too long, showing 500 out of 769 lines.\nUse more precise expression if possible.\n\nnet/bridge/br.c=268=br_toggle_fdb_local_vlan_0(struct net_bridge *br, bool on,\n--\nnet/bridge/br.c-272-\nnet/bridge/br.c:273:\tif (br_opt_get(br, BROPT_FDB_LOCAL_VLAN_0) == on)\nnet/bridge/br.c-274-\t\treturn 0;\n--\nnet/bridge/br.c-279-\nnet/bridge/br.c:280:\tbr_opt_toggle(br, BROPT_FDB_LOCAL_VLAN_0, on);\nnet/bridge/br.c-281-\treturn 0;\n--\nnet/bridge/br.c=294=int br_boolopt_toggle(struct net_bridge *br, enum br_boolopt_id opt, bool on,\n--\nnet/bridge/br.c-300-\tcase BR_BOOLOPT_NO_LL_LEARN:\nnet/bridge/br.c:301:\t\tbr_opt_toggle(br, BROPT_NO_LL_LEARN, on);\nnet/bridge/br.c-302-\t\tbreak;\n--\nnet/bridge/br.c-309-\tcase BR_BOOLOPT_MDB_OFFLOAD_FAIL_NOTIFICATION:\nnet/bridge/br.c:310:\t\tbr_opt_toggle(br, BROPT_MDB_OFFLOAD_FAIL_NOTIFICATION, on);\nnet/bridge/br.c-311-\t\tbreak;\n--\nnet/bridge/br.c=324=int br_boolopt_get(const struct net_bridge *br, enum br_boolopt_id opt)\n--\nnet/bridge/br.c-327-\tcase BR_BOOLOPT_NO_LL_LEARN:\nnet/bridge/br.c:328:\t\treturn br_opt_get(br, BROPT_NO_LL_LEARN);\nnet/bridge/br.c-329-\tcase BR_BOOLOPT_MCAST_VLAN_SNOOPING:\nnet/bridge/br.c:330:\t\treturn br_opt_get(br, BROPT_MCAST_VLAN_SNOOPING_ENABLED);\nnet/bridge/br.c-331-\tcase BR_BOOLOPT_MST_ENABLE:\nnet/bridge/br.c:332:\t\treturn br_opt_get(br, BROPT_MST_ENABLED);\nnet/bridge/br.c-333-\tcase BR_BOOLOPT_MDB_OFFLOAD_FAIL_NOTIFICATION:\nnet/bridge/br.c:334:\t\treturn br_opt_get(br, BROPT_MDB_OFFLOAD_FAIL_NOTIFICATION);\nnet/bridge/br.c-335-\tcase BR_BOOLOPT_FDB_LOCAL_VLAN_0:\nnet/bridge/br.c:336:\t\treturn br_opt_get(br, BROPT_FDB_LOCAL_VLAN_0);\nnet/bridge/br.c-337-\tdefault:\n--\nnet/bridge/br.c=375=void br_boolopt_multi_get(const struct net_bridge *br,\n--\nnet/bridge/br.c-388-/* private bridge options, controlled by the kernel */\nnet/bridge/br.c:389:void br_opt_toggle(struct net_bridge *br, enum net_bridge_opts opt, bool on)\nnet/bridge/br.c-390-{\nnet/bridge/br.c:391:\tbool cur = !!br_opt_get(br, opt);\nnet/bridge/br.c-392-\n--\nnet/bridge/br_arp_nd_proxy.c=27=void br_recalculate_neigh_suppress_enabled(struct net_bridge *br)\n--\nnet/bridge/br_arp_nd_proxy.c-38-\nnet/bridge/br_arp_nd_proxy.c:39:\tbr_opt_toggle(br, BROPT_NEIGH_SUPPRESS_ENABLED, neigh_suppress);\nnet/bridge/br_arp_nd_proxy.c-40-}\n--\nnet/bridge/br_arp_nd_proxy.c=125=void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br,\n--\nnet/bridge/br_arp_nd_proxy.c-160-\nnet/bridge/br_arp_nd_proxy.c:161:\tif (br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED)) {\nnet/bridge/br_arp_nd_proxy.c-162-\t\tif (br_is_neigh_suppress_enabled(p, vid))\n--\nnet/bridge/br_arp_nd_proxy.c-186-\nnet/bridge/br_arp_nd_proxy.c:187:\tif (br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED) \u0026\u0026\nnet/bridge/br_arp_nd_proxy.c-188-\t    br_is_local_ip(vlandev, tip)) {\n--\nnet/bridge/br_arp_nd_proxy.c-229-\t\t\tif (replied ||\nnet/bridge/br_arp_nd_proxy.c:230:\t\t\t    br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED))\nnet/bridge/br_arp_nd_proxy.c-231-\t\t\t\tBR_INPUT_SKB_CB(skb)-\u003eproxyarp_replied = 1;\n--\nnet/bridge/br_arp_nd_proxy.c=415=void br_do_suppress_nd(struct sk_buff *skb, struct net_bridge *br,\n--\nnet/bridge/br_arp_nd_proxy.c-503-\t\t\tif (replied ||\nnet/bridge/br_arp_nd_proxy.c:504:\t\t\t    br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED))\nnet/bridge/br_arp_nd_proxy.c-505-\t\t\t\tBR_INPUT_SKB_CB(skb)-\u003eproxyarp_replied = 1;\n--\nnet/bridge/br_cfm.c=492=int br_cfm_mep_create(struct net_bridge *br,\n--\nnet/bridge/br_cfm.c-556-\tif (hlist_empty(\u0026br-\u003emep_list))\nnet/bridge/br_cfm.c:557:\t\tbr_opt_toggle(br, BROPT_CFM_ENABLED, true);\nnet/bridge/br_cfm.c-558-\n--\nnet/bridge/br_cfm.c=564=static void mep_delete_implementation(struct net_bridge *br,\n--\nnet/bridge/br_cfm.c-585-\tif (hlist_empty(\u0026br-\u003emep_list))\nnet/bridge/br_cfm.c:586:\t\tbr_opt_toggle(br, BROPT_CFM_ENABLED, false);\nnet/bridge/br_cfm.c-587-}\n--\nnet/bridge/br_device.c=30=netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)\n--\nnet/bridge/br_device.c-74-\t     eth_hdr(skb)-\u003eh_proto == htons(ETH_P_RARP)) \u0026\u0026\nnet/bridge/br_device.c:75:\t    br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED)) {\nnet/bridge/br_device.c-76-\t\tbr_do_proxy_suppress_arp(skb, br, vid, NULL);\n--\nnet/bridge/br_device.c-78-\t\t   skb-\u003eprotocol == htons(ETH_P_IPV6) \u0026\u0026\nnet/bridge/br_device.c:79:\t\t   br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED) \u0026\u0026\nnet/bridge/br_device.c-80-\t\t   pskb_may_pull(skb, sizeof(struct ipv6hdr) +\n--\nnet/bridge/br_device.c=164=static int br_dev_open(struct net_device *dev)\n--\nnet/bridge/br_device.c-172-\nnet/bridge/br_device.c:173:\tif (br_opt_get(br, BROPT_MULTICAST_ENABLED))\nnet/bridge/br_device.c-174-\t\tbr_multicast_join_snoopers(br);\n--\nnet/bridge/br_device.c=189=static int br_dev_stop(struct net_device *dev)\n--\nnet/bridge/br_device.c-195-\nnet/bridge/br_device.c:196:\tif (br_opt_get(br, BROPT_MULTICAST_ENABLED))\nnet/bridge/br_device.c-197-\t\tbr_multicast_leave_snoopers(br);\n--\nnet/bridge/br_device.c=204=static int br_change_mtu(struct net_device *dev, int new_mtu)\n--\nnet/bridge/br_device.c-210-\t/* this flag will be cleared if the MTU was automatically adjusted */\nnet/bridge/br_device.c:211:\tbr_opt_toggle(br, BROPT_MTU_SET_BY_USER, true);\nnet/bridge/br_device.c-212-#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)\n--\nnet/bridge/br_fdb.c=460=void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr)\n--\nnet/bridge/br_fdb.c-467-\nnet/bridge/br_fdb.c:468:\tlocal_vlan_0 = br_opt_get(br, BROPT_FDB_LOCAL_VLAN_0);\nnet/bridge/br_fdb.c-469-\n--\nnet/bridge/br_fdb.c=506=void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr)\n--\nnet/bridge/br_fdb.c-512-\nnet/bridge/br_fdb.c:513:\tlocal_vlan_0 = br_opt_get(br, BROPT_FDB_LOCAL_VLAN_0);\nnet/bridge/br_fdb.c-514-\n--\nnet/bridge/br_if.c=520=void br_mtu_auto_adjust(struct net_bridge *br)\n--\nnet/bridge/br_if.c-524-\t/* if the bridge MTU was manually configured don't mess with it */\nnet/bridge/br_if.c:525:\tif (br_opt_get(br, BROPT_MTU_SET_BY_USER))\nnet/bridge/br_if.c-526-\t\treturn;\n--\nnet/bridge/br_if.c-531-\tdev_set_mtu(br-\u003edev, br_mtu_min(br));\nnet/bridge/br_if.c:532:\tbr_opt_toggle(br, BROPT_MTU_SET_BY_USER, false);\nnet/bridge/br_if.c-533-}\n--\nnet/bridge/br_input.c=76=int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb)\n--\nnet/bridge/br_input.c-174-\t\t   skb-\u003eprotocol == htons(ETH_P_IPV6) \u0026\u0026\nnet/bridge/br_input.c:175:\t\t   br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED) \u0026\u0026\nnet/bridge/br_input.c-176-\t\t   pskb_may_pull(skb, sizeof(struct ipv6hdr) +\n--\nnet/bridge/br_input.c-205-\t\tif (unlikely(!dst \u0026\u0026 vid \u0026\u0026\nnet/bridge/br_input.c:206:\t\t\t     br_opt_get(br, BROPT_FDB_LOCAL_VLAN_0))) {\nnet/bridge/br_input.c-207-\t\t\tdst = br_fdb_find_rcu(br, eth_hdr(skb)-\u003eh_dest, 0);\n--\nnet/bridge/br_input.c=245=static void __br_handle_local_finish(struct sk_buff *skb)\n--\nnet/bridge/br_input.c-252-\t    nbp_state_should_learn(p) \u0026\u0026\nnet/bridge/br_input.c:253:\t    !br_opt_get(p-\u003ebr, BROPT_NO_LL_LEARN) \u0026\u0026\nnet/bridge/br_input.c-254-\t    br_should_learn(p, skb, \u0026vid))\n--\nnet/bridge/br_input.c=329=static int br_process_frame_type(struct net_bridge_port *p,\n--\nnet/bridge/br_input.c-335-\tif (skb-\u003eprotocol == htons(ETH_P_CFM) \u0026\u0026\nnet/bridge/br_input.c:336:\t    br_opt_get(br, BROPT_CFM_ENABLED))\nnet/bridge/br_input.c-337-\t\treturn br_cfm_frame_rx(p, skb);\n--\nnet/bridge/br_input.c-340-\tif (skb-\u003eprotocol == htons(ETH_P_MRP) \u0026\u0026\nnet/bridge/br_input.c:341:\t    br_opt_get(br, BROPT_MRP_ENABLED))\nnet/bridge/br_input.c-342-\t\treturn br_mrp_process(p, skb);\n--\nnet/bridge/br_mdb.c=708=__br_mdb_choose_context(struct net_bridge *br,\n--\nnet/bridge/br_mdb.c-714-\nnet/bridge/br_mdb.c:715:\tif (!br_opt_get(br, BROPT_MCAST_VLAN_SNOOPING_ENABLED)) {\nnet/bridge/br_mdb.c-716-\t\tbrmctx = \u0026br-\u003emulticast_ctx;\n--\nnet/bridge/br_mdb.c=1231=static int br_mdb_config_init(struct br_mdb_config *cfg, struct net_device *dev,\n--\nnet/bridge/br_mdb.c-1248-\nnet/bridge/br_mdb.c:1249:\tif (!br_opt_get(cfg-\u003ebr, BROPT_MULTICAST_ENABLED)) {\nnet/bridge/br_mdb.c-1250-\t\tNL_SET_ERR_MSG_MOD(extack, \"Bridge's multicast processing is disabled\");\n--\nnet/bridge/br_mrp.c=419=static void br_mrp_del_impl(struct net_bridge *br, struct br_mrp *mrp)\n--\nnet/bridge/br_mrp.c-481-\tif (hlist_empty(\u0026br-\u003emrp_list))\nnet/bridge/br_mrp.c:482:\t\tbr_opt_toggle(br, BROPT_MRP_ENABLED, false);\nnet/bridge/br_mrp.c-483-}\n--\nnet/bridge/br_mrp.c=488=int br_mrp_add(struct net_bridge *br, struct br_mrp_instance *instance)\n--\nnet/bridge/br_mrp.c-531-\tif (hlist_empty(\u0026br-\u003emrp_list))\nnet/bridge/br_mrp.c:532:\t\tbr_opt_toggle(br, BROPT_MRP_ENABLED, true);\nnet/bridge/br_mrp.c-533-\n--\nnet/bridge/br_mst.c=16=bool br_mst_enabled(const struct net_device *dev)\n--\nnet/bridge/br_mst.c-20-\nnet/bridge/br_mst.c:21:\treturn br_opt_get(netdev_priv(dev), BROPT_MST_ENABLED);\nnet/bridge/br_mst.c-22-}\n--\nnet/bridge/br_mst.c=25=void br_mst_uninit(struct net_bridge *br)\nnet/bridge/br_mst.c-26-{\nnet/bridge/br_mst.c:27:\tif (br_opt_get(br, BROPT_MST_ENABLED))\nnet/bridge/br_mst.c-28-\t\tstatic_branch_dec(\u0026br_mst_used);\n--\nnet/bridge/br_mst.c=31=int br_mst_get_info(const struct net_device *dev, u16 msti, unsigned long *vids)\n--\nnet/bridge/br_mst.c-42-\tbr = netdev_priv(dev);\nnet/bridge/br_mst.c:43:\tif (!br_opt_get(br, BROPT_MST_ENABLED))\nnet/bridge/br_mst.c-44-\t\treturn -EINVAL;\n--\nnet/bridge/br_mst.c=57=int br_mst_get_state(const struct net_device *dev, u16 msti, u8 *state)\n--\nnet/bridge/br_mst.c-65-\tp = br_port_get_check_rtnl(dev);\nnet/bridge/br_mst.c:66:\tif (!p || !br_opt_get(p-\u003ebr, BROPT_MST_ENABLED))\nnet/bridge/br_mst.c-67-\t\treturn -EINVAL;\n--\nnet/bridge/br_mst.c=203=int br_mst_set_enabled(struct net_bridge *br, bool on,\n--\nnet/bridge/br_mst.c-225-\nnet/bridge/br_mst.c:226:\tif (br_opt_get(br, BROPT_MST_ENABLED) == on)\nnet/bridge/br_mst.c-227-\t\treturn 0;\n--\nnet/bridge/br_mst.c-237-\nnet/bridge/br_mst.c:238:\tbr_opt_toggle(br, BROPT_MST_ENABLED, on);\nnet/bridge/br_mst.c-239-\treturn 0;\n--\nnet/bridge/br_mst.c=334=int br_mst_process(struct net_bridge_port *p, const struct nlattr *mst_attr,\n--\nnet/bridge/br_mst.c-340-\nnet/bridge/br_mst.c:341:\tif (!br_opt_get(p-\u003ebr, BROPT_MST_ENABLED)) {\nnet/bridge/br_mst.c-342-\t\tNL_SET_ERR_MSG_MOD(extack, \"Can't modify MST state when MST is disabled\");\n--\nnet/bridge/br_multicast.c=149=br_mdb_entry_skb_get(struct net_bridge_mcast *brmctx, struct sk_buff *skb,\n--\nnet/bridge/br_multicast.c-154-\nnet/bridge/br_multicast.c:155:\tif (!br_opt_get(br, BROPT_MULTICAST_ENABLED) ||\nnet/bridge/br_multicast.c-156-\t    br_multicast_ctx_vlan_global_disabled(brmctx))\n--\nnet/bridge/br_multicast.c=210=br_multicast_pg_to_port_ctx(const struct net_bridge_port_group *pg)\n--\nnet/bridge/br_multicast.c-218-\tif (!pg-\u003ekey.addr.vid ||\nnet/bridge/br_multicast.c:219:\t    !br_opt_get(pg-\u003ekey.port-\u003ebr, BROPT_MCAST_VLAN_SNOOPING_ENABLED))\nnet/bridge/br_multicast.c-220-\t\tgoto out;\n--\nnet/bridge/br_multicast.c=924=static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge_mcast *brmctx,\n--\nnet/bridge/br_multicast.c-995-\tiph-\u003eprotocol = IPPROTO_IGMP;\nnet/bridge/br_multicast.c:996:\tiph-\u003esaddr = br_opt_get(brmctx-\u003ebr, BROPT_MULTICAST_QUERY_USE_IFADDR) ?\nnet/bridge/br_multicast.c-997-\t\t     inet_select_addr(brmctx-\u003ebr-\u003edev, 0, RT_SCOPE_LINK) : 0;\n--\nnet/bridge/br_multicast.c=1068=static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge_mcast *brmctx,\n--\nnet/bridge/br_multicast.c-1143-\t\tkfree_skb(skb);\nnet/bridge/br_multicast.c:1144:\t\tbr_opt_toggle(brmctx-\u003ebr, BROPT_HAS_IPV6_ADDR, false);\nnet/bridge/br_multicast.c-1145-\t\treturn NULL;\n--\nnet/bridge/br_multicast.c-1147-\nnet/bridge/br_multicast.c:1148:\tbr_opt_toggle(brmctx-\u003ebr, BROPT_HAS_IPV6_ADDR, true);\nnet/bridge/br_multicast.c-1149-\tipv6_eth_mc_map(\u0026ip6h-\u003edaddr, eth-\u003eh_dest);\n--\nnet/bridge/br_multicast.c=1269=struct net_bridge_mdb_entry *br_multicast_new_group(struct net_bridge *br,\n--\nnet/bridge/br_multicast.c-1281-\t\tbr_mc_disabled_update(br-\u003edev, false, NULL);\nnet/bridge/br_multicast.c:1282:\t\tbr_opt_toggle(br, BROPT_MULTICAST_ENABLED, false);\nnet/bridge/br_multicast.c-1283-\t\treturn ERR_PTR(-E2BIG);\n--\nnet/bridge/br_multicast.c=1723=static void br_multicast_querier_expired(struct net_bridge_mcast *brmctx,\n--\nnet/bridge/br_multicast.c-1728-\t    br_multicast_ctx_vlan_global_disabled(brmctx) ||\nnet/bridge/br_multicast.c:1729:\t    !br_opt_get(brmctx-\u003ebr, BROPT_MULTICAST_ENABLED))\nnet/bridge/br_multicast.c-1730-\t\tgoto out;\n--\nnet/bridge/br_multicast.c=1899=static void br_multicast_send_query(struct net_bridge_mcast *brmctx,\n--\nnet/bridge/br_multicast.c-1908-\tif (!br_multicast_ctx_should_use(brmctx, pmctx) ||\nnet/bridge/br_multicast.c:1909:\t    !br_opt_get(brmctx-\u003ebr, BROPT_MULTICAST_ENABLED) ||\nnet/bridge/br_multicast.c-1910-\t    !brmctx-\u003emulticast_querier)\n--\nnet/bridge/br_multicast.c=1987=static void br_multicast_port_group_rexmit(struct timer_list *t)\n--\nnet/bridge/br_multicast.c-1998-\tif (!netif_running(br-\u003edev) || hlist_unhashed(\u0026pg-\u003emglist) ||\nnet/bridge/br_multicast.c:1999:\t    !br_opt_get(br, BROPT_MULTICAST_ENABLED))\nnet/bridge/br_multicast.c-2000-\t\tgoto out;\n--\nnet/bridge/br_multicast.c=2103=int br_multicast_add_port(struct net_bridge_port *port)\n--\nnet/bridge/br_multicast.c-2110-\terr = br_mc_disabled_update(port-\u003edev,\nnet/bridge/br_multicast.c:2111:\t\t\t\t    br_opt_get(port-\u003ebr,\nnet/bridge/br_multicast.c-2112-\t\t\t\t\t       BROPT_MULTICAST_ENABLED),\n--\nnet/bridge/br_multicast.c=2149=static void __br_multicast_enable_port_ctx(struct net_bridge_mcast_port *pmctx)\n--\nnet/bridge/br_multicast.c-2154-\tbrmctx = br_multicast_port_ctx_get_global(pmctx);\nnet/bridge/br_multicast.c:2155:\tif (!br_opt_get(br, BROPT_MULTICAST_ENABLED) ||\nnet/bridge/br_multicast.c-2156-\t    !netif_running(br-\u003edev))\n--\nnet/bridge/br_multicast.c=2221=static void br_multicast_toggle_port(struct net_bridge_port *port, bool on)\n--\nnet/bridge/br_multicast.c-2223-#if IS_ENABLED(CONFIG_BRIDGE_VLAN_FILTERING)\nnet/bridge/br_multicast.c:2224:\tif (br_opt_get(port-\u003ebr, BROPT_MCAST_VLAN_SNOOPING_ENABLED)) {\nnet/bridge/br_multicast.c-2225-\t\tstruct net_bridge_vlan_group *vg;\n--\nnet/bridge/br_multicast.c=2291=static void __grp_src_query_marked_and_rexmit(struct net_bridge_mcast *brmctx,\n--\nnet/bridge/br_multicast.c-2300-\tif (!netif_running(brmctx-\u003ebr-\u003edev) ||\nnet/bridge/br_multicast.c:2301:\t    !br_opt_get(brmctx-\u003ebr, BROPT_MULTICAST_ENABLED))\nnet/bridge/br_multicast.c-2302-\t\treturn;\n--\nnet/bridge/br_multicast.c=2338=static void __grp_send_query_and_rexmit(struct net_bridge_mcast *brmctx,\n--\nnet/bridge/br_multicast.c-2345-\tif (!netif_running(brmctx-\u003ebr-\u003edev) ||\nnet/bridge/br_multicast.c:2346:\t    !br_opt_get(brmctx-\u003ebr, BROPT_MULTICAST_ENABLED))\nnet/bridge/br_multicast.c-2347-\t\treturn;\n--\nnet/bridge/br_multicast.c=3244=int br_multicast_dump_querier_state(struct sk_buff *skb,\n--\nnet/bridge/br_multicast.c-3251-\nnet/bridge/br_multicast.c:3252:\tif (!br_opt_get(brmctx-\u003ebr, BROPT_MULTICAST_ENABLED) ||\nnet/bridge/br_multicast.c-3253-\t    br_multicast_ctx_vlan_global_disabled(brmctx))\n--\nnet/bridge/br_multicast.c=3868=static void br_multicast_err_count(const struct net_bridge *br,\n--\nnet/bridge/br_multicast.c-3874-\nnet/bridge/br_multicast.c:3875:\tif (!br_opt_get(br, BROPT_MULTICAST_STATS_ENABLED))\nnet/bridge/br_multicast.c-3876-\t\treturn;\n--\nnet/bridge/br_multicast.c=4057=int br_multicast_rcv(struct net_bridge_mcast **brmctx,\n--\nnet/bridge/br_multicast.c-4066-\nnet/bridge/br_multicast.c:4067:\tif (!br_opt_get((*brmctx)-\u003ebr, BROPT_MULTICAST_ENABLED))\nnet/bridge/br_multicast.c-4068-\t\treturn 0;\nnet/bridge/br_multicast.c-4069-\nnet/bridge/br_multicast.c:4070:\tif (br_opt_get((*brmctx)-\u003ebr, BROPT_MCAST_VLAN_SNOOPING_ENABLED) \u0026\u0026 vlan) {\nnet/bridge/br_multicast.c-4071-\t\tconst struct net_bridge_vlan *masterv;\n--\nnet/bridge/br_multicast.c=4206=void br_multicast_init(struct net_bridge *br)\n--\nnet/bridge/br_multicast.c-4211-\nnet/bridge/br_multicast.c:4212:\tbr_opt_toggle(br, BROPT_MULTICAST_ENABLED, true);\nnet/bridge/br_multicast.c:4213:\tbr_opt_toggle(br, BROPT_HAS_IPV6_ADDR, true);\nnet/bridge/br_multicast.c-4214-\n--\nnet/bridge/br_multicast.c=4283=static void __br_multicast_open_query(struct net_bridge *br,\n--\nnet/bridge/br_multicast.c-4287-\nnet/bridge/br_multicast.c:4288:\tif (!br_opt_get(br, BROPT_MULTICAST_ENABLED))\nnet/bridge/br_multicast.c-4289-\t\treturn;\n--\nnet/bridge/br_multicast.c=4302=void br_multicast_open(struct net_bridge *br)\n--\nnet/bridge/br_multicast.c-4305-\nnet/bridge/br_multicast.c:4306:\tif (br_opt_get(br, BROPT_MCAST_VLAN_SNOOPING_ENABLED)) {\nnet/bridge/br_multicast.c-4307-\t\tstruct net_bridge_vlan_group *vg;\n--\nnet/bridge/br_multicast.c=4340=void br_multicast_update_vlan_mcast_ctx(struct net_bridge_vlan *v, u8 state)\n--\nnet/bridge/br_multicast.c-4352-\nnet/bridge/br_multicast.c:4353:\tif (!br_opt_get(br, BROPT_MCAST_VLAN_SNOOPING_ENABLED))\nnet/bridge/br_multicast.c-4354-\t\treturn;\n--\nnet/bridge/br_multicast.c=4431=int br_multicast_toggle_vlan_snooping(struct net_bridge *br, bool on,\n--\nnet/bridge/br_multicast.c-4437-\nnet/bridge/br_multicast.c:4438:\tif (br_opt_get(br, BROPT_MCAST_VLAN_SNOOPING_ENABLED) == on)\nnet/bridge/br_multicast.c-4439-\t\treturn 0;\nnet/bridge/br_multicast.c-4440-\nnet/bridge/br_multicast.c:4441:\tif (on \u0026\u0026 !br_opt_get(br, BROPT_VLAN_ENABLED)) {\nnet/bridge/br_multicast.c-4442-\t\tNL_SET_ERR_MSG_MOD(extack, \"Cannot enable multicast vlan snooping with vlan filtering disabled\");\n--\nnet/bridge/br_multicast.c-4449-\nnet/bridge/br_multicast.c:4450:\tbr_opt_toggle(br, BROPT_MCAST_VLAN_SNOOPING_ENABLED, on);\nnet/bridge/br_multicast.c-4451-\n--\nnet/bridge/br_multicast.c=4486=void br_multicast_stop(struct net_bridge *br)\n--\nnet/bridge/br_multicast.c-4489-\nnet/bridge/br_multicast.c:4490:\tif (br_opt_get(br, BROPT_MCAST_VLAN_SNOOPING_ENABLED)) {\nnet/bridge/br_multicast.c-4491-\t\tstruct net_bridge_vlan_group *vg;\n--\nnet/bridge/br_multicast.c=4708=static void br_multicast_enable_all_ports(struct net_bridge *br)\n--\nnet/bridge/br_multicast.c-4711-\nnet/bridge/br_multicast.c:4712:\tif (br_opt_get(br, BROPT_MCAST_VLAN_SNOOPING_ENABLED))\nnet/bridge/br_multicast.c-4713-\t\treturn;\n--\nnet/bridge/br_multicast.c=4719=static void br_multicast_disable_all_ports(struct net_bridge *br)\n--\nnet/bridge/br_multicast.c-4722-\nnet/bridge/br_multicast.c:4723:\tif (br_opt_get(br, BROPT_MCAST_VLAN_SNOOPING_ENABLED))\nnet/bridge/br_multicast.c-4724-\t\treturn;\n--\nnet/bridge/br_multicast.c=4730=int br_multicast_toggle(struct net_bridge *br, unsigned long val,\n--\nnet/bridge/br_multicast.c-4736-\tspin_lock_bh(\u0026br-\u003emulticast_lock);\nnet/bridge/br_multicast.c:4737:\tif (!!br_opt_get(br, BROPT_MULTICAST_ENABLED) == !!val)\nnet/bridge/br_multicast.c-4738-\t\tgoto unlock;\n--\nnet/bridge/br_multicast.c-4745-\nnet/bridge/br_multicast.c:4746:\tbr_opt_toggle(br, BROPT_MULTICAST_ENABLED, !!val);\nnet/bridge/br_multicast.c:4747:\tif (!br_opt_get(br, BROPT_MULTICAST_ENABLED)) {\nnet/bridge/br_multicast.c-4748-\t\tchange_snoopers = true;\n--\nnet/bridge/br_multicast.c-4776-\tif (change_snoopers) {\nnet/bridge/br_multicast.c:4777:\t\tif (br_opt_get(br, BROPT_MULTICAST_ENABLED))\nnet/bridge/br_multicast.c-4778-\t\t\tbr_multicast_join_snoopers(br);\n--\nnet/bridge/br_multicast.c=4786=bool br_multicast_enabled(const struct net_device *dev)\n--\nnet/bridge/br_multicast.c-4789-\nnet/bridge/br_multicast.c:4790:\treturn !!br_opt_get(br, BROPT_MULTICAST_ENABLED);\nnet/bridge/br_multicast.c-4791-}\n--\nnet/bridge/br_multicast.c=5207=void br_multicast_count(struct net_bridge *br,\n--\nnet/bridge/br_multicast.c-5213-\t/* if multicast_disabled is true then igmp type can't be set */\nnet/bridge/br_multicast.c:5214:\tif (!type || !br_opt_get(br, BROPT_MULTICAST_STATS_ENABLED))\nnet/bridge/br_multicast.c-5215-\t\treturn;\n--\nnet/bridge/br_netfilter_hooks.c=483=static unsigned int br_nf_pre_routing(void *priv,\n--\nnet/bridge/br_netfilter_hooks.c-504-\t\tif (!brnet-\u003ecall_ip6tables \u0026\u0026\nnet/bridge/br_netfilter_hooks.c:505:\t\t    !br_opt_get(br, BROPT_NF_CALL_IP6TABLES))\nnet/bridge/br_netfilter_hooks.c-506-\t\t\treturn NF_ACCEPT;\n--\nnet/bridge/br_netfilter_hooks.c-515-\nnet/bridge/br_netfilter_hooks.c:516:\tif (!brnet-\u003ecall_iptables \u0026\u0026 !br_opt_get(br, BROPT_NF_CALL_IPTABLES))\nnet/bridge/br_netfilter_hooks.c-517-\t\treturn NF_ACCEPT;\n--\nnet/bridge/br_netfilter_hooks.c=728=static unsigned int br_nf_forward_arp(struct sk_buff *skb,\n--\nnet/bridge/br_netfilter_hooks.c-741-\tbrnet = net_generic(state-\u003enet, brnf_net_id);\nnet/bridge/br_netfilter_hooks.c:742:\tif (!brnet-\u003ecall_arptables \u0026\u0026 !br_opt_get(br, BROPT_NF_CALL_ARPTABLES))\nnet/bridge/br_netfilter_hooks.c-743-\t\treturn NF_ACCEPT;\n--\nnet/bridge/br_netlink.c=458=static int br_fill_ifinfo(struct sk_buff *skb,\n--\nnet/bridge/br_netlink.c-594-\tif ((filter_mask \u0026 RTEXT_FILTER_MST) \u0026\u0026\nnet/bridge/br_netlink.c:595:\t    br_opt_get(br, BROPT_MST_ENABLED) \u0026\u0026 port) {\nnet/bridge/br_netlink.c-596-\t\tconst struct net_bridge_vlan_group *vg = nbp_vlan_group(port);\n--\nnet/bridge/br_netlink.c=1295=static int br_changelink(struct net_device *brdev, struct nlattr *tb[],\n--\nnet/bridge/br_netlink.c-1424-\t\tspin_unlock_bh(\u0026br-\u003elock);\nnet/bridge/br_netlink.c:1425:\t\tbr_opt_toggle(br, BROPT_GROUP_ADDR_SET, true);\nnet/bridge/br_netlink.c-1426-\t\tbr_recalculate_fwd_mask(br);\n--\nnet/bridge/br_netlink.c-1458-\t\tval = nla_get_u8(data[IFLA_BR_MCAST_QUERY_USE_IFADDR]);\nnet/bridge/br_netlink.c:1459:\t\tbr_opt_toggle(br, BROPT_MULTICAST_QUERY_USE_IFADDR, !!val);\nnet/bridge/br_netlink.c-1460-\t}\n--\nnet/bridge/br_netlink.c-1529-\t\tmcast_stats = nla_get_u8(data[IFLA_BR_MCAST_STATS_ENABLED]);\nnet/bridge/br_netlink.c:1530:\t\tbr_opt_toggle(br, BROPT_MULTICAST_STATS_ENABLED, !!mcast_stats);\nnet/bridge/br_netlink.c-1531-\t}\n--\nnet/bridge/br_netlink.c-1558-\nnet/bridge/br_netlink.c:1559:\t\tbr_opt_toggle(br, BROPT_NF_CALL_IPTABLES, !!val);\nnet/bridge/br_netlink.c-1560-\t}\n--\nnet/bridge/br_netlink.c-1564-\nnet/bridge/br_netlink.c:1565:\t\tbr_opt_toggle(br, BROPT_NF_CALL_IP6TABLES, !!val);\nnet/bridge/br_netlink.c-1566-\t}\n--\nnet/bridge/br_netlink.c-1570-\nnet/bridge/br_netlink.c:1571:\t\tbr_opt_toggle(br, BROPT_NF_CALL_ARPTABLES, !!val);\nnet/bridge/br_netlink.c-1572-\t}\n--\nnet/bridge/br_netlink.c=1678=static int br_fill_info(struct sk_buff *skb, const struct net_device *brdev)\n--\nnet/bridge/br_netlink.c-1734-\t    nla_put_u8(skb, IFLA_BR_VLAN_STATS_ENABLED,\nnet/bridge/br_netlink.c:1735:\t\t       br_opt_get(br, BROPT_VLAN_STATS_ENABLED)) ||\nnet/bridge/br_netlink.c-1736-\t    nla_put_u8(skb, IFLA_BR_VLAN_STATS_PER_PORT,\nnet/bridge/br_netlink.c:1737:\t\t       br_opt_get(br, BROPT_VLAN_STATS_PER_PORT)))\nnet/bridge/br_netlink.c-1738-\t\treturn -EMSGSIZE;\n--\nnet/bridge/br_netlink.c-1743-\t    nla_put_u8(skb, IFLA_BR_MCAST_SNOOPING,\nnet/bridge/br_netlink.c:1744:\t\t       br_opt_get(br, BROPT_MULTICAST_ENABLED)) ||\nnet/bridge/br_netlink.c-1745-\t    nla_put_u8(skb, IFLA_BR_MCAST_QUERY_USE_IFADDR,\nnet/bridge/br_netlink.c:1746:\t\t       br_opt_get(br, BROPT_MULTICAST_QUERY_USE_IFADDR)) ||\nnet/bridge/br_netlink.c-1747-\t    nla_put_u8(skb, IFLA_BR_MCAST_QUERIER,\n--\nnet/bridge/br_netlink.c-1749-\t    nla_put_u8(skb, IFLA_BR_MCAST_STATS_ENABLED,\nnet/bridge/br_netlink.c:1750:\t\t       br_opt_get(br, BROPT_MULTICAST_STATS_ENABLED)) ||\nnet/bridge/br_netlink.c-1751-\t    nla_put_u32(skb, IFLA_BR_MCAST_HASH_ELASTICITY, RHT_ELASTICITY) ||\n--\nnet/bridge/br_netlink.c-1793-\tif (nla_put_u8(skb, IFLA_BR_NF_CALL_IPTABLES,\nnet/bridge/br_netlink.c:1794:\t\t       br_opt_get(br, BROPT_NF_CALL_IPTABLES) ? 1 : 0) ||\nnet/bridge/br_netlink.c-1795-\t    nla_put_u8(skb, IFLA_BR_NF_CALL_IP6TABLES,\nnet/bridge/br_netlink.c:1796:\t\t       br_opt_get(br, BROPT_NF_CALL_IP6TABLES) ? 1 : 0) ||\nnet/bridge/br_netlink.c-1797-\t    nla_put_u8(skb, IFLA_BR_NF_CALL_ARPTABLES,\nnet/bridge/br_netlink.c:1798:\t\t       br_opt_get(br, BROPT_NF_CALL_ARPTABLES) ? 1 : 0))\nnet/bridge/br_netlink.c-1799-\t\treturn -EMSGSIZE;\n--\nnet/bridge/br_private.h=757=static inline int br_afspec_cmd_to_rtm(int cmd)\n--\nnet/bridge/br_private.h-768-\nnet/bridge/br_private.h:769:static inline int br_opt_get(const struct net_bridge *br,\nnet/bridge/br_private.h-770-\t\t\t     enum net_bridge_opts opt)\n--\nnet/bridge/br_private.h=781=void br_boolopt_multi_get(const struct net_bridge *br,\nnet/bridge/br_private.h-782-\t\t\t  struct br_boolopt_multi *bm);\nnet/bridge/br_private.h:783:void br_opt_toggle(struct net_bridge *br, enum net_bridge_opts opt, bool on);\nnet/bridge/br_private.h-784-\n--\nnet/bridge/br_private.h=1158=__br_multicast_querier_exists(struct net_bridge_mcast *brmctx,\n--\nnet/bridge/br_private.h-1164-\tif (brmctx-\u003emulticast_querier) {\nnet/bridge/br_private.h:1165:\t\tif (is_ipv6 \u0026\u0026 !br_opt_get(brmctx-\u003ebr, BROPT_HAS_IPV6_ADDR))\nnet/bridge/br_private.h-1166-\t\t\town_querier_enabled = false;\n--\nnet/bridge/br_private.h=1263=br_multicast_ctx_vlan_global_disabled(const struct net_bridge_mcast *brmctx)\n--\nnet/bridge/br_private.h-1265-\treturn br_multicast_ctx_is_vlan(brmctx) \u0026\u0026\nnet/bridge/br_private.h:1266:\t       (!br_opt_get(brmctx-\u003ebr, BROPT_MCAST_VLAN_SNOOPING_ENABLED) ||\n\n"
}

23/3 2026/08/31 12:20 llm kmsan-evaluator
0m Model:
gemini-3.7-flash

Args:
null

Results:
null

Tokens:
							input: 18800
							output: 182
							thoughts: 133
						

Thoughts:
**KMSAN Assessment: A Clean Optimization**

Okay, so I've looked this over, and it's pretty clear-cut. This patch is all about tidying up the bridge's packet input path. The gist is removing the old dynamic frame handler system (`br_frame_type` and the linked list) and replacing it with direct, static checks against the bridge's `options` bitmask. We're talking `BROPT_CFM_ENABLED` and `BROPT_MRP_ENABLED` flags, nothing fancy.

From what I can see, this is a pure refactoring and optimization effort. There aren't any new structs being exposed to userspace, which is always a good thing. I can't spot any uninitialized memory reads or branches, and definitely no new buffer allocations or uninitialized fields. Given that, KMSAN is completely unnecessary here. We can safely set `NeedsKMSAN` to false. 

Alright, let's get that `set-results` call prepped and move on to the next one. This was a pretty simple assessment.



24/3 2026/08/31 12:20 tool set-results
0m Args:
{
  "KMSANReasoning": "The patch refactors the bridge subsystem's CFM (Connectivity Fault Management) and MRP (Media Redundancy Protocol) frame dispatch mechanism by replacing the dynamic frame-type linked list (`frame_type_list`) with bit flags in the existing bridge options bitmask (`BROPT_CFM_ENABLED` and `BROPT_MRP_ENABLED`). \n\nNo new structures, allocations, or data buffers are created or exported to user space. The logic relies on already-allocated and initialized bridge structures (`struct net_bridge`), toggling and checking existing bit flags. No uninitialized memory is read, branched on, or leaked to userspace. Standard KASAN/sanitizer configurations are sufficient to catch any regression. Dedicated KMSAN fuzzing is not required.",
  "NeedsKMSAN": false
}

Results:
{
  "KMSANReasoning": "The patch refactors the bridge subsystem's CFM (Connectivity Fault Management) and MRP (Media Redundancy Protocol) frame dispatch mechanism by replacing the dynamic frame-type linked list (`frame_type_list`) with bit flags in the existing bridge options bitmask (`BROPT_CFM_ENABLED` and `BROPT_MRP_ENABLED`). \n\nNo new structures, allocations, or data buffers are created or exported to user space. The logic relies on already-allocated and initialized bridge structures (`struct net_bridge`), toggling and checking existing bit flags. No uninitialized memory is read, branched on, or leaked to userspace. Standard KASAN/sanitizer configurations are sufficient to catch any regression. Dedicated KMSAN fuzzing is not required.",
  "NeedsKMSAN": false
}

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)