diff options
author | Nicolas Dichtel <nicolas.dichtel@dev.6wind.com> | 2010-03-25 19:45:35 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-03-27 11:33:21 -0400 |
commit | 7438189baa0a2fe30084bdc97e3d540ebc5444f3 (patch) | |
tree | 6627b63b785df9175e04a0ce1b49d5eea8ea0777 /net/ipv4 | |
parent | e7d481a6f3c13041446b7bb8f98ab861460076a3 (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>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/ipmr.c | 11 |
1 files changed, 7 insertions, 4 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))); |