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.c45
1 files changed, 25 insertions, 20 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index ab293a3066b3..7ebed55b5f7d 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1300,7 +1300,6 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
1300 s_h = cb->args[0]; 1300 s_h = cb->args[0];
1301 s_idx = cb->args[1]; 1301 s_idx = cb->args[1];
1302 1302
1303 rcu_read_lock();
1304 cb->seq = net->dev_base_seq; 1303 cb->seq = net->dev_base_seq;
1305 1304
1306 /* A hack to preserve kernel<->userspace interface. 1305 /* A hack to preserve kernel<->userspace interface.
@@ -1322,7 +1321,7 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
1322 for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { 1321 for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
1323 idx = 0; 1322 idx = 0;
1324 head = &net->dev_index_head[h]; 1323 head = &net->dev_index_head[h];
1325 hlist_for_each_entry_rcu(dev, head, index_hlist) { 1324 hlist_for_each_entry(dev, head, index_hlist) {
1326 if (idx < s_idx) 1325 if (idx < s_idx)
1327 goto cont; 1326 goto cont;
1328 err = rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK, 1327 err = rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK,
@@ -1344,7 +1343,6 @@ cont:
1344 } 1343 }
1345 } 1344 }
1346out: 1345out:
1347 rcu_read_unlock();
1348 cb->args[1] = idx; 1346 cb->args[1] = idx;
1349 cb->args[0] = h; 1347 cb->args[0] = h;
1350 1348
@@ -1934,10 +1932,10 @@ static int rtnl_group_changelink(const struct sk_buff *skb,
1934 struct ifinfomsg *ifm, 1932 struct ifinfomsg *ifm,
1935 struct nlattr **tb) 1933 struct nlattr **tb)
1936{ 1934{
1937 struct net_device *dev; 1935 struct net_device *dev, *aux;
1938 int err; 1936 int err;
1939 1937
1940 for_each_netdev(net, dev) { 1938 for_each_netdev_safe(net, dev, aux) {
1941 if (dev->group == group) { 1939 if (dev->group == group) {
1942 err = do_setlink(skb, dev, ifm, tb, NULL, 0); 1940 err = do_setlink(skb, dev, ifm, tb, NULL, 0);
1943 if (err < 0) 1941 if (err < 0)
@@ -2012,8 +2010,8 @@ replay:
2012 } 2010 }
2013 2011
2014 if (1) { 2012 if (1) {
2015 struct nlattr *attr[ops ? ops->maxtype + 1 : 0]; 2013 struct nlattr *attr[ops ? ops->maxtype + 1 : 1];
2016 struct nlattr *slave_attr[m_ops ? m_ops->slave_maxtype + 1 : 0]; 2014 struct nlattr *slave_attr[m_ops ? m_ops->slave_maxtype + 1 : 1];
2017 struct nlattr **data = NULL; 2015 struct nlattr **data = NULL;
2018 struct nlattr **slave_data = NULL; 2016 struct nlattr **slave_data = NULL;
2019 struct net *dest_net, *link_net = NULL; 2017 struct net *dest_net, *link_net = NULL;
@@ -2122,6 +2120,10 @@ replay:
2122 if (IS_ERR(dest_net)) 2120 if (IS_ERR(dest_net))
2123 return PTR_ERR(dest_net); 2121 return PTR_ERR(dest_net);
2124 2122
2123 err = -EPERM;
2124 if (!netlink_ns_capable(skb, dest_net->user_ns, CAP_NET_ADMIN))
2125 goto out;
2126
2125 if (tb[IFLA_LINK_NETNSID]) { 2127 if (tb[IFLA_LINK_NETNSID]) {
2126 int id = nla_get_s32(tb[IFLA_LINK_NETNSID]); 2128 int id = nla_get_s32(tb[IFLA_LINK_NETNSID]);
2127 2129
@@ -2130,6 +2132,9 @@ replay:
2130 err = -EINVAL; 2132 err = -EINVAL;
2131 goto out; 2133 goto out;
2132 } 2134 }
2135 err = -EPERM;
2136 if (!netlink_ns_capable(skb, link_net->user_ns, CAP_NET_ADMIN))
2137 goto out;
2133 } 2138 }
2134 2139
2135 dev = rtnl_create_link(link_net ? : dest_net, ifname, 2140 dev = rtnl_create_link(link_net ? : dest_net, ifname,
@@ -2161,28 +2166,28 @@ replay:
2161 } 2166 }
2162 } 2167 }
2163 err = rtnl_configure_link(dev, ifm); 2168 err = rtnl_configure_link(dev, ifm);
2164 if (err < 0) { 2169 if (err < 0)
2165 if (ops->newlink) { 2170 goto out_unregister;
2166 LIST_HEAD(list_kill);
2167
2168 ops->dellink(dev, &list_kill);
2169 unregister_netdevice_many(&list_kill);
2170 } else {
2171 unregister_netdevice(dev);
2172 }
2173 goto out;
2174 }
2175
2176 if (link_net) { 2171 if (link_net) {
2177 err = dev_change_net_namespace(dev, dest_net, ifname); 2172 err = dev_change_net_namespace(dev, dest_net, ifname);
2178 if (err < 0) 2173 if (err < 0)
2179 unregister_netdevice(dev); 2174 goto out_unregister;
2180 } 2175 }
2181out: 2176out:
2182 if (link_net) 2177 if (link_net)
2183 put_net(link_net); 2178 put_net(link_net);
2184 put_net(dest_net); 2179 put_net(dest_net);
2185 return err; 2180 return err;
2181out_unregister:
2182 if (ops->newlink) {
2183 LIST_HEAD(list_kill);
2184
2185 ops->dellink(dev, &list_kill);
2186 unregister_netdevice_many(&list_kill);
2187 } else {
2188 unregister_netdevice(dev);
2189 }
2190 goto out;
2186 } 2191 }
2187} 2192}
2188 2193