aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-06-19 19:49:39 -0400
committerDavid S. Miller <davem@davemloft.net>2013-06-19 19:49:39 -0400
commitd98cae64e4a733ff377184d78aa0b1f2b54faede (patch)
treee973e3c93fe7e17741567ac3947f5197bc9d582d /net/wireless/nl80211.c
parent646093a29f85630d8efe2aa38fa585d2c3ea2e46 (diff)
parent4067c666f2dccf56f5db5c182713e68c40d46013 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts: drivers/net/wireless/ath/ath9k/Kconfig drivers/net/xen-netback/netback.c net/batman-adv/bat_iv_ogm.c net/wireless/nl80211.c The ath9k Kconfig conflict was a change of a Kconfig option name right next to the deletion of another option. The xen-netback conflict was overlapping changes involving the handling of the notify list in xen_netbk_rx_action(). Batman conflict resolution provided by Antonio Quartulli, basically keep everything in both conflict hunks. The nl80211 conflict is a little more involved. In 'net' we added a dynamic memory allocation to nl80211_dump_wiphy() to fix a race that Linus reported. Meanwhile in 'net-next' the handlers were converted to use pre and post doit handlers which use a flag to determine whether to hold the RTNL mutex around the operation. However, the dump handlers to not use this logic. Instead they have to explicitly do the locking. There were apparent bugs in the conversion of nl80211_dump_wiphy() in that we were not dropping the RTNL mutex in all the return paths, and it seems we very much should be doing so. So I fixed that whilst handling the overlapping changes. To simplify the initial returns, I take the RTNL mutex after we try to allocate 'tb'. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 31d265f36d2c..ea74b9dd9d82 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1527,12 +1527,18 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
1527 struct cfg80211_registered_device *dev; 1527 struct cfg80211_registered_device *dev;
1528 s64 filter_wiphy = -1; 1528 s64 filter_wiphy = -1;
1529 bool split = false; 1529 bool split = false;
1530 struct nlattr **tb = nl80211_fam.attrbuf; 1530 struct nlattr **tb;
1531 int res; 1531 int res;
1532 1532
1533 /* will be zeroed in nlmsg_parse() */
1534 tb = kmalloc(sizeof(*tb) * (NL80211_ATTR_MAX + 1), GFP_KERNEL);
1535 if (!tb)
1536 return -ENOMEM;
1537
1533 rtnl_lock(); 1538 rtnl_lock();
1539
1534 res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, 1540 res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
1535 tb, nl80211_fam.maxattr, nl80211_policy); 1541 tb, NL80211_ATTR_MAX, nl80211_policy);
1536 if (res == 0) { 1542 if (res == 0) {
1537 split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP]; 1543 split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP];
1538 if (tb[NL80211_ATTR_WIPHY]) 1544 if (tb[NL80211_ATTR_WIPHY])
@@ -1544,8 +1550,11 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
1544 int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]); 1550 int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
1545 1551
1546 netdev = dev_get_by_index(sock_net(skb->sk), ifidx); 1552 netdev = dev_get_by_index(sock_net(skb->sk), ifidx);
1547 if (!netdev) 1553 if (!netdev) {
1554 rtnl_unlock();
1555 kfree(tb);
1548 return -ENODEV; 1556 return -ENODEV;
1557 }
1549 if (netdev->ieee80211_ptr) { 1558 if (netdev->ieee80211_ptr) {
1550 dev = wiphy_to_dev( 1559 dev = wiphy_to_dev(
1551 netdev->ieee80211_ptr->wiphy); 1560 netdev->ieee80211_ptr->wiphy);
@@ -1554,6 +1563,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
1554 dev_put(netdev); 1563 dev_put(netdev);
1555 } 1564 }
1556 } 1565 }
1566 kfree(tb);
1557 1567
1558 list_for_each_entry(dev, &cfg80211_rdev_list, list) { 1568 list_for_each_entry(dev, &cfg80211_rdev_list, list) {
1559 if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk))) 1569 if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk)))
@@ -1589,6 +1599,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
1589 !skb->len && 1599 !skb->len &&
1590 cb->min_dump_alloc < 4096) { 1600 cb->min_dump_alloc < 4096) {
1591 cb->min_dump_alloc = 4096; 1601 cb->min_dump_alloc = 4096;
1602 rtnl_unlock();
1592 return 1; 1603 return 1;
1593 } 1604 }
1594 idx--; 1605 idx--;