Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8ca94183 authored by Scott Feldman's avatar Scott Feldman Committed by David S. Miller
Browse files

netlink: bug fix: don't overrun skbs on vf_port dump



Noticed by Patrick McHardy: was continuing to fill skb after a
nla_put_failure, ignoring the size calculated by upper layer.  Now,
return -EMSGSIZE on any overruns, but also allow netdev to
fail ndo_get_vf_port with error other than -EMSGSIZE, thus unwinding
nest.

Signed-off-by: default avatarScott Feldman <scofeldm@cisco.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 50636af7
Loading
Loading
Loading
Loading
+9 −6
Original line number Original line Diff line number Diff line
@@ -722,14 +722,13 @@ static int rtnl_vf_ports_fill(struct sk_buff *skb, struct net_device *dev)


	for (vf = 0; vf < dev_num_vf(dev->dev.parent); vf++) {
	for (vf = 0; vf < dev_num_vf(dev->dev.parent); vf++) {
		vf_port = nla_nest_start(skb, IFLA_VF_PORT);
		vf_port = nla_nest_start(skb, IFLA_VF_PORT);
		if (!vf_port) {
		if (!vf_port)
			nla_nest_cancel(skb, vf_ports);
			goto nla_put_failure;
			return -EMSGSIZE;
		}
		NLA_PUT_U32(skb, IFLA_PORT_VF, vf);
		NLA_PUT_U32(skb, IFLA_PORT_VF, vf);
		err = dev->netdev_ops->ndo_get_vf_port(dev, vf, skb);
		err = dev->netdev_ops->ndo_get_vf_port(dev, vf, skb);
		if (err == -EMSGSIZE)
			goto nla_put_failure;
		if (err) {
		if (err) {
nla_put_failure:
			nla_nest_cancel(skb, vf_port);
			nla_nest_cancel(skb, vf_port);
			continue;
			continue;
		}
		}
@@ -739,6 +738,10 @@ static int rtnl_vf_ports_fill(struct sk_buff *skb, struct net_device *dev)
	nla_nest_end(skb, vf_ports);
	nla_nest_end(skb, vf_ports);


	return 0;
	return 0;

nla_put_failure:
	nla_nest_cancel(skb, vf_ports);
	return -EMSGSIZE;
}
}


static int rtnl_port_self_fill(struct sk_buff *skb, struct net_device *dev)
static int rtnl_port_self_fill(struct sk_buff *skb, struct net_device *dev)
@@ -753,7 +756,7 @@ static int rtnl_port_self_fill(struct sk_buff *skb, struct net_device *dev)
	err = dev->netdev_ops->ndo_get_vf_port(dev, PORT_SELF_VF, skb);
	err = dev->netdev_ops->ndo_get_vf_port(dev, PORT_SELF_VF, skb);
	if (err) {
	if (err) {
		nla_nest_cancel(skb, port_self);
		nla_nest_cancel(skb, port_self);
		return err;
		return (err == -EMSGSIZE) ? err : 0;
	}
	}


	nla_nest_end(skb, port_self);
	nla_nest_end(skb, port_self);