aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Dichtel <nicolas.dichtel@dev.6wind.com>2010-03-25 19:45:35 -0400
committerDavid S. Miller <davem@davemloft.net>2010-03-27 11:33:21 -0400
commit7438189baa0a2fe30084bdc97e3d540ebc5444f3 (patch)
tree6627b63b785df9175e04a0ce1b49d5eea8ea0777
parente7d481a6f3c13041446b7bb8f98ab861460076a3 (diff)
net: ipmr/ip6mr: prevent out-of-bounds vif_table access
When cache is unresolved, c->mf[6]c_parent is set to 65535 and minvif, maxvif are not initialized, hence we must avoid to parse IIF and OIF. A second problem can happen when the user dumps a cache entry where a VIF, that was referenced at creation time, has been removed. Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv4/ipmr.c11
-rw-r--r--net/ipv6/ip6mr.c11
2 files changed, 14 insertions, 8 deletions
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 0b9d03c54dc3..d0a6092a67be 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -1616,17 +1616,20 @@ ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm)
1616 int ct; 1616 int ct;
1617 struct rtnexthop *nhp; 1617 struct rtnexthop *nhp;
1618 struct net *net = mfc_net(c); 1618 struct net *net = mfc_net(c);
1619 struct net_device *dev = net->ipv4.vif_table[c->mfc_parent].dev;
1620 u8 *b = skb_tail_pointer(skb); 1619 u8 *b = skb_tail_pointer(skb);
1621 struct rtattr *mp_head; 1620 struct rtattr *mp_head;
1622 1621
1623 if (dev) 1622 /* If cache is unresolved, don't try to parse IIF and OIF */
1624 RTA_PUT(skb, RTA_IIF, 4, &dev->ifindex); 1623 if (c->mfc_parent > MAXVIFS)
1624 return -ENOENT;
1625
1626 if (VIF_EXISTS(net, c->mfc_parent))
1627 RTA_PUT(skb, RTA_IIF, 4, &net->ipv4.vif_table[c->mfc_parent].dev->ifindex);
1625 1628
1626 mp_head = (struct rtattr *)skb_put(skb, RTA_LENGTH(0)); 1629 mp_head = (struct rtattr *)skb_put(skb, RTA_LENGTH(0));
1627 1630
1628 for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) { 1631 for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) {
1629 if (c->mfc_un.res.ttls[ct] < 255) { 1632 if (VIF_EXISTS(net, ct) && c->mfc_un.res.ttls[ct] < 255) {
1630 if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4)) 1633 if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4))
1631 goto rtattr_failure; 1634 goto rtattr_failure;
1632 nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp))); 1635 nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp)));
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 23e4ac0cc30e..27acfb58650a 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -1695,17 +1695,20 @@ ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm)
1695 int ct; 1695 int ct;
1696 struct rtnexthop *nhp; 1696 struct rtnexthop *nhp;
1697 struct net *net = mfc6_net(c); 1697 struct net *net = mfc6_net(c);
1698 struct net_device *dev = net->ipv6.vif6_table[c->mf6c_parent].dev;
1699 u8 *b = skb_tail_pointer(skb); 1698 u8 *b = skb_tail_pointer(skb);
1700 struct rtattr *mp_head; 1699 struct rtattr *mp_head;
1701 1700
1702 if (dev) 1701 /* If cache is unresolved, don't try to parse IIF and OIF */
1703 RTA_PUT(skb, RTA_IIF, 4, &dev->ifindex); 1702 if (c->mf6c_parent > MAXMIFS)
1703 return -ENOENT;
1704
1705 if (MIF_EXISTS(net, c->mf6c_parent))
1706 RTA_PUT(skb, RTA_IIF, 4, &net->ipv6.vif6_table[c->mf6c_parent].dev->ifindex);
1704 1707
1705 mp_head = (struct rtattr *)skb_put(skb, RTA_LENGTH(0)); 1708 mp_head = (struct rtattr *)skb_put(skb, RTA_LENGTH(0));
1706 1709
1707 for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) { 1710 for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) {
1708 if (c->mfc_un.res.ttls[ct] < 255) { 1711 if (MIF_EXISTS(net, ct) && c->mfc_un.res.ttls[ct] < 255) {
1709 if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4)) 1712 if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4))
1710 goto rtattr_failure; 1713 goto rtattr_failure;
1711 nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp))); 1714 nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp)));