| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/09/21 11:31 | flow | patch-triage |
3mArgs:null Results: {
"EnableConfigs": [
"BRIDGE",
"BRIDGE_VLAN_FILTERING",
"BRIDGE_CFM",
"VLAN_8021Q"
],
"FocusSymbols": [
"br_fill_ifinfo",
"br_getlink",
"ndo_dflt_bridge_getlink",
"rtnl_bridge_getlink",
"rtnl_bridge_notify",
"rtnl_bridge_setlink",
"rtnl_bridge_dellink"
],
"KMSANReasoning": "The patch series plumbs a `netlink_ext_ack *extack` parameter through `ndo_bridge_getlink`, `ndo_dflt_bridge_getlink`, and several network device driver implementations. In `net/bridge/br_netlink.c`, it converts `nla_nest_end()` calls to `nla_nest_end_safe()` to guard against nested attribute length overflows (\u003e U16_MAX), reporting an error string via `NL_SET_ERR_MSG_MOD` on failure.\n\nThese changes do not allocate or copy any uninitialized heap, stack, or page memory, nor do they introduce struct padding leaks or conditional branching on uninitialized data. The extack message is a compile-time string literal. The bounds checking added via `nla_nest_end_safe()` strictly prevents attribute size truncation rather than enabling reads of uninitialized bytes. Thus, there are no uninitialized memory or info-leak risks that would necessitate a dedicated KMSAN fuzzing session.",
"NeedsKMSAN": false,
"Reasoning": "The patch modifies core networking and bridging code (net/bridge/br_netlink.c, net/core/rtnetlink.c) to validate nested netlink attribute sizes using nla_nest_end_safe() and return -E2BIG with extended ack errors when nested attributes exceed U16_MAX. It also threads netlink_ext_ack down through ndo_bridge_getlink and bridge netlink helper functions. These code paths are fully reachable in virtualized environments via netlink bridge queries and modifications (PF_BRIDGE RTM_GETLINK / RTM_SETLINK / RTM_DELLINK).",
"WorthFuzzing": true
} |
| 1/1 | 2026/09/21 11:31 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 284ebb15ce96705cc106dfbe5def8bcc3bf8fb2e\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Mon Sep 21 11:31:39 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c\nindex ca99f4b1a63c3..a752e66bf6368 100644\n--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c\n+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c\n@@ -16154,12 +16154,12 @@ static const struct udp_tunnel_nic_info bnxt_udp_tunnels = {\n \n static int bnxt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,\n \t\t\t struct net_device *dev, u32 filter_mask,\n-\t\t\t int nlflags)\n+\t\t\t int nlflags, struct netlink_ext_ack *extack)\n {\n \tstruct bnxt *bp = netdev_priv(dev);\n \n \treturn ndo_dflt_bridge_getlink(skb, pid, seq, dev, bp-\u003ebr_mode, 0, 0,\n-\t\t\t\t nlflags, filter_mask, NULL);\n+\t\t\t\t nlflags, filter_mask, NULL, extack);\n }\n \n static int bnxt_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,\ndiff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c\nindex ed302f5ec4768..cc9c87539a429 100644\n--- a/drivers/net/ethernet/emulex/benet/be_main.c\n+++ b/drivers/net/ethernet/emulex/benet/be_main.c\n@@ -5011,7 +5011,7 @@ static int be_ndo_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,\n \n static int be_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,\n \t\t\t\t struct net_device *dev, u32 filter_mask,\n-\t\t\t\t int nlflags)\n+\t\t\t\t int nlflags, struct netlink_ext_ack *extack)\n {\n \tstruct be_adapter *adapter = netdev_priv(dev);\n \tint status = 0;\n@@ -5037,7 +5037,7 @@ static int be_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,\n \treturn ndo_dflt_bridge_getlink(skb, pid, seq, dev,\n \t\t\t\t hsw_mode == PORT_FWD_TYPE_VEPA ?\n \t\t\t\t BRIDGE_MODE_VEPA : BRIDGE_MODE_VEB,\n-\t\t\t\t 0, 0, nlflags, filter_mask, NULL);\n+\t\t\t\t 0, 0, nlflags, filter_mask, NULL, extack);\n }\n \n static struct be_cmd_work *be_alloc_work(struct be_adapter *adapter,\ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c\nindex abbc71e815ae3..52c2b393aacd2 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_main.c\n+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c\n@@ -13151,6 +13151,7 @@ static int i40e_ndo_bridge_setlink(struct net_device *dev,\n * @dev: the netdev being configured\n * @filter_mask: unused\n * @nlflags: netlink flags passed in\n+ * @extack: netlink extended ack\n *\n * Return the mode in which the hardware bridge is operating in\n * i.e VEB or VEPA.\n@@ -13158,7 +13159,8 @@ static int i40e_ndo_bridge_setlink(struct net_device *dev,\n static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,\n \t\t\t\t struct net_device *dev,\n \t\t\t\t u32 __always_unused filter_mask,\n-\t\t\t\t int nlflags)\n+\t\t\t\t int nlflags,\n+\t\t\t\t struct netlink_ext_ack *extack)\n {\n \tstruct i40e_netdev_priv *np = netdev_priv(dev);\n \tstruct i40e_vsi *vsi = np-\u003evsi;\n@@ -13175,7 +13177,7 @@ static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,\n \t\treturn 0;\n \n \treturn ndo_dflt_bridge_getlink(skb, pid, seq, dev, veb-\u003ebridge_mode,\n-\t\t\t\t 0, 0, nlflags, filter_mask, NULL);\n+\t\t\t\t 0, 0, nlflags, filter_mask, NULL, extack);\n }\n \n /**\ndiff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c\nindex 707c7431b91a6..f98295438df78 100644\n--- a/drivers/net/ethernet/intel/ice/ice_main.c\n+++ b/drivers/net/ethernet/intel/ice/ice_main.c\n@@ -8095,12 +8095,14 @@ int ice_set_rss_hfunc(struct ice_vsi *vsi, u8 hfunc)\n * @dev: the netdev being configured\n * @filter_mask: filter mask passed in\n * @nlflags: netlink flags passed in\n+ * @extack: netlink extended ack\n *\n * Return the bridge mode (VEB/VEPA)\n */\n static int\n ice_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,\n-\t\t struct net_device *dev, u32 filter_mask, int nlflags)\n+\t\t struct net_device *dev, u32 filter_mask, int nlflags,\n+\t\t struct netlink_ext_ack *extack)\n {\n \tstruct ice_pf *pf = ice_netdev_to_pf(dev);\n \tu16 bmode;\n@@ -8108,7 +8110,7 @@ ice_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,\n \tbmode = pf-\u003efirst_sw-\u003ebridge_mode;\n \n \treturn ndo_dflt_bridge_getlink(skb, pid, seq, dev, bmode, 0, 0, nlflags,\n-\t\t\t\t filter_mask, NULL);\n+\t\t\t\t filter_mask, NULL, extack);\n }\n \n /**\ndiff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c\nindex f91856498eb2d..77dfd80a6e368 100644\n--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c\n+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c\n@@ -10726,7 +10726,8 @@ static int ixgbe_ndo_bridge_setlink(struct net_device *dev,\n \n static int ixgbe_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,\n \t\t\t\t struct net_device *dev,\n-\t\t\t\t u32 filter_mask, int nlflags)\n+\t\t\t\t u32 filter_mask, int nlflags,\n+\t\t\t\t struct netlink_ext_ack *extack)\n {\n \tstruct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);\n \n@@ -10735,7 +10736,7 @@ static int ixgbe_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,\n \n \treturn ndo_dflt_bridge_getlink(skb, pid, seq, dev,\n \t\t\t\t adapter-\u003ebridge_mode, 0, 0, nlflags,\n-\t\t\t\t filter_mask, NULL);\n+\t\t\t\t filter_mask, NULL, extack);\n }\n \n static void *ixgbe_fwd_add(struct net_device *pdev, struct net_device *vdev)\ndiff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c\nindex fc110a7d16e8d..53bf79dbe08de 100644\n--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c\n+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c\n@@ -5277,7 +5277,7 @@ static int mlx5e_xdp(struct net_device *dev, struct netdev_bpf *xdp)\n #ifdef CONFIG_MLX5_ESWITCH\n static int mlx5e_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,\n \t\t\t\tstruct net_device *dev, u32 filter_mask,\n-\t\t\t\tint nlflags)\n+\t\t\t\tint nlflags, struct netlink_ext_ack *extack)\n {\n \tstruct mlx5e_priv *priv = netdev_priv(dev);\n \tstruct mlx5_core_dev *mdev = priv-\u003emdev;\n@@ -5288,7 +5288,7 @@ static int mlx5e_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,\n \tmode = setting ? BRIDGE_MODE_VEPA : BRIDGE_MODE_VEB;\n \treturn ndo_dflt_bridge_getlink(skb, pid, seq, dev,\n \t\t\t\t mode,\n-\t\t\t\t 0, 0, nlflags, filter_mask, NULL);\n+\t\t\t\t 0, 0, nlflags, filter_mask, NULL, extack);\n }\n \n static int mlx5e_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,\ndiff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c\nindex 7928e76da723e..cb751dddb6887 100644\n--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c\n+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c\n@@ -2257,7 +2257,7 @@ static int nfp_net_set_mac_address(struct net_device *netdev, void *addr)\n \n static int nfp_net_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,\n \t\t\t\t struct net_device *dev, u32 filter_mask,\n-\t\t\t\t int nlflags)\n+\t\t\t\t int nlflags, struct netlink_ext_ack *extack)\n {\n \tstruct nfp_net *nn = netdev_priv(dev);\n \tu16 mode;\n@@ -2269,7 +2269,7 @@ static int nfp_net_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,\n \t BRIDGE_MODE_VEPA : BRIDGE_MODE_VEB;\n \n \treturn ndo_dflt_bridge_getlink(skb, pid, seq, dev, mode, 0, 0,\n-\t\t\t\t nlflags, filter_mask, NULL);\n+\t\t\t\t nlflags, filter_mask, NULL, extack);\n }\n \n static int nfp_net_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,\ndiff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c\nindex 2935c2ecc314b..f960cf5a97a29 100644\n--- a/drivers/s390/net/qeth_l2_main.c\n+++ b/drivers/s390/net/qeth_l2_main.c\n@@ -935,7 +935,7 @@ static void qeth_l2_br2dev_put(void)\n \n static int qeth_l2_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,\n \t\t\t\t struct net_device *dev, u32 filter_mask,\n-\t\t\t\t int nlflags)\n+\t\t\t\t int nlflags, struct netlink_ext_ack *extack)\n {\n \tstruct qeth_priv *priv = netdev_priv(dev);\n \tstruct qeth_card *card = dev-\u003eml_priv;\n@@ -949,7 +949,7 @@ static int qeth_l2_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,\n \treturn ndo_dflt_bridge_getlink(skb, pid, seq, dev,\n \t\t\t\t mode, priv-\u003ebrport_features,\n \t\t\t\t priv-\u003ebrport_hw_features,\n-\t\t\t\t nlflags, filter_mask, NULL);\n+\t\t\t\t nlflags, filter_mask, NULL, extack);\n }\n \n static const struct nla_policy qeth_brport_policy[IFLA_BRPORT_MAX + 1] = {\ndiff --git a/include/linux/netdevice.h b/include/linux/netdevice.h\nindex 1f0710eef185b..02238b1e33453 100644\n--- a/include/linux/netdevice.h\n+++ b/include/linux/netdevice.h\n@@ -1360,7 +1360,7 @@ struct netdev_net_notifier {\n *\t\t\t u16 flags, struct netlink_ext_ack *extack)\n * int (*ndo_bridge_getlink)(struct sk_buff *skb, u32 pid, u32 seq,\n *\t\t\t struct net_device *dev, u32 filter_mask,\n- *\t\t\t int nlflags)\n+ *\t\t\t int nlflags, struct netlink_ext_ack *extack)\n * int (*ndo_bridge_dellink)(struct net_device *dev, struct nlmsghdr *nlh,\n *\t\t\t u16 flags);\n *\n@@ -1659,7 +1659,8 @@ struct net_device_ops {\n \t\t\t\t\t\t u32 pid, u32 seq,\n \t\t\t\t\t\t struct net_device *dev,\n \t\t\t\t\t\t u32 filter_mask,\n-\t\t\t\t\t\t int nlflags);\n+\t\t\t\t\t\t int nlflags,\n+\t\t\t\t\t\t struct netlink_ext_ack *extack);\n \tint\t\t\t(*ndo_bridge_dellink)(struct net_device *dev,\n \t\t\t\t\t\t struct nlmsghdr *nlh,\n \t\t\t\t\t\t u16 flags);\ndiff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h\nindex 95729339e7a54..a408c36a7b558 100644\n--- a/include/linux/rtnetlink.h\n+++ b/include/linux/rtnetlink.h\n@@ -222,7 +222,8 @@ extern int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,\n \t\t\t\t u32 filter_mask,\n \t\t\t\t int (*vlan_fill)(struct sk_buff *skb,\n \t\t\t\t\t\t struct net_device *dev,\n-\t\t\t\t\t\t u32 filter_mask));\n+\t\t\t\t\t\t u32 filter_mask),\n+\t\t\t\t struct netlink_ext_ack *extack);\n \n extern void rtnl_offload_xstats_notify(struct net_device *dev);\n \ndiff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c\nindex ae76df0de05a0..fbd91b86d4268 100644\n--- a/net/bridge/br_netlink.c\n+++ b/net/bridge/br_netlink.c\n@@ -459,7 +459,7 @@ static int br_fill_ifinfo(struct sk_buff *skb,\n \t\t\t const struct net_bridge_port *port,\n \t\t\t u32 pid, u32 seq, int event, unsigned int flags,\n \t\t\t u32 filter_mask, const struct net_device *dev,\n-\t\t\t bool getlink)\n+\t\t\t bool getlink, struct netlink_ext_ack *extack)\n {\n \tu8 operstate = netif_running(dev) ? READ_ONCE(dev-\u003eoperstate) :\n \t\t\t\t\t IF_OPER_DOWN;\n@@ -588,7 +588,8 @@ static int br_fill_ifinfo(struct sk_buff *skb,\n \t\t\t\tgoto nla_put_failure;\n \t\t}\n \n-\t\tnla_nest_end(skb, cfm_nest);\n+\t\tif (nla_nest_end_safe(skb, cfm_nest) \u003c 0)\n+\t\t\tgoto nla_nest_too_large;\n \t}\n \n \tif ((filter_mask \u0026 RTEXT_FILTER_MST) \u0026\u0026\n@@ -608,20 +609,27 @@ static int br_fill_ifinfo(struct sk_buff *skb,\n \t\tif (err)\n \t\t\tgoto nla_put_failure;\n \n-\t\tnla_nest_end(skb, mst_nest);\n+\t\tif (nla_nest_end_safe(skb, mst_nest) \u003c 0)\n+\t\t\tgoto nla_nest_too_large;\n \t}\n \n done:\n \tif (af) {\n-\t\tif (nlmsg_get_pos(skb) - (void *)af \u003e nla_attr_size(0))\n-\t\t\tnla_nest_end(skb, af);\n-\t\telse\n+\t\tif (nla_nest_end_safe(skb, af) \u003c 0)\n+\t\t\tgoto nla_nest_too_large;\n+\t\tif (!nla_len(af))\n \t\t\tnla_nest_cancel(skb, af);\n \t}\n \n \tnlmsg_end(skb, nlh);\n \treturn 0;\n \n+nla_nest_too_large:\n+\tNL_SET_ERR_MSG_MOD(extack,\n+\t\t\t \"AF_SPEC info too large, use per-object dumps (e.g. RTM_GETVLAN)\");\n+\tnlmsg_cancel(skb, nlh);\n+\treturn -E2BIG;\n+\n nla_put_failure:\n \tnlmsg_cancel(skb, nlh);\n \treturn -EMSGSIZE;\n@@ -654,7 +662,8 @@ void br_info_notify(int event, const struct net_bridge *br,\n \tif (skb == NULL)\n \t\tgoto errout;\n \n-\terr = br_fill_ifinfo(skb, port, 0, 0, event, 0, filter, dev, false);\n+\terr = br_fill_ifinfo(skb, port, 0, 0, event, 0, filter, dev, false,\n+\t\t\t NULL);\n \tif (err \u003c 0) {\n \t\t/* -EMSGSIZE implies BUG in br_nlmsg_size() */\n \t\tWARN_ON(err == -EMSGSIZE);\n@@ -680,7 +689,8 @@ void br_ifinfo_notify(int event, const struct net_bridge *br,\n * Dump information about all ports, in response to GETLINK\n */\n int br_getlink(struct sk_buff *skb, u32 pid, u32 seq,\n-\t struct net_device *dev, u32 filter_mask, int nlflags)\n+\t struct net_device *dev, u32 filter_mask, int nlflags,\n+\t struct netlink_ext_ack *extack)\n {\n \tstruct net_bridge_port *port = br_port_get_rtnl(dev);\n \n@@ -692,7 +702,7 @@ int br_getlink(struct sk_buff *skb, u32 pid, u32 seq,\n \t\treturn 0;\n \n \treturn br_fill_ifinfo(skb, port, pid, seq, RTM_NEWLINK, nlflags,\n-\t\t\t filter_mask, dev, true);\n+\t\t\t filter_mask, dev, true, extack);\n }\n \n static int br_vlan_info(struct net_bridge *br, struct net_bridge_port *p,\ndiff --git a/net/bridge/br_private.h b/net/bridge/br_private.h\nindex 09c397e303307..edbe7a1f57363 100644\n--- a/net/bridge/br_private.h\n+++ b/net/bridge/br_private.h\n@@ -2179,7 +2179,7 @@ int br_setlink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags,\n \t struct netlink_ext_ack *extack);\n int br_dellink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags);\n int br_getlink(struct sk_buff *skb, u32 pid, u32 seq, struct net_device *dev,\n-\t u32 filter_mask, int nlflags);\n+\t u32 filter_mask, int nlflags, struct netlink_ext_ack *extack);\n int br_process_vlan_info(struct net_bridge *br,\n \t\t\t struct net_bridge_port *p, int cmd,\n \t\t\t struct bridge_vlan_info *vinfo_curr,\ndiff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c\nindex e3444fd240615..a341e06f47d31 100644\n--- a/net/core/rtnetlink.c\n+++ b/net/core/rtnetlink.c\n@@ -5420,7 +5420,8 @@ int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,\n \t\t\t u32 filter_mask,\n \t\t\t int (*vlan_fill)(struct sk_buff *skb,\n \t\t\t\t\t struct net_device *dev,\n-\t\t\t\t\t u32 filter_mask))\n+\t\t\t\t\t u32 filter_mask),\n+\t\t\t struct netlink_ext_ack *extack)\n {\n \tstruct nlmsghdr *nlh;\n \tstruct ifinfomsg *ifm;\n@@ -5596,7 +5597,8 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)\n \t\t\tif (idx \u003e= cb-\u003eargs[0]) {\n \t\t\t\terr = br_dev-\u003enetdev_ops-\u003endo_bridge_getlink(\n \t\t\t\t\t\tskb, portid, seq, dev,\n-\t\t\t\t\t\tfilter_mask, NLM_F_MULTI);\n+\t\t\t\t\t\tfilter_mask, NLM_F_MULTI,\n+\t\t\t\t\t\tcb-\u003eextack);\n \t\t\t\tif (err \u003c 0 \u0026\u0026 err != -EOPNOTSUPP) {\n \t\t\t\t\tif (likely(skb-\u003elen))\n \t\t\t\t\t\tbreak;\n@@ -5612,7 +5614,8 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)\n \t\t\t\terr = ops-\u003endo_bridge_getlink(skb, portid,\n \t\t\t\t\t\t\t seq, dev,\n \t\t\t\t\t\t\t filter_mask,\n-\t\t\t\t\t\t\t NLM_F_MULTI);\n+\t\t\t\t\t\t\t NLM_F_MULTI,\n+\t\t\t\t\t\t\t cb-\u003eextack);\n \t\t\t\tif (err \u003c 0 \u0026\u0026 err != -EOPNOTSUPP) {\n \t\t\t\t\tif (likely(skb-\u003elen))\n \t\t\t\t\t\tbreak;\n@@ -5646,7 +5649,8 @@ static inline size_t bridge_nlmsg_size(void)\n \t\t+ nla_total_size(sizeof(u16));\t/* IFLA_BRIDGE_MODE */\n }\n \n-static int rtnl_bridge_notify(struct net_device *dev)\n+static int rtnl_bridge_notify(struct net_device *dev,\n+\t\t\t struct netlink_ext_ack *extack)\n {\n \tstruct net *net = dev_net(dev);\n \tstruct sk_buff *skb;\n@@ -5661,7 +5665,7 @@ static int rtnl_bridge_notify(struct net_device *dev)\n \t\tgoto errout;\n \t}\n \n-\terr = dev-\u003enetdev_ops-\u003endo_bridge_getlink(skb, 0, 0, dev, 0, 0);\n+\terr = dev-\u003enetdev_ops-\u003endo_bridge_getlink(skb, 0, 0, dev, 0, 0, extack);\n \tif (err \u003c 0)\n \t\tgoto errout;\n \n@@ -5752,7 +5756,7 @@ static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,\n \t\t\t/* Generate event to notify upper layer of bridge\n \t\t\t * change\n \t\t\t */\n-\t\t\terr = rtnl_bridge_notify(dev);\n+\t\t\terr = rtnl_bridge_notify(dev, extack);\n \t\t}\n \t}\n \n@@ -5827,7 +5831,7 @@ static int rtnl_bridge_dellink(struct sk_buff *skb, struct nlmsghdr *nlh,\n \t\t\t/* Generate event to notify upper layer of bridge\n \t\t\t * change\n \t\t\t */\n-\t\t\terr = rtnl_bridge_notify(dev);\n+\t\t\terr = rtnl_bridge_notify(dev, extack);\n \t\t}\n \t}\n \n"
} |
| 2/1 | 2026/09/21 11:31 | agent | patch-evaluator |
2mModel:core Args: null Results: {
"EnableConfigs": [
"BRIDGE",
"BRIDGE_VLAN_FILTERING",
"BRIDGE_CFM",
"VLAN_8021Q"
],
"FocusSymbols": [
"br_fill_ifinfo",
"br_getlink",
"ndo_dflt_bridge_getlink",
"rtnl_bridge_getlink",
"rtnl_bridge_notify",
"rtnl_bridge_setlink",
"rtnl_bridge_dellink"
],
"Reasoning": "The patch modifies core networking and bridging code (net/bridge/br_netlink.c, net/core/rtnetlink.c) to validate nested netlink attribute sizes using nla_nest_end_safe() and return -E2BIG with extended ack errors when nested attributes exceed U16_MAX. It also threads netlink_ext_ack down through ndo_bridge_getlink and bridge netlink helper functions. These code paths are fully reachable in virtualized environments via netlink bridge queries and modifications (PF_BRIDGE RTM_GETLINK / RTM_SETLINK / RTM_DELLINK).",
"WorthFuzzing": true
}Instruction: You are an expert Linux kernel maintainer and security engineer.
Your job is to review a provided patch series and evaluate whether it warrants fuzzing with syzkaller.
IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on internal assumptions. You must actively use your code access
tools to inspect the actual source code, callers, and surrounding context.
================================================================================
1. CORE TRIAGE PHILOSOPHY
================================================================================
The goal of patch fuzzing is to discover crashes, regressions, exposed latent bugs,
and newly triggered assertions introduced by the patch series.
- REACHABILITY IS THE PRIMARY GATE:
Fuzzing can only discover bugs in code that can actually execute in standard virtualized
environments (GCE or QEMU, utilizing software-emulated devices like USB gadgets, netdev, tun/tap).
If the modified code is structurally unreachable (see Section 2), it MUST NOT be fuzzed,
regardless of whether it adds assertions or complex logic.
- DO NOT BLINDLY TRUST "NO FUNCTIONAL CHANGE" (NFCI) OR "REFACTORING" CLAIMS:
Patch authors routinely label changes as "cleanups", "refactorings", or state
"No functional change intended". Do NOT take these claims at face value.
Code refactorings that rearrange logic, introduce helper functions, or alter state management
in core subsystems frequently introduce subtle semantic shifts or uncover latent kernel bugs.
If reachable executable code is modified or refactored, it MUST be fuzzed.
- NEW OR MODIFIED ASSERTIONS IN REACHABLE CODE MUST BE FUZZED:
When a patch introduces or modifies runtime checks or assertions (e.g., WARN_ON*, VM_WARN_ON*,
BUG_ON*, lockdep_assert*) in reachable code paths, it enforces new or stricter invariants.
Even if the author believes the invariant always holds, fuzzing is essential to verify whether
an unusual sequence of operations can violate it.
================================================================================
2. WHEN TO RETURN WorthFuzzing=false (NEGATIVE CRITERIA)
================================================================================
Return WorthFuzzing=false ONLY IF all modified code falls strictly into one or more of these categories:
- Non-kernel and non-executable changes:
* Modifications to Documentation/, comments, or spelling fixes.
* User-space directories, self-tests, samples, or scripts (e.g., tools/, samples/, scripts/, usr/)
that do not affect the compiled kernel image (vmlinux) or kernel modules.
* Purely decorative logging (e.g., message strings in pr_err, printk, dev_info) or tracepoints
that do not alter control flow or data structures.
* Build system or Kconfig changes that do not alter compiled C logic.
- Structurally unreachable hardware:
* Vendor-specific PCIe switches, SmartNICs, or GPU drivers (e.g., mlxsw, pds_core, qed,
ionic, amdgpu) requiring physical ASIC/PCIe cards not emulated in standard QEMU.
- Unreachable execution paths:
* Driver teardown callbacks (.remove, .shutdown, pci_unregister_driver) executed only during
physical PCI hot-unplug or manual sysfs driver unbinding.
* Code paths exclusive to architectures other than the target architecture.
================================================================================
3. WHEN TO RETURN WorthFuzzing=true (POSITIVE CRITERIA)
================================================================================
Return WorthFuzzing=true whenever the patch touches reachable executable code, including:
- Core Subsystems:
* Any logic modifications in memory management (mm/), synchronization/locking (kernel/locking/),
BPF, scheduler, core networking, VFS, or syscall handling.
- Refactorings and Code Cleanups:
* Any restructuring of reachable data structures, helper abstractions, or algorithm flows.
- Runtime Assertions and Defensive Checks:
* Any introduction or alteration of assertions (WARN_ON*, VM_WARN_ON*, BUG_ON*, etc.) in reachable paths.
- Reachable Drivers and Protocols:
* Drivers accessible via virtual buses (virtio, USB gadget, loopback, netlink, binder, sockets, etc.).
================================================================================
4. EXTRACTING FocusSymbols (PREVENTING DILUTION)
================================================================================
When WorthFuzzing=true, you must extract specific kernel functions into FocusSymbols to guide the fuzzer:
- AVOID UBIQUITOUS LIFECYCLE HOT-PATHS:
Do NOT list generic, ubiquitous functions called by almost every program in the corpus
(including, but not limited to: general memory allocators and deallocators, page fault
and trap handlers, or core synchronization primitives; this is not an exhaustive list).
Listing ubiquitous functions causes the fuzzer to classify thousands of unrelated tests as "focused",
which severely dilutes fuzzing effort away from the actual changes.
- TARGET SPECIFIC FEATURE LOGIC AND ENTRYPOINTS:
List functions that specifically implement the logic being added or altered, or direct API entrypoints
for the subsystem feature under review.
- HANDLING STATIC INLINE FUNCTIONS IN HEADERS (.h):
Compiler-inlined static functions (such as static inlines in mm/*.h or include/linux/*.h) lack
distinct symbol addresses in vmlinux and cannot be targeted directly by symbol coverage filters.
If the changes are primarily in static inline helpers, identify non-static, feature-specific caller
functions in .c files that exercise them (avoiding ubiquitous lifecycle wrappers).
================================================================================
5. IDENTIFYING EnableConfigs
================================================================================
Identify any specific CONFIG_ options required to properly compile and reach the modified code:
- Inspect Kconfig files and #ifdef guards; do not make assumptions.
- Check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed.
- Strip any '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: Target architecture: amd64
For your convenience, here is the diff of the changes:
commit 284ebb15ce96705cc106dfbe5def8bcc3bf8fb2e
Author: syz-cluster <triage@syzkaller.com>
Date: Mon Sep 21 11:31:39 2026 +0000
syz-cluster: applied patch under review
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index ca99f4b1a63c3..a752e66bf6368 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -16154,12 +16154,12 @@ static const struct udp_tunnel_nic_info bnxt_udp_tunnels = {
static int bnxt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
struct net_device *dev, u32 filter_mask,
- int nlflags)
+ int nlflags, struct netlink_ext_ack *extack)
{
struct bnxt *bp = netdev_priv(dev);
return ndo_dflt_bridge_getlink(skb, pid, seq, dev, bp->br_mode, 0, 0,
- nlflags, filter_mask, NULL);
+ nlflags, filter_mask, NULL, extack);
}
static int bnxt_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index ed302f5ec4768..cc9c87539a429 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -5011,7 +5011,7 @@ static int be_ndo_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
static int be_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
struct net_device *dev, u32 filter_mask,
- int nlflags)
+ int nlflags, struct netlink_ext_ack *extack)
{
struct be_adapter *adapter = netdev_priv(dev);
int status = 0;
@@ -5037,7 +5037,7 @@ static int be_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
return ndo_dflt_bridge_getlink(skb, pid, seq, dev,
hsw_mode == PORT_FWD_TYPE_VEPA ?
BRIDGE_MODE_VEPA : BRIDGE_MODE_VEB,
- 0, 0, nlflags, filter_mask, NULL);
+ 0, 0, nlflags, filter_mask, NULL, extack);
}
static struct be_cmd_work *be_alloc_work(struct be_adapter *adapter,
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index abbc71e815ae3..52c2b393aacd2 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -13151,6 +13151,7 @@ static int i40e_ndo_bridge_setlink(struct net_device *dev,
* @dev: the netdev being configured
* @filter_mask: unused
* @nlflags: netlink flags passed in
+ * @extack: netlink extended ack
*
* Return the mode in which the hardware bridge is operating in
* i.e VEB or VEPA.
@@ -13158,7 +13159,8 @@ static int i40e_ndo_bridge_setlink(struct net_device *dev,
static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
struct net_device *dev,
u32 __always_unused filter_mask,
- int nlflags)
+ int nlflags,
+ struct netlink_ext_ack *extack)
{
struct i40e_netdev_priv *np = netdev_priv(dev);
struct i40e_vsi *vsi = np->vsi;
@@ -13175,7 +13177,7 @@ static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
return 0;
return ndo_dflt_bridge_getlink(skb, pid, seq, dev, veb->bridge_mode,
- 0, 0, nlflags, filter_mask, NULL);
+ 0, 0, nlflags, filter_mask, NULL, extack);
}
/**
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 707c7431b91a6..f98295438df78 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -8095,12 +8095,14 @@ int ice_set_rss_hfunc(struct ice_vsi *vsi, u8 hfunc)
* @dev: the netdev being configured
* @filter_mask: filter mask passed in
* @nlflags: netlink flags passed in
+ * @extack: netlink extended ack
*
* Return the bridge mode (VEB/VEPA)
*/
static int
ice_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
- struct net_device *dev, u32 filter_mask, int nlflags)
+ struct net_device *dev, u32 filter_mask, int nlflags,
+ struct netlink_ext_ack *extack)
{
struct ice_pf *pf = ice_netdev_to_pf(dev);
u16 bmode;
@@ -8108,7 +8110,7 @@ ice_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
bmode = pf->first_sw->bridge_mode;
return ndo_dflt_bridge_getlink(skb, pid, seq, dev, bmode, 0, 0, nlflags,
- filter_mask, NULL);
+ filter_mask, NULL, extack);
}
/**
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index f91856498eb2d..77dfd80a6e368 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -10726,7 +10726,8 @@ static int ixgbe_ndo_bridge_setlink(struct net_device *dev,
static int ixgbe_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
struct net_device *dev,
- u32 filter_mask, int nlflags)
+ u32 filter_mask, int nlflags,
+ struct netlink_ext_ack *extack)
{
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
@@ -10735,7 +10736,7 @@ static int ixgbe_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
return ndo_dflt_bridge_getlink(skb, pid, seq, dev,
adapter->bridge_mode, 0, 0, nlflags,
- filter_mask, NULL);
+ filter_mask, NULL, extack);
}
static void *ixgbe_fwd_add(struct net_device *pdev, struct net_device *vdev)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index fc110a7d16e8d..53bf79dbe08de 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -5277,7 +5277,7 @@ static int mlx5e_xdp(struct net_device *dev, struct netdev_bpf *xdp)
#ifdef CONFIG_MLX5_ESWITCH
static int mlx5e_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
struct net_device *dev, u32 filter_mask,
- int nlflags)
+ int nlflags, struct netlink_ext_ack *extack)
{
struct mlx5e_priv *priv = netdev_priv(dev);
struct mlx5_core_dev *mdev = priv->mdev;
@@ -5288,7 +5288,7 @@ static int mlx5e_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
mode = setting ? BRIDGE_MODE_VEPA : BRIDGE_MODE_VEB;
return ndo_dflt_bridge_getlink(skb, pid, seq, dev,
mode,
- 0, 0, nlflags, filter_mask, NULL);
+ 0, 0, nlflags, filter_mask, NULL, extack);
}
static int mlx5e_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 7928e76da723e..cb751dddb6887 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -2257,7 +2257,7 @@ static int nfp_net_set_mac_address(struct net_device *netdev, void *addr)
static int nfp_net_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
struct net_device *dev, u32 filter_mask,
- int nlflags)
+ int nlflags, struct netlink_ext_ack *extack)
{
struct nfp_net *nn = netdev_priv(dev);
u16 mode;
@@ -2269,7 +2269,7 @@ static int nfp_net_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
BRIDGE_MODE_VEPA : BRIDGE_MODE_VEB;
return ndo_dflt_bridge_getlink(skb, pid, seq, dev, mode, 0, 0,
- nlflags, filter_mask, NULL);
+ nlflags, filter_mask, NULL, extack);
}
static int nfp_net_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index 2935c2ecc314b..f960cf5a97a29 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -935,7 +935,7 @@ static void qeth_l2_br2dev_put(void)
static int qeth_l2_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
struct net_device *dev, u32 filter_mask,
- int nlflags)
+ int nlflags, struct netlink_ext_ack *extack)
{
struct qeth_priv *priv = netdev_priv(dev);
struct qeth_card *card = dev->ml_priv;
@@ -949,7 +949,7 @@ static int qeth_l2_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
return ndo_dflt_bridge_getlink(skb, pid, seq, dev,
mode, priv->brport_features,
priv->brport_hw_features,
- nlflags, filter_mask, NULL);
+ nlflags, filter_mask, NULL, extack);
}
static const struct nla_policy qeth_brport_policy[IFLA_BRPORT_MAX + 1] = {
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 1f0710eef185b..02238b1e33453 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1360,7 +1360,7 @@ struct netdev_net_notifier {
* u16 flags, struct netlink_ext_ack *extack)
* int (*ndo_bridge_getlink)(struct sk_buff *skb, u32 pid, u32 seq,
* struct net_device *dev, u32 filter_mask,
- * int nlflags)
+ * int nlflags, struct netlink_ext_ack *extack)
* int (*ndo_bridge_dellink)(struct net_device *dev, struct nlmsghdr *nlh,
* u16 flags);
*
@@ -1659,7 +1659,8 @@ struct net_device_ops {
u32 pid, u32 seq,
struct net_device *dev,
u32 filter_mask,
- int nlflags);
+ int nlflags,
+ struct netlink_ext_ack *extack);
int (*ndo_bridge_dellink)(struct net_device *dev,
struct nlmsghdr *nlh,
u16 flags);
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 95729339e7a54..a408c36a7b558 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -222,7 +222,8 @@ extern int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
u32 filter_mask,
int (*vlan_fill)(struct sk_buff *skb,
struct net_device *dev,
- u32 filter_mask));
+ u32 filter_mask),
+ struct netlink_ext_ack *extack);
extern void rtnl_offload_xstats_notify(struct net_device *dev);
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index ae76df0de05a0..fbd91b86d4268 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -459,7 +459,7 @@ static int br_fill_ifinfo(struct sk_buff *skb,
const struct net_bridge_port *port,
u32 pid, u32 seq, int event, unsigned int flags,
u32 filter_mask, const struct net_device *dev,
- bool getlink)
+ bool getlink, struct netlink_ext_ack *extack)
{
u8 operstate = netif_running(dev) ? READ_ONCE(dev->operstate) :
IF_OPER_DOWN;
@@ -588,7 +588,8 @@ static int br_fill_ifinfo(struct sk_buff *skb,
goto nla_put_failure;
}
- nla_nest_end(skb, cfm_nest);
+ if (nla_nest_end_safe(skb, cfm_nest) < 0)
+ goto nla_nest_too_large;
}
if ((filter_mask & RTEXT_FILTER_MST) &&
@@ -608,20 +609,27 @@ static int br_fill_ifinfo(struct sk_buff *skb,
if (err)
goto nla_put_failure;
- nla_nest_end(skb, mst_nest);
+ if (nla_nest_end_safe(skb, mst_nest) < 0)
+ goto nla_nest_too_large;
}
done:
if (af) {
- if (nlmsg_get_pos(skb) - (void *)af > nla_attr_size(0))
- nla_nest_end(skb, af);
- else
+ if (nla_nest_end_safe(skb, af) < 0)
+ goto nla_nest_too_large;
+ if (!nla_len(af))
nla_nest_cancel(skb, af);
}
nlmsg_end(skb, nlh);
return 0;
+nla_nest_too_large:
+ NL_SET_ERR_MSG_MOD(extack,
+ "AF_SPEC info too large, use per-object dumps (e.g. RTM_GETVLAN)");
+ nlmsg_cancel(skb, nlh);
+ return -E2BIG;
+
nla_put_failure:
nlmsg_cancel(skb, nlh);
return -EMSGSIZE;
@@ -654,7 +662,8 @@ void br_info_notify(int event, const struct net_bridge *br,
if (skb == NULL)
goto errout;
- err = br_fill_ifinfo(skb, port, 0, 0, event, 0, filter, dev, false);
+ err = br_fill_ifinfo(skb, port, 0, 0, event, 0, filter, dev, false,
+ NULL);
if (err < 0) {
/* -EMSGSIZE implies BUG in br_nlmsg_size() */
WARN_ON(err == -EMSGSIZE);
@@ -680,7 +689,8 @@ void br_ifinfo_notify(int event, const struct net_bridge *br,
* Dump information about all ports, in response to GETLINK
*/
int br_getlink(struct sk_buff *skb, u32 pid, u32 seq,
- struct net_device *dev, u32 filter_mask, int nlflags)
+ struct net_device *dev, u32 filter_mask, int nlflags,
+ struct netlink_ext_ack *extack)
{
struct net_bridge_port *port = br_port_get_rtnl(dev);
@@ -692,7 +702,7 @@ int br_getlink(struct sk_buff *skb, u32 pid, u32 seq,
return 0;
return br_fill_ifinfo(skb, port, pid, seq, RTM_NEWLINK, nlflags,
- filter_mask, dev, true);
+ filter_mask, dev, true, extack);
}
static int br_vlan_info(struct net_bridge *br, struct net_bridge_port *p,
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 09c397e303307..edbe7a1f57363 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -2179,7 +2179,7 @@ int br_setlink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags,
struct netlink_ext_ack *extack);
int br_dellink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags);
int br_getlink(struct sk_buff *skb, u32 pid, u32 seq, struct net_device *dev,
- u32 filter_mask, int nlflags);
+ u32 filter_mask, int nlflags, struct netlink_ext_ack *extack);
int br_process_vlan_info(struct net_bridge *br,
struct net_bridge_port *p, int cmd,
struct bridge_vlan_info *vinfo_curr,
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index e3444fd240615..a341e06f47d31 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -5420,7 +5420,8 @@ int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
u32 filter_mask,
int (*vlan_fill)(struct sk_buff *skb,
struct net_device *dev,
- u32 filter_mask))
+ u32 filter_mask),
+ struct netlink_ext_ack *extack)
{
struct nlmsghdr *nlh;
struct ifinfomsg *ifm;
@@ -5596,7 +5597,8 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
if (idx >= cb->args[0]) {
err = br_dev->netdev_ops->ndo_bridge_getlink(
skb, portid, seq, dev,
- filter_mask, NLM_F_MULTI);
+ filter_mask, NLM_F_MULTI,
+ cb->extack);
if (err < 0 && err != -EOPNOTSUPP) {
if (likely(skb->len))
break;
@@ -5612,7 +5614,8 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
err = ops->ndo_bridge_getlink(skb, portid,
seq, dev,
filter_mask,
- NLM_F_MULTI);
+ NLM_F_MULTI,
+ cb->extack);
if (err < 0 && err != -EOPNOTSUPP) {
if (likely(skb->len))
break;
@@ -5646,7 +5649,8 @@ static inline size_t bridge_nlmsg_size(void)
+ nla_total_size(sizeof(u16)); /* IFLA_BRIDGE_MODE */
}
-static int rtnl_bridge_notify(struct net_device *dev)
+static int rtnl_bridge_notify(struct net_device *dev,
+ struct netlink_ext_ack *extack)
{
struct net *net = dev_net(dev);
struct sk_buff *skb;
@@ -5661,7 +5665,7 @@ static int rtnl_bridge_notify(struct net_device *dev)
goto errout;
}
- err = dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev, 0, 0);
+ err = dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev, 0, 0, extack);
if (err < 0)
goto errout;
@@ -5752,7 +5756,7 @@ static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
/* Generate event to notify upper layer of bridge
* change
*/
- err = rtnl_bridge_notify(dev);
+ err = rtnl_bridge_notify(dev, extack);
}
}
@@ -5827,7 +5831,7 @@ static int rtnl_bridge_dellink(struct sk_buff *skb, struct nlmsghdr *nlh,
/* Generate event to notify upper layer of bridge
* change
*/
- err = rtnl_bridge_notify(dev);
+ err = rtnl_bridge_notify(dev, extack);
}
}
|
| 3/2 | 2026/09/21 11:31 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 9431 output: 38 thoughts: 1425 Thoughts: **Analyzing the Bridge Netlink Patch** Okay, let's dive into this patch. My initial assessment is that it looks like a concerted effort to enhance error reporting, specifically related to bridge information retrieval via Netlink. It's a broad touch, modifying several drivers and core networking components. First, I see a clear pattern: the addition of `struct netlink_ext_ack *extack` to various `*bridge_getlink` functions across several Ethernet drivers (bnxt, benet, i40e, ice, ixgbe, mlx5, nfp, and qeth). These drivers are implementing bridge-specific link information retrieval. They are now all passing this new extended acknowledgement structure to the core `ndo_dflt_bridge_getlink`. This immediately tells me the intention is to provide a more granular way to report errors during bridge configuration and information retrieval, potentially within the `ndo_dflt_bridge_getlink` function itself. I need to understand what this `extack` structure will provide. Next, I see a few key updates: `netdevice.h` and `rtnetlink.h` are updated to reflect the new API and function signature. This is expected. Now, looking at `net/bridge/br_netlink.c`, the changes within `br_fill_ifinfo` are intriguing. The original use of `nla_nest_end` is replaced with `nla_nest_end_safe`, which is definitely a security-focused change. The introduction of `nla_nest_too_large` and the `NL_SET_ERR_MSG_MOD` macro suggests this is to handle cases where the returned nested attribute data exceeds the buffer size, preventing potential buffer overflows. The message indicates we're addressing issues with the `AF_SPEC` info, meaning Address Family specific data, for the bridge interface. It suggests that if data is too large, the kernel will suggest to use per-object dumps, like RTM_GETVLAN. The fact that the `extack` is passed all the way down to `br_fill_ifinfo` means any errors detected there can be propagated back to the user space via the Netlink message. The usage of `nlmsg_cancel` and the error code `-E2BIG` is standard practice when a message construction fails. I also observe the updates in `br_getlink`, where `extack` is now passed to `br_fill_ifinfo`. `br_info_notify` passes `NULL` for `extack`. This indicates that `br_getlink` is responsible for reporting extended error information when retrieving a link, but `br_info_notify`, which probably deals with notifications, doesn't need to. Finally, in `net/core/rtnetlink.c`, it's clear the changes ripple through the core Netlink handling. `ndo_dflt_bridge_getlink` is updated. `rtnl_bridge_getlink`, `rtnl_bridge_notify`, `rtnl_bridge_setlink`, and `rtnl_bridge_dellink` all now correctly use the `extack` mechanism to manage and pass the extended acknowledgement structure. The call flow, if I understand it correctly, is: user-space Netlink request, calling `rtnl_bridge_*`, which then call `ndo_bridge_getlink`, passing down to the driver, and finally, error reporting through the `extack`. The fact that this touches `net/bridge` and `net/core/rtnetlink` is significant. These are fundamental networking components. The bridge implementation is virtual and therefore is fully exposed to Netlink control and is absolutely fuzzable. I need to keep this in mind as I assess the risks. I need to pay close attention to the `nla_nest_end_safe` changes and the error handling within `br_fill_ifinfo`. This looks like a potentially important hardening measure. |
| 4/2 | 2026/09/21 11:32 | tool | read-file |
0mArgs:{
"File": "net/bridge/br_netlink.c",
"FirstLine": 580,
"LineCount": 55
}Results: {
"Contents": " 580:\t\t\t\t\tgoto nla_put_failure;\n 581:\t\t\t}\n 582:\t\n 583:\t\t\tif (filter_mask \u0026 RTEXT_FILTER_CFM_STATUS) {\n 584:\t\t\t\trcu_read_lock();\n 585:\t\t\t\terr = br_cfm_status_fill_info(skb, br, getlink);\n 586:\t\t\t\trcu_read_unlock();\n 587:\t\t\t\tif (err)\n 588:\t\t\t\t\tgoto nla_put_failure;\n 589:\t\t\t}\n 590:\t\n 591:\t\t\tif (nla_nest_end_safe(skb, cfm_nest) \u003c 0)\n 592:\t\t\t\tgoto nla_nest_too_large;\n 593:\t\t}\n 594:\t\n 595:\t\tif ((filter_mask \u0026 RTEXT_FILTER_MST) \u0026\u0026\n 596:\t\t br_opt_get(br, BROPT_MST_ENABLED) \u0026\u0026 port) {\n 597:\t\t\tconst struct net_bridge_vlan_group *vg = nbp_vlan_group(port);\n 598:\t\t\tstruct nlattr *mst_nest;\n 599:\t\t\tint err;\n 600:\t\n 601:\t\t\tif (!vg || !vg-\u003enum_vlans)\n 602:\t\t\t\tgoto done;\n 603:\t\n 604:\t\t\tmst_nest = nla_nest_start(skb, IFLA_BRIDGE_MST);\n 605:\t\t\tif (!mst_nest)\n 606:\t\t\t\tgoto nla_put_failure;\n 607:\t\n 608:\t\t\terr = br_mst_fill_info(skb, vg);\n 609:\t\t\tif (err)\n 610:\t\t\t\tgoto nla_put_failure;\n 611:\t\n 612:\t\t\tif (nla_nest_end_safe(skb, mst_nest) \u003c 0)\n 613:\t\t\t\tgoto nla_nest_too_large;\n 614:\t\t}\n 615:\t\n 616:\tdone:\n 617:\t\tif (af) {\n 618:\t\t\tif (nla_nest_end_safe(skb, af) \u003c 0)\n 619:\t\t\t\tgoto nla_nest_too_large;\n 620:\t\t\tif (!nla_len(af))\n 621:\t\t\t\tnla_nest_cancel(skb, af);\n 622:\t\t}\n 623:\t\n 624:\t\tnlmsg_end(skb, nlh);\n 625:\t\treturn 0;\n 626:\t\n 627:\tnla_nest_too_large:\n 628:\t\tNL_SET_ERR_MSG_MOD(extack,\n 629:\t\t\t\t \"AF_SPEC info too large, use per-object dumps (e.g. RTM_GETVLAN)\");\n 630:\t\tnlmsg_cancel(skb, nlh);\n 631:\t\treturn -E2BIG;\n 632:\t\n 633:\tnla_put_failure:\n 634:\t\tnlmsg_cancel(skb, nlh);\n"
} |
| 5/2 | 2026/09/21 11:32 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 12579 output: 22 thoughts: 41 Thoughts: Okay, here's my interpretation of that thought process, tailored for an expert audience, and presented as if it were my own stream of consciousness: **Dissecting This Code - Starting with the Obvious** Alright, let's dive into this patch. My immediate reaction is, "What the heck is this code doing? Specifically, what's with this `nla_nest_end_safe`? I've seen it before, but I need a refresher on the precise context here. Probably related to nested Netlink attributes, but I want to be certain." Time to fire up the grepper. I'll search for `nla_nest_end_safe` in the codebase. I need to understand its exact purpose within the scope of this change, and how it interacts with the surrounding `nla_*` functions. Is it ensuring safe nesting closure, preventing buffer overflows, or something else entirely? I expect to find a definition, usages, and hopefully some relevant comments that shed light on the design. Understanding *why* it's being used is key. Hopefully, it is in a module I am familiar with. |
| 6/2 | 2026/09/21 11:32 | tool | grepper |
0mArgs:{
"Expression": "nla_nest_end_safe"
}Results: {
"Output": "drivers/net/macvlan.c=1746=static int macvlan_fill_info(struct sk_buff *skb,\n--\ndrivers/net/macvlan.c-1778-\t\t\tnla_nest_cancel(skb, nest);\ndrivers/net/macvlan.c:1779:\t\telse if (nla_nest_end_safe(skb, nest) \u003c 0)\ndrivers/net/macvlan.c-1780-\t\t\tgoto nla_put_failure;\n--\ninclude/net/netlink.h=2261=static inline int nla_nest_end(struct sk_buff *skb, struct nlattr *start)\n--\ninclude/net/netlink.h-2270-/**\ninclude/net/netlink.h:2271: * nla_nest_end_safe - Validate and finalize nesting of attributes\ninclude/net/netlink.h-2272- * @skb: socket buffer the attributes are stored in\n--\ninclude/net/netlink.h-2280- */\ninclude/net/netlink.h:2281:static inline int nla_nest_end_safe(struct sk_buff *skb, struct nlattr *start)\ninclude/net/netlink.h-2282-{\n--\nnet/bridge/br_netlink.c=458=static int br_fill_ifinfo(struct sk_buff *skb,\n--\nnet/bridge/br_netlink.c-590-\nnet/bridge/br_netlink.c:591:\t\tif (nla_nest_end_safe(skb, cfm_nest) \u003c 0)\nnet/bridge/br_netlink.c-592-\t\t\tgoto nla_nest_too_large;\n--\nnet/bridge/br_netlink.c-611-\nnet/bridge/br_netlink.c:612:\t\tif (nla_nest_end_safe(skb, mst_nest) \u003c 0)\nnet/bridge/br_netlink.c-613-\t\t\tgoto nla_nest_too_large;\n--\nnet/bridge/br_netlink.c-617-\tif (af) {\nnet/bridge/br_netlink.c:618:\t\tif (nla_nest_end_safe(skb, af) \u003c 0)\nnet/bridge/br_netlink.c-619-\t\t\tgoto nla_nest_too_large;\n--\nnet/core/rtnetlink.c=2011=static int rtnl_fill_prop_list(struct sk_buff *skb,\n--\nnet/core/rtnetlink.c-2025-\tret = -EMSGSIZE;\nnet/core/rtnetlink.c:2026:\tif (nla_nest_end_safe(skb, prop_list) \u003c 0)\nnet/core/rtnetlink.c-2027-\t\tgoto nest_cancel;\n--\nnet/ethtool/strset.c=418=static int strset_fill_set(struct sk_buff *skb,\n--\nnet/ethtool/strset.c-445-\t\t}\nnet/ethtool/strset.c:446:\t\tif (nla_nest_end_safe(skb, strings_attr) \u003c 0)\nnet/ethtool/strset.c-447-\t\t\tgoto nla_put_failure;\n"
} |
| 7/2 | 2026/09/21 11:32 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 13746 output: 37 thoughts: 36 Thoughts: Here's my take on those thoughts: **Peering into netlink.h** Alright, let's dive into the guts of this. I need to understand how this `nla_nest_end_safe` function in `include/net/netlink.h` works. I recall seeing it around line 2280 – that's usually where the relevant definitions are for this part of the netlink structure. My aim is to refresh my understanding of how this function safely terminates a nested netlink attribute. I'll need to remember all the edge cases it handles, particularly if there are any subtle differences from the regular `nla_nest_end` that I should know. |
| 8/2 | 2026/09/21 11:32 | tool | read-file |
0mArgs:{
"File": "include/net/netlink.h",
"FirstLine": 2270,
"LineCount": 30
}Results: {
"Contents": "2270:\t/**\n2271:\t * nla_nest_end_safe - Validate and finalize nesting of attributes\n2272:\t * @skb: socket buffer the attributes are stored in\n2273:\t * @start: container attribute\n2274:\t *\n2275:\t * Corrects the container attribute header to include all appended\n2276:\t * attributes.\n2277:\t *\n2278:\t * Returns: the total data length of the skb, or -EMSGSIZE if the\n2279:\t * nested attribute length exceeds U16_MAX.\n2280:\t */\n2281:\tstatic inline int nla_nest_end_safe(struct sk_buff *skb, struct nlattr *start)\n2282:\t{\n2283:\t\tif (skb_tail_pointer(skb) - (unsigned char *)start \u003e U16_MAX)\n2284:\t\t\treturn -EMSGSIZE;\n2285:\t\n2286:\t\treturn nla_nest_end(skb, start);\n2287:\t}\n2288:\t\n2289:\t/**\n2290:\t * nla_nest_cancel - Cancel nesting of attributes\n2291:\t * @skb: socket buffer the message is stored in\n2292:\t * @start: container attribute\n2293:\t *\n2294:\t * Removes the container attribute and including all nested\n2295:\t * attributes. Returns -EMSGSIZE\n2296:\t */\n2297:\tstatic inline void nla_nest_cancel(struct sk_buff *skb, struct nlattr *start)\n2298:\t{\n2299:\t\tnlmsg_trim(skb, start);\n"
} |
| 9/2 | 2026/09/21 11:32 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 14429 output: 18 thoughts: 849 Thoughts: **Analyzing Potential Errors in Bridge Netlink Message Handling**
Okay, so I'm looking into the bridge netlink code, specifically `net/bridge/br_netlink.c`. I'm starting to see a potential problem in how large nested attributes are handled. `nla_nest_end_safe(skb, af)` returns a negative value if the size of the nested attribute `af` exceeds 64KB, due to the `u16` length limitation of netlink attributes. I remember that the previous code in `br_fill_ifinfo` had some checks, but they've been updated to use `nla_nest_end_safe`. The new code now checks for the error from `nla_nest_end_safe` and calls `nla_nest_cancel` if the length of attribute is zero. This update is passed up the call stack from `rtnl_bridge_getlink` down to `br_fill_ifinfo`.
Now, I'm thinking about `br_info_notify`. There's an interesting condition there: `if (err < 0) { WARN_ON(err == -EMSGSIZE); ... }`. This seems to be warning about an `EMSGSIZE` error, which typically indicates a buffer size issue. The code explicitly checks for `-EMSGSIZE`, but what if a different error code, like `-E2BIG`, is returned? It wouldn't trigger the `WARN_ON`, and the error might not be handled correctly, which could lead to unexpected behavior. The function `br_info_notify` calls `br_fill_ifinfo`.
Next, I'm looking at `rtnl_bridge_notify`, specifically this line: `err = dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev, 0, 0, extack);`. This calls `ndo_bridge_getlink`, but I need to figure out how `ndo_bridge_getlink` is registered, whether for a bridge device or a bridge port. I need to trace where `br_getlink` or `ndo_bridge_getlink` is actually defined to get a clearer picture of how this works. I'm going to look for the registration of that function.
|
| 10/2 | 2026/09/21 11:32 | tool | grepper |
0mArgs:{
"Expression": "br_getlink"
}Results: {
"Output": "net/bridge/br_device.c=439=static const struct net_device_ops br_netdev_ops = {\n--\nnet/bridge/br_device.c-468-\t.ndo_mdb_get\t\t = br_mdb_get,\nnet/bridge/br_device.c:469:\t.ndo_bridge_getlink\t = br_getlink,\nnet/bridge/br_device.c-470-\t.ndo_bridge_setlink\t = br_setlink,\n--\nnet/bridge/br_netlink.c=680=void br_ifinfo_notify(int event, const struct net_bridge *br,\n--\nnet/bridge/br_netlink.c-690- */\nnet/bridge/br_netlink.c:691:int br_getlink(struct sk_buff *skb, u32 pid, u32 seq,\nnet/bridge/br_netlink.c-692-\t struct net_device *dev, u32 filter_mask, int nlflags,\n--\nnet/bridge/br_private.h=2180=int br_dellink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags);\nnet/bridge/br_private.h:2181:int br_getlink(struct sk_buff *skb, u32 pid, u32 seq, struct net_device *dev,\nnet/bridge/br_private.h-2182-\t u32 filter_mask, int nlflags, struct netlink_ext_ack *extack);\n"
} |
| 11/2 | 2026/09/21 11:32 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 16187 output: 38 thoughts: 47 Thoughts: Okay, here's my interpretation of those thoughts, tailored for an expert audience, presented in the first person: **Bridge Link Information - Digging Deeper** Aha! So, I see that the `br_netdev_ops` struct *does* indeed have a `.ndo_bridge_getlink` function pointer, and it's pointing to `br_getlink`. That's the expected basic plumbing for retrieving link-layer information from a bridge itself. But... hang on a second. What about the *ports* that make up that bridge? Is `br_getlink` handling that information too? I don't recall seeing any port-specific handling in it directly... Okay, I need to check something else to be sure. Let me go look at `rtnl_bridge_getlink`... It's the standard Netlink interface handler for getting link information from bridges, so it should be the right place to get port information, I hope. I need to refresh my memory about how these calls are designed. |
| 12/2 | 2026/09/21 11:32 | tool | read-file |
0mArgs:{
"File": "net/core/rtnetlink.c",
"FirstLine": 5585,
"LineCount": 45
}Results: {
"Contents": "5585:\t\n5586:\t\terr = valid_bridge_getlink_req(nlh, cb-\u003estrict_check, \u0026filter_mask,\n5587:\t\t\t\t\t cb-\u003eextack);\n5588:\t\tif (err \u003c 0 \u0026\u0026 cb-\u003estrict_check)\n5589:\t\t\treturn err;\n5590:\t\n5591:\t\trcu_read_lock();\n5592:\t\tfor_each_netdev_rcu(net, dev) {\n5593:\t\t\tconst struct net_device_ops *ops = dev-\u003enetdev_ops;\n5594:\t\t\tstruct net_device *br_dev = netdev_master_upper_dev_get(dev);\n5595:\t\n5596:\t\t\tif (br_dev \u0026\u0026 br_dev-\u003enetdev_ops-\u003endo_bridge_getlink) {\n5597:\t\t\t\tif (idx \u003e= cb-\u003eargs[0]) {\n5598:\t\t\t\t\terr = br_dev-\u003enetdev_ops-\u003endo_bridge_getlink(\n5599:\t\t\t\t\t\t\tskb, portid, seq, dev,\n5600:\t\t\t\t\t\t\tfilter_mask, NLM_F_MULTI,\n5601:\t\t\t\t\t\t\tcb-\u003eextack);\n5602:\t\t\t\t\tif (err \u003c 0 \u0026\u0026 err != -EOPNOTSUPP) {\n5603:\t\t\t\t\t\tif (likely(skb-\u003elen))\n5604:\t\t\t\t\t\t\tbreak;\n5605:\t\n5606:\t\t\t\t\t\tgoto out_err;\n5607:\t\t\t\t\t}\n5608:\t\t\t\t}\n5609:\t\t\t\tidx++;\n5610:\t\t\t}\n5611:\t\n5612:\t\t\tif (ops-\u003endo_bridge_getlink) {\n5613:\t\t\t\tif (idx \u003e= cb-\u003eargs[0]) {\n5614:\t\t\t\t\terr = ops-\u003endo_bridge_getlink(skb, portid,\n5615:\t\t\t\t\t\t\t\t seq, dev,\n5616:\t\t\t\t\t\t\t\t filter_mask,\n5617:\t\t\t\t\t\t\t\t NLM_F_MULTI,\n5618:\t\t\t\t\t\t\t\t cb-\u003eextack);\n5619:\t\t\t\t\tif (err \u003c 0 \u0026\u0026 err != -EOPNOTSUPP) {\n5620:\t\t\t\t\t\tif (likely(skb-\u003elen))\n5621:\t\t\t\t\t\t\tbreak;\n5622:\t\n5623:\t\t\t\t\t\tgoto out_err;\n5624:\t\t\t\t\t}\n5625:\t\t\t\t}\n5626:\t\t\t\tidx++;\n5627:\t\t\t}\n5628:\t\t}\n5629:\t\terr = skb-\u003elen;\n"
} |
| 13/2 | 2026/09/21 11:32 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 17153 output: 21 thoughts: 1007 Thoughts: **Analyzing Bridge Netlink Interaction** Okay, here's what I'm seeing: there's this `br_dev = netdev_master_upper_dev_get(dev);` call, and if `br_dev` exists and has `ndo_bridge_getlink`, it triggers a call to `br_dev->netdev_ops->ndo_bridge_getlink`. This also applies directly if the device ops has `ndo_bridge_getlink`. That tells me the bridge master device will be calling `br_getlink` for all of its port netdevs, and the bridge itself! This is all happening within `rtnl_bridge_getlink`, the handler for `RTM_GETLINK` with bridge information. Excellent, that's the setup. Now, let's examine `rtnl_bridge_setlink` and `rtnl_bridge_dellink`. I see they're calling `rtnl_bridge_notify` after a bridge change. And what does `rtnl_bridge_notify` do? It creates a netlink message, then *calls `dev->netdev_ops->ndo_bridge_getlink`* to populate that message! Very interesting. We're using the same function to generate the initial link information and to notify about changes. Hold on, something's odd in `net/bridge/br_netlink.c`. I'm seeing this code block with an `af` attribute. Previously, if `nlmsg_get_pos(skb) - (void *)af > nla_attr_size(0)`, it calls `nla_nest_end(skb, af)`, but now there's `nla_nest_end_safe(skb, af)` and then `!nla_len(af)`. The `nla_nest_end_safe` is setting `af->nla_len = skb_tail_pointer(skb) - (unsigned char *)af;`. Here's the problem: if no attributes were added inside of `af` the `nla_nest_end_safe` call would make the len of that attribute to be `sizeof(struct nlattr)` which equals `4`. Now, `!nla_len(af)` is being checked. What does `nla_len` actually return in that case? That's the key. I need to go look at the definition of `nla_len` to understand exactly what's being tested, and make sure that this logic is correct. I have a hunch that there's a possible subtle bug here. Let's dig deeper into the macro. |
| 14/2 | 2026/09/21 11:33 | tool | grepper |
0mError:no matches Args: {
"Expression": "static inline int nla_len"
}Results: {
"error": "no matches"
} |
| 15/2 | 2026/09/21 11:33 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 18765 output: 33 thoughts: 21 Thoughts: Here's my thought process, as requested: **Checking `nla_len` in `netlink.h`** Okay, so I need to refresh my memory on how `nla_len` is handled in the Netlink context. Time to dive into `include/net/netlink.h`. I'm specifically interested in how the length field of the Netlink Attribute (NLA) structures is defined and used. I'll be looking for the underlying definition of `nla_len` itself, but also how it's *used* in calculating offsets, validating attribute lengths, and iterating through attribute lists. I want to make sure I'm not missing any subtle interactions or potential pitfalls related to alignment or potential size limitations. I need to understand how the length is encoded and interpreted in different scenarios, especially if there are any specific considerations for different Netlink message types or attribute types. Gotta be thorough. This kind of detail is essential for robust Netlink code. |
| 16/2 | 2026/09/21 11:33 | tool | grepper |
0mArgs:{
"Expression": "nla_len\\(",
"PathPrefix": "include/net/netlink.h"
}Results: {
"Output": "include/net/netlink.h-86- * +----------+- - -+- - - - - - - - - +- - -+-------- - -\ninclude/net/netlink.h:87: * \u003c- nla_len(nla) -\u003e ^\ninclude/net/netlink.h-88- * nla_data(nla)----^ |\n--\ninclude/net/netlink.h-131- * nla_data(nla)\t\t\thead of attribute payload\ninclude/net/netlink.h:132: * nla_len(nla)\t\t\tlength of attribute payload\ninclude/net/netlink.h-133- *\n--\ninclude/net/netlink.h=1285=static inline void *nla_data(const struct nlattr *nla)\n--\ninclude/net/netlink.h-1293- */\ninclude/net/netlink.h:1294:static inline u16 nla_len(const struct nlattr *nla)\ninclude/net/netlink.h-1295-{\n--\ninclude/net/netlink.h=1335=nla_find_nested(const struct nlattr *nla, int attrtype)\ninclude/net/netlink.h-1336-{\ninclude/net/netlink.h:1337:\treturn nla_find(nla_data(nla), nla_len(nla), attrtype);\ninclude/net/netlink.h-1338-}\n--\ninclude/net/netlink.h=1350=static inline int nla_parse_nested(struct nlattr *tb[], int maxtype,\n--\ninclude/net/netlink.h-1359-\ninclude/net/netlink.h:1360:\treturn __nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy,\ninclude/net/netlink.h-1361-\t\t\t NL_VALIDATE_STRICT, extack);\n--\ninclude/net/netlink.h=1374=static inline int nla_parse_nested_deprecated(struct nlattr *tb[], int maxtype,\n--\ninclude/net/netlink.h-1378-{\ninclude/net/netlink.h:1379:\treturn __nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy,\ninclude/net/netlink.h-1380-\t\t\t NL_VALIDATE_LIBERAL, extack);\n--\ninclude/net/netlink.h=1924=static inline u64 nla_get_uint(const struct nlattr *nla)\ninclude/net/netlink.h-1925-{\ninclude/net/netlink.h:1926:\tif (nla_len(nla) == sizeof(u32))\ninclude/net/netlink.h-1927-\t\treturn nla_get_u32(nla);\n--\ninclude/net/netlink.h=2097=static inline s64 nla_get_sint(const struct nlattr *nla)\ninclude/net/netlink.h-2098-{\ninclude/net/netlink.h:2099:\tif (nla_len(nla) == sizeof(s32))\ninclude/net/netlink.h-2100-\t\treturn nla_get_s32(nla);\n--\ninclude/net/netlink.h=2208=static inline void *nla_memdup_noprof(const struct nlattr *src, gfp_t gfp)\ninclude/net/netlink.h-2209-{\ninclude/net/netlink.h:2210:\treturn kmemdup_noprof(nla_data(src), nla_len(src), gfp);\ninclude/net/netlink.h-2211-}\n--\ninclude/net/netlink.h=2330=static inline int __nla_validate_nested(const struct nlattr *start, int maxtype,\n--\ninclude/net/netlink.h-2334-{\ninclude/net/netlink.h:2335:\treturn __nla_validate(nla_data(start), nla_len(start), maxtype, policy,\ninclude/net/netlink.h-2336-\t\t\t validate, extack);\n--\ninclude/net/netlink.h=2403=static inline int nla_total_size_64bit(int payload)\n--\ninclude/net/netlink.h-2442-#define nla_for_each_nested(pos, nla, rem) \\\ninclude/net/netlink.h:2443:\tnla_for_each_attr(pos, nla_data(nla), nla_len(nla), rem)\ninclude/net/netlink.h-2444-\n"
} |
| 17/2 | 2026/09/21 11:33 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 20268 output: 36 thoughts: 2844 Thoughts: **Analysis of Bridge Netlink Vulnerability and Patch Effectiveness** Okay, let's break this down. My primary concern here is that this patch addresses a potential buffer overflow vulnerability within the bridge netlink interface. I need to be thorough. First, I see the core problem: `nla_len` and how it interacts with nested attributes, specifically when `nla_nest_end` is used. If nothing is added within a nested attribute, `nla_len` reports zero. The code checks for this and, if zero, *cancels* the nested attribute using `nla_nest_cancel`. However, if the nested data exceeds `U16_MAX`, the code jumps to `nla_nest_too_large` which results in `-E2BIG` and an extack message. My thought: Previously, if the `AF_SPEC` data for a single bridge port exceeded 64KB, there was the potential for the `start->nla_len` to wrap around, resulting in a truncated, and corrupt, netlink message to userspace. This patch fixes this by using `nla_nest_end_safe` which checks and catches the size overflow, returning -E2BIG, and notifying userspace. This is a critical security fix. The patch itself modifies several NIC drivers and core networking files. These driver changes appear to be mostly propagating the extack to the default bridge getlink function. However, the modification of `net/bridge/br_netlink.c`, `net/core/rtnetlink.c`, `include/linux/netdevice.h`, and `include/linux/rtnetlink.h` are the critical ones. This means changes to the bridge netlink logic (`br_fill_ifinfo`, `br_getlink`), core rtnetlink logic (`rtnl_bridge_getlink`, `rtnl_bridge_notify`, `rtnl_bridge_setlink`, `rtnl_bridge_dellink`, and `ndo_dflt_bridge_getlink`) are the focus. This is where the actual vulnerability and the fix lie. New error paths, changes in nesting validation, extack propagation, and control flow changes are introduced. This is all *highly* reachable in standard QEMU/syzkaller environments. The bridge driver (`CONFIG_BRIDGE`) is standard and accessible by any user with `CAP_NET_ADMIN` or within user/net namespaces. **Therefore, it is critical that this is fuzzed! I will mark `WorthFuzzing` as TRUE.** Now, let's be strategic and focus our fuzzing efforts. I need to determine the `FocusSymbols` and `EnableConfigs`. We need to find specific entrypoints and feature-specific logic. I need to avoid broad, ubiquitous functions and instead target the modified code. Here's my initial list of modified symbols to be considered as `FocusSymbols`: * `br_fill_ifinfo` (in `net/bridge/br_netlink.c`) - Static function used to fill the ifinfo (interface info) in netlink messages for bridge ports. * `br_getlink` (in `net/bridge/br_netlink.c`) - Called by the netdev operation to get link information. * `ndo_dflt_bridge_getlink` (in `net/core/rtnetlink.c`) - Exported to allow drivers to add extra bridge information * `rtnl_bridge_getlink` (in `net/core/rtnetlink.c`) - The netlink dump callback for `RTM_GETLINK` on `PF_BRIDGE`. * `rtnl_bridge_notify` (in `net/core/rtnetlink.c`) * `rtnl_bridge_setlink` (in `net/core/rtnetlink.c`) * `rtnl_bridge_dellink` (in `net/core/rtnetlink.c`) Now, let's refine this list. `br_fill_ifinfo` is not inlined and appears to be the most relevant function in which the changes occur. It handles the actual population of the netlink attribute data. It is the target of the size checks and, thus, the focus of the bug and fix. `br_getlink` is a caller of `br_fill_ifinfo`. Static functions in `.c` files *are* exposed as symbols. The fact they are static only limits their direct calls within the file. They can still be targeted. `br_getlink` and `ndo_dflt_bridge_getlink` are good starting points for fuzzing. `rtnl_bridge_getlink` is a crucial callback. |
| 18/2 | 2026/09/21 11:33 | tool | grepper |
0mArgs:{
"Expression": "rtnl_bridge_getlink",
"PathPrefix": "net/core/rtnetlink.c"
}Results: {
"Output": "net/core/rtnetlink.c=5521=static int valid_bridge_getlink_req(const struct nlmsghdr *nlh,\n--\nnet/core/rtnetlink.c-5574-\nnet/core/rtnetlink.c:5575:static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)\nnet/core/rtnetlink.c-5576-{\n--\nnet/core/rtnetlink.c=7265=static const struct rtnl_msg_handler rtnetlink_rtnl_msg_handlers[] __initconst = {\n--\nnet/core/rtnetlink.c-7285-\t{.protocol = PF_BRIDGE, .msgtype = RTM_GETLINK,\nnet/core/rtnetlink.c:7286:\t .dumpit = rtnl_bridge_getlink},\nnet/core/rtnetlink.c-7287-\t{.protocol = PF_BRIDGE, .msgtype = RTM_DELLINK,\n"
} |
| 19/2 | 2026/09/21 11:33 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 24441 output: 35 thoughts: 60 Thoughts: Here's my take on those thoughts: **Peering into the Bridge Code** Okay, so `rtnl_bridge_getlink` is definitely the right handler – it's the `.dumpit` function for `PF_BRIDGE` within the `RTM_GETLINK` request. That makes sense, keeps things consistent with my existing knowledge of netlink and bridge internals. Now, a crucial aspect of bridge management is the event notification side, so what about `rtnl_bridge_notify`? Where exactly is that called? I need to trace its usage to understand how the kernel communicates bridge state changes to user space, and more importantly how it relates to my current problem set. Time to go digging through the call sites... I suspect it'll be related to some hook in my network namespace work, but better to check directly. |
| 20/2 | 2026/09/21 11:33 | tool | grepper |
0mArgs:{
"Expression": "rtnl_bridge_notify",
"PathPrefix": "net/core/rtnetlink.c"
}Results: {
"Output": "net/core/rtnetlink.c=5637=static inline size_t bridge_nlmsg_size(void)\n--\nnet/core/rtnetlink.c-5651-\nnet/core/rtnetlink.c:5652:static int rtnl_bridge_notify(struct net_device *dev,\nnet/core/rtnetlink.c-5653-\t\t\t struct netlink_ext_ack *extack)\n--\nnet/core/rtnetlink.c=5689=static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,\n--\nnet/core/rtnetlink.c-5758-\t\t\t */\nnet/core/rtnetlink.c:5759:\t\t\terr = rtnl_bridge_notify(dev, extack);\nnet/core/rtnetlink.c-5760-\t\t}\n--\nnet/core/rtnetlink.c=5769=static int rtnl_bridge_dellink(struct sk_buff *skb, struct nlmsghdr *nlh,\n--\nnet/core/rtnetlink.c-5833-\t\t\t */\nnet/core/rtnetlink.c:5834:\t\t\terr = rtnl_bridge_notify(dev, extack);\nnet/core/rtnetlink.c-5835-\t\t}\n"
} |
| 21/2 | 2026/09/21 11:33 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 25061 output: 38 thoughts: 109 Thoughts: **My Analysis of Bridge Netlink Operations** Okay, so I'm looking at how bridge interfaces are managed via netlink. Specifically, `rtnl_bridge_notify` is clearly being called in both `rtnl_bridge_setlink` and `rtnl_bridge_dellink`. That makes sense - we need to notify the relevant subscribers of link state changes. Now, it's starting to become clear: `rtnl_bridge_setlink` is, fundamentally, the `.doit` function for `PF_BRIDGE` with `RTM_SETLINK` messages. And, as expected, `rtnl_bridge_dellink` is the `.doit` function for `PF_BRIDGE` and `RTM_DELLINK`. Of course, this is essential in establishing the interface. I'd better double-check the `rtnetlink_rtnl_msg_handlers` structure to confirm that I am on the right track here, so I am going to investigate that now. |
| 22/2 | 2026/09/21 11:33 | tool | read-file |
0mArgs:{
"File": "net/core/rtnetlink.c",
"FirstLine": 7280,
"LineCount": 25
}Results: {
"Contents": "7280:\t\t{.msgtype = RTM_GETSTATS, .doit = rtnl_stats_get,\n7281:\t\t .dumpit = rtnl_stats_dump},\n7282:\t\t{.msgtype = RTM_SETSTATS, .doit = rtnl_stats_set},\n7283:\t\t{.msgtype = RTM_NEWLINKPROP, .doit = rtnl_newlinkprop},\n7284:\t\t{.msgtype = RTM_DELLINKPROP, .doit = rtnl_dellinkprop},\n7285:\t\t{.protocol = PF_BRIDGE, .msgtype = RTM_GETLINK,\n7286:\t\t .dumpit = rtnl_bridge_getlink},\n7287:\t\t{.protocol = PF_BRIDGE, .msgtype = RTM_DELLINK,\n7288:\t\t .doit = rtnl_bridge_dellink},\n7289:\t\t{.protocol = PF_BRIDGE, .msgtype = RTM_SETLINK,\n7290:\t\t .doit = rtnl_bridge_setlink},\n7291:\t\t{.protocol = PF_BRIDGE, .msgtype = RTM_NEWNEIGH, .doit = rtnl_fdb_add},\n7292:\t\t{.protocol = PF_BRIDGE, .msgtype = RTM_DELNEIGH, .doit = rtnl_fdb_del,\n7293:\t\t .flags = RTNL_FLAG_BULK_DEL_SUPPORTED},\n7294:\t\t{.protocol = PF_BRIDGE, .msgtype = RTM_GETNEIGH, .doit = rtnl_fdb_get,\n7295:\t\t .dumpit = rtnl_fdb_dump},\n7296:\t\t{.protocol = PF_BRIDGE, .msgtype = RTM_NEWMDB, .doit = rtnl_mdb_add},\n7297:\t\t{.protocol = PF_BRIDGE, .msgtype = RTM_DELMDB, .doit = rtnl_mdb_del,\n7298:\t\t .flags = RTNL_FLAG_BULK_DEL_SUPPORTED},\n7299:\t\t{.protocol = PF_BRIDGE, .msgtype = RTM_GETMDB, .doit = rtnl_mdb_get,\n7300:\t\t .dumpit = rtnl_mdb_dump},\n7301:\t};\n7302:\t\n7303:\tvoid __init rtnetlink_init(void)\n7304:\t{\n"
} |
| 23/2 | 2026/09/21 11:33 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 26039 output: 27 thoughts: 39 Thoughts: Okay, here's my take on those thoughts, framed as an expert's internal monologue: **Investigating Bridge Netlink Configuration** Alright, time to get this sorted. First, I need to confirm the configuration for `net/bridge` and the bridge netlink specifically. I'm going to jump straight into the Kconfig files. That's usually the quickest way to get a handle on the available options, dependencies, and default states. I'll start with the main `net/bridge/Kconfig` file. Then I'll check the associated Makefile to see how things are built and any potential nuances in the build process. Understanding the relationship between the Kconfig and Makefile is critical to avoid any potential misconfigurations. |
| 24/2 | 2026/09/21 11:33 | tool | grepper |
0mArgs:{
"Expression": "br_netlink",
"PathPrefix": "net/bridge"
}Results: {
"Output": "net/bridge/Makefile=8=bridge-y\t:= br.o br_device.o br_fdb.o br_forward.o br_if.o br_input.o \\\nnet/bridge/Makefile-9-\t\t\tbr_ioctl.o br_stp.o br_stp_bpdu.o \\\nnet/bridge/Makefile:10:\t\t\tbr_stp_if.o br_stp_timer.o br_netlink.o \\\nnet/bridge/Makefile:11:\t\t\tbr_netlink_tunnel.o br_arp_nd_proxy.o\nnet/bridge/Makefile-12-\n--\nnet/bridge/br.c=425=static int __init br_init(void)\n--\nnet/bridge/br.c-460-\nnet/bridge/br.c:461:\terr = br_netlink_init();\nnet/bridge/br.c-462-\tif (err)\n--\nnet/bridge/br.c=492=static void __exit br_deinit(void)\n--\nnet/bridge/br.c-494-\tstp_proto_unregister(\u0026br_stp_proto);\nnet/bridge/br.c:495:\tbr_netlink_fini();\nnet/bridge/br.c-496-\tunregister_switchdev_blocking_notifier(\u0026br_switchdev_blocking_notifier);\n--\nnet/bridge/br_netlink.c=1958=struct rtnl_link_ops br_link_ops __read_mostly = {\n--\nnet/bridge/br_netlink.c-1979-\nnet/bridge/br_netlink.c:1980:int __init br_netlink_init(void)\nnet/bridge/br_netlink.c-1981-{\n--\nnet/bridge/br_netlink.c-2005-\nnet/bridge/br_netlink.c:2006:void br_netlink_fini(void)\nnet/bridge/br_netlink.c-2007-{\n--\nnet/bridge/br_private.h=2163=static inline int br_cfm_peer_mep_count(struct net_bridge *br, u32 *count)\n--\nnet/bridge/br_private.h-2169-\nnet/bridge/br_private.h:2170:/* br_netlink.c */\nnet/bridge/br_private.h-2171-extern struct rtnl_link_ops br_link_ops;\nnet/bridge/br_private.h:2172:int br_netlink_init(void);\nnet/bridge/br_private.h:2173:void br_netlink_fini(void);\nnet/bridge/br_private.h-2174-void br_ifinfo_notify(int event, const struct net_bridge *br,\n--\nnet/bridge/br_private_tunnel.h=12=struct vtunnel_info {\n--\nnet/bridge/br_private_tunnel.h-17-\nnet/bridge/br_private_tunnel.h:18:/* br_netlink_tunnel.c */\nnet/bridge/br_private_tunnel.h-19-int br_parse_vlan_tunnel_info(struct nlattr *attr,\n"
} |
| 25/2 | 2026/09/21 11:33 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 27072 output: 32 thoughts: 12 Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience: **Diving into the Bridge Configuration** Okay, so I need to understand something about the bridging configuration in the Linux kernel. Where would I start? Naturally, the first place I'd look is `net/bridge/Kconfig`. This file *should* hold the core configuration options related to the bridge module. It'll give me a clear picture of what's available at compile time: the various features, dependencies on other kernel subsystems, and any associated default values. Going straight to the Kconfig file avoids wasted time searching around for relevant modules. I hope it is all self-documenting. This is the correct starting point. |
| 26/2 | 2026/09/21 11:33 | tool | read-file |
0mArgs:{
"File": "net/bridge/Kconfig",
"FirstLine": 1,
"LineCount": 50
}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"
} |
| 27/2 | 2026/09/21 11:33 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 27960 output: 33 thoughts: 35 Thoughts: Here's my summary, as the expert: **Navigating the Net/Bridge Configurations** Okay, so I'm diving into `net/bridge/Kconfig` now. It's time to get a more granular look at the bridging configuration options. I need to refresh my understanding of the interactions between those VLAN filtering features, and how they relate to the more recent MRP and CFM capabilities. Specifically, I'm thinking about the implications for performance and control planes as these features have matured. I want to see how these elements can be manipulated. |
| 28/2 | 2026/09/21 11:33 | tool | read-file |
0mArgs:{
"File": "net/bridge/Kconfig",
"FirstLine": 50,
"LineCount": 50
}Results: {
"Contents": " 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"
} |
| 29/2 | 2026/09/21 11:33 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 28588 output: 38 thoughts: 106 Thoughts: **Investigating the `br_netlink.c` Code for CFM and MST Filtering** Okay, so I'm looking at `br_netlink.c` and I've noticed something interesting. Specifically, the calls to `nla_nest_end_safe(skb, cfm_nest)` – they're conditionally executed within those `if` statements: `if (filter_mask & RTEXT_FILTER_CFM_STATUS)` and `if (filter_mask & RTEXT_FILTER_CFM_CONFIG)`. My initial thought is, "Wait a minute! What's actually *protecting* the CFM and MST code here? What are the broader guards around those functionalities?" I need to understand the control flow better. To get a clearer picture of the context, I need to zoom out a bit. Time to dive into the surrounding code – specifically lines 550 through 620 of `net/bridge/br_netlink.c`. I'll focus on that section to see what conditions, checks, or configurations are in place that might be related to those filtering flags and the nesting operations. I expect this section will clarify which conditions are satisfied when `RTEXT_FILTER_CFM_STATUS` or `RTEXT_FILTER_CFM_CONFIG` are active. I am particularly curious to know if these flags are always set together, or whether these functionalities can be conditionally included. I also expect that this section will highlight any safety checks or boundary conditions. |
| 30/2 | 2026/09/21 11:33 | tool | read-file |
0mArgs:{
"File": "net/bridge/br_netlink.c",
"FirstLine": 540,
"LineCount": 60
}Results: {
"Contents": " 540:\t\t\telse\n 541:\t\t\t\terr = br_fill_ifvlaninfo(skb, vg);\n 542:\t\n 543:\t\t\tif (port \u0026\u0026 test_bit(BR_VLAN_TUNNEL_BIT, \u0026port-\u003eflags))\n 544:\t\t\t\terr = br_fill_vlan_tunnel_info(skb, vg);\n 545:\t\t\trcu_read_unlock();\n 546:\t\t\tif (err)\n 547:\t\t\t\tgoto nla_put_failure;\n 548:\t\t}\n 549:\t\n 550:\t\tif (filter_mask \u0026 RTEXT_FILTER_MRP) {\n 551:\t\t\tint err;\n 552:\t\n 553:\t\t\tif (!br_mrp_enabled(br) || port)\n 554:\t\t\t\tgoto done;\n 555:\t\n 556:\t\t\trcu_read_lock();\n 557:\t\t\terr = br_mrp_fill_info(skb, br);\n 558:\t\t\trcu_read_unlock();\n 559:\t\n 560:\t\t\tif (err)\n 561:\t\t\t\tgoto nla_put_failure;\n 562:\t\t}\n 563:\t\n 564:\t\tif (filter_mask \u0026 (RTEXT_FILTER_CFM_CONFIG | RTEXT_FILTER_CFM_STATUS)) {\n 565:\t\t\tstruct nlattr *cfm_nest = NULL;\n 566:\t\t\tint err;\n 567:\t\n 568:\t\t\tif (!br_cfm_created(br) || port)\n 569:\t\t\t\tgoto done;\n 570:\t\n 571:\t\t\tcfm_nest = nla_nest_start(skb, IFLA_BRIDGE_CFM);\n 572:\t\t\tif (!cfm_nest)\n 573:\t\t\t\tgoto nla_put_failure;\n 574:\t\n 575:\t\t\tif (filter_mask \u0026 RTEXT_FILTER_CFM_CONFIG) {\n 576:\t\t\t\trcu_read_lock();\n 577:\t\t\t\terr = br_cfm_config_fill_info(skb, br);\n 578:\t\t\t\trcu_read_unlock();\n 579:\t\t\t\tif (err)\n 580:\t\t\t\t\tgoto nla_put_failure;\n 581:\t\t\t}\n 582:\t\n 583:\t\t\tif (filter_mask \u0026 RTEXT_FILTER_CFM_STATUS) {\n 584:\t\t\t\trcu_read_lock();\n 585:\t\t\t\terr = br_cfm_status_fill_info(skb, br, getlink);\n 586:\t\t\t\trcu_read_unlock();\n 587:\t\t\t\tif (err)\n 588:\t\t\t\t\tgoto nla_put_failure;\n 589:\t\t\t}\n 590:\t\n 591:\t\t\tif (nla_nest_end_safe(skb, cfm_nest) \u003c 0)\n 592:\t\t\t\tgoto nla_nest_too_large;\n 593:\t\t}\n 594:\t\n 595:\t\tif ((filter_mask \u0026 RTEXT_FILTER_MST) \u0026\u0026\n 596:\t\t br_opt_get(br, BROPT_MST_ENABLED) \u0026\u0026 port) {\n 597:\t\t\tconst struct net_bridge_vlan_group *vg = nbp_vlan_group(port);\n 598:\t\t\tstruct nlattr *mst_nest;\n 599:\t\t\tint err;\n"
} |
| 31/2 | 2026/09/21 11:33 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 29958 output: 31 thoughts: 99 Thoughts: **Examining the Bridge Configuration** Okay, let's break this down. First, `CONFIG_BRIDGE` is the central configuration option for the bridging functionality – that's straightforward. Now, I'm curious about the details. What does `CONFIG_BRIDGE_CFM` do exactly? Ah, right, enabling it means CFM support gets compiled in. Now, onto the VLAN complexities. What is `CONFIG_BRIDGE_VLAN_FILTERING` used for? Aha, MST (Multiple Spanning Tree) has a dependency; it *requires* VLAN filtering because of the `nbp_vlan_group(port)` call. To get the full picture on file compilation, I should examine `net/bridge/Makefile`. That should reveal how the different components are linked together. |
| 32/2 | 2026/09/21 11:33 | tool | read-file |
0mArgs:{
"File": "net/bridge/Makefile",
"FirstLine": 1,
"LineCount": 35
}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"
} |
| 33/2 | 2026/09/21 11:33 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 30917 output: 261 thoughts: 1322 Thoughts: **Analysis of Bridge Netlink Changes for Fuzzing** Okay, let's break this down. It looks like we're dealing with modifications within the bridge netlink subsystem. My initial thought is that we have `bridge-y` which depends on `br_netlink.o`, and then we have conditional components like `br_mst.o` under `CONFIG_BRIDGE_VLAN_FILTERING` and `br_cfm.o` under `CONFIG_BRIDGE_CFM`. The core of the changes seem to be within `br_fill_ifinfo`. Specifically, this patch alters how we handle nesting checks for CFM, MST, and AF_SPEC in `br_fill_ifinfo` using `nla_nest_end_safe`. There's a new error exit using `nla_nest_too_large` which also introduces an extack, `NL_SET_ERR_MSG_MOD`. The extack is then passed around to multiple functions related to bridge management: `br_getlink`, `br_fill_ifinfo`, `ndo_dflt_bridge_getlink`, `rtnl_bridge_getlink`, and `rtnl_bridge_notify`, etc. So, if we enable `BRIDGE`, `BRIDGE_CFM`, and `BRIDGE_VLAN_FILTERING`, we're enabling the relevant code paths. Let's make sure that's correct. `BRIDGE_VLAN_FILTERING` depends on `BRIDGE` and `VLAN_8021Q`, and `BRIDGE_CFM` depends on `BRIDGE`. That looks good. Now, let's verify what the `BRIDGE` config option means. Ah, none, but selects `LLC` and `STP`. Next, the critical part: defining the `FocusSymbols`. We want to target the specific entrypoints related to these netlink changes. We'll use: `br_fill_ifinfo`, `br_getlink`, `rtnl_bridge_getlink`, `rtnl_bridge_notify`, `rtnl_bridge_setlink`, `rtnl_bridge_dellink`, and `ndo_dflt_bridge_getlink`. Crucially, let's make sure these aren't ubiquitous functions. `br_fill_ifinfo` is clearly specific to bridge netlink dumps. The `rtnl_*` family is all specific to the rtnetlink interfaces. So we're good there. There are also driver-specific `bridge_getlink` functions, but those are hardware-specific (bnxt, be, i40e, ice, ixgbe, mlx5, nfp, qeth) and not relevant in standard virtualization environments like QEMU. We should NOT include these. Also, it looks like `br_info_notify` gets `NULL` for the `extack` parameter. Now, for setting the results, we're going to need: * `EnableConfigs`: `["BRIDGE", "BRIDGE_VLAN_FILTERING", "BRIDGE_CFM", "VLAN_8021Q"]` * `FocusSymbols`: `["br_fill_ifinfo", "br_getlink", "ndo_dflt_bridge_getlink", "rtnl_bridge_getlink", "rtnl_bridge_notify", "rtnl_bridge_setlink", "rtnl_bridge_dellink"]` * `Reasoning`: Concise explanation of the verdict * `WorthFuzzing`: `true` Just double-checking everything against the fuzzing instructions: We're dealing with core networking (net/bridge and net/core/rtnetlink), using accessible netlink drivers and protocols, and focusing on non-ubiquitous entrypoints. We have all the required elements. Time to call `set-results`. |
| 34/2 | 2026/09/21 11:34 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"BRIDGE",
"BRIDGE_VLAN_FILTERING",
"BRIDGE_CFM",
"VLAN_8021Q"
],
"FocusSymbols": [
"br_fill_ifinfo",
"br_getlink",
"ndo_dflt_bridge_getlink",
"rtnl_bridge_getlink",
"rtnl_bridge_notify",
"rtnl_bridge_setlink",
"rtnl_bridge_dellink"
],
"Reasoning": "The patch modifies core networking and bridging code (net/bridge/br_netlink.c, net/core/rtnetlink.c) to validate nested netlink attribute sizes using nla_nest_end_safe() and return -E2BIG with extended ack errors when nested attributes exceed U16_MAX. It also threads netlink_ext_ack down through ndo_bridge_getlink and bridge netlink helper functions. These code paths are fully reachable in virtualized environments via netlink bridge queries and modifications (PF_BRIDGE RTM_GETLINK / RTM_SETLINK / RTM_DELLINK).",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"BRIDGE",
"BRIDGE_VLAN_FILTERING",
"BRIDGE_CFM",
"VLAN_8021Q"
],
"FocusSymbols": [
"br_fill_ifinfo",
"br_getlink",
"ndo_dflt_bridge_getlink",
"rtnl_bridge_getlink",
"rtnl_bridge_notify",
"rtnl_bridge_setlink",
"rtnl_bridge_dellink"
],
"Reasoning": "The patch modifies core networking and bridging code (net/bridge/br_netlink.c, net/core/rtnetlink.c) to validate nested netlink attribute sizes using nla_nest_end_safe() and return -E2BIG with extended ack errors when nested attributes exceed U16_MAX. It also threads netlink_ext_ack down through ndo_bridge_getlink and bridge netlink helper functions. These code paths are fully reachable in virtualized environments via netlink bridge queries and modifications (PF_BRIDGE RTM_GETLINK / RTM_SETLINK / RTM_DELLINK).",
"WorthFuzzing": true
} |
| 35/1 | 2026/09/21 11:34 | action | If |
0mArgs:{
"WorthFuzzing": true
}Results: null |
| 36/2 | 2026/09/21 11:34 | agent | kmsan-evaluator |
0mModel:core Args: null Results: {
"KMSANReasoning": "The patch series plumbs a `netlink_ext_ack *extack` parameter through `ndo_bridge_getlink`, `ndo_dflt_bridge_getlink`, and several network device driver implementations. In `net/bridge/br_netlink.c`, it converts `nla_nest_end()` calls to `nla_nest_end_safe()` to guard against nested attribute length overflows (\u003e U16_MAX), reporting an error string via `NL_SET_ERR_MSG_MOD` on failure.\n\nThese changes do not allocate or copy any uninitialized heap, stack, or page memory, nor do they introduce struct padding leaks or conditional branching on uninitialized data. The extack message is a compile-time string literal. The bounds checking added via `nla_nest_end_safe()` strictly prevents attribute size truncation rather than enabling reads of uninitialized bytes. Thus, there are no uninitialized memory or info-leak risks that would necessitate a dedicated KMSAN fuzzing session.",
"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: Target architecture: amd64
For your convenience, here is the diff of the changes:
commit 284ebb15ce96705cc106dfbe5def8bcc3bf8fb2e
Author: syz-cluster <triage@syzkaller.com>
Date: Mon Sep 21 11:31:39 2026 +0000
syz-cluster: applied patch under review
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index ca99f4b1a63c3..a752e66bf6368 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -16154,12 +16154,12 @@ static const struct udp_tunnel_nic_info bnxt_udp_tunnels = {
static int bnxt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
struct net_device *dev, u32 filter_mask,
- int nlflags)
+ int nlflags, struct netlink_ext_ack *extack)
{
struct bnxt *bp = netdev_priv(dev);
return ndo_dflt_bridge_getlink(skb, pid, seq, dev, bp->br_mode, 0, 0,
- nlflags, filter_mask, NULL);
+ nlflags, filter_mask, NULL, extack);
}
static int bnxt_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index ed302f5ec4768..cc9c87539a429 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -5011,7 +5011,7 @@ static int be_ndo_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
static int be_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
struct net_device *dev, u32 filter_mask,
- int nlflags)
+ int nlflags, struct netlink_ext_ack *extack)
{
struct be_adapter *adapter = netdev_priv(dev);
int status = 0;
@@ -5037,7 +5037,7 @@ static int be_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
return ndo_dflt_bridge_getlink(skb, pid, seq, dev,
hsw_mode == PORT_FWD_TYPE_VEPA ?
BRIDGE_MODE_VEPA : BRIDGE_MODE_VEB,
- 0, 0, nlflags, filter_mask, NULL);
+ 0, 0, nlflags, filter_mask, NULL, extack);
}
static struct be_cmd_work *be_alloc_work(struct be_adapter *adapter,
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index abbc71e815ae3..52c2b393aacd2 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -13151,6 +13151,7 @@ static int i40e_ndo_bridge_setlink(struct net_device *dev,
* @dev: the netdev being configured
* @filter_mask: unused
* @nlflags: netlink flags passed in
+ * @extack: netlink extended ack
*
* Return the mode in which the hardware bridge is operating in
* i.e VEB or VEPA.
@@ -13158,7 +13159,8 @@ static int i40e_ndo_bridge_setlink(struct net_device *dev,
static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
struct net_device *dev,
u32 __always_unused filter_mask,
- int nlflags)
+ int nlflags,
+ struct netlink_ext_ack *extack)
{
struct i40e_netdev_priv *np = netdev_priv(dev);
struct i40e_vsi *vsi = np->vsi;
@@ -13175,7 +13177,7 @@ static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
return 0;
return ndo_dflt_bridge_getlink(skb, pid, seq, dev, veb->bridge_mode,
- 0, 0, nlflags, filter_mask, NULL);
+ 0, 0, nlflags, filter_mask, NULL, extack);
}
/**
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 707c7431b91a6..f98295438df78 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -8095,12 +8095,14 @@ int ice_set_rss_hfunc(struct ice_vsi *vsi, u8 hfunc)
* @dev: the netdev being configured
* @filter_mask: filter mask passed in
* @nlflags: netlink flags passed in
+ * @extack: netlink extended ack
*
* Return the bridge mode (VEB/VEPA)
*/
static int
ice_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
- struct net_device *dev, u32 filter_mask, int nlflags)
+ struct net_device *dev, u32 filter_mask, int nlflags,
+ struct netlink_ext_ack *extack)
{
struct ice_pf *pf = ice_netdev_to_pf(dev);
u16 bmode;
@@ -8108,7 +8110,7 @@ ice_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
bmode = pf->first_sw->bridge_mode;
return ndo_dflt_bridge_getlink(skb, pid, seq, dev, bmode, 0, 0, nlflags,
- filter_mask, NULL);
+ filter_mask, NULL, extack);
}
/**
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index f91856498eb2d..77dfd80a6e368 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -10726,7 +10726,8 @@ static int ixgbe_ndo_bridge_setlink(struct net_device *dev,
static int ixgbe_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
struct net_device *dev,
- u32 filter_mask, int nlflags)
+ u32 filter_mask, int nlflags,
+ struct netlink_ext_ack *extack)
{
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
@@ -10735,7 +10736,7 @@ static int ixgbe_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
return ndo_dflt_bridge_getlink(skb, pid, seq, dev,
adapter->bridge_mode, 0, 0, nlflags,
- filter_mask, NULL);
+ filter_mask, NULL, extack);
}
static void *ixgbe_fwd_add(struct net_device *pdev, struct net_device *vdev)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index fc110a7d16e8d..53bf79dbe08de 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -5277,7 +5277,7 @@ static int mlx5e_xdp(struct net_device *dev, struct netdev_bpf *xdp)
#ifdef CONFIG_MLX5_ESWITCH
static int mlx5e_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
struct net_device *dev, u32 filter_mask,
- int nlflags)
+ int nlflags, struct netlink_ext_ack *extack)
{
struct mlx5e_priv *priv = netdev_priv(dev);
struct mlx5_core_dev *mdev = priv->mdev;
@@ -5288,7 +5288,7 @@ static int mlx5e_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
mode = setting ? BRIDGE_MODE_VEPA : BRIDGE_MODE_VEB;
return ndo_dflt_bridge_getlink(skb, pid, seq, dev,
mode,
- 0, 0, nlflags, filter_mask, NULL);
+ 0, 0, nlflags, filter_mask, NULL, extack);
}
static int mlx5e_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 7928e76da723e..cb751dddb6887 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -2257,7 +2257,7 @@ static int nfp_net_set_mac_address(struct net_device *netdev, void *addr)
static int nfp_net_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
struct net_device *dev, u32 filter_mask,
- int nlflags)
+ int nlflags, struct netlink_ext_ack *extack)
{
struct nfp_net *nn = netdev_priv(dev);
u16 mode;
@@ -2269,7 +2269,7 @@ static int nfp_net_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
BRIDGE_MODE_VEPA : BRIDGE_MODE_VEB;
return ndo_dflt_bridge_getlink(skb, pid, seq, dev, mode, 0, 0,
- nlflags, filter_mask, NULL);
+ nlflags, filter_mask, NULL, extack);
}
static int nfp_net_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index 2935c2ecc314b..f960cf5a97a29 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -935,7 +935,7 @@ static void qeth_l2_br2dev_put(void)
static int qeth_l2_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
struct net_device *dev, u32 filter_mask,
- int nlflags)
+ int nlflags, struct netlink_ext_ack *extack)
{
struct qeth_priv *priv = netdev_priv(dev);
struct qeth_card *card = dev->ml_priv;
@@ -949,7 +949,7 @@ static int qeth_l2_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
return ndo_dflt_bridge_getlink(skb, pid, seq, dev,
mode, priv->brport_features,
priv->brport_hw_features,
- nlflags, filter_mask, NULL);
+ nlflags, filter_mask, NULL, extack);
}
static const struct nla_policy qeth_brport_policy[IFLA_BRPORT_MAX + 1] = {
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 1f0710eef185b..02238b1e33453 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1360,7 +1360,7 @@ struct netdev_net_notifier {
* u16 flags, struct netlink_ext_ack *extack)
* int (*ndo_bridge_getlink)(struct sk_buff *skb, u32 pid, u32 seq,
* struct net_device *dev, u32 filter_mask,
- * int nlflags)
+ * int nlflags, struct netlink_ext_ack *extack)
* int (*ndo_bridge_dellink)(struct net_device *dev, struct nlmsghdr *nlh,
* u16 flags);
*
@@ -1659,7 +1659,8 @@ struct net_device_ops {
u32 pid, u32 seq,
struct net_device *dev,
u32 filter_mask,
- int nlflags);
+ int nlflags,
+ struct netlink_ext_ack *extack);
int (*ndo_bridge_dellink)(struct net_device *dev,
struct nlmsghdr *nlh,
u16 flags);
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 95729339e7a54..a408c36a7b558 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -222,7 +222,8 @@ extern int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
u32 filter_mask,
int (*vlan_fill)(struct sk_buff *skb,
struct net_device *dev,
- u32 filter_mask));
+ u32 filter_mask),
+ struct netlink_ext_ack *extack);
extern void rtnl_offload_xstats_notify(struct net_device *dev);
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index ae76df0de05a0..fbd91b86d4268 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -459,7 +459,7 @@ static int br_fill_ifinfo(struct sk_buff *skb,
const struct net_bridge_port *port,
u32 pid, u32 seq, int event, unsigned int flags,
u32 filter_mask, const struct net_device *dev,
- bool getlink)
+ bool getlink, struct netlink_ext_ack *extack)
{
u8 operstate = netif_running(dev) ? READ_ONCE(dev->operstate) :
IF_OPER_DOWN;
@@ -588,7 +588,8 @@ static int br_fill_ifinfo(struct sk_buff *skb,
goto nla_put_failure;
}
- nla_nest_end(skb, cfm_nest);
+ if (nla_nest_end_safe(skb, cfm_nest) < 0)
+ goto nla_nest_too_large;
}
if ((filter_mask & RTEXT_FILTER_MST) &&
@@ -608,20 +609,27 @@ static int br_fill_ifinfo(struct sk_buff *skb,
if (err)
goto nla_put_failure;
- nla_nest_end(skb, mst_nest);
+ if (nla_nest_end_safe(skb, mst_nest) < 0)
+ goto nla_nest_too_large;
}
done:
if (af) {
- if (nlmsg_get_pos(skb) - (void *)af > nla_attr_size(0))
- nla_nest_end(skb, af);
- else
+ if (nla_nest_end_safe(skb, af) < 0)
+ goto nla_nest_too_large;
+ if (!nla_len(af))
nla_nest_cancel(skb, af);
}
nlmsg_end(skb, nlh);
return 0;
+nla_nest_too_large:
+ NL_SET_ERR_MSG_MOD(extack,
+ "AF_SPEC info too large, use per-object dumps (e.g. RTM_GETVLAN)");
+ nlmsg_cancel(skb, nlh);
+ return -E2BIG;
+
nla_put_failure:
nlmsg_cancel(skb, nlh);
return -EMSGSIZE;
@@ -654,7 +662,8 @@ void br_info_notify(int event, const struct net_bridge *br,
if (skb == NULL)
goto errout;
- err = br_fill_ifinfo(skb, port, 0, 0, event, 0, filter, dev, false);
+ err = br_fill_ifinfo(skb, port, 0, 0, event, 0, filter, dev, false,
+ NULL);
if (err < 0) {
/* -EMSGSIZE implies BUG in br_nlmsg_size() */
WARN_ON(err == -EMSGSIZE);
@@ -680,7 +689,8 @@ void br_ifinfo_notify(int event, const struct net_bridge *br,
* Dump information about all ports, in response to GETLINK
*/
int br_getlink(struct sk_buff *skb, u32 pid, u32 seq,
- struct net_device *dev, u32 filter_mask, int nlflags)
+ struct net_device *dev, u32 filter_mask, int nlflags,
+ struct netlink_ext_ack *extack)
{
struct net_bridge_port *port = br_port_get_rtnl(dev);
@@ -692,7 +702,7 @@ int br_getlink(struct sk_buff *skb, u32 pid, u32 seq,
return 0;
return br_fill_ifinfo(skb, port, pid, seq, RTM_NEWLINK, nlflags,
- filter_mask, dev, true);
+ filter_mask, dev, true, extack);
}
static int br_vlan_info(struct net_bridge *br, struct net_bridge_port *p,
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 09c397e303307..edbe7a1f57363 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -2179,7 +2179,7 @@ int br_setlink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags,
struct netlink_ext_ack *extack);
int br_dellink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags);
int br_getlink(struct sk_buff *skb, u32 pid, u32 seq, struct net_device *dev,
- u32 filter_mask, int nlflags);
+ u32 filter_mask, int nlflags, struct netlink_ext_ack *extack);
int br_process_vlan_info(struct net_bridge *br,
struct net_bridge_port *p, int cmd,
struct bridge_vlan_info *vinfo_curr,
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index e3444fd240615..a341e06f47d31 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -5420,7 +5420,8 @@ int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
u32 filter_mask,
int (*vlan_fill)(struct sk_buff *skb,
struct net_device *dev,
- u32 filter_mask))
+ u32 filter_mask),
+ struct netlink_ext_ack *extack)
{
struct nlmsghdr *nlh;
struct ifinfomsg *ifm;
@@ -5596,7 +5597,8 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
if (idx >= cb->args[0]) {
err = br_dev->netdev_ops->ndo_bridge_getlink(
skb, portid, seq, dev,
- filter_mask, NLM_F_MULTI);
+ filter_mask, NLM_F_MULTI,
+ cb->extack);
if (err < 0 && err != -EOPNOTSUPP) {
if (likely(skb->len))
break;
@@ -5612,7 +5614,8 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
err = ops->ndo_bridge_getlink(skb, portid,
seq, dev,
filter_mask,
- NLM_F_MULTI);
+ NLM_F_MULTI,
+ cb->extack);
if (err < 0 && err != -EOPNOTSUPP) {
if (likely(skb->len))
break;
@@ -5646,7 +5649,8 @@ static inline size_t bridge_nlmsg_size(void)
+ nla_total_size(sizeof(u16)); /* IFLA_BRIDGE_MODE */
}
-static int rtnl_bridge_notify(struct net_device *dev)
+static int rtnl_bridge_notify(struct net_device *dev,
+ struct netlink_ext_ack *extack)
{
struct net *net = dev_net(dev);
struct sk_buff *skb;
@@ -5661,7 +5665,7 @@ static int rtnl_bridge_notify(struct net_device *dev)
goto errout;
}
- err = dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev, 0, 0);
+ err = dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev, 0, 0, extack);
if (err < 0)
goto errout;
@@ -5752,7 +5756,7 @@ static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
/* Generate event to notify upper layer of bridge
* change
*/
- err = rtnl_bridge_notify(dev);
+ err = rtnl_bridge_notify(dev, extack);
}
}
@@ -5827,7 +5831,7 @@ static int rtnl_bridge_dellink(struct sk_buff *skb, struct nlmsghdr *nlh,
/* Generate event to notify upper layer of bridge
* change
*/
- err = rtnl_bridge_notify(dev);
+ err = rtnl_bridge_notify(dev, extack);
}
}
|
| 37/3 | 2026/09/21 11:34 | llm | kmsan-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 8643 output: 22 thoughts: 660 Thoughts: **Evaluating the Need for a KMSAN Fuzzing Session** Okay, so I need to decide if this kernel patch warrants a dedicated KMSAN fuzzing run. Let's break this down. First, the rules of the game: if KASAN, Lockdep, or any of the usual suspects can catch a bug, there's no point in KMSAN. KMSAN is for the *unique* territory of uninitialized memory reads, whether they are on the stack, heap, or page allocations, and kernel-to-user memory info leaks. I need to make sure this patch *specifically* introduces or exposes this type of bug. Alright, let's look at the patch itself. It's touching `ndo_bridge_getlink` signatures; adding a `struct netlink_ext_ack *extack` parameter to it and `ndo_dflt_bridge_getlink`. Okay, standard stuff, adapting for extended ack. Then I see some changes within `net/bridge/br_netlink.c`. `br_fill_ifinfo` now takes `struct netlink_ext_ack *extack` too, which is consistent. The real meat seems to be around `nla_nest_end_safe`. It's replaced the standard `nla_nest_end` calls with `nla_nest_end_safe` and added error handling related to "AF_SPEC info too large." There are now checks and goto logic dealing with `nla_nest_too_large` which cancels the skb and returns -E2BIG. It seems like the patch introduces error handling to handle the case where the information being put into the nest is too large. The key question is, does this expose uninitialized memory? The changes appear to be more about error handling, preventing a large nest and potential buffer overflow, and improving error messaging. While the patch deals with the netlink and nested attributes, it doesn't immediately scream "uninitialized memory." I need to dig deeper into what `nla_nest_end_safe` *actually* does. Time to grep for that function and understand its implementation and use cases across the codebase. That will tell me if there's a latent KMSAN issue lurking in this patch. Based on this initial skim, my gut says **no** for KMSAN and more in line with a standard validation, but I won't fully trust my gut. Need to dive deeper into the implementation. |
| 38/3 | 2026/09/21 11:34 | tool | grepper |
0mArgs:{
"Expression": "nla_nest_end_safe"
}Results: {
"Output": "drivers/net/macvlan.c=1746=static int macvlan_fill_info(struct sk_buff *skb,\n--\ndrivers/net/macvlan.c-1778-\t\t\tnla_nest_cancel(skb, nest);\ndrivers/net/macvlan.c:1779:\t\telse if (nla_nest_end_safe(skb, nest) \u003c 0)\ndrivers/net/macvlan.c-1780-\t\t\tgoto nla_put_failure;\n--\ninclude/net/netlink.h=2261=static inline int nla_nest_end(struct sk_buff *skb, struct nlattr *start)\n--\ninclude/net/netlink.h-2270-/**\ninclude/net/netlink.h:2271: * nla_nest_end_safe - Validate and finalize nesting of attributes\ninclude/net/netlink.h-2272- * @skb: socket buffer the attributes are stored in\n--\ninclude/net/netlink.h-2280- */\ninclude/net/netlink.h:2281:static inline int nla_nest_end_safe(struct sk_buff *skb, struct nlattr *start)\ninclude/net/netlink.h-2282-{\n--\nnet/bridge/br_netlink.c=458=static int br_fill_ifinfo(struct sk_buff *skb,\n--\nnet/bridge/br_netlink.c-590-\nnet/bridge/br_netlink.c:591:\t\tif (nla_nest_end_safe(skb, cfm_nest) \u003c 0)\nnet/bridge/br_netlink.c-592-\t\t\tgoto nla_nest_too_large;\n--\nnet/bridge/br_netlink.c-611-\nnet/bridge/br_netlink.c:612:\t\tif (nla_nest_end_safe(skb, mst_nest) \u003c 0)\nnet/bridge/br_netlink.c-613-\t\t\tgoto nla_nest_too_large;\n--\nnet/bridge/br_netlink.c-617-\tif (af) {\nnet/bridge/br_netlink.c:618:\t\tif (nla_nest_end_safe(skb, af) \u003c 0)\nnet/bridge/br_netlink.c-619-\t\t\tgoto nla_nest_too_large;\n--\nnet/core/rtnetlink.c=2011=static int rtnl_fill_prop_list(struct sk_buff *skb,\n--\nnet/core/rtnetlink.c-2025-\tret = -EMSGSIZE;\nnet/core/rtnetlink.c:2026:\tif (nla_nest_end_safe(skb, prop_list) \u003c 0)\nnet/core/rtnetlink.c-2027-\t\tgoto nest_cancel;\n--\nnet/ethtool/strset.c=418=static int strset_fill_set(struct sk_buff *skb,\n--\nnet/ethtool/strset.c-445-\t\t}\nnet/ethtool/strset.c:446:\t\tif (nla_nest_end_safe(skb, strings_attr) \u003c 0)\nnet/ethtool/strset.c-447-\t\t\tgoto nla_put_failure;\n"
} |
| 39/3 | 2026/09/21 11:34 | llm | kmsan-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 10710 output: 37 thoughts: 22 Thoughts: Here's my summary, as if I were the one thinking it: **Diving into netlink.h** Okay, time to dig in. I need to get a better handle on how this netlink stuff works under the hood. Specifically, I'm going to start with `include/net/netlink.h`, and I'm zeroing in on the area around line 2281. Let's see what interesting tidbits are hiding in there. Hopefully, this section holds some clues about the particular issue I'm chasing, or at least provides a solid foundation for understanding the relevant structures or functions. Let's get to it. |
| 40/3 | 2026/09/21 11:34 | tool | read-file |
0mArgs:{
"File": "include/net/netlink.h",
"FirstLine": 2260,
"LineCount": 40
}Results: {
"Contents": "2260:\t */\n2261:\tstatic inline int nla_nest_end(struct sk_buff *skb, struct nlattr *start)\n2262:\t{\n2263:\t\tunsigned long diff = skb_tail_pointer(skb) - (unsigned char *)start;\n2264:\t\n2265:\t\tDEBUG_NET_WARN_ON_ONCE(diff \u003e U16_MAX);\n2266:\t\tstart-\u003enla_len = diff;\n2267:\t\treturn skb-\u003elen;\n2268:\t}\n2269:\t\n2270:\t/**\n2271:\t * nla_nest_end_safe - Validate and finalize nesting of attributes\n2272:\t * @skb: socket buffer the attributes are stored in\n2273:\t * @start: container attribute\n2274:\t *\n2275:\t * Corrects the container attribute header to include all appended\n2276:\t * attributes.\n2277:\t *\n2278:\t * Returns: the total data length of the skb, or -EMSGSIZE if the\n2279:\t * nested attribute length exceeds U16_MAX.\n2280:\t */\n2281:\tstatic inline int nla_nest_end_safe(struct sk_buff *skb, struct nlattr *start)\n2282:\t{\n2283:\t\tif (skb_tail_pointer(skb) - (unsigned char *)start \u003e U16_MAX)\n2284:\t\t\treturn -EMSGSIZE;\n2285:\t\n2286:\t\treturn nla_nest_end(skb, start);\n2287:\t}\n2288:\t\n2289:\t/**\n2290:\t * nla_nest_cancel - Cancel nesting of attributes\n2291:\t * @skb: socket buffer the message is stored in\n2292:\t * @start: container attribute\n2293:\t *\n2294:\t * Removes the container attribute and including all nested\n2295:\t * attributes. Returns -EMSGSIZE\n2296:\t */\n2297:\tstatic inline void nla_nest_cancel(struct sk_buff *skb, struct nlattr *start)\n2298:\t{\n2299:\t\tnlmsg_trim(skb, start);\n"
} |
| 41/3 | 2026/09/21 11:34 | llm | kmsan-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 11523 output: 38 thoughts: 34 Thoughts: Okay, here's my take on those thoughts, tailored for an expert audience: **Diving into `br_fill_ifinfo` - Pre and Post Line 610** Alright, let's take a closer look at `br_fill_ifinfo` within `net/bridge/br_netlink.c`. I need to zero in on how this function behaves *around* line 610. I know this is where things get interesting, probably related to… well, that's what I need to figure out, isn’t it? I have a hunch it might be related to a specific ifinfo attribute processing, or perhaps some kind of error handling or data structure modification. I need to understand what's happening *before* line 610, the *exact* state of variables or the logic involved, and then pinpoint the precise changes or actions initiated by line 610 and after. My goal is to comprehend the impact of that particular line and how it alters the flow or the state of this interface information. Time to dig in! |
| 42/3 | 2026/09/21 11:34 | tool | read-file |
0mArgs:{
"File": "net/bridge/br_netlink.c",
"FirstLine": 605,
"LineCount": 40
}Results: {
"Contents": " 605:\t\t\tif (!mst_nest)\n 606:\t\t\t\tgoto nla_put_failure;\n 607:\t\n 608:\t\t\terr = br_mst_fill_info(skb, vg);\n 609:\t\t\tif (err)\n 610:\t\t\t\tgoto nla_put_failure;\n 611:\t\n 612:\t\t\tif (nla_nest_end_safe(skb, mst_nest) \u003c 0)\n 613:\t\t\t\tgoto nla_nest_too_large;\n 614:\t\t}\n 615:\t\n 616:\tdone:\n 617:\t\tif (af) {\n 618:\t\t\tif (nla_nest_end_safe(skb, af) \u003c 0)\n 619:\t\t\t\tgoto nla_nest_too_large;\n 620:\t\t\tif (!nla_len(af))\n 621:\t\t\t\tnla_nest_cancel(skb, af);\n 622:\t\t}\n 623:\t\n 624:\t\tnlmsg_end(skb, nlh);\n 625:\t\treturn 0;\n 626:\t\n 627:\tnla_nest_too_large:\n 628:\t\tNL_SET_ERR_MSG_MOD(extack,\n 629:\t\t\t\t \"AF_SPEC info too large, use per-object dumps (e.g. RTM_GETVLAN)\");\n 630:\t\tnlmsg_cancel(skb, nlh);\n 631:\t\treturn -E2BIG;\n 632:\t\n 633:\tnla_put_failure:\n 634:\t\tnlmsg_cancel(skb, nlh);\n 635:\t\treturn -EMSGSIZE;\n 636:\t}\n 637:\t\n 638:\tvoid br_info_notify(int event, const struct net_bridge *br,\n 639:\t\t\t const struct net_bridge_port *port, u32 filter)\n 640:\t{\n 641:\t\tstruct net_device *dev;\n 642:\t\tstruct sk_buff *skb;\n 643:\t\tint err = -ENOBUFS;\n 644:\t\tstruct net *net;\n"
} |
| 43/3 | 2026/09/21 11:34 | llm | kmsan-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 12416 output: 38 thoughts: 287 Thoughts: **Analyzing the Code Modification**
Okay, let's break this down. I'm looking at this code snippet where we're handling nested attributes in the Netlink messages, specifically concerning how we're finishing a nested attribute set. My initial thought is to examine the implications of calling `!nla_len(af)` *after* `nla_nest_end_safe(skb, af)`. The original code, as I recall, used `nla_nest_end` or `nla_nest_cancel` based on the attribute's size relative to `nla_attr_size(0)`. Now, this is what the modification looks like:
```c
if (af) {
if (nla_nest_end_safe(skb, af) < 0)
goto nla_nest_too_large;
if (!nla_len(af))
nla_nest_cancel(skb, af);
}
```
The new code replaces the size check with `nla_nest_end_safe` and then introduces the `!nla_len(af)` check. My first question is about `nla_len(af)`. What exactly is that doing? I need to refresh my memory on what `nla_len` is defined as. Ah, right, it's:
`static inline int nla_len(const struct nlattr *nla) { return nla->nla_len - NLA_HDRLEN; }`
So, `nla_len` calculates the length of the attribute data by subtracting the header length, `NLA_HDRLEN`, from the total length stored in `nla->nla_len`. Essentially, this is a check for whether there is data inside a nested attribute. I need to remember the context of how `af` is created. That information is in `br_fill_ifinfo`... So, I'll need to double check that.
|
| 44/3 | 2026/09/21 11:34 | tool | read-file |
0mArgs:{
"File": "net/bridge/br_netlink.c",
"FirstLine": 560,
"LineCount": 45
}Results: {
"Contents": " 560:\t\t\tif (err)\n 561:\t\t\t\tgoto nla_put_failure;\n 562:\t\t}\n 563:\t\n 564:\t\tif (filter_mask \u0026 (RTEXT_FILTER_CFM_CONFIG | RTEXT_FILTER_CFM_STATUS)) {\n 565:\t\t\tstruct nlattr *cfm_nest = NULL;\n 566:\t\t\tint err;\n 567:\t\n 568:\t\t\tif (!br_cfm_created(br) || port)\n 569:\t\t\t\tgoto done;\n 570:\t\n 571:\t\t\tcfm_nest = nla_nest_start(skb, IFLA_BRIDGE_CFM);\n 572:\t\t\tif (!cfm_nest)\n 573:\t\t\t\tgoto nla_put_failure;\n 574:\t\n 575:\t\t\tif (filter_mask \u0026 RTEXT_FILTER_CFM_CONFIG) {\n 576:\t\t\t\trcu_read_lock();\n 577:\t\t\t\terr = br_cfm_config_fill_info(skb, br);\n 578:\t\t\t\trcu_read_unlock();\n 579:\t\t\t\tif (err)\n 580:\t\t\t\t\tgoto nla_put_failure;\n 581:\t\t\t}\n 582:\t\n 583:\t\t\tif (filter_mask \u0026 RTEXT_FILTER_CFM_STATUS) {\n 584:\t\t\t\trcu_read_lock();\n 585:\t\t\t\terr = br_cfm_status_fill_info(skb, br, getlink);\n 586:\t\t\t\trcu_read_unlock();\n 587:\t\t\t\tif (err)\n 588:\t\t\t\t\tgoto nla_put_failure;\n 589:\t\t\t}\n 590:\t\n 591:\t\t\tif (nla_nest_end_safe(skb, cfm_nest) \u003c 0)\n 592:\t\t\t\tgoto nla_nest_too_large;\n 593:\t\t}\n 594:\t\n 595:\t\tif ((filter_mask \u0026 RTEXT_FILTER_MST) \u0026\u0026\n 596:\t\t br_opt_get(br, BROPT_MST_ENABLED) \u0026\u0026 port) {\n 597:\t\t\tconst struct net_bridge_vlan_group *vg = nbp_vlan_group(port);\n 598:\t\t\tstruct nlattr *mst_nest;\n 599:\t\t\tint err;\n 600:\t\n 601:\t\t\tif (!vg || !vg-\u003enum_vlans)\n 602:\t\t\t\tgoto done;\n 603:\t\n 604:\t\t\tmst_nest = nla_nest_start(skb, IFLA_BRIDGE_MST);\n"
} |
| 45/3 | 2026/09/21 11:34 | llm | kmsan-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 13872 output: 38 thoughts: 20 Thoughts: Here's my thought process, as requested: **Tracing the Genesis of `af` in `br_fill_ifinfo`** Okay, so I need to understand where the variable `af` is initialized or assigned a value within the `br_fill_ifinfo` function. This is a pretty standard debugging step. It's often the first thing I do when I'm trying to understand how a specific variable is used or where its value originates. Knowing the creation point of a variable is crucial for tracking down bugs, understanding data flow, or just comprehending how a particular piece of code works. I'll need to go back and carefully examine the code preceding the point where `af` is used, looking for assignments, function calls that might return or modify it, or any other potential initialization. Time to dig in. |
| 46/3 | 2026/09/21 11:34 | tool | read-file |
0mArgs:{
"File": "net/bridge/br_netlink.c",
"FirstLine": 520,
"LineCount": 45
}Results: {
"Contents": " 520:\t\n 521:\t\t/* Check if the VID information is requested */\n 522:\t\tif ((filter_mask \u0026 RTEXT_FILTER_BRVLAN) ||\n 523:\t\t (filter_mask \u0026 RTEXT_FILTER_BRVLAN_COMPRESSED)) {\n 524:\t\t\tstruct net_bridge_vlan_group *vg;\n 525:\t\t\tint err;\n 526:\t\n 527:\t\t\t/* RCU needed because of the VLAN locking rules (rcu || rtnl) */\n 528:\t\t\trcu_read_lock();\n 529:\t\t\tif (port)\n 530:\t\t\t\tvg = nbp_vlan_group_rcu(port);\n 531:\t\t\telse\n 532:\t\t\t\tvg = br_vlan_group_rcu(br);\n 533:\t\n 534:\t\t\tif (!vg || !READ_ONCE(vg-\u003enum_vlans)) {\n 535:\t\t\t\trcu_read_unlock();\n 536:\t\t\t\tgoto done;\n 537:\t\t\t}\n 538:\t\t\tif (filter_mask \u0026 RTEXT_FILTER_BRVLAN_COMPRESSED)\n 539:\t\t\t\terr = br_fill_ifvlaninfo_compressed(skb, vg);\n 540:\t\t\telse\n 541:\t\t\t\terr = br_fill_ifvlaninfo(skb, vg);\n 542:\t\n 543:\t\t\tif (port \u0026\u0026 test_bit(BR_VLAN_TUNNEL_BIT, \u0026port-\u003eflags))\n 544:\t\t\t\terr = br_fill_vlan_tunnel_info(skb, vg);\n 545:\t\t\trcu_read_unlock();\n 546:\t\t\tif (err)\n 547:\t\t\t\tgoto nla_put_failure;\n 548:\t\t}\n 549:\t\n 550:\t\tif (filter_mask \u0026 RTEXT_FILTER_MRP) {\n 551:\t\t\tint err;\n 552:\t\n 553:\t\t\tif (!br_mrp_enabled(br) || port)\n 554:\t\t\t\tgoto done;\n 555:\t\n 556:\t\t\trcu_read_lock();\n 557:\t\t\terr = br_mrp_fill_info(skb, br);\n 558:\t\t\trcu_read_unlock();\n 559:\t\n 560:\t\t\tif (err)\n 561:\t\t\t\tgoto nla_put_failure;\n 562:\t\t}\n 563:\t\n 564:\t\tif (filter_mask \u0026 (RTEXT_FILTER_CFM_CONFIG | RTEXT_FILTER_CFM_STATUS)) {\n"
} |
| 47/3 | 2026/09/21 11:34 | llm | kmsan-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 14801 output: 38 thoughts: 22 Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience: **Tracing the Execution Path of `af`** Okay, so I need to understand where the `af` function is initiated within this codebase. Let's get to the specifics; jumping around within the code to lines 480-520 seems like a logical starting point to locate its initial call. Hopefully, I'll find its origin point there, which is critical for comprehending its subsequent behavior. |
| 48/3 | 2026/09/21 11:34 | tool | read-file |
0mArgs:{
"File": "net/bridge/br_netlink.c",
"FirstLine": 480,
"LineCount": 45
}Results: {
"Contents": " 480:\t\tif (nlh == NULL)\n 481:\t\t\treturn -EMSGSIZE;\n 482:\t\n 483:\t\thdr = nlmsg_data(nlh);\n 484:\t\thdr-\u003eifi_family = AF_BRIDGE;\n 485:\t\thdr-\u003e__ifi_pad = 0;\n 486:\t\thdr-\u003eifi_type = dev-\u003etype;\n 487:\t\thdr-\u003eifi_index = dev-\u003eifindex;\n 488:\t\thdr-\u003eifi_flags = netif_get_flags(dev);\n 489:\t\thdr-\u003eifi_change = 0;\n 490:\t\n 491:\t\tif (nla_put_string(skb, IFLA_IFNAME, dev-\u003ename) ||\n 492:\t\t nla_put_u32(skb, IFLA_MASTER, br-\u003edev-\u003eifindex) ||\n 493:\t\t nla_put_u32(skb, IFLA_MTU, dev-\u003emtu) ||\n 494:\t\t nla_put_u8(skb, IFLA_OPERSTATE, operstate) ||\n 495:\t\t (dev-\u003eaddr_len \u0026\u0026\n 496:\t\t nla_put(skb, IFLA_ADDRESS, dev-\u003eaddr_len, dev-\u003edev_addr)) ||\n 497:\t\t (dev-\u003eifindex != dev_get_iflink(dev) \u0026\u0026\n 498:\t\t nla_put_u32(skb, IFLA_LINK, dev_get_iflink(dev))))\n 499:\t\t\tgoto nla_put_failure;\n 500:\t\n 501:\t\tif (event == RTM_NEWLINK \u0026\u0026 port) {\n 502:\t\t\tstruct nlattr *nest;\n 503:\t\n 504:\t\t\tnest = nla_nest_start(skb, IFLA_PROTINFO);\n 505:\t\t\tif (nest == NULL || br_port_fill_attrs(skb, port) \u003c 0)\n 506:\t\t\t\tgoto nla_put_failure;\n 507:\t\t\tnla_nest_end(skb, nest);\n 508:\t\t}\n 509:\t\n 510:\t\tif (filter_mask \u0026 (RTEXT_FILTER_BRVLAN |\n 511:\t\t\t\t RTEXT_FILTER_BRVLAN_COMPRESSED |\n 512:\t\t\t\t RTEXT_FILTER_MRP |\n 513:\t\t\t\t RTEXT_FILTER_CFM_CONFIG |\n 514:\t\t\t\t RTEXT_FILTER_CFM_STATUS |\n 515:\t\t\t\t RTEXT_FILTER_MST)) {\n 516:\t\t\taf = nla_nest_start_noflag(skb, IFLA_AF_SPEC);\n 517:\t\t\tif (!af)\n 518:\t\t\t\tgoto nla_put_failure;\n 519:\t\t}\n 520:\t\n 521:\t\t/* Check if the VID information is requested */\n 522:\t\tif ((filter_mask \u0026 RTEXT_FILTER_BRVLAN) ||\n 523:\t\t (filter_mask \u0026 RTEXT_FILTER_BRVLAN_COMPRESSED)) {\n 524:\t\t\tstruct net_bridge_vlan_group *vg;\n"
} |
| 49/3 | 2026/09/21 11:34 | llm | kmsan-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 15816 output: 38 thoughts: 553 Thoughts: **Analyzing the AF_SPEC Attribute Handling in Netlink Messages** Okay, let's break this down. I'm looking at how the `AF_SPEC` attribute is handled within the Netlink messages. It starts with `nla_nest_start_noflag(skb, IFLA_AF_SPEC)`, which I know creates a nested attribute. Inside this `af` attribute, various child attributes are placed, like VLANs, MRP, CFM, and MST. The code's been updated, so I'm comparing the old and the new versions. Previously, there was a check to see if anything had been added inside. If not, the nested attribute was either ended or canceled. Now, the `nla_nest_end_safe(skb, af)` function is used. Essentially, it calculates the length of the nested attribute, which is the difference between the current tail of the SKB and the start of the `af` attribute. This difference becomes the `nla_len` field. The crucial part is if nothing *was* added, the calculated length is just the size of the `nlattr` header ( `sizeof(struct nlattr)`), so `nla_len(af)` will be zero. In that case, we need `nla_nest_cancel(skb, af)`, which trims the SKB back to the point just *before* we started the nested attribute. Now, here's an important detail: `nla_nest_end_safe` has this safeguard. If the calculated length is larger than `U16_MAX`, it returns a negative value. That means the attribute's getting too big. It jumps to `nla_nest_too_large`, cancels the entire Netlink message using `nlmsg_cancel(skb, nlh)`, and sets an error message indicating that we should use per-object dumps, e.g., RTM_GETVLAN and returns `-E2BIG`. I should probably see if `ndo_dflt_bridge_getlink` in `net/core/rtnetlink.c` is properly using the extended ack framework. Let me check lines 5420-5450 in `net/core/rtnetlink.c`. |
| 50/3 | 2026/09/21 11:34 | tool | read-file |
0mArgs:{
"File": "net/core/rtnetlink.c",
"FirstLine": 5420,
"LineCount": 45
}Results: {
"Contents": "5420:\t\t\t\t u32 filter_mask,\n5421:\t\t\t\t int (*vlan_fill)(struct sk_buff *skb,\n5422:\t\t\t\t\t\t struct net_device *dev,\n5423:\t\t\t\t\t\t u32 filter_mask),\n5424:\t\t\t\t struct netlink_ext_ack *extack)\n5425:\t{\n5426:\t\tstruct nlmsghdr *nlh;\n5427:\t\tstruct ifinfomsg *ifm;\n5428:\t\tstruct nlattr *br_afspec;\n5429:\t\tstruct nlattr *protinfo;\n5430:\t\tu8 operstate = netif_running(dev) ? dev-\u003eoperstate : IF_OPER_DOWN;\n5431:\t\tstruct net_device *br_dev = netdev_master_upper_dev_get(dev);\n5432:\t\tint err = 0;\n5433:\t\n5434:\t\tnlh = nlmsg_put(skb, pid, seq, RTM_NEWLINK, sizeof(*ifm), nlflags);\n5435:\t\tif (nlh == NULL)\n5436:\t\t\treturn -EMSGSIZE;\n5437:\t\n5438:\t\tifm = nlmsg_data(nlh);\n5439:\t\tifm-\u003eifi_family = AF_BRIDGE;\n5440:\t\tifm-\u003e__ifi_pad = 0;\n5441:\t\tifm-\u003eifi_type = dev-\u003etype;\n5442:\t\tifm-\u003eifi_index = dev-\u003eifindex;\n5443:\t\tifm-\u003eifi_flags = netif_get_flags(dev);\n5444:\t\tifm-\u003eifi_change = 0;\n5445:\t\n5446:\t\n5447:\t\tif (nla_put_string(skb, IFLA_IFNAME, dev-\u003ename) ||\n5448:\t\t nla_put_u32(skb, IFLA_MTU, dev-\u003emtu) ||\n5449:\t\t nla_put_u8(skb, IFLA_OPERSTATE, operstate) ||\n5450:\t\t (br_dev \u0026\u0026\n5451:\t\t nla_put_u32(skb, IFLA_MASTER, br_dev-\u003eifindex)) ||\n5452:\t\t (dev-\u003eaddr_len \u0026\u0026\n5453:\t\t nla_put(skb, IFLA_ADDRESS, dev-\u003eaddr_len, dev-\u003edev_addr)) ||\n5454:\t\t (dev-\u003eifindex != dev_get_iflink(dev) \u0026\u0026\n5455:\t\t nla_put_u32(skb, IFLA_LINK, dev_get_iflink(dev))))\n5456:\t\t\tgoto nla_put_failure;\n5457:\t\n5458:\t\tbr_afspec = nla_nest_start_noflag(skb, IFLA_AF_SPEC);\n5459:\t\tif (!br_afspec)\n5460:\t\t\tgoto nla_put_failure;\n5461:\t\n5462:\t\tif (nla_put_u16(skb, IFLA_BRIDGE_FLAGS, BRIDGE_FLAGS_SELF)) {\n5463:\t\t\tnla_nest_cancel(skb, br_afspec);\n5464:\t\t\tgoto nla_put_failure;\n"
} |
| 51/3 | 2026/09/21 11:34 | llm | kmsan-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 17770 output: 38 thoughts: 19 Thoughts: Okay, here's my take on those thoughts, tailored for an expert audience, and delivered as a first-person summary: **Digging Deeper into `ndo_dflt_bridge_getlink`** Right, so we're looking at `ndo_dflt_bridge_getlink`. Okay, I get it; we need to examine this further. We already know the function name, the context. Let's see what else we can uncover about this particular function and see if there are any gotchas in the surrounding code. Gotta make sure we've got the full picture here before making any moves. Let's start by looking at how the function is used by the system. |
| 52/3 | 2026/09/21 11:34 | tool | read-file |
0mArgs:{
"File": "net/core/rtnetlink.c",
"FirstLine": 5465,
"LineCount": 45
}Results: {
"Contents": "5465:\t\t}\n5466:\t\n5467:\t\tif (mode != BRIDGE_MODE_UNDEF) {\n5468:\t\t\tif (nla_put_u16(skb, IFLA_BRIDGE_MODE, mode)) {\n5469:\t\t\t\tnla_nest_cancel(skb, br_afspec);\n5470:\t\t\t\tgoto nla_put_failure;\n5471:\t\t\t}\n5472:\t\t}\n5473:\t\tif (vlan_fill) {\n5474:\t\t\terr = vlan_fill(skb, dev, filter_mask);\n5475:\t\t\tif (err) {\n5476:\t\t\t\tnla_nest_cancel(skb, br_afspec);\n5477:\t\t\t\tgoto nla_put_failure;\n5478:\t\t\t}\n5479:\t\t}\n5480:\t\tnla_nest_end(skb, br_afspec);\n5481:\t\n5482:\t\tprotinfo = nla_nest_start(skb, IFLA_PROTINFO);\n5483:\t\tif (!protinfo)\n5484:\t\t\tgoto nla_put_failure;\n5485:\t\n5486:\t\tif (brport_nla_put_flag(skb, flags, mask,\n5487:\t\t\t\t\tIFLA_BRPORT_MODE, BR_HAIRPIN_MODE) ||\n5488:\t\t brport_nla_put_flag(skb, flags, mask,\n5489:\t\t\t\t\tIFLA_BRPORT_GUARD, BR_BPDU_GUARD) ||\n5490:\t\t brport_nla_put_flag(skb, flags, mask,\n5491:\t\t\t\t\tIFLA_BRPORT_FAST_LEAVE,\n5492:\t\t\t\t\tBR_MULTICAST_FAST_LEAVE) ||\n5493:\t\t brport_nla_put_flag(skb, flags, mask,\n5494:\t\t\t\t\tIFLA_BRPORT_PROTECT, BR_ROOT_BLOCK) ||\n5495:\t\t brport_nla_put_flag(skb, flags, mask,\n5496:\t\t\t\t\tIFLA_BRPORT_LEARNING, BR_LEARNING) ||\n5497:\t\t brport_nla_put_flag(skb, flags, mask,\n5498:\t\t\t\t\tIFLA_BRPORT_LEARNING_SYNC, BR_LEARNING_SYNC) ||\n5499:\t\t brport_nla_put_flag(skb, flags, mask,\n5500:\t\t\t\t\tIFLA_BRPORT_UNICAST_FLOOD, BR_FLOOD) ||\n5501:\t\t brport_nla_put_flag(skb, flags, mask,\n5502:\t\t\t\t\tIFLA_BRPORT_PROXYARP, BR_PROXYARP) ||\n5503:\t\t brport_nla_put_flag(skb, flags, mask,\n5504:\t\t\t\t\tIFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD) ||\n5505:\t\t brport_nla_put_flag(skb, flags, mask,\n5506:\t\t\t\t\tIFLA_BRPORT_BCAST_FLOOD, BR_BCAST_FLOOD)) {\n5507:\t\t\tnla_nest_cancel(skb, protinfo);\n5508:\t\t\tgoto nla_put_failure;\n5509:\t\t}\n"
} |
| 53/3 | 2026/09/21 11:34 | llm | kmsan-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 18854 output: 239 thoughts: 1017 Thoughts: **KMSAN Assessment: No Uninitialized Memory Risks** Okay, let's break this down from a memory safety perspective. My primary concern is always uninitialized memory, leaks, and potential KASAN/KMSAN implications. The code I'm analyzing primarily deals with netlink messages and bridge interfaces. My focus is on determining if this patch introduces any new risks in that domain. Initially, I see `ndo_dflt_bridge_getlink` doesn't even use `extack` except as an argument. All the driver implementations appear to simply pass `extack` through to this function. Now in `br_netlink.c`, it's passed to `br_fill_ifinfo` and used within a call to `NL_SET_ERR_MSG_MOD` if `nla_nest_end_safe` detects that nested attributes exceed `U16_MAX`, so a nested netlink attribute overflow is the main threat to consider. I'll have to see how `extack` is passed to the other functions, to track if it is used. Looking into `rtnl_bridge_getlink` in `net/core/rtnetlink.c`, I see that it passes `cb->extack` to `ndo_bridge_getlink`. And `rtnl_bridge_notify` propagates `extack` from either `rtnl_bridge_setlink` or `rtnl_bridge_dellink`. This means there's propagation, but no new allocation. Now, for potential uninitialized memory risks, I need to methodically check: Are any structures sent to user space where fields or padding might not be fully initialized? The answer is no, because this patch doesn't send any. The code *only* checks the return value of `nla_nest_end_safe`. Conditional logic or branching based on uninitialized variables? Also no. The new check is on the return of a well-defined integer. Allocation or initialization of complex data structures? None added here. Bounds checks, lengths, or logic that could allow access to uninitialized bytes? The new check *prevents* overflow by using `nla_nest_end_safe`. This check enforces a hard limit of `U16_MAX` on nested attribute lengths. If exceeded, it errors out with `-E2BIG`. This is important: `nla_nest_end_safe` replaces the previous, potentially unsafe behavior where `diff` (length difference) could truncate if it exceeded `U16_MAX`. It checks, and then returns `-E2BIG`. The patch handles `extack` correctly and cancels netlink message when errors happen. The pointers and buffers are existing, handled by standard netlink helpers. The `extack` pointer is managed by the netlink core. So, is there any uninitialized memory read or info leak? Absolutely none. Does the patch introduce new uninitialized memory issues? No. Can standard KASAN or detectors catch potential bugs? Yes, standard KASAN and testing will handle any standard errors or pointer issues that arise. Therefore, because there are zero uninitialized memory risks or potential info leaks, `NeedsKMSAN = false`. KMSAN is for detecting memory leaks from kernel space, and this patch doesn't introduce any new allocations that could contribute to this. Standard KASAN is sufficient for the issues presented here. This is well-reasoned and documented. Calling `set-results`. |
| 54/3 | 2026/09/21 11:34 | tool | set-results |
0mArgs:{
"KMSANReasoning": "The patch series plumbs a `netlink_ext_ack *extack` parameter through `ndo_bridge_getlink`, `ndo_dflt_bridge_getlink`, and several network device driver implementations. In `net/bridge/br_netlink.c`, it converts `nla_nest_end()` calls to `nla_nest_end_safe()` to guard against nested attribute length overflows (\u003e U16_MAX), reporting an error string via `NL_SET_ERR_MSG_MOD` on failure.\n\nThese changes do not allocate or copy any uninitialized heap, stack, or page memory, nor do they introduce struct padding leaks or conditional branching on uninitialized data. The extack message is a compile-time string literal. The bounds checking added via `nla_nest_end_safe()` strictly prevents attribute size truncation rather than enabling reads of uninitialized bytes. Thus, there are no uninitialized memory or info-leak risks that would necessitate a dedicated KMSAN fuzzing session.",
"NeedsKMSAN": false
}Results: {
"KMSANReasoning": "The patch series plumbs a `netlink_ext_ack *extack` parameter through `ndo_bridge_getlink`, `ndo_dflt_bridge_getlink`, and several network device driver implementations. In `net/bridge/br_netlink.c`, it converts `nla_nest_end()` calls to `nla_nest_end_safe()` to guard against nested attribute length overflows (\u003e U16_MAX), reporting an error string via `NL_SET_ERR_MSG_MOD` on failure.\n\nThese changes do not allocate or copy any uninitialized heap, stack, or page memory, nor do they introduce struct padding leaks or conditional branching on uninitialized data. The extack message is a compile-time string literal. The bounds checking added via `nla_nest_end_safe()` strictly prevents attribute size truncation rather than enabling reads of uninitialized bytes. Thus, there are no uninitialized memory or info-leak risks that would necessitate a dedicated KMSAN fuzzing session.",
"NeedsKMSAN": false
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|