@@ -1902,6 +1902,49 @@ struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[])
1902
1902
}
1903
1903
EXPORT_SYMBOL (rtnl_link_get_net );
1904
1904
1905
+ /* Figure out which network namespace we are talking about by
1906
+ * examining the link attributes in the following order:
1907
+ *
1908
+ * 1. IFLA_NET_NS_PID
1909
+ * 2. IFLA_NET_NS_FD
1910
+ * 3. IFLA_IF_NETNSID
1911
+ */
1912
+ static struct net * rtnl_link_get_net_by_nlattr (struct net * src_net ,
1913
+ struct nlattr * tb [])
1914
+ {
1915
+ struct net * net ;
1916
+
1917
+ if (tb [IFLA_NET_NS_PID ] || tb [IFLA_NET_NS_FD ])
1918
+ return rtnl_link_get_net (src_net , tb );
1919
+
1920
+ if (!tb [IFLA_IF_NETNSID ])
1921
+ return get_net (src_net );
1922
+
1923
+ net = get_net_ns_by_id (src_net , nla_get_u32 (tb [IFLA_IF_NETNSID ]));
1924
+ if (!net )
1925
+ return ERR_PTR (- EINVAL );
1926
+
1927
+ return net ;
1928
+ }
1929
+
1930
+ static struct net * rtnl_link_get_net_capable (const struct sk_buff * skb ,
1931
+ struct net * src_net ,
1932
+ struct nlattr * tb [], int cap )
1933
+ {
1934
+ struct net * net ;
1935
+
1936
+ net = rtnl_link_get_net_by_nlattr (src_net , tb );
1937
+ if (IS_ERR (net ))
1938
+ return net ;
1939
+
1940
+ if (!netlink_ns_capable (skb , net -> user_ns , cap )) {
1941
+ put_net (net );
1942
+ return ERR_PTR (- EPERM );
1943
+ }
1944
+
1945
+ return net ;
1946
+ }
1947
+
1905
1948
static int validate_linkmsg (struct net_device * dev , struct nlattr * tb [])
1906
1949
{
1907
1950
if (dev ) {
@@ -2164,17 +2207,14 @@ static int do_setlink(const struct sk_buff *skb,
2164
2207
const struct net_device_ops * ops = dev -> netdev_ops ;
2165
2208
int err ;
2166
2209
2167
- if (tb [IFLA_NET_NS_PID ] || tb [IFLA_NET_NS_FD ]) {
2168
- struct net * net = rtnl_link_get_net (dev_net (dev ), tb );
2210
+ if (tb [IFLA_NET_NS_PID ] || tb [IFLA_NET_NS_FD ] || tb [IFLA_IF_NETNSID ]) {
2211
+ struct net * net = rtnl_link_get_net_capable (skb , dev_net (dev ),
2212
+ tb , CAP_NET_ADMIN );
2169
2213
if (IS_ERR (net )) {
2170
2214
err = PTR_ERR (net );
2171
2215
goto errout ;
2172
2216
}
2173
- if (!netlink_ns_capable (skb , net -> user_ns , CAP_NET_ADMIN )) {
2174
- put_net (net );
2175
- err = - EPERM ;
2176
- goto errout ;
2177
- }
2217
+
2178
2218
err = dev_change_net_namespace (dev , net , ifname );
2179
2219
put_net (net );
2180
2220
if (err )
@@ -2515,9 +2555,6 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
2515
2555
if (err < 0 )
2516
2556
goto errout ;
2517
2557
2518
- if (tb [IFLA_IF_NETNSID ])
2519
- return - EOPNOTSUPP ;
2520
-
2521
2558
if (tb [IFLA_IFNAME ])
2522
2559
nla_strlcpy (ifname , tb [IFLA_IFNAME ], IFNAMSIZ );
2523
2560
else
@@ -2602,36 +2639,53 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh,
2602
2639
struct netlink_ext_ack * extack )
2603
2640
{
2604
2641
struct net * net = sock_net (skb -> sk );
2605
- struct net_device * dev ;
2642
+ struct net * tgt_net = net ;
2643
+ struct net_device * dev = NULL ;
2606
2644
struct ifinfomsg * ifm ;
2607
2645
char ifname [IFNAMSIZ ];
2608
2646
struct nlattr * tb [IFLA_MAX + 1 ];
2609
2647
int err ;
2648
+ int netnsid = -1 ;
2610
2649
2611
2650
err = nlmsg_parse (nlh , sizeof (* ifm ), tb , IFLA_MAX , ifla_policy , extack );
2612
2651
if (err < 0 )
2613
2652
return err ;
2614
2653
2615
- if (tb [IFLA_IF_NETNSID ])
2616
- return - EOPNOTSUPP ;
2617
-
2618
2654
if (tb [IFLA_IFNAME ])
2619
2655
nla_strlcpy (ifname , tb [IFLA_IFNAME ], IFNAMSIZ );
2620
2656
2657
+ if (tb [IFLA_IF_NETNSID ]) {
2658
+ netnsid = nla_get_s32 (tb [IFLA_IF_NETNSID ]);
2659
+ tgt_net = get_target_net (NETLINK_CB (skb ).sk , netnsid );
2660
+ if (IS_ERR (tgt_net ))
2661
+ return PTR_ERR (tgt_net );
2662
+ }
2663
+
2664
+ err = - EINVAL ;
2621
2665
ifm = nlmsg_data (nlh );
2622
2666
if (ifm -> ifi_index > 0 )
2623
- dev = __dev_get_by_index (net , ifm -> ifi_index );
2667
+ dev = __dev_get_by_index (tgt_net , ifm -> ifi_index );
2624
2668
else if (tb [IFLA_IFNAME ])
2625
- dev = __dev_get_by_name (net , ifname );
2669
+ dev = __dev_get_by_name (tgt_net , ifname );
2626
2670
else if (tb [IFLA_GROUP ])
2627
- return rtnl_group_dellink (net , nla_get_u32 (tb [IFLA_GROUP ]));
2671
+ err = rtnl_group_dellink (tgt_net , nla_get_u32 (tb [IFLA_GROUP ]));
2628
2672
else
2629
- return - EINVAL ;
2673
+ goto out ;
2630
2674
2631
- if (!dev )
2632
- return - ENODEV ;
2675
+ if (!dev ) {
2676
+ if (tb [IFLA_IFNAME ] || ifm -> ifi_index > 0 )
2677
+ err = - ENODEV ;
2678
+
2679
+ goto out ;
2680
+ }
2681
+
2682
+ err = rtnl_delete_link (dev );
2683
+
2684
+ out :
2685
+ if (netnsid >= 0 )
2686
+ put_net (tgt_net );
2633
2687
2634
- return rtnl_delete_link ( dev ) ;
2688
+ return err ;
2635
2689
}
2636
2690
2637
2691
int rtnl_configure_link (struct net_device * dev , const struct ifinfomsg * ifm )
0 commit comments