diff options
author | David S. Miller <davem@davemloft.net> | 2014-11-26 15:29:10 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-11-26 15:29:10 -0500 |
commit | a7650238a0cf82d84d1d7aff4383f84807616d8f (patch) | |
tree | 92ea43345e093ad57f1068a52577428be4b45e9f | |
parent | 571dcfde23712b92e45a126f415d9424af0c2886 (diff) | |
parent | aa68c20ff32f9a6fb3ca7f93ed9beae01899d00d (diff) |
Merge branch 'bridge_nl_validation'
Thomas Graf says:
====================
bridge: Fix missing Netlink message validations
Adds various missing length checks in the bridging code for Netlink
messages and corresponding attributes provided by user space.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_main.c | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 5 | ||||
-rw-r--r-- | net/bridge/br_netlink.c | 1 | ||||
-rw-r--r-- | net/core/rtnetlink.c | 23 |
4 files changed, 29 insertions, 5 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 3e8475cae4f9..597c463e384d 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c | |||
@@ -4309,11 +4309,16 @@ static int be_ndo_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh) | |||
4309 | return -EOPNOTSUPP; | 4309 | return -EOPNOTSUPP; |
4310 | 4310 | ||
4311 | br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC); | 4311 | br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC); |
4312 | if (!br_spec) | ||
4313 | return -EINVAL; | ||
4312 | 4314 | ||
4313 | nla_for_each_nested(attr, br_spec, rem) { | 4315 | nla_for_each_nested(attr, br_spec, rem) { |
4314 | if (nla_type(attr) != IFLA_BRIDGE_MODE) | 4316 | if (nla_type(attr) != IFLA_BRIDGE_MODE) |
4315 | continue; | 4317 | continue; |
4316 | 4318 | ||
4319 | if (nla_len(attr) < sizeof(mode)) | ||
4320 | return -EINVAL; | ||
4321 | |||
4317 | mode = nla_get_u16(attr); | 4322 | mode = nla_get_u16(attr); |
4318 | if (mode != BRIDGE_MODE_VEPA && mode != BRIDGE_MODE_VEB) | 4323 | if (mode != BRIDGE_MODE_VEPA && mode != BRIDGE_MODE_VEB) |
4319 | return -EINVAL; | 4324 | return -EINVAL; |
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 82ffe8bdb898..cc51554c9e99 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | |||
@@ -7669,6 +7669,8 @@ static int ixgbe_ndo_bridge_setlink(struct net_device *dev, | |||
7669 | return -EOPNOTSUPP; | 7669 | return -EOPNOTSUPP; |
7670 | 7670 | ||
7671 | br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC); | 7671 | br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC); |
7672 | if (!br_spec) | ||
7673 | return -EINVAL; | ||
7672 | 7674 | ||
7673 | nla_for_each_nested(attr, br_spec, rem) { | 7675 | nla_for_each_nested(attr, br_spec, rem) { |
7674 | __u16 mode; | 7676 | __u16 mode; |
@@ -7677,6 +7679,9 @@ static int ixgbe_ndo_bridge_setlink(struct net_device *dev, | |||
7677 | if (nla_type(attr) != IFLA_BRIDGE_MODE) | 7679 | if (nla_type(attr) != IFLA_BRIDGE_MODE) |
7678 | continue; | 7680 | continue; |
7679 | 7681 | ||
7682 | if (nla_len(attr) < sizeof(mode)) | ||
7683 | return -EINVAL; | ||
7684 | |||
7680 | mode = nla_get_u16(attr); | 7685 | mode = nla_get_u16(attr); |
7681 | if (mode == BRIDGE_MODE_VEPA) { | 7686 | if (mode == BRIDGE_MODE_VEPA) { |
7682 | reg = 0; | 7687 | reg = 0; |
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 2ff9706647f2..e5ec470b851f 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c | |||
@@ -280,6 +280,7 @@ static const struct nla_policy br_port_policy[IFLA_BRPORT_MAX + 1] = { | |||
280 | [IFLA_BRPORT_MODE] = { .type = NLA_U8 }, | 280 | [IFLA_BRPORT_MODE] = { .type = NLA_U8 }, |
281 | [IFLA_BRPORT_GUARD] = { .type = NLA_U8 }, | 281 | [IFLA_BRPORT_GUARD] = { .type = NLA_U8 }, |
282 | [IFLA_BRPORT_PROTECT] = { .type = NLA_U8 }, | 282 | [IFLA_BRPORT_PROTECT] = { .type = NLA_U8 }, |
283 | [IFLA_BRPORT_FAST_LEAVE]= { .type = NLA_U8 }, | ||
283 | [IFLA_BRPORT_LEARNING] = { .type = NLA_U8 }, | 284 | [IFLA_BRPORT_LEARNING] = { .type = NLA_U8 }, |
284 | [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NLA_U8 }, | 285 | [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NLA_U8 }, |
285 | }; | 286 | }; |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index a6882686ca3a..b9b7dfaf202b 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -2685,13 +2685,20 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb) | |||
2685 | int idx = 0; | 2685 | int idx = 0; |
2686 | u32 portid = NETLINK_CB(cb->skb).portid; | 2686 | u32 portid = NETLINK_CB(cb->skb).portid; |
2687 | u32 seq = cb->nlh->nlmsg_seq; | 2687 | u32 seq = cb->nlh->nlmsg_seq; |
2688 | struct nlattr *extfilt; | ||
2689 | u32 filter_mask = 0; | 2688 | u32 filter_mask = 0; |
2690 | 2689 | ||
2691 | extfilt = nlmsg_find_attr(cb->nlh, sizeof(struct ifinfomsg), | 2690 | if (nlmsg_len(cb->nlh) > sizeof(struct ifinfomsg)) { |
2692 | IFLA_EXT_MASK); | 2691 | struct nlattr *extfilt; |
2693 | if (extfilt) | 2692 | |
2694 | filter_mask = nla_get_u32(extfilt); | 2693 | extfilt = nlmsg_find_attr(cb->nlh, sizeof(struct ifinfomsg), |
2694 | IFLA_EXT_MASK); | ||
2695 | if (extfilt) { | ||
2696 | if (nla_len(extfilt) < sizeof(filter_mask)) | ||
2697 | return -EINVAL; | ||
2698 | |||
2699 | filter_mask = nla_get_u32(extfilt); | ||
2700 | } | ||
2701 | } | ||
2695 | 2702 | ||
2696 | rcu_read_lock(); | 2703 | rcu_read_lock(); |
2697 | for_each_netdev_rcu(net, dev) { | 2704 | for_each_netdev_rcu(net, dev) { |
@@ -2798,6 +2805,9 @@ static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
2798 | if (br_spec) { | 2805 | if (br_spec) { |
2799 | nla_for_each_nested(attr, br_spec, rem) { | 2806 | nla_for_each_nested(attr, br_spec, rem) { |
2800 | if (nla_type(attr) == IFLA_BRIDGE_FLAGS) { | 2807 | if (nla_type(attr) == IFLA_BRIDGE_FLAGS) { |
2808 | if (nla_len(attr) < sizeof(flags)) | ||
2809 | return -EINVAL; | ||
2810 | |||
2801 | have_flags = true; | 2811 | have_flags = true; |
2802 | flags = nla_get_u16(attr); | 2812 | flags = nla_get_u16(attr); |
2803 | break; | 2813 | break; |
@@ -2868,6 +2878,9 @@ static int rtnl_bridge_dellink(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
2868 | if (br_spec) { | 2878 | if (br_spec) { |
2869 | nla_for_each_nested(attr, br_spec, rem) { | 2879 | nla_for_each_nested(attr, br_spec, rem) { |
2870 | if (nla_type(attr) == IFLA_BRIDGE_FLAGS) { | 2880 | if (nla_type(attr) == IFLA_BRIDGE_FLAGS) { |
2881 | if (nla_len(attr) < sizeof(flags)) | ||
2882 | return -EINVAL; | ||
2883 | |||
2871 | have_flags = true; | 2884 | have_flags = true; |
2872 | flags = nla_get_u16(attr); | 2885 | flags = nla_get_u16(attr); |
2873 | break; | 2886 | break; |