diff options
Diffstat (limited to 'net/core/rtnetlink.c')
-rw-r--r-- | net/core/rtnetlink.c | 41 |
1 files changed, 28 insertions, 13 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 63ce2283a456..37c7936124e6 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -1898,10 +1898,8 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | |||
1898 | if (tb[IFLA_IF_NETNSID]) { | 1898 | if (tb[IFLA_IF_NETNSID]) { |
1899 | netnsid = nla_get_s32(tb[IFLA_IF_NETNSID]); | 1899 | netnsid = nla_get_s32(tb[IFLA_IF_NETNSID]); |
1900 | tgt_net = get_target_net(skb->sk, netnsid); | 1900 | tgt_net = get_target_net(skb->sk, netnsid); |
1901 | if (IS_ERR(tgt_net)) { | 1901 | if (IS_ERR(tgt_net)) |
1902 | tgt_net = net; | 1902 | return PTR_ERR(tgt_net); |
1903 | netnsid = -1; | ||
1904 | } | ||
1905 | } | 1903 | } |
1906 | 1904 | ||
1907 | if (tb[IFLA_EXT_MASK]) | 1905 | if (tb[IFLA_EXT_MASK]) |
@@ -2837,6 +2835,12 @@ struct net_device *rtnl_create_link(struct net *net, | |||
2837 | else if (ops->get_num_rx_queues) | 2835 | else if (ops->get_num_rx_queues) |
2838 | num_rx_queues = ops->get_num_rx_queues(); | 2836 | num_rx_queues = ops->get_num_rx_queues(); |
2839 | 2837 | ||
2838 | if (num_tx_queues < 1 || num_tx_queues > 4096) | ||
2839 | return ERR_PTR(-EINVAL); | ||
2840 | |||
2841 | if (num_rx_queues < 1 || num_rx_queues > 4096) | ||
2842 | return ERR_PTR(-EINVAL); | ||
2843 | |||
2840 | dev = alloc_netdev_mqs(ops->priv_size, ifname, name_assign_type, | 2844 | dev = alloc_netdev_mqs(ops->priv_size, ifname, name_assign_type, |
2841 | ops->setup, num_tx_queues, num_rx_queues); | 2845 | ops->setup, num_tx_queues, num_rx_queues); |
2842 | if (!dev) | 2846 | if (!dev) |
@@ -3744,16 +3748,27 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
3744 | int err = 0; | 3748 | int err = 0; |
3745 | int fidx = 0; | 3749 | int fidx = 0; |
3746 | 3750 | ||
3747 | err = nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, | 3751 | /* A hack to preserve kernel<->userspace interface. |
3748 | IFLA_MAX, ifla_policy, NULL); | 3752 | * Before Linux v4.12 this code accepted ndmsg since iproute2 v3.3.0. |
3749 | if (err < 0) { | 3753 | * However, ndmsg is shorter than ifinfomsg thus nlmsg_parse() bails. |
3750 | return -EINVAL; | 3754 | * So, check for ndmsg with an optional u32 attribute (not used here). |
3751 | } else if (err == 0) { | 3755 | * Fortunately these sizes don't conflict with the size of ifinfomsg |
3752 | if (tb[IFLA_MASTER]) | 3756 | * with an optional attribute. |
3753 | br_idx = nla_get_u32(tb[IFLA_MASTER]); | 3757 | */ |
3754 | } | 3758 | if (nlmsg_len(cb->nlh) != sizeof(struct ndmsg) && |
3759 | (nlmsg_len(cb->nlh) != sizeof(struct ndmsg) + | ||
3760 | nla_attr_size(sizeof(u32)))) { | ||
3761 | err = nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, | ||
3762 | IFLA_MAX, ifla_policy, NULL); | ||
3763 | if (err < 0) { | ||
3764 | return -EINVAL; | ||
3765 | } else if (err == 0) { | ||
3766 | if (tb[IFLA_MASTER]) | ||
3767 | br_idx = nla_get_u32(tb[IFLA_MASTER]); | ||
3768 | } | ||
3755 | 3769 | ||
3756 | brport_idx = ifm->ifi_index; | 3770 | brport_idx = ifm->ifi_index; |
3771 | } | ||
3757 | 3772 | ||
3758 | if (br_idx) { | 3773 | if (br_idx) { |
3759 | br_dev = __dev_get_by_index(net, br_idx); | 3774 | br_dev = __dev_get_by_index(net, br_idx); |