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 <[email protected]> --- 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
