@@ -921,7 +921,8 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev,
921921 + nla_total_size (4 ) /* IFLA_EVENT */
922922 + nla_total_size (4 ) /* IFLA_NEW_NETNSID */
923923 + nla_total_size (1 ); /* IFLA_PROTO_DOWN */
924-
924+ + nla_total_size (4 ) /* IFLA_IF_NETNSID */
925+ + 0 ;
925926}
926927
927928static 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,
13701371}
13711372
13721373static 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 )
13741376{
13751377 if (dev -> rtnl_link_ops && dev -> rtnl_link_ops -> get_link_net ) {
13761378 struct net * link_net = dev -> rtnl_link_ops -> get_link_net (dev );
13771379
13781380 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 );
13801382
13811383 if (nla_put_s32 (skb , IFLA_LINK_NETNSID , id ))
13821384 return - EMSGSIZE ;
@@ -1427,10 +1429,11 @@ static int rtnl_fill_link_af(struct sk_buff *skb,
14271429 return 0 ;
14281430}
14291431
1430- static int rtnl_fill_ifinfo (struct sk_buff * skb , struct net_device * dev ,
1432+ static int rtnl_fill_ifinfo (struct sk_buff * skb ,
1433+ struct net_device * dev , struct net * src_net ,
14311434 int type , u32 pid , u32 seq , u32 change ,
14321435 unsigned int flags , u32 ext_filter_mask ,
1433- u32 event , int * new_nsid )
1436+ u32 event , int * new_nsid , int tgt_netnsid )
14341437{
14351438 struct ifinfomsg * ifm ;
14361439 struct nlmsghdr * nlh ;
@@ -1448,6 +1451,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
14481451 ifm -> ifi_flags = dev_get_flags (dev );
14491452 ifm -> ifi_change = change ;
14501453
1454+ if (tgt_netnsid >= 0 && nla_put_s32 (skb , IFLA_IF_NETNSID , tgt_netnsid ))
1455+ goto nla_put_failure ;
1456+
14511457 if (nla_put_string (skb , IFLA_IFNAME , dev -> name ) ||
14521458 nla_put_u32 (skb , IFLA_TXQLEN , dev -> tx_queue_len ) ||
14531459 nla_put_u8 (skb , IFLA_OPERSTATE ,
@@ -1513,7 +1519,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
15131519 goto nla_put_failure ;
15141520 }
15151521
1516- if (rtnl_fill_link_netnsid (skb , dev ))
1522+ if (rtnl_fill_link_netnsid (skb , dev , src_net ))
15171523 goto nla_put_failure ;
15181524
15191525 if (new_nsid &&
@@ -1571,6 +1577,7 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
15711577 [IFLA_XDP ] = { .type = NLA_NESTED },
15721578 [IFLA_EVENT ] = { .type = NLA_U32 },
15731579 [IFLA_GROUP ] = { .type = NLA_U32 },
1580+ [IFLA_IF_NETNSID ] = { .type = NLA_S32 },
15741581};
15751582
15761583static const struct nla_policy ifla_info_policy [IFLA_INFO_MAX + 1 ] = {
@@ -1674,9 +1681,28 @@ static bool link_dump_filtered(struct net_device *dev,
16741681 return false;
16751682}
16761683
1684+ static 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+
16771702static int rtnl_dump_ifinfo (struct sk_buff * skb , struct netlink_callback * cb )
16781703{
16791704 struct net * net = sock_net (skb -> sk );
1705+ struct net * tgt_net = net ;
16801706 int h , s_h ;
16811707 int idx = 0 , s_idx ;
16821708 struct net_device * dev ;
@@ -1686,6 +1712,7 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
16861712 const struct rtnl_link_ops * kind_ops = NULL ;
16871713 unsigned int flags = NLM_F_MULTI ;
16881714 int master_idx = 0 ;
1715+ int netnsid = -1 ;
16891716 int err ;
16901717 int hdrlen ;
16911718
@@ -1704,6 +1731,15 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
17041731
17051732 if (nlmsg_parse (cb -> nlh , hdrlen , tb , IFLA_MAX ,
17061733 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+
17071743 if (tb [IFLA_EXT_MASK ])
17081744 ext_filter_mask = nla_get_u32 (tb [IFLA_EXT_MASK ]);
17091745
@@ -1719,17 +1755,19 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
17191755
17201756 for (h = s_h ; h < NETDEV_HASHENTRIES ; h ++ , s_idx = 0 ) {
17211757 idx = 0 ;
1722- head = & net -> dev_index_head [h ];
1758+ head = & tgt_net -> dev_index_head [h ];
17231759 hlist_for_each_entry (dev , head , index_hlist ) {
17241760 if (link_dump_filtered (dev , master_idx , kind_ops ))
17251761 goto cont ;
17261762 if (idx < s_idx )
17271763 goto cont ;
1728- err = rtnl_fill_ifinfo (skb , dev , RTM_NEWLINK ,
1764+ err = rtnl_fill_ifinfo (skb , dev , net ,
1765+ RTM_NEWLINK ,
17291766 NETLINK_CB (cb -> skb ).portid ,
17301767 cb -> nlh -> nlmsg_seq , 0 ,
17311768 flags ,
1732- ext_filter_mask , 0 , NULL );
1769+ ext_filter_mask , 0 , NULL ,
1770+ netnsid );
17331771
17341772 if (err < 0 ) {
17351773 if (likely (skb -> len ))
@@ -1748,6 +1786,8 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
17481786 cb -> args [0 ] = h ;
17491787 cb -> seq = net -> dev_base_seq ;
17501788 nl_dump_check_consistent (cb , nlmsg_hdr (skb ));
1789+ if (netnsid >= 0 )
1790+ put_net (tgt_net );
17511791
17521792 return err ;
17531793}
@@ -2360,6 +2400,9 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
23602400 if (err < 0 )
23612401 goto errout ;
23622402
2403+ if (tb [IFLA_IF_NETNSID ])
2404+ return - EOPNOTSUPP ;
2405+
23632406 if (tb [IFLA_IFNAME ])
23642407 nla_strlcpy (ifname , tb [IFLA_IFNAME ], IFNAMSIZ );
23652408 else
@@ -2454,6 +2497,9 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh,
24542497 if (err < 0 )
24552498 return err ;
24562499
2500+ if (tb [IFLA_IF_NETNSID ])
2501+ return - EOPNOTSUPP ;
2502+
24572503 if (tb [IFLA_IFNAME ])
24582504 nla_strlcpy (ifname , tb [IFLA_IFNAME ], IFNAMSIZ );
24592505
@@ -2585,6 +2631,9 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
25852631 if (err < 0 )
25862632 return err ;
25872633
2634+ if (tb [IFLA_IF_NETNSID ])
2635+ return - EOPNOTSUPP ;
2636+
25882637 if (tb [IFLA_IFNAME ])
25892638 nla_strlcpy (ifname , tb [IFLA_IFNAME ], IFNAMSIZ );
25902639 else
@@ -2818,47 +2867,64 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr *nlh,
28182867 struct netlink_ext_ack * extack )
28192868{
28202869 struct net * net = sock_net (skb -> sk );
2870+ struct net * tgt_net = net ;
28212871 struct ifinfomsg * ifm ;
28222872 char ifname [IFNAMSIZ ];
28232873 struct nlattr * tb [IFLA_MAX + 1 ];
28242874 struct net_device * dev = NULL ;
28252875 struct sk_buff * nskb ;
2876+ int netnsid = -1 ;
28262877 int err ;
28272878 u32 ext_filter_mask = 0 ;
28282879
28292880 err = nlmsg_parse (nlh , sizeof (* ifm ), tb , IFLA_MAX , ifla_policy , extack );
28302881 if (err < 0 )
28312882 return err ;
28322883
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+
28332891 if (tb [IFLA_IFNAME ])
28342892 nla_strlcpy (ifname , tb [IFLA_IFNAME ], IFNAMSIZ );
28352893
28362894 if (tb [IFLA_EXT_MASK ])
28372895 ext_filter_mask = nla_get_u32 (tb [IFLA_EXT_MASK ]);
28382896
2897+ err = - EINVAL ;
28392898 ifm = nlmsg_data (nlh );
28402899 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 );
28422901 else if (tb [IFLA_IFNAME ])
2843- dev = __dev_get_by_name (net , ifname );
2902+ dev = __dev_get_by_name (tgt_net , ifname );
28442903 else
2845- return - EINVAL ;
2904+ goto out ;
28462905
2906+ err = - ENODEV ;
28472907 if (dev == NULL )
2848- return - ENODEV ;
2908+ goto out ;
28492909
2910+ err = - ENOBUFS ;
28502911 nskb = nlmsg_new (if_nlmsg_size (dev , ext_filter_mask ), GFP_KERNEL );
28512912 if (nskb == NULL )
2852- return - ENOBUFS ;
2913+ goto out ;
28532914
2854- err = rtnl_fill_ifinfo (nskb , dev , RTM_NEWLINK , NETLINK_CB (skb ).portid ,
2855- nlh -> nlmsg_seq , 0 , 0 , ext_filter_mask , 0 , NULL );
2915+ err = rtnl_fill_ifinfo (nskb , dev , net ,
2916+ RTM_NEWLINK , NETLINK_CB (skb ).portid ,
2917+ nlh -> nlmsg_seq , 0 , 0 , ext_filter_mask ,
2918+ 0 , NULL , netnsid );
28562919 if (err < 0 ) {
28572920 /* -EMSGSIZE implies BUG in if_nlmsg_size */
28582921 WARN_ON (err == - EMSGSIZE );
28592922 kfree_skb (nskb );
28602923 } else
28612924 err = rtnl_unicast (nskb , net , NETLINK_CB (skb ).portid );
2925+ out :
2926+ if (netnsid >= 0 )
2927+ put_net (tgt_net );
28622928
28632929 return err ;
28642930}
@@ -2948,8 +3014,9 @@ struct sk_buff *rtmsg_ifinfo_build_skb(int type, struct net_device *dev,
29483014 if (skb == NULL )
29493015 goto errout ;
29503016
2951- err = rtnl_fill_ifinfo (skb , dev , type , 0 , 0 , change , 0 , 0 , event ,
2952- new_nsid );
3017+ err = rtnl_fill_ifinfo (skb , dev , dev_net (dev ),
3018+ type , 0 , 0 , change , 0 , 0 , event ,
3019+ new_nsid , -1 );
29533020 if (err < 0 ) {
29543021 /* -EMSGSIZE implies BUG in if_nlmsg_size() */
29553022 WARN_ON (err == - EMSGSIZE );
0 commit comments