Signed-off-by: Jiri Benc <jb...@redhat.com> --- net/core/rtnetlink.c | 84 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 33 deletions(-)
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 9d08ad6ee5c3..1af929e468cf 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1465,7 +1465,8 @@ struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]) } EXPORT_SYMBOL(rtnl_link_get_net); -static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[]) +static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[], + bool strict) { if (dev) { if (tb[IFLA_ADDRESS] && @@ -1492,7 +1493,7 @@ static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[]) if (af_ops->validate_link_af) { err = af_ops->validate_link_af(dev, af, - false); + strict); if (err < 0) return err; } @@ -1637,7 +1638,8 @@ static int do_set_master(struct net_device *dev, int ifindex) #define DO_SETLINK_NOTIFY 0x03 static int do_setlink(const struct sk_buff *skb, struct net_device *dev, struct ifinfomsg *ifm, - struct nlattr **tb, char *ifname, int status) + struct nlattr **tb, char *ifname, int status, + bool strict) { const struct net_device_ops *ops = dev->netdev_ops; int err; @@ -1799,8 +1801,9 @@ static int do_setlink(const struct sk_buff *skb, err = -EINVAL; goto errout; } - err = nla_parse_nested(vfinfo, IFLA_VF_MAX, attr, - ifla_vf_policy); + err = nla_strict_parse_nested(vfinfo, IFLA_VF_MAX, + strict, attr, + ifla_vf_policy); if (err < 0) goto errout; err = do_setvfinfo(dev, vfinfo); @@ -1827,8 +1830,9 @@ static int do_setlink(const struct sk_buff *skb, err = -EINVAL; goto errout; } - err = nla_parse_nested(port, IFLA_PORT_MAX, attr, - ifla_port_policy); + err = nla_strict_parse_nested(port, IFLA_PORT_MAX, + strict, attr, + ifla_port_policy); if (err < 0) goto errout; if (!port[IFLA_PORT_VF]) { @@ -1847,8 +1851,9 @@ static int do_setlink(const struct sk_buff *skb, if (tb[IFLA_PORT_SELF]) { struct nlattr *port[IFLA_PORT_MAX+1]; - err = nla_parse_nested(port, IFLA_PORT_MAX, - tb[IFLA_PORT_SELF], ifla_port_policy); + err = nla_strict_parse_nested(port, IFLA_PORT_MAX, strict, + tb[IFLA_PORT_SELF], + ifla_port_policy); if (err < 0) goto errout; @@ -1908,8 +1913,10 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh) int err; struct nlattr *tb[IFLA_MAX+1]; char ifname[IFNAMSIZ]; + bool strict = nlh->nlmsg_flags & NLM_F_STRICT; - err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); + err = nlmsg_strict_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, strict, + ifla_policy); if (err < 0) goto errout; @@ -1932,11 +1939,11 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh) goto errout; } - err = validate_linkmsg(dev, tb); + err = validate_linkmsg(dev, tb, strict); if (err < 0) goto errout; - err = do_setlink(skb, dev, ifm, tb, ifname, 0); + err = do_setlink(skb, dev, ifm, tb, ifname, 0, strict); errout: return err; } @@ -2000,9 +2007,11 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh) struct ifinfomsg *ifm; char ifname[IFNAMSIZ]; struct nlattr *tb[IFLA_MAX+1]; + bool strict = nlh->nlmsg_flags & NLM_F_STRICT; int err; - err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); + err = nlmsg_strict_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, strict, + ifla_policy); if (err < 0) return err; @@ -2102,14 +2111,14 @@ EXPORT_SYMBOL(rtnl_create_link); static int rtnl_group_changelink(const struct sk_buff *skb, struct net *net, int group, struct ifinfomsg *ifm, - struct nlattr **tb) + struct nlattr **tb, bool strict) { struct net_device *dev, *aux; int err; for_each_netdev_safe(net, dev, aux) { if (dev->group == group) { - err = do_setlink(skb, dev, ifm, tb, NULL, 0); + err = do_setlink(skb, dev, ifm, tb, NULL, 0, strict); if (err < 0) return err; } @@ -2131,12 +2140,14 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh) struct nlattr *tb[IFLA_MAX+1]; struct nlattr *linkinfo[IFLA_INFO_MAX+1]; unsigned char name_assign_type = NET_NAME_USER; + bool strict = nlh->nlmsg_flags & NLM_F_STRICT; int err; #ifdef CONFIG_MODULES replay: #endif - err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); + err = nlmsg_strict_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, strict, + ifla_policy); if (err < 0) return err; @@ -2161,13 +2172,14 @@ replay: m_ops = master_dev->rtnl_link_ops; } - err = validate_linkmsg(dev, tb); + err = validate_linkmsg(dev, tb, strict); if (err < 0) return err; if (tb[IFLA_LINKINFO]) { - err = nla_parse_nested(linkinfo, IFLA_INFO_MAX, - tb[IFLA_LINKINFO], ifla_info_policy); + err = nla_strict_parse_nested(linkinfo, IFLA_INFO_MAX, + strict, tb[IFLA_LINKINFO], + ifla_info_policy); if (err < 0) return err; } else @@ -2190,15 +2202,16 @@ replay: if (ops) { if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) { - err = nla_parse_nested(attr, ops->maxtype, - linkinfo[IFLA_INFO_DATA], - ops->policy); + err = nla_strict_parse_nested(attr, ops->maxtype, + strict, + linkinfo[IFLA_INFO_DATA], + ops->policy); if (err < 0) return err; data = attr; } if (ops->validate) { - err = ops->validate(tb, data, false); + err = ops->validate(tb, data, strict); if (err < 0) return err; } @@ -2207,17 +2220,18 @@ replay: if (m_ops) { if (m_ops->slave_maxtype && linkinfo[IFLA_INFO_SLAVE_DATA]) { - err = nla_parse_nested(slave_attr, - m_ops->slave_maxtype, - linkinfo[IFLA_INFO_SLAVE_DATA], - m_ops->slave_policy); + err = nla_strict_parse_nested(slave_attr, + m_ops->slave_maxtype, + strict, + linkinfo[IFLA_INFO_SLAVE_DATA], + m_ops->slave_policy); if (err < 0) return err; slave_data = slave_attr; } if (m_ops->slave_validate) { err = m_ops->slave_validate(tb, slave_data, - false); + strict); if (err < 0) return err; } @@ -2253,14 +2267,15 @@ replay: status |= DO_SETLINK_NOTIFY; } - return do_setlink(skb, dev, ifm, tb, ifname, status); + return do_setlink(skb, dev, ifm, tb, ifname, status, + strict); } if (!(nlh->nlmsg_flags & NLM_F_CREATE)) { if (ifm->ifi_index == 0 && tb[IFLA_GROUP]) return rtnl_group_changelink(skb, net, nla_get_u32(tb[IFLA_GROUP]), - ifm, tb); + ifm, tb, strict); return -ENODEV; } @@ -3443,9 +3458,12 @@ void __init rtnetlink_init(void) rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink, rtnl_dump_ifinfo, rtnl_calcit); - rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL, NULL); - rtnl_register(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL, NULL); - rtnl_register(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL, NULL); + rtnl_register_flags(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL, NULL, + RTNL_F_STRICT); + rtnl_register_flags(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL, NULL, + RTNL_F_STRICT); + rtnl_register_flags(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL, NULL, + RTNL_F_STRICT); rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all, NULL); rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all, NULL); -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html