* [PATCH net-next v2 0/2] bridge: report an oversized IFLA_AF_SPEC nest instead of truncating
@ 2026-09-12 13:50 Artem Lytkin
2026-09-12 13:50 ` [PATCH net-next v2 1/2] rtnetlink: pass extack to ndo_bridge_getlink() Artem Lytkin
2026-09-12 13:50 ` [PATCH net-next v2 2/2] net: bridge: fail link info that does not fit the IFLA_AF_SPEC nest Artem Lytkin
0 siblings, 2 replies; 7+ messages in thread
From: Artem Lytkin @ 2026-09-12 13:50 UTC (permalink / raw)
To: netdev
Cc: bridge, razor, idosch, davem, edumazet, kuba, pabeni, horms,
andrew+netdev, kuniyu, michael.chan, pavan.chebbi, ajit.khaparde,
sriharsha.basavapatna, anthony.l.nguyen, przemyslaw.kitszel,
intel-wired-lan, saeedm, tariqt, mbloch, oss-drivers, wintera,
aswin, linux-s390
v1 clamped the VLAN lists to keep the nest under the u16 nla_len.
Nikolay asked for an explicit error for both RTM_GETLINK and
notifications, with the extack set by the bridge itself. So patch 1
plumbs extack through ndo_bridge_getlink() and patch 2 returns -E2BIG
and points userspace at RTM_GETVLAN.
v1: https://lore.kernel.org/netdev/20260906224246.21719-1-iprintercanon@gmail.com/
Artem Lytkin (2):
rtnetlink: pass extack to ndo_bridge_getlink()
net: bridge: fail link info that does not fit the IFLA_AF_SPEC nest
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 4 ++--
drivers/net/ethernet/emulex/benet/be_main.c | 4 ++--
drivers/net/ethernet/intel/i40e/i40e_main.c | 6 ++++--
drivers/net/ethernet/intel/ice/ice_main.c | 6 ++++--
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 5 +++--
.../net/ethernet/mellanox/mlx5/core/en_main.c | 4 ++--
.../ethernet/netronome/nfp/nfp_net_common.c | 4 ++--
drivers/s390/net/qeth_l2_main.c | 4 ++--
include/linux/netdevice.h | 5 +++--
include/linux/rtnetlink.h | 3 ++-
net/bridge/br_netlink.c | 16 ++++++++++++----
net/bridge/br_private.h | 2 +-
net/core/rtnetlink.c | 18 +++++++++++-------
13 files changed, 50 insertions(+), 31 deletions(-)
base-commit: 879e280b8486d4612ad1aa050d6fada2dd80cf1c
--
2.43.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH net-next v2 1/2] rtnetlink: pass extack to ndo_bridge_getlink()
2026-09-12 13:50 [PATCH net-next v2 0/2] bridge: report an oversized IFLA_AF_SPEC nest instead of truncating Artem Lytkin
@ 2026-09-12 13:50 ` Artem Lytkin
2026-09-13 13:50 ` sashiko-bot
2026-09-12 13:50 ` [PATCH net-next v2 2/2] net: bridge: fail link info that does not fit the IFLA_AF_SPEC nest Artem Lytkin
1 sibling, 1 reply; 7+ messages in thread
From: Artem Lytkin @ 2026-09-12 13:50 UTC (permalink / raw)
To: netdev
Cc: bridge, razor, idosch, davem, edumazet, kuba, pabeni, horms,
andrew+netdev, kuniyu, michael.chan, pavan.chebbi, ajit.khaparde,
sriharsha.basavapatna, anthony.l.nguyen, przemyslaw.kitszel,
intel-wired-lan, saeedm, tariqt, mbloch, oss-drivers, wintera,
aswin, linux-s390
Let the bridge report why it could not fill in the link info for a
port. rtnl_bridge_getlink() passes the dump extack, rtnl_bridge_notify()
gets one from its setlink and dellink callers.
No functional change.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Artem Lytkin <iprintercanon@gmail.com>
---
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 4 ++--
drivers/net/ethernet/emulex/benet/be_main.c | 4 ++--
drivers/net/ethernet/intel/i40e/i40e_main.c | 6 ++++--
drivers/net/ethernet/intel/ice/ice_main.c | 6 ++++--
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 5 +++--
.../net/ethernet/mellanox/mlx5/core/en_main.c | 4 ++--
.../ethernet/netronome/nfp/nfp_net_common.c | 4 ++--
drivers/s390/net/qeth_l2_main.c | 4 ++--
include/linux/netdevice.h | 5 +++--
include/linux/rtnetlink.h | 3 ++-
net/bridge/br_netlink.c | 3 ++-
net/bridge/br_private.h | 2 +-
net/core/rtnetlink.c | 18 +++++++++++-------
13 files changed, 40 insertions(+), 28 deletions(-)
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 fe47ec0ba8094..038ce1fe5bfe5 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -8086,12 +8086,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;
@@ -8099,7 +8101,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 707b2e51c2b97..18a03f0f6f113 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..855a46aec3a89 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -680,7 +680,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);
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 be9d1625bac31..967b587ef6648 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -5398,7 +5398,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;
@@ -5574,7 +5575,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;
@@ -5590,7 +5592,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;
@@ -5624,7 +5627,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;
@@ -5639,7 +5643,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;
@@ -5730,7 +5734,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);
}
}
@@ -5805,7 +5809,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);
}
}
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH net-next v2 2/2] net: bridge: fail link info that does not fit the IFLA_AF_SPEC nest
2026-09-12 13:50 [PATCH net-next v2 0/2] bridge: report an oversized IFLA_AF_SPEC nest instead of truncating Artem Lytkin
2026-09-12 13:50 ` [PATCH net-next v2 1/2] rtnetlink: pass extack to ndo_bridge_getlink() Artem Lytkin
@ 2026-09-12 13:50 ` Artem Lytkin
2026-09-13 13:50 ` sashiko-bot
` (2 more replies)
1 sibling, 3 replies; 7+ messages in thread
From: Artem Lytkin @ 2026-09-12 13:50 UTC (permalink / raw)
To: netdev
Cc: bridge, razor, idosch, davem, edumazet, kuba, pabeni, horms,
andrew+netdev, kuniyu, michael.chan, pavan.chebbi, ajit.khaparde,
sriharsha.basavapatna, anthony.l.nguyen, przemyslaw.kitszel,
intel-wired-lan, saeedm, tariqt, mbloch, oss-drivers, wintera,
aswin, linux-s390
br_fill_ifinfo() puts all of a port's VLAN, tunnel and MST entries into
one nest, and nla_len is a u16, so a large enough port produces a nest
whose length wraps and userspace reads garbage.
Cancel the message and return -E2BIG with an extack pointing at
RTM_GETVLAN instead. The dump retries the port with an empty skb and
the error goes to userspace; notifications reach rtnl_set_sk_err() and
listeners resync. Not -EMSGSIZE, since no bigger buffer would help.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Artem Lytkin <iprintercanon@gmail.com>
---
net/bridge/br_netlink.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 855a46aec3a89..53676df9e4d11 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;
@@ -613,6 +613,12 @@ static int br_fill_ifinfo(struct sk_buff *skb,
done:
if (af) {
+ if (skb_tail_pointer(skb) - (unsigned char *)af > U16_MAX) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "VLAN information does not fit in one message, use RTM_GETVLAN");
+ nlmsg_cancel(skb, nlh);
+ return -E2BIG;
+ }
if (nlmsg_get_pos(skb) - (void *)af > nla_attr_size(0))
nla_nest_end(skb, af);
else
@@ -654,7 +660,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);
@@ -693,7 +700,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,
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH net-next v2 1/2] rtnetlink: pass extack to ndo_bridge_getlink()
2026-09-12 13:50 ` [PATCH net-next v2 1/2] rtnetlink: pass extack to ndo_bridge_getlink() Artem Lytkin
@ 2026-09-13 13:50 ` sashiko-bot
0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-09-13 13:50 UTC (permalink / raw)
To: Artem Lytkin
Cc: linux-s390, Heiko Carstens, Vasily Gorbik, Christian Borntraeger,
Alexander Gordeev
> Let the bridge report why it could not fill in the link info for a
> port. rtnl_bridge_getlink() passes the dump extack, rtnl_bridge_notify()
> gets one from its setlink and dellink callers.
>
> No functional change.
>
> Assisted-by: Claude:claude-opus-5
> Signed-off-by: Artem Lytkin <iprintercanon@gmail.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260912135022.1701-1-iprintercanon@gmail.com?part=1
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net-next v2 2/2] net: bridge: fail link info that does not fit the IFLA_AF_SPEC nest
2026-09-12 13:50 ` [PATCH net-next v2 2/2] net: bridge: fail link info that does not fit the IFLA_AF_SPEC nest Artem Lytkin
@ 2026-09-13 13:50 ` sashiko-bot
2026-09-14 8:48 ` Nikolay Aleksandrov
2026-09-15 18:51 ` netdev-bot+sashiko
2 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-09-13 13:50 UTC (permalink / raw)
To: Artem Lytkin
Cc: linux-s390, Vasily Gorbik, Alexander Gordeev, Heiko Carstens,
Christian Borntraeger
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] br_info_notify() propagates -E2BIG to rtnl_set_sk_err(), bypassing NETLINK_NO_ENOBUFS and breaking listeners.
--
commit 9b1aaa64ff49b7a437b098d6d662cc77e1219f4b
Author: Artem Lytkin <iprintercanon@gmail.com>
net: bridge: fail link info that does not fit the IFLA_AF_SPEC nest
br_fill_ifinfo() puts all of a port's VLAN, tunnel and MST entries into
one nest, and nla_len is a u16, so a large enough port produces a nest
whose length wraps and userspace reads garbage.
Cancel the message and return -E2BIG with an extack pointing at
RTM_GETVLAN instead. The dump retries the port with an empty skb and
the error goes to userspace; notifications reach rtnl_set_sk_err() and
listeners resync. Not -EMSGSIZE, since no bigger buffer would help.
> diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
> index 855a46aec3a89..53676df9e4d11 100644
> --- a/net/bridge/br_netlink.c
> +++ b/net/bridge/br_netlink.c
[ ... ]
> @@ -654,7 +660,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);
[Severity: High]
The commit message states "notifications reach rtnl_set_sk_err() and
listeners resync." Could this approach introduce a regression where -E2BIG
is broadcasted to netlink listeners instead of being filtered?
When br_fill_ifinfo() returns -E2BIG due to adding many VLANs to a bridge
port, br_info_notify() will jump to the errout label and pass the error to
rtnl_set_sk_err():
errout:
rtnl_set_sk_err(net, RTNLGRP_LINK, err);
Passing -E2BIG here bypasses the NETLINK_NO_ENOBUFS socket option which
only filters ENOBUFS. Will this unhandled E2BIG error cause network
management daemons to crash or drop connections?
Might this lead to a system-wide denial of service if unprivileged users
trigger this path?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260912135022.1701-1-iprintercanon@gmail.com?part=2
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net-next v2 2/2] net: bridge: fail link info that does not fit the IFLA_AF_SPEC nest
2026-09-12 13:50 ` [PATCH net-next v2 2/2] net: bridge: fail link info that does not fit the IFLA_AF_SPEC nest Artem Lytkin
2026-09-13 13:50 ` sashiko-bot
@ 2026-09-14 8:48 ` Nikolay Aleksandrov
2026-09-15 18:51 ` netdev-bot+sashiko
2 siblings, 0 replies; 7+ messages in thread
From: Nikolay Aleksandrov @ 2026-09-14 8:48 UTC (permalink / raw)
To: Artem Lytkin, netdev
Cc: bridge, idosch, davem, edumazet, kuba, pabeni, horms,
andrew+netdev, kuniyu, michael.chan, pavan.chebbi, ajit.khaparde,
sriharsha.basavapatna, anthony.l.nguyen, przemyslaw.kitszel,
intel-wired-lan, saeedm, tariqt, mbloch, oss-drivers, wintera,
aswin, linux-s390
On 12/09/2026 16:50, Artem Lytkin wrote:
> br_fill_ifinfo() puts all of a port's VLAN, tunnel and MST entries into
> one nest, and nla_len is a u16, so a large enough port produces a nest
> whose length wraps and userspace reads garbage.
>
> Cancel the message and return -E2BIG with an extack pointing at
> RTM_GETVLAN instead. The dump retries the port with an empty skb and
> the error goes to userspace; notifications reach rtnl_set_sk_err() and
> listeners resync. Not -EMSGSIZE, since no bigger buffer would help.
>
> Assisted-by: Claude:claude-opus-5
> Signed-off-by: Artem Lytkin <iprintercanon@gmail.com>
> ---
> net/bridge/br_netlink.c | 13 ++++++++++---
> 1 file changed, 10 insertions(+), 3 deletions(-)
>
This patch seems incomplete, it doesn't fix the same problem for MST and CFM.
They both can use the same helper - nla_nest_end_safe().
More below...
> diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
> index 855a46aec3a89..53676df9e4d11 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;
> @@ -613,6 +613,12 @@ static int br_fill_ifinfo(struct sk_buff *skb,
>
> done:
> if (af) {
> + if (skb_tail_pointer(skb) - (unsigned char *)af > U16_MAX) {
here you can use nla_nest_end_safe()
> + NL_SET_ERR_MSG_MOD(extack,
> + "VLAN information does not fit in one message, use RTM_GETVLAN");
> + nlmsg_cancel(skb, nlh);
> + return -E2BIG;
> + }
> if (nlmsg_get_pos(skb) - (void *)af > nla_attr_size(0))
while here you can just change this to if !nla_len(af) nla_nest_cancel()
Also add a common label and goto it from all errors e.g:
nla_nest_too_large:
nlmsg_cancel(skb, nlh);
return -E2BIG;
> nla_nest_end(skb, af);
> else
> @@ -654,7 +660,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);
> @@ -693,7 +700,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,
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net-next v2 2/2] net: bridge: fail link info that does not fit the IFLA_AF_SPEC nest
2026-09-12 13:50 ` [PATCH net-next v2 2/2] net: bridge: fail link info that does not fit the IFLA_AF_SPEC nest Artem Lytkin
2026-09-13 13:50 ` sashiko-bot
2026-09-14 8:48 ` Nikolay Aleksandrov
@ 2026-09-15 18:51 ` netdev-bot+sashiko
2 siblings, 0 replies; 7+ messages in thread
From: netdev-bot+sashiko @ 2026-09-15 18:51 UTC (permalink / raw)
To: iprintercanon
Cc: netdev, bridge, razor, idosch, davem, edumazet, kuba, pabeni,
horms, andrew+netdev, kuniyu, michael.chan, pavan.chebbi,
ajit.khaparde, sriharsha.basavapatna, anthony.l.nguyen,
przemyslaw.kitszel, intel-wired-lan, saeedm, tariqt, mbloch,
oss-drivers, wintera, aswin, linux-s390
Thank you for your contribution! Sashiko AI review found 3 potential
issue(s) to consider:
Critical: 0 · High: 1 · Medium: 1 · Low: 1
- [High] Incomplete bounds check: the new U16_MAX guard only measures the
outer IFLA_AF_SPEC nest and only runs at the 'done:' label, i.e. after…
- [Medium] Returning -E2BIG from br_fill_ifinfo()/br_getlink() aborts the
whole RTM_GETLINK/AF_BRIDGE dump at the offending device:…
- [Low] The patch changes user-visible behaviour to fix a data-corruption
bug (the commit message itself says 'a large enough port produces a…
--
net: bridge: fail link info that does not fit the IFLA_AF_SPEC nest
br_fill_ifinfo() now measures the IFLA_AF_SPEC nest at the done: label and,
if the accumulated payload exceeds U16_MAX, cancels the message and returns
-E2BIG with an extack. An extack argument is threaded into br_fill_ifinfo()
from br_getlink(), while br_info_notify() passes NULL.
A couple of questions on the placement of the check and on the resulting
dump behaviour.
First, on the commit message trailers:
> Assisted-by: Claude:claude-opus-5
> Signed-off-by: Artem Lytkin <iprintercanon@gmail.com>
[Severity: Low]
The commit message describes a user-visible corruption ("a large enough port
produces a nest whose length wraps and userspace reads garbage"), but there
is no Fixes: tag. Should one be added naming the commit that first made more
than 64 KiB of IFLA_AF_SPEC content possible, for example the per-VLAN
tunnel-info netlink support or the IFLA_BRIDGE_MST support, so that stable
tooling picks this up and the affected range is clear?
Also, Assisted-by: is not one of the documented trailers.
> diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
> index 855a46aec3a89..53676df9e4d11 100644
> --- a/net/bridge/br_netlink.c
> +++ b/net/bridge/br_netlink.c
[ ... ]
> @@ -613,6 +613,12 @@ static int br_fill_ifinfo(struct sk_buff *skb,
>
> done:
> if (af) {
> + if (skb_tail_pointer(skb) - (unsigned char *)af > U16_MAX) {
> + NL_SET_ERR_MSG_MOD(extack,
> + "VLAN information does not fit in one message, use RTM_GETVLAN");
> + nlmsg_cancel(skb, nlh);
> + return -E2BIG;
> + }
[Severity: High]
Does this check come too late to cover the inner nests?
The MST and CFM nests are closed earlier in br_fill_ifinfo(), before control
reaches done:
net/bridge/br_netlink.c:br_fill_ifinfo() {
...
err = br_mst_fill_info(skb, vg);
if (err)
goto nla_put_failure;
nla_nest_end(skb, mst_nest);
}
done:
if (af) {
if (skb_tail_pointer(skb) - (unsigned char *)af > U16_MAX) {
...
}
and nla_nest_end() both warns and performs the truncating store:
include/net/netlink.h:nla_nest_end() {
unsigned long diff = skb_tail_pointer(skb) - (unsigned char *)start;
DEBUG_NET_WARN_ON_ONCE(diff > U16_MAX);
start->nla_len = diff;
...
}
Can IFLA_BRIDGE_MST alone exceed 65535 bytes? br_mst_fill_info() emits one
roughly 20 byte IFLA_BRIDGE_MST_ENTRY per distinct MSTI, with no aggregate
size accounting:
net/bridge/br_mst.c:br_mst_fill_info() {
list_for_each_entry(v, &vg->vlan_list, vlist) {
if (test_bit(v->brvlan->msti, seen))
continue;
nest = nla_nest_start_noflag(skb, IFLA_BRIDGE_MST_ENTRY);
...
}
With up to 4094 distinct MSTIs that is roughly 82 KB, and the same applies to
IFLA_BRIDGE_CFM where each peer-MEP status entry is roughly 76 bytes. The
dump skb is sized from br_get_link_af_size_filtered() via rtnl_calcit() into
cb->min_dump_alloc, which is a u32 with no 64 KiB cap, so the oversized nest
is actually written out.
So for the inner nests the wrapped nla_len is still stored, and on
CONFIG_DEBUG_NET kernels the DEBUG_NET_WARN_ON_ONCE fires from an ordinary
unprivileged RTM_GETLINK/AF_BRIDGE dump. Would the size have to be bounded
while each nest is being filled, rather than once after the whole message has
been serialized?
[Severity: Medium]
Does returning -E2BIG here stop the rest of the dump?
The chain is rtnl_bridge_getlink() -> br_getlink() -> br_fill_ifinfo(), and
rtnl_bridge_getlink() treats any negative error other than -EOPNOTSUPP as
terminal for the whole walk:
net/core/rtnetlink.c:rtnl_bridge_getlink() {
...
if (err < 0 && err != -EOPNOTSUPP) {
if (likely(skb->len))
break;
goto out_err;
}
}
idx++;
...
err = skb->len;
out_err:
rcu_read_unlock();
cb->args[0] = idx;
}
Since idx is not incremented for the failing device, cb->args[0] still points
at it on the retry round. That round starts with skb->len == 0, so it takes
goto out_err and the dump ends with -E2BIG. Are all ports after the
offending one then never enumerated, and does every subsequent dump fail at
the same device again? Before the patch the same configuration produced one
message with a wrapped AF_SPEC length but the walk continued.
The commit message says only that "the error goes to userspace"; should it
mention that the remainder of the dump is dropped?
On the extack text: the same overflow is reachable for a request that sets
only RTEXT_FILTER_MST or only RTEXT_FILTER_CFM_CONFIG / RTEXT_FILTER_CFM_STATUS,
where no VLAN data is emitted at all and RTM_GETVLAN is not a substitute.
Could the message be made specific to what actually overflowed?
> if (nlmsg_get_pos(skb) - (void *)af > nla_attr_size(0))
> nla_nest_end(skb, af);
> else
[ ... ]
--
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260912135022.1701-1-iprintercanon%40gmail.com
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-09-15 18:51 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-12 13:50 [PATCH net-next v2 0/2] bridge: report an oversized IFLA_AF_SPEC nest instead of truncating Artem Lytkin
2026-09-12 13:50 ` [PATCH net-next v2 1/2] rtnetlink: pass extack to ndo_bridge_getlink() Artem Lytkin
2026-09-13 13:50 ` sashiko-bot
2026-09-12 13:50 ` [PATCH net-next v2 2/2] net: bridge: fail link info that does not fit the IFLA_AF_SPEC nest Artem Lytkin
2026-09-13 13:50 ` sashiko-bot
2026-09-14 8:48 ` Nikolay Aleksandrov
2026-09-15 18:51 ` netdev-bot+sashiko
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.