aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorScott Feldman <scofeldm@cisco.com>2010-05-28 06:42:18 -0400
committerDavid S. Miller <davem@davemloft.net>2010-05-28 06:42:18 -0400
commit8ca9418350eccd5dd2659931807c1901224dd638 (patch)
tree2b476e5a084de1da3cb68dbddcce80c0c917578a /net/core
parent50636af715ac1ceb1872bd29a4bdcc68975c3263 (diff)
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: Scott Feldman <scofeldm@cisco.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/rtnetlink.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 7ab86f3a1ea..7331bb2f6b9 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -722,14 +722,13 @@ static int rtnl_vf_ports_fill(struct sk_buff *skb, struct net_device *dev)
722 722
723 for (vf = 0; vf < dev_num_vf(dev->dev.parent); vf++) { 723 for (vf = 0; vf < dev_num_vf(dev->dev.parent); vf++) {
724 vf_port = nla_nest_start(skb, IFLA_VF_PORT); 724 vf_port = nla_nest_start(skb, IFLA_VF_PORT);
725 if (!vf_port) { 725 if (!vf_port)
726 nla_nest_cancel(skb, vf_ports); 726 goto nla_put_failure;
727 return -EMSGSIZE;
728 }
729 NLA_PUT_U32(skb, IFLA_PORT_VF, vf); 727 NLA_PUT_U32(skb, IFLA_PORT_VF, vf);
730 err = dev->netdev_ops->ndo_get_vf_port(dev, vf, skb); 728 err = dev->netdev_ops->ndo_get_vf_port(dev, vf, skb);
729 if (err == -EMSGSIZE)
730 goto nla_put_failure;
731 if (err) { 731 if (err) {
732nla_put_failure:
733 nla_nest_cancel(skb, vf_port); 732 nla_nest_cancel(skb, vf_port);
734 continue; 733 continue;
735 } 734 }
@@ -739,6 +738,10 @@ nla_put_failure:
739 nla_nest_end(skb, vf_ports); 738 nla_nest_end(skb, vf_ports);
740 739
741 return 0; 740 return 0;
741
742nla_put_failure:
743 nla_nest_cancel(skb, vf_ports);
744 return -EMSGSIZE;
742} 745}
743 746
744static int rtnl_port_self_fill(struct sk_buff *skb, struct net_device *dev) 747static 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)
753 err = dev->netdev_ops->ndo_get_vf_port(dev, PORT_SELF_VF, skb); 756 err = dev->netdev_ops->ndo_get_vf_port(dev, PORT_SELF_VF, skb);
754 if (err) { 757 if (err) {
755 nla_nest_cancel(skb, port_self); 758 nla_nest_cancel(skb, port_self);
756 return err; 759 return (err == -EMSGSIZE) ? err : 0;
757 } 760 }
758 761
759 nla_nest_end(skb, port_self); 762 nla_nest_end(skb, port_self);