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.c103
1 files changed, 85 insertions, 18 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index de24d394c69e..8a8c51937edf 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -921,7 +921,8 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev,
921 + nla_total_size(4) /* IFLA_EVENT */ 921 + nla_total_size(4) /* IFLA_EVENT */
922 + nla_total_size(4) /* IFLA_NEW_NETNSID */ 922 + nla_total_size(4) /* IFLA_NEW_NETNSID */
923 + nla_total_size(1); /* IFLA_PROTO_DOWN */ 923 + nla_total_size(1); /* IFLA_PROTO_DOWN */
924 924 + nla_total_size(4) /* IFLA_IF_NETNSID */
925 + 0;
925} 926}
926 927
927static int rtnl_vf_ports_fill(struct sk_buff *skb, struct net_device *dev) 928static int rtnl_vf_ports_fill(struct sk_buff *skb, struct net_device *dev)
@@ -1370,13 +1371,14 @@ static noinline_for_stack int nla_put_ifalias(struct sk_buff *skb,
1370} 1371}
1371 1372
1372static int rtnl_fill_link_netnsid(struct sk_buff *skb, 1373static int rtnl_fill_link_netnsid(struct sk_buff *skb,
1373 const struct net_device *dev) 1374 const struct net_device *dev,
1375 struct net *src_net)
1374{ 1376{
1375 if (dev->rtnl_link_ops && dev->rtnl_link_ops->get_link_net) { 1377 if (dev->rtnl_link_ops && dev->rtnl_link_ops->get_link_net) {
1376 struct net *link_net = dev->rtnl_link_ops->get_link_net(dev); 1378 struct net *link_net = dev->rtnl_link_ops->get_link_net(dev);
1377 1379
1378 if (!net_eq(dev_net(dev), link_net)) { 1380 if (!net_eq(dev_net(dev), link_net)) {
1379 int id = peernet2id_alloc(dev_net(dev), link_net); 1381 int id = peernet2id_alloc(src_net, link_net);
1380 1382
1381 if (nla_put_s32(skb, IFLA_LINK_NETNSID, id)) 1383 if (nla_put_s32(skb, IFLA_LINK_NETNSID, id))
1382 return -EMSGSIZE; 1384 return -EMSGSIZE;
@@ -1427,10 +1429,11 @@ static int rtnl_fill_link_af(struct sk_buff *skb,
1427 return 0; 1429 return 0;
1428} 1430}
1429 1431
1430static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, 1432static int rtnl_fill_ifinfo(struct sk_buff *skb,
1433 struct net_device *dev, struct net *src_net,
1431 int type, u32 pid, u32 seq, u32 change, 1434 int type, u32 pid, u32 seq, u32 change,
1432 unsigned int flags, u32 ext_filter_mask, 1435 unsigned int flags, u32 ext_filter_mask,
1433 u32 event, int *new_nsid) 1436 u32 event, int *new_nsid, int tgt_netnsid)
1434{ 1437{
1435 struct ifinfomsg *ifm; 1438 struct ifinfomsg *ifm;
1436 struct nlmsghdr *nlh; 1439 struct nlmsghdr *nlh;
@@ -1448,6 +1451,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
1448 ifm->ifi_flags = dev_get_flags(dev); 1451 ifm->ifi_flags = dev_get_flags(dev);
1449 ifm->ifi_change = change; 1452 ifm->ifi_change = change;
1450 1453
1454 if (tgt_netnsid >= 0 && nla_put_s32(skb, IFLA_IF_NETNSID, tgt_netnsid))
1455 goto nla_put_failure;
1456
1451 if (nla_put_string(skb, IFLA_IFNAME, dev->name) || 1457 if (nla_put_string(skb, IFLA_IFNAME, dev->name) ||
1452 nla_put_u32(skb, IFLA_TXQLEN, dev->tx_queue_len) || 1458 nla_put_u32(skb, IFLA_TXQLEN, dev->tx_queue_len) ||
1453 nla_put_u8(skb, IFLA_OPERSTATE, 1459 nla_put_u8(skb, IFLA_OPERSTATE,
@@ -1513,7 +1519,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
1513 goto nla_put_failure; 1519 goto nla_put_failure;
1514 } 1520 }
1515 1521
1516 if (rtnl_fill_link_netnsid(skb, dev)) 1522 if (rtnl_fill_link_netnsid(skb, dev, src_net))
1517 goto nla_put_failure; 1523 goto nla_put_failure;
1518 1524
1519 if (new_nsid && 1525 if (new_nsid &&
@@ -1571,6 +1577,7 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
1571 [IFLA_XDP] = { .type = NLA_NESTED }, 1577 [IFLA_XDP] = { .type = NLA_NESTED },
1572 [IFLA_EVENT] = { .type = NLA_U32 }, 1578 [IFLA_EVENT] = { .type = NLA_U32 },
1573 [IFLA_GROUP] = { .type = NLA_U32 }, 1579 [IFLA_GROUP] = { .type = NLA_U32 },
1580 [IFLA_IF_NETNSID] = { .type = NLA_S32 },
1574}; 1581};
1575 1582
1576static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { 1583static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
@@ -1674,9 +1681,28 @@ static bool link_dump_filtered(struct net_device *dev,
1674 return false; 1681 return false;
1675} 1682}
1676 1683
1684static struct net *get_target_net(struct sk_buff *skb, int netnsid)
1685{
1686 struct net *net;
1687
1688 net = get_net_ns_by_id(sock_net(skb->sk), netnsid);
1689 if (!net)
1690 return ERR_PTR(-EINVAL);
1691
1692 /* For now, the caller is required to have CAP_NET_ADMIN in
1693 * the user namespace owning the target net ns.
1694 */
1695 if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) {
1696 put_net(net);
1697 return ERR_PTR(-EACCES);
1698 }
1699 return net;
1700}
1701
1677static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) 1702static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
1678{ 1703{
1679 struct net *net = sock_net(skb->sk); 1704 struct net *net = sock_net(skb->sk);
1705 struct net *tgt_net = net;
1680 int h, s_h; 1706 int h, s_h;
1681 int idx = 0, s_idx; 1707 int idx = 0, s_idx;
1682 struct net_device *dev; 1708 struct net_device *dev;
@@ -1686,6 +1712,7 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
1686 const struct rtnl_link_ops *kind_ops = NULL; 1712 const struct rtnl_link_ops *kind_ops = NULL;
1687 unsigned int flags = NLM_F_MULTI; 1713 unsigned int flags = NLM_F_MULTI;
1688 int master_idx = 0; 1714 int master_idx = 0;
1715 int netnsid = -1;
1689 int err; 1716 int err;
1690 int hdrlen; 1717 int hdrlen;
1691 1718
@@ -1704,6 +1731,15 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
1704 1731
1705 if (nlmsg_parse(cb->nlh, hdrlen, tb, IFLA_MAX, 1732 if (nlmsg_parse(cb->nlh, hdrlen, tb, IFLA_MAX,
1706 ifla_policy, NULL) >= 0) { 1733 ifla_policy, NULL) >= 0) {
1734 if (tb[IFLA_IF_NETNSID]) {
1735 netnsid = nla_get_s32(tb[IFLA_IF_NETNSID]);
1736 tgt_net = get_target_net(skb, netnsid);
1737 if (IS_ERR(tgt_net)) {
1738 tgt_net = net;
1739 netnsid = -1;
1740 }
1741 }
1742
1707 if (tb[IFLA_EXT_MASK]) 1743 if (tb[IFLA_EXT_MASK])
1708 ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]); 1744 ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
1709 1745
@@ -1719,17 +1755,19 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
1719 1755
1720 for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { 1756 for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
1721 idx = 0; 1757 idx = 0;
1722 head = &net->dev_index_head[h]; 1758 head = &tgt_net->dev_index_head[h];
1723 hlist_for_each_entry(dev, head, index_hlist) { 1759 hlist_for_each_entry(dev, head, index_hlist) {
1724 if (link_dump_filtered(dev, master_idx, kind_ops)) 1760 if (link_dump_filtered(dev, master_idx, kind_ops))
1725 goto cont; 1761 goto cont;
1726 if (idx < s_idx) 1762 if (idx < s_idx)
1727 goto cont; 1763 goto cont;
1728 err = rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK, 1764 err = rtnl_fill_ifinfo(skb, dev, net,
1765 RTM_NEWLINK,
1729 NETLINK_CB(cb->skb).portid, 1766 NETLINK_CB(cb->skb).portid,
1730 cb->nlh->nlmsg_seq, 0, 1767 cb->nlh->nlmsg_seq, 0,
1731 flags, 1768 flags,
1732 ext_filter_mask, 0, NULL); 1769 ext_filter_mask, 0, NULL,
1770 netnsid);
1733 1771
1734 if (err < 0) { 1772 if (err < 0) {
1735 if (likely(skb->len)) 1773 if (likely(skb->len))
@@ -1748,6 +1786,8 @@ out_err:
1748 cb->args[0] = h; 1786 cb->args[0] = h;
1749 cb->seq = net->dev_base_seq; 1787 cb->seq = net->dev_base_seq;
1750 nl_dump_check_consistent(cb, nlmsg_hdr(skb)); 1788 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
1789 if (netnsid >= 0)
1790 put_net(tgt_net);
1751 1791
1752 return err; 1792 return err;
1753} 1793}
@@ -2360,6 +2400,9 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
2360 if (err < 0) 2400 if (err < 0)
2361 goto errout; 2401 goto errout;
2362 2402
2403 if (tb[IFLA_IF_NETNSID])
2404 return -EOPNOTSUPP;
2405
2363 if (tb[IFLA_IFNAME]) 2406 if (tb[IFLA_IFNAME])
2364 nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); 2407 nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
2365 else 2408 else
@@ -2454,6 +2497,9 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh,
2454 if (err < 0) 2497 if (err < 0)
2455 return err; 2498 return err;
2456 2499
2500 if (tb[IFLA_IF_NETNSID])
2501 return -EOPNOTSUPP;
2502
2457 if (tb[IFLA_IFNAME]) 2503 if (tb[IFLA_IFNAME])
2458 nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); 2504 nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
2459 2505
@@ -2585,6 +2631,9 @@ replay:
2585 if (err < 0) 2631 if (err < 0)
2586 return err; 2632 return err;
2587 2633
2634 if (tb[IFLA_IF_NETNSID])
2635 return -EOPNOTSUPP;
2636
2588 if (tb[IFLA_IFNAME]) 2637 if (tb[IFLA_IFNAME])
2589 nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); 2638 nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
2590 else 2639 else
@@ -2818,11 +2867,13 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr *nlh,
2818 struct netlink_ext_ack *extack) 2867 struct netlink_ext_ack *extack)
2819{ 2868{
2820 struct net *net = sock_net(skb->sk); 2869 struct net *net = sock_net(skb->sk);
2870 struct net *tgt_net = net;
2821 struct ifinfomsg *ifm; 2871 struct ifinfomsg *ifm;
2822 char ifname[IFNAMSIZ]; 2872 char ifname[IFNAMSIZ];
2823 struct nlattr *tb[IFLA_MAX+1]; 2873 struct nlattr *tb[IFLA_MAX+1];
2824 struct net_device *dev = NULL; 2874 struct net_device *dev = NULL;
2825 struct sk_buff *nskb; 2875 struct sk_buff *nskb;
2876 int netnsid = -1;
2826 int err; 2877 int err;
2827 u32 ext_filter_mask = 0; 2878 u32 ext_filter_mask = 0;
2828 2879
@@ -2830,35 +2881,50 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr *nlh,
2830 if (err < 0) 2881 if (err < 0)
2831 return err; 2882 return err;
2832 2883
2884 if (tb[IFLA_IF_NETNSID]) {
2885 netnsid = nla_get_s32(tb[IFLA_IF_NETNSID]);
2886 tgt_net = get_target_net(skb, netnsid);
2887 if (IS_ERR(tgt_net))
2888 return PTR_ERR(tgt_net);
2889 }
2890
2833 if (tb[IFLA_IFNAME]) 2891 if (tb[IFLA_IFNAME])
2834 nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); 2892 nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
2835 2893
2836 if (tb[IFLA_EXT_MASK]) 2894 if (tb[IFLA_EXT_MASK])
2837 ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]); 2895 ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
2838 2896
2897 err = -EINVAL;
2839 ifm = nlmsg_data(nlh); 2898 ifm = nlmsg_data(nlh);
2840 if (ifm->ifi_index > 0) 2899 if (ifm->ifi_index > 0)
2841 dev = __dev_get_by_index(net, ifm->ifi_index); 2900 dev = __dev_get_by_index(tgt_net, ifm->ifi_index);
2842 else if (tb[IFLA_IFNAME]) 2901 else if (tb[IFLA_IFNAME])
2843 dev = __dev_get_by_name(net, ifname); 2902 dev = __dev_get_by_name(tgt_net, ifname);
2844 else 2903 else
2845 return -EINVAL; 2904 goto out;
2846 2905
2906 err = -ENODEV;
2847 if (dev == NULL) 2907 if (dev == NULL)
2848 return -ENODEV; 2908 goto out;
2849 2909
2910 err = -ENOBUFS;
2850 nskb = nlmsg_new(if_nlmsg_size(dev, ext_filter_mask), GFP_KERNEL); 2911 nskb = nlmsg_new(if_nlmsg_size(dev, ext_filter_mask), GFP_KERNEL);
2851 if (nskb == NULL) 2912 if (nskb == NULL)
2852 return -ENOBUFS; 2913 goto out;
2853 2914
2854 err = rtnl_fill_ifinfo(nskb, dev, RTM_NEWLINK, NETLINK_CB(skb).portid, 2915 err = rtnl_fill_ifinfo(nskb, dev, net,
2855 nlh->nlmsg_seq, 0, 0, ext_filter_mask, 0, NULL); 2916 RTM_NEWLINK, NETLINK_CB(skb).portid,
2917 nlh->nlmsg_seq, 0, 0, ext_filter_mask,
2918 0, NULL, netnsid);
2856 if (err < 0) { 2919 if (err < 0) {
2857 /* -EMSGSIZE implies BUG in if_nlmsg_size */ 2920 /* -EMSGSIZE implies BUG in if_nlmsg_size */
2858 WARN_ON(err == -EMSGSIZE); 2921 WARN_ON(err == -EMSGSIZE);
2859 kfree_skb(nskb); 2922 kfree_skb(nskb);
2860 } else 2923 } else
2861 err = rtnl_unicast(nskb, net, NETLINK_CB(skb).portid); 2924 err = rtnl_unicast(nskb, net, NETLINK_CB(skb).portid);
2925out:
2926 if (netnsid >= 0)
2927 put_net(tgt_net);
2862 2928
2863 return err; 2929 return err;
2864} 2930}
@@ -2948,8 +3014,9 @@ struct sk_buff *rtmsg_ifinfo_build_skb(int type, struct net_device *dev,
2948 if (skb == NULL) 3014 if (skb == NULL)
2949 goto errout; 3015 goto errout;
2950 3016
2951 err = rtnl_fill_ifinfo(skb, dev, type, 0, 0, change, 0, 0, event, 3017 err = rtnl_fill_ifinfo(skb, dev, dev_net(dev),
2952 new_nsid); 3018 type, 0, 0, change, 0, 0, event,
3019 new_nsid, -1);
2953 if (err < 0) { 3020 if (err < 0) {
2954 /* -EMSGSIZE implies BUG in if_nlmsg_size() */ 3021 /* -EMSGSIZE implies BUG in if_nlmsg_size() */
2955 WARN_ON(err == -EMSGSIZE); 3022 WARN_ON(err == -EMSGSIZE);