aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/rtnetlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/rtnetlink.c')
-rw-r--r--net/core/rtnetlink.c53
1 files changed, 33 insertions, 20 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index d4ff41739b0f..9837bebf93ce 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -774,7 +774,8 @@ static inline int rtnl_vfinfo_size(const struct net_device *dev,
774 return 0; 774 return 0;
775} 775}
776 776
777static size_t rtnl_port_size(const struct net_device *dev) 777static size_t rtnl_port_size(const struct net_device *dev,
778 u32 ext_filter_mask)
778{ 779{
779 size_t port_size = nla_total_size(4) /* PORT_VF */ 780 size_t port_size = nla_total_size(4) /* PORT_VF */
780 + nla_total_size(PORT_PROFILE_MAX) /* PORT_PROFILE */ 781 + nla_total_size(PORT_PROFILE_MAX) /* PORT_PROFILE */
@@ -790,7 +791,8 @@ static size_t rtnl_port_size(const struct net_device *dev)
790 size_t port_self_size = nla_total_size(sizeof(struct nlattr)) 791 size_t port_self_size = nla_total_size(sizeof(struct nlattr))
791 + port_size; 792 + port_size;
792 793
793 if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent) 794 if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent ||
795 !(ext_filter_mask & RTEXT_FILTER_VF))
794 return 0; 796 return 0;
795 if (dev_num_vf(dev->dev.parent)) 797 if (dev_num_vf(dev->dev.parent))
796 return port_self_size + vf_ports_size + 798 return port_self_size + vf_ports_size +
@@ -826,7 +828,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev,
826 + nla_total_size(ext_filter_mask 828 + nla_total_size(ext_filter_mask
827 & RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */ 829 & RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */
828 + rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */ 830 + rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */
829 + rtnl_port_size(dev) /* IFLA_VF_PORTS + IFLA_PORT_SELF */ 831 + rtnl_port_size(dev, ext_filter_mask) /* IFLA_VF_PORTS + IFLA_PORT_SELF */
830 + rtnl_link_get_size(dev) /* IFLA_LINKINFO */ 832 + rtnl_link_get_size(dev) /* IFLA_LINKINFO */
831 + rtnl_link_get_af_size(dev) /* IFLA_AF_SPEC */ 833 + rtnl_link_get_af_size(dev) /* IFLA_AF_SPEC */
832 + nla_total_size(MAX_PHYS_PORT_ID_LEN); /* IFLA_PHYS_PORT_ID */ 834 + nla_total_size(MAX_PHYS_PORT_ID_LEN); /* IFLA_PHYS_PORT_ID */
@@ -888,11 +890,13 @@ static int rtnl_port_self_fill(struct sk_buff *skb, struct net_device *dev)
888 return 0; 890 return 0;
889} 891}
890 892
891static int rtnl_port_fill(struct sk_buff *skb, struct net_device *dev) 893static int rtnl_port_fill(struct sk_buff *skb, struct net_device *dev,
894 u32 ext_filter_mask)
892{ 895{
893 int err; 896 int err;
894 897
895 if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent) 898 if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent ||
899 !(ext_filter_mask & RTEXT_FILTER_VF))
896 return 0; 900 return 0;
897 901
898 err = rtnl_port_self_fill(skb, dev); 902 err = rtnl_port_self_fill(skb, dev);
@@ -1079,7 +1083,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
1079 nla_nest_end(skb, vfinfo); 1083 nla_nest_end(skb, vfinfo);
1080 } 1084 }
1081 1085
1082 if (rtnl_port_fill(skb, dev)) 1086 if (rtnl_port_fill(skb, dev, ext_filter_mask))
1083 goto nla_put_failure; 1087 goto nla_put_failure;
1084 1088
1085 if (dev->rtnl_link_ops || rtnl_have_link_slave_info(dev)) { 1089 if (dev->rtnl_link_ops || rtnl_have_link_slave_info(dev)) {
@@ -1198,6 +1202,7 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
1198 struct hlist_head *head; 1202 struct hlist_head *head;
1199 struct nlattr *tb[IFLA_MAX+1]; 1203 struct nlattr *tb[IFLA_MAX+1];
1200 u32 ext_filter_mask = 0; 1204 u32 ext_filter_mask = 0;
1205 int err;
1201 1206
1202 s_h = cb->args[0]; 1207 s_h = cb->args[0];
1203 s_idx = cb->args[1]; 1208 s_idx = cb->args[1];
@@ -1218,11 +1223,17 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
1218 hlist_for_each_entry_rcu(dev, head, index_hlist) { 1223 hlist_for_each_entry_rcu(dev, head, index_hlist) {
1219 if (idx < s_idx) 1224 if (idx < s_idx)
1220 goto cont; 1225 goto cont;
1221 if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK, 1226 err = rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK,
1222 NETLINK_CB(cb->skb).portid, 1227 NETLINK_CB(cb->skb).portid,
1223 cb->nlh->nlmsg_seq, 0, 1228 cb->nlh->nlmsg_seq, 0,
1224 NLM_F_MULTI, 1229 NLM_F_MULTI,
1225 ext_filter_mask) <= 0) 1230 ext_filter_mask);
1231 /* If we ran out of room on the first message,
1232 * we're in trouble
1233 */
1234 WARN_ON((err == -EMSGSIZE) && (skb->len == 0));
1235
1236 if (err <= 0)
1226 goto out; 1237 goto out;
1227 1238
1228 nl_dump_check_consistent(cb, nlmsg_hdr(skb)); 1239 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
@@ -1395,7 +1406,8 @@ static int do_set_master(struct net_device *dev, int ifindex)
1395 return 0; 1406 return 0;
1396} 1407}
1397 1408
1398static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, 1409static int do_setlink(const struct sk_buff *skb,
1410 struct net_device *dev, struct ifinfomsg *ifm,
1399 struct nlattr **tb, char *ifname, int modified) 1411 struct nlattr **tb, char *ifname, int modified)
1400{ 1412{
1401 const struct net_device_ops *ops = dev->netdev_ops; 1413 const struct net_device_ops *ops = dev->netdev_ops;
@@ -1407,7 +1419,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
1407 err = PTR_ERR(net); 1419 err = PTR_ERR(net);
1408 goto errout; 1420 goto errout;
1409 } 1421 }
1410 if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) { 1422 if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) {
1411 err = -EPERM; 1423 err = -EPERM;
1412 goto errout; 1424 goto errout;
1413 } 1425 }
@@ -1661,7 +1673,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh)
1661 if (err < 0) 1673 if (err < 0)
1662 goto errout; 1674 goto errout;
1663 1675
1664 err = do_setlink(dev, ifm, tb, ifname, 0); 1676 err = do_setlink(skb, dev, ifm, tb, ifname, 0);
1665errout: 1677errout:
1666 return err; 1678 return err;
1667} 1679}
@@ -1778,7 +1790,8 @@ err:
1778} 1790}
1779EXPORT_SYMBOL(rtnl_create_link); 1791EXPORT_SYMBOL(rtnl_create_link);
1780 1792
1781static int rtnl_group_changelink(struct net *net, int group, 1793static int rtnl_group_changelink(const struct sk_buff *skb,
1794 struct net *net, int group,
1782 struct ifinfomsg *ifm, 1795 struct ifinfomsg *ifm,
1783 struct nlattr **tb) 1796 struct nlattr **tb)
1784{ 1797{
@@ -1787,7 +1800,7 @@ static int rtnl_group_changelink(struct net *net, int group,
1787 1800
1788 for_each_netdev(net, dev) { 1801 for_each_netdev(net, dev) {
1789 if (dev->group == group) { 1802 if (dev->group == group) {
1790 err = do_setlink(dev, ifm, tb, NULL, 0); 1803 err = do_setlink(skb, dev, ifm, tb, NULL, 0);
1791 if (err < 0) 1804 if (err < 0)
1792 return err; 1805 return err;
1793 } 1806 }
@@ -1929,12 +1942,12 @@ replay:
1929 modified = 1; 1942 modified = 1;
1930 } 1943 }
1931 1944
1932 return do_setlink(dev, ifm, tb, ifname, modified); 1945 return do_setlink(skb, dev, ifm, tb, ifname, modified);
1933 } 1946 }
1934 1947
1935 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) { 1948 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
1936 if (ifm->ifi_index == 0 && tb[IFLA_GROUP]) 1949 if (ifm->ifi_index == 0 && tb[IFLA_GROUP])
1937 return rtnl_group_changelink(net, 1950 return rtnl_group_changelink(skb, net,
1938 nla_get_u32(tb[IFLA_GROUP]), 1951 nla_get_u32(tb[IFLA_GROUP]),
1939 ifm, tb); 1952 ifm, tb);
1940 return -ENODEV; 1953 return -ENODEV;
@@ -2321,7 +2334,7 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh)
2321 int err = -EINVAL; 2334 int err = -EINVAL;
2322 __u8 *addr; 2335 __u8 *addr;
2323 2336
2324 if (!capable(CAP_NET_ADMIN)) 2337 if (!netlink_capable(skb, CAP_NET_ADMIN))
2325 return -EPERM; 2338 return -EPERM;
2326 2339
2327 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL); 2340 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
@@ -2773,7 +2786,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
2773 sz_idx = type>>2; 2786 sz_idx = type>>2;
2774 kind = type&3; 2787 kind = type&3;
2775 2788
2776 if (kind != 2 && !ns_capable(net->user_ns, CAP_NET_ADMIN)) 2789 if (kind != 2 && !netlink_net_capable(skb, CAP_NET_ADMIN))
2777 return -EPERM; 2790 return -EPERM;
2778 2791
2779 if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) { 2792 if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {