diff options
Diffstat (limited to 'net/core/rtnetlink.c')
-rw-r--r-- | net/core/rtnetlink.c | 27 |
1 files changed, 21 insertions, 6 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 61ac8d06292c..2bd9c5f7627d 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -689,10 +689,12 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = { | |||
689 | [IFLA_BROADCAST] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, | 689 | [IFLA_BROADCAST] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, |
690 | [IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) }, | 690 | [IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) }, |
691 | [IFLA_MTU] = { .type = NLA_U32 }, | 691 | [IFLA_MTU] = { .type = NLA_U32 }, |
692 | [IFLA_LINK] = { .type = NLA_U32 }, | ||
692 | [IFLA_TXQLEN] = { .type = NLA_U32 }, | 693 | [IFLA_TXQLEN] = { .type = NLA_U32 }, |
693 | [IFLA_WEIGHT] = { .type = NLA_U32 }, | 694 | [IFLA_WEIGHT] = { .type = NLA_U32 }, |
694 | [IFLA_OPERSTATE] = { .type = NLA_U8 }, | 695 | [IFLA_OPERSTATE] = { .type = NLA_U8 }, |
695 | [IFLA_LINKMODE] = { .type = NLA_U8 }, | 696 | [IFLA_LINKMODE] = { .type = NLA_U8 }, |
697 | [IFLA_LINKINFO] = { .type = NLA_NESTED }, | ||
696 | [IFLA_NET_NS_PID] = { .type = NLA_U32 }, | 698 | [IFLA_NET_NS_PID] = { .type = NLA_U32 }, |
697 | }; | 699 | }; |
698 | 700 | ||
@@ -720,6 +722,21 @@ static struct net *get_net_ns_by_pid(pid_t pid) | |||
720 | return net; | 722 | return net; |
721 | } | 723 | } |
722 | 724 | ||
725 | static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[]) | ||
726 | { | ||
727 | if (dev) { | ||
728 | if (tb[IFLA_ADDRESS] && | ||
729 | nla_len(tb[IFLA_ADDRESS]) < dev->addr_len) | ||
730 | return -EINVAL; | ||
731 | |||
732 | if (tb[IFLA_BROADCAST] && | ||
733 | nla_len(tb[IFLA_BROADCAST]) < dev->addr_len) | ||
734 | return -EINVAL; | ||
735 | } | ||
736 | |||
737 | return 0; | ||
738 | } | ||
739 | |||
723 | static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, | 740 | static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, |
724 | struct nlattr **tb, char *ifname, int modified) | 741 | struct nlattr **tb, char *ifname, int modified) |
725 | { | 742 | { |
@@ -892,12 +909,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
892 | goto errout; | 909 | goto errout; |
893 | } | 910 | } |
894 | 911 | ||
895 | if (tb[IFLA_ADDRESS] && | 912 | if ((err = validate_linkmsg(dev, tb)) < 0) |
896 | nla_len(tb[IFLA_ADDRESS]) < dev->addr_len) | ||
897 | goto errout_dev; | ||
898 | |||
899 | if (tb[IFLA_BROADCAST] && | ||
900 | nla_len(tb[IFLA_BROADCAST]) < dev->addr_len) | ||
901 | goto errout_dev; | 913 | goto errout_dev; |
902 | 914 | ||
903 | err = do_setlink(dev, ifm, tb, ifname, 0); | 915 | err = do_setlink(dev, ifm, tb, ifname, 0); |
@@ -1018,6 +1030,9 @@ replay: | |||
1018 | else | 1030 | else |
1019 | dev = NULL; | 1031 | dev = NULL; |
1020 | 1032 | ||
1033 | if ((err = validate_linkmsg(dev, tb)) < 0) | ||
1034 | return err; | ||
1035 | |||
1021 | if (tb[IFLA_LINKINFO]) { | 1036 | if (tb[IFLA_LINKINFO]) { |
1022 | err = nla_parse_nested(linkinfo, IFLA_INFO_MAX, | 1037 | err = nla_parse_nested(linkinfo, IFLA_INFO_MAX, |
1023 | tb[IFLA_LINKINFO], ifla_info_policy); | 1038 | tb[IFLA_LINKINFO], ifla_info_policy); |