aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-03-12 04:55:09 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-03-27 20:12:56 -0400
commit3b85875a252dbbd95c2e04d73639719a0a79634e (patch)
tree573142df787d9ccd52944695478546f543489504 /net/wireless
parent8f655dde240293f3b82313cae91c64ffd7b64c50 (diff)
nl80211: rework locking
When I added scanning to cfg80211, we got a lock dependency like this: rtnl --> cfg80211_mtx nl80211, on the other hand, has the reverse lock dependency: cfg80211_mtx --> rtnl which clearly is a bad idea. This patch reworks nl80211 to take these two locks in the other order to fix the possible, and easily triggerable, deadlock. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/nl80211.c271
1 files changed, 166 insertions, 105 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 58ee1b1aff8..a3ecf8d7389 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -602,9 +602,12 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
602 602
603 memset(&params, 0, sizeof(params)); 603 memset(&params, 0, sizeof(params));
604 604
605 rtnl_lock();
606
605 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 607 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
606 if (err) 608 if (err)
607 return err; 609 goto unlock_rtnl;
610
608 ifindex = dev->ifindex; 611 ifindex = dev->ifindex;
609 type = dev->ieee80211_ptr->iftype; 612 type = dev->ieee80211_ptr->iftype;
610 dev_put(dev); 613 dev_put(dev);
@@ -641,17 +644,17 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
641 if (!err) 644 if (!err)
642 flags = &_flags; 645 flags = &_flags;
643 } 646 }
644 rtnl_lock(); 647
645 err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, 648 err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex,
646 type, flags, &params); 649 type, flags, &params);
647 650
648 dev = __dev_get_by_index(&init_net, ifindex); 651 dev = __dev_get_by_index(&init_net, ifindex);
649 WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type)); 652 WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type));
650 653
651 rtnl_unlock();
652
653 unlock: 654 unlock:
654 cfg80211_put_dev(drv); 655 cfg80211_put_dev(drv);
656 unlock_rtnl:
657 rtnl_unlock();
655 return err; 658 return err;
656} 659}
657 660
@@ -674,9 +677,13 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
674 return -EINVAL; 677 return -EINVAL;
675 } 678 }
676 679
680 rtnl_lock();
681
677 drv = cfg80211_get_dev_from_info(info); 682 drv = cfg80211_get_dev_from_info(info);
678 if (IS_ERR(drv)) 683 if (IS_ERR(drv)) {
679 return PTR_ERR(drv); 684 err = PTR_ERR(drv);
685 goto unlock_rtnl;
686 }
680 687
681 if (!drv->ops->add_virtual_intf || 688 if (!drv->ops->add_virtual_intf ||
682 !(drv->wiphy.interface_modes & (1 << type))) { 689 !(drv->wiphy.interface_modes & (1 << type))) {
@@ -690,18 +697,17 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
690 params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); 697 params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
691 } 698 }
692 699
693 rtnl_lock();
694 err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? 700 err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
695 info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, 701 info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
696 &flags); 702 &flags);
697 err = drv->ops->add_virtual_intf(&drv->wiphy, 703 err = drv->ops->add_virtual_intf(&drv->wiphy,
698 nla_data(info->attrs[NL80211_ATTR_IFNAME]), 704 nla_data(info->attrs[NL80211_ATTR_IFNAME]),
699 type, err ? NULL : &flags, &params); 705 type, err ? NULL : &flags, &params);
700 rtnl_unlock();
701
702 706
703 unlock: 707 unlock:
704 cfg80211_put_dev(drv); 708 cfg80211_put_dev(drv);
709 unlock_rtnl:
710 rtnl_unlock();
705 return err; 711 return err;
706} 712}
707 713
@@ -711,9 +717,11 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
711 int ifindex, err; 717 int ifindex, err;
712 struct net_device *dev; 718 struct net_device *dev;
713 719
720 rtnl_lock();
721
714 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 722 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
715 if (err) 723 if (err)
716 return err; 724 goto unlock_rtnl;
717 ifindex = dev->ifindex; 725 ifindex = dev->ifindex;
718 dev_put(dev); 726 dev_put(dev);
719 727
@@ -722,12 +730,12 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
722 goto out; 730 goto out;
723 } 731 }
724 732
725 rtnl_lock();
726 err = drv->ops->del_virtual_intf(&drv->wiphy, ifindex); 733 err = drv->ops->del_virtual_intf(&drv->wiphy, ifindex);
727 rtnl_unlock();
728 734
729 out: 735 out:
730 cfg80211_put_dev(drv); 736 cfg80211_put_dev(drv);
737 unlock_rtnl:
738 rtnl_unlock();
731 return err; 739 return err;
732} 740}
733 741
@@ -779,9 +787,11 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
779 if (info->attrs[NL80211_ATTR_MAC]) 787 if (info->attrs[NL80211_ATTR_MAC])
780 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 788 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
781 789
790 rtnl_lock();
791
782 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 792 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
783 if (err) 793 if (err)
784 return err; 794 goto unlock_rtnl;
785 795
786 if (!drv->ops->get_key) { 796 if (!drv->ops->get_key) {
787 err = -EOPNOTSUPP; 797 err = -EOPNOTSUPP;
@@ -809,10 +819,8 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
809 if (mac_addr) 819 if (mac_addr)
810 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); 820 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
811 821
812 rtnl_lock();
813 err = drv->ops->get_key(&drv->wiphy, dev, key_idx, mac_addr, 822 err = drv->ops->get_key(&drv->wiphy, dev, key_idx, mac_addr,
814 &cookie, get_key_callback); 823 &cookie, get_key_callback);
815 rtnl_unlock();
816 824
817 if (err) 825 if (err)
818 goto out; 826 goto out;
@@ -830,6 +838,9 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
830 out: 838 out:
831 cfg80211_put_dev(drv); 839 cfg80211_put_dev(drv);
832 dev_put(dev); 840 dev_put(dev);
841 unlock_rtnl:
842 rtnl_unlock();
843
833 return err; 844 return err;
834} 845}
835 846
@@ -858,9 +869,11 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
858 !info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]) 869 !info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT])
859 return -EINVAL; 870 return -EINVAL;
860 871
872 rtnl_lock();
873
861 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 874 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
862 if (err) 875 if (err)
863 return err; 876 goto unlock_rtnl;
864 877
865 if (info->attrs[NL80211_ATTR_KEY_DEFAULT]) 878 if (info->attrs[NL80211_ATTR_KEY_DEFAULT])
866 func = drv->ops->set_default_key; 879 func = drv->ops->set_default_key;
@@ -872,13 +885,15 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
872 goto out; 885 goto out;
873 } 886 }
874 887
875 rtnl_lock();
876 err = func(&drv->wiphy, dev, key_idx); 888 err = func(&drv->wiphy, dev, key_idx);
877 rtnl_unlock();
878 889
879 out: 890 out:
880 cfg80211_put_dev(drv); 891 cfg80211_put_dev(drv);
881 dev_put(dev); 892 dev_put(dev);
893
894 unlock_rtnl:
895 rtnl_unlock();
896
882 return err; 897 return err;
883} 898}
884 899
@@ -948,22 +963,25 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
948 return -EINVAL; 963 return -EINVAL;
949 } 964 }
950 965
966 rtnl_lock();
967
951 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 968 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
952 if (err) 969 if (err)
953 return err; 970 goto unlock_rtnl;
954 971
955 if (!drv->ops->add_key) { 972 if (!drv->ops->add_key) {
956 err = -EOPNOTSUPP; 973 err = -EOPNOTSUPP;
957 goto out; 974 goto out;
958 } 975 }
959 976
960 rtnl_lock();
961 err = drv->ops->add_key(&drv->wiphy, dev, key_idx, mac_addr, &params); 977 err = drv->ops->add_key(&drv->wiphy, dev, key_idx, mac_addr, &params);
962 rtnl_unlock();
963 978
964 out: 979 out:
965 cfg80211_put_dev(drv); 980 cfg80211_put_dev(drv);
966 dev_put(dev); 981 dev_put(dev);
982 unlock_rtnl:
983 rtnl_unlock();
984
967 return err; 985 return err;
968} 986}
969 987
@@ -984,22 +1002,26 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
984 if (info->attrs[NL80211_ATTR_MAC]) 1002 if (info->attrs[NL80211_ATTR_MAC])
985 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 1003 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
986 1004
1005 rtnl_lock();
1006
987 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1007 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
988 if (err) 1008 if (err)
989 return err; 1009 goto unlock_rtnl;
990 1010
991 if (!drv->ops->del_key) { 1011 if (!drv->ops->del_key) {
992 err = -EOPNOTSUPP; 1012 err = -EOPNOTSUPP;
993 goto out; 1013 goto out;
994 } 1014 }
995 1015
996 rtnl_lock();
997 err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr); 1016 err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr);
998 rtnl_unlock();
999 1017
1000 out: 1018 out:
1001 cfg80211_put_dev(drv); 1019 cfg80211_put_dev(drv);
1002 dev_put(dev); 1020 dev_put(dev);
1021
1022 unlock_rtnl:
1023 rtnl_unlock();
1024
1003 return err; 1025 return err;
1004} 1026}
1005 1027
@@ -1013,9 +1035,11 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
1013 struct beacon_parameters params; 1035 struct beacon_parameters params;
1014 int haveinfo = 0; 1036 int haveinfo = 0;
1015 1037
1038 rtnl_lock();
1039
1016 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1040 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1017 if (err) 1041 if (err)
1018 return err; 1042 goto unlock_rtnl;
1019 1043
1020 switch (info->genlhdr->cmd) { 1044 switch (info->genlhdr->cmd) {
1021 case NL80211_CMD_NEW_BEACON: 1045 case NL80211_CMD_NEW_BEACON:
@@ -1076,13 +1100,14 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
1076 goto out; 1100 goto out;
1077 } 1101 }
1078 1102
1079 rtnl_lock();
1080 err = call(&drv->wiphy, dev, &params); 1103 err = call(&drv->wiphy, dev, &params);
1081 rtnl_unlock();
1082 1104
1083 out: 1105 out:
1084 cfg80211_put_dev(drv); 1106 cfg80211_put_dev(drv);
1085 dev_put(dev); 1107 dev_put(dev);
1108 unlock_rtnl:
1109 rtnl_unlock();
1110
1086 return err; 1111 return err;
1087} 1112}
1088 1113
@@ -1092,22 +1117,25 @@ static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info)
1092 int err; 1117 int err;
1093 struct net_device *dev; 1118 struct net_device *dev;
1094 1119
1120 rtnl_lock();
1121
1095 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1122 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1096 if (err) 1123 if (err)
1097 return err; 1124 goto unlock_rtnl;
1098 1125
1099 if (!drv->ops->del_beacon) { 1126 if (!drv->ops->del_beacon) {
1100 err = -EOPNOTSUPP; 1127 err = -EOPNOTSUPP;
1101 goto out; 1128 goto out;
1102 } 1129 }
1103 1130
1104 rtnl_lock();
1105 err = drv->ops->del_beacon(&drv->wiphy, dev); 1131 err = drv->ops->del_beacon(&drv->wiphy, dev);
1106 rtnl_unlock();
1107 1132
1108 out: 1133 out:
1109 cfg80211_put_dev(drv); 1134 cfg80211_put_dev(drv);
1110 dev_put(dev); 1135 dev_put(dev);
1136 unlock_rtnl:
1137 rtnl_unlock();
1138
1111 return err; 1139 return err;
1112} 1140}
1113 1141
@@ -1273,14 +1301,18 @@ static int nl80211_dump_station(struct sk_buff *skb,
1273 return -EINVAL; 1301 return -EINVAL;
1274 } 1302 }
1275 1303
1276 netdev = dev_get_by_index(&init_net, ifidx); 1304 rtnl_lock();
1277 if (!netdev) 1305
1278 return -ENODEV; 1306 netdev = __dev_get_by_index(&init_net, ifidx);
1307 if (!netdev) {
1308 err = -ENODEV;
1309 goto out_rtnl;
1310 }
1279 1311
1280 dev = cfg80211_get_dev_from_ifindex(ifidx); 1312 dev = cfg80211_get_dev_from_ifindex(ifidx);
1281 if (IS_ERR(dev)) { 1313 if (IS_ERR(dev)) {
1282 err = PTR_ERR(dev); 1314 err = PTR_ERR(dev);
1283 goto out_put_netdev; 1315 goto out_rtnl;
1284 } 1316 }
1285 1317
1286 if (!dev->ops->dump_station) { 1318 if (!dev->ops->dump_station) {
@@ -1288,15 +1320,13 @@ static int nl80211_dump_station(struct sk_buff *skb,
1288 goto out_err; 1320 goto out_err;
1289 } 1321 }
1290 1322
1291 rtnl_lock();
1292
1293 while (1) { 1323 while (1) {
1294 err = dev->ops->dump_station(&dev->wiphy, netdev, sta_idx, 1324 err = dev->ops->dump_station(&dev->wiphy, netdev, sta_idx,
1295 mac_addr, &sinfo); 1325 mac_addr, &sinfo);
1296 if (err == -ENOENT) 1326 if (err == -ENOENT)
1297 break; 1327 break;
1298 if (err) 1328 if (err)
1299 goto out_err_rtnl; 1329 goto out_err;
1300 1330
1301 if (nl80211_send_station(skb, 1331 if (nl80211_send_station(skb,
1302 NETLINK_CB(cb->skb).pid, 1332 NETLINK_CB(cb->skb).pid,
@@ -1312,12 +1342,10 @@ static int nl80211_dump_station(struct sk_buff *skb,
1312 out: 1342 out:
1313 cb->args[1] = sta_idx; 1343 cb->args[1] = sta_idx;
1314 err = skb->len; 1344 err = skb->len;
1315 out_err_rtnl:
1316 rtnl_unlock();
1317 out_err: 1345 out_err:
1318 cfg80211_put_dev(dev); 1346 cfg80211_put_dev(dev);
1319 out_put_netdev: 1347 out_rtnl:
1320 dev_put(netdev); 1348 rtnl_unlock();
1321 1349
1322 return err; 1350 return err;
1323} 1351}
@@ -1338,19 +1366,18 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
1338 1366
1339 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 1367 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1340 1368
1369 rtnl_lock();
1370
1341 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1371 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1342 if (err) 1372 if (err)
1343 return err; 1373 goto out_rtnl;
1344 1374
1345 if (!drv->ops->get_station) { 1375 if (!drv->ops->get_station) {
1346 err = -EOPNOTSUPP; 1376 err = -EOPNOTSUPP;
1347 goto out; 1377 goto out;
1348 } 1378 }
1349 1379
1350 rtnl_lock();
1351 err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &sinfo); 1380 err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &sinfo);
1352 rtnl_unlock();
1353
1354 if (err) 1381 if (err)
1355 goto out; 1382 goto out;
1356 1383
@@ -1367,10 +1394,12 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
1367 1394
1368 out_free: 1395 out_free:
1369 nlmsg_free(msg); 1396 nlmsg_free(msg);
1370
1371 out: 1397 out:
1372 cfg80211_put_dev(drv); 1398 cfg80211_put_dev(drv);
1373 dev_put(dev); 1399 dev_put(dev);
1400 out_rtnl:
1401 rtnl_unlock();
1402
1374 return err; 1403 return err;
1375} 1404}
1376 1405
@@ -1438,9 +1467,11 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
1438 params.plink_action = 1467 params.plink_action =
1439 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); 1468 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
1440 1469
1470 rtnl_lock();
1471
1441 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1472 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1442 if (err) 1473 if (err)
1443 return err; 1474 goto out_rtnl;
1444 1475
1445 err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan); 1476 err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
1446 if (err) 1477 if (err)
@@ -1451,15 +1482,16 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
1451 goto out; 1482 goto out;
1452 } 1483 }
1453 1484
1454 rtnl_lock();
1455 err = drv->ops->change_station(&drv->wiphy, dev, mac_addr, &params); 1485 err = drv->ops->change_station(&drv->wiphy, dev, mac_addr, &params);
1456 rtnl_unlock();
1457 1486
1458 out: 1487 out:
1459 if (params.vlan) 1488 if (params.vlan)
1460 dev_put(params.vlan); 1489 dev_put(params.vlan);
1461 cfg80211_put_dev(drv); 1490 cfg80211_put_dev(drv);
1462 dev_put(dev); 1491 dev_put(dev);
1492 out_rtnl:
1493 rtnl_unlock();
1494
1463 return err; 1495 return err;
1464} 1496}
1465 1497
@@ -1501,9 +1533,11 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
1501 &params.station_flags)) 1533 &params.station_flags))
1502 return -EINVAL; 1534 return -EINVAL;
1503 1535
1536 rtnl_lock();
1537
1504 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1538 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1505 if (err) 1539 if (err)
1506 return err; 1540 goto out_rtnl;
1507 1541
1508 err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan); 1542 err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
1509 if (err) 1543 if (err)
@@ -1514,15 +1548,16 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
1514 goto out; 1548 goto out;
1515 } 1549 }
1516 1550
1517 rtnl_lock();
1518 err = drv->ops->add_station(&drv->wiphy, dev, mac_addr, &params); 1551 err = drv->ops->add_station(&drv->wiphy, dev, mac_addr, &params);
1519 rtnl_unlock();
1520 1552
1521 out: 1553 out:
1522 if (params.vlan) 1554 if (params.vlan)
1523 dev_put(params.vlan); 1555 dev_put(params.vlan);
1524 cfg80211_put_dev(drv); 1556 cfg80211_put_dev(drv);
1525 dev_put(dev); 1557 dev_put(dev);
1558 out_rtnl:
1559 rtnl_unlock();
1560
1526 return err; 1561 return err;
1527} 1562}
1528 1563
@@ -1536,22 +1571,25 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
1536 if (info->attrs[NL80211_ATTR_MAC]) 1571 if (info->attrs[NL80211_ATTR_MAC])
1537 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 1572 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1538 1573
1574 rtnl_lock();
1575
1539 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1576 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1540 if (err) 1577 if (err)
1541 return err; 1578 goto out_rtnl;
1542 1579
1543 if (!drv->ops->del_station) { 1580 if (!drv->ops->del_station) {
1544 err = -EOPNOTSUPP; 1581 err = -EOPNOTSUPP;
1545 goto out; 1582 goto out;
1546 } 1583 }
1547 1584
1548 rtnl_lock();
1549 err = drv->ops->del_station(&drv->wiphy, dev, mac_addr); 1585 err = drv->ops->del_station(&drv->wiphy, dev, mac_addr);
1550 rtnl_unlock();
1551 1586
1552 out: 1587 out:
1553 cfg80211_put_dev(drv); 1588 cfg80211_put_dev(drv);
1554 dev_put(dev); 1589 dev_put(dev);
1590 out_rtnl:
1591 rtnl_unlock();
1592
1555 return err; 1593 return err;
1556} 1594}
1557 1595
@@ -1632,14 +1670,18 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
1632 return -EINVAL; 1670 return -EINVAL;
1633 } 1671 }
1634 1672
1635 netdev = dev_get_by_index(&init_net, ifidx); 1673 rtnl_lock();
1636 if (!netdev) 1674
1637 return -ENODEV; 1675 netdev = __dev_get_by_index(&init_net, ifidx);
1676 if (!netdev) {
1677 err = -ENODEV;
1678 goto out_rtnl;
1679 }
1638 1680
1639 dev = cfg80211_get_dev_from_ifindex(ifidx); 1681 dev = cfg80211_get_dev_from_ifindex(ifidx);
1640 if (IS_ERR(dev)) { 1682 if (IS_ERR(dev)) {
1641 err = PTR_ERR(dev); 1683 err = PTR_ERR(dev);
1642 goto out_put_netdev; 1684 goto out_rtnl;
1643 } 1685 }
1644 1686
1645 if (!dev->ops->dump_mpath) { 1687 if (!dev->ops->dump_mpath) {
@@ -1647,15 +1689,13 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
1647 goto out_err; 1689 goto out_err;
1648 } 1690 }
1649 1691
1650 rtnl_lock();
1651
1652 while (1) { 1692 while (1) {
1653 err = dev->ops->dump_mpath(&dev->wiphy, netdev, path_idx, 1693 err = dev->ops->dump_mpath(&dev->wiphy, netdev, path_idx,
1654 dst, next_hop, &pinfo); 1694 dst, next_hop, &pinfo);
1655 if (err == -ENOENT) 1695 if (err == -ENOENT)
1656 break; 1696 break;
1657 if (err) 1697 if (err)
1658 goto out_err_rtnl; 1698 goto out_err;
1659 1699
1660 if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).pid, 1700 if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).pid,
1661 cb->nlh->nlmsg_seq, NLM_F_MULTI, 1701 cb->nlh->nlmsg_seq, NLM_F_MULTI,
@@ -1670,12 +1710,10 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
1670 out: 1710 out:
1671 cb->args[1] = path_idx; 1711 cb->args[1] = path_idx;
1672 err = skb->len; 1712 err = skb->len;
1673 out_err_rtnl:
1674 rtnl_unlock();
1675 out_err: 1713 out_err:
1676 cfg80211_put_dev(dev); 1714 cfg80211_put_dev(dev);
1677 out_put_netdev: 1715 out_rtnl:
1678 dev_put(netdev); 1716 rtnl_unlock();
1679 1717
1680 return err; 1718 return err;
1681} 1719}
@@ -1697,19 +1735,18 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
1697 1735
1698 dst = nla_data(info->attrs[NL80211_ATTR_MAC]); 1736 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
1699 1737
1738 rtnl_lock();
1739
1700 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1740 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1701 if (err) 1741 if (err)
1702 return err; 1742 goto out_rtnl;
1703 1743
1704 if (!drv->ops->get_mpath) { 1744 if (!drv->ops->get_mpath) {
1705 err = -EOPNOTSUPP; 1745 err = -EOPNOTSUPP;
1706 goto out; 1746 goto out;
1707 } 1747 }
1708 1748
1709 rtnl_lock();
1710 err = drv->ops->get_mpath(&drv->wiphy, dev, dst, next_hop, &pinfo); 1749 err = drv->ops->get_mpath(&drv->wiphy, dev, dst, next_hop, &pinfo);
1711 rtnl_unlock();
1712
1713 if (err) 1750 if (err)
1714 goto out; 1751 goto out;
1715 1752
@@ -1726,10 +1763,12 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
1726 1763
1727 out_free: 1764 out_free:
1728 nlmsg_free(msg); 1765 nlmsg_free(msg);
1729
1730 out: 1766 out:
1731 cfg80211_put_dev(drv); 1767 cfg80211_put_dev(drv);
1732 dev_put(dev); 1768 dev_put(dev);
1769 out_rtnl:
1770 rtnl_unlock();
1771
1733 return err; 1772 return err;
1734} 1773}
1735 1774
@@ -1750,22 +1789,25 @@ static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
1750 dst = nla_data(info->attrs[NL80211_ATTR_MAC]); 1789 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
1751 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]); 1790 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
1752 1791
1792 rtnl_lock();
1793
1753 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1794 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1754 if (err) 1795 if (err)
1755 return err; 1796 goto out_rtnl;
1756 1797
1757 if (!drv->ops->change_mpath) { 1798 if (!drv->ops->change_mpath) {
1758 err = -EOPNOTSUPP; 1799 err = -EOPNOTSUPP;
1759 goto out; 1800 goto out;
1760 } 1801 }
1761 1802
1762 rtnl_lock();
1763 err = drv->ops->change_mpath(&drv->wiphy, dev, dst, next_hop); 1803 err = drv->ops->change_mpath(&drv->wiphy, dev, dst, next_hop);
1764 rtnl_unlock();
1765 1804
1766 out: 1805 out:
1767 cfg80211_put_dev(drv); 1806 cfg80211_put_dev(drv);
1768 dev_put(dev); 1807 dev_put(dev);
1808 out_rtnl:
1809 rtnl_unlock();
1810
1769 return err; 1811 return err;
1770} 1812}
1771static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info) 1813static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
@@ -1785,22 +1827,25 @@ static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
1785 dst = nla_data(info->attrs[NL80211_ATTR_MAC]); 1827 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
1786 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]); 1828 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
1787 1829
1830 rtnl_lock();
1831
1788 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1832 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1789 if (err) 1833 if (err)
1790 return err; 1834 goto out_rtnl;
1791 1835
1792 if (!drv->ops->add_mpath) { 1836 if (!drv->ops->add_mpath) {
1793 err = -EOPNOTSUPP; 1837 err = -EOPNOTSUPP;
1794 goto out; 1838 goto out;
1795 } 1839 }
1796 1840
1797 rtnl_lock();
1798 err = drv->ops->add_mpath(&drv->wiphy, dev, dst, next_hop); 1841 err = drv->ops->add_mpath(&drv->wiphy, dev, dst, next_hop);
1799 rtnl_unlock();
1800 1842
1801 out: 1843 out:
1802 cfg80211_put_dev(drv); 1844 cfg80211_put_dev(drv);
1803 dev_put(dev); 1845 dev_put(dev);
1846 out_rtnl:
1847 rtnl_unlock();
1848
1804 return err; 1849 return err;
1805} 1850}
1806 1851
@@ -1814,22 +1859,25 @@ static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
1814 if (info->attrs[NL80211_ATTR_MAC]) 1859 if (info->attrs[NL80211_ATTR_MAC])
1815 dst = nla_data(info->attrs[NL80211_ATTR_MAC]); 1860 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
1816 1861
1862 rtnl_lock();
1863
1817 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1864 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1818 if (err) 1865 if (err)
1819 return err; 1866 goto out_rtnl;
1820 1867
1821 if (!drv->ops->del_mpath) { 1868 if (!drv->ops->del_mpath) {
1822 err = -EOPNOTSUPP; 1869 err = -EOPNOTSUPP;
1823 goto out; 1870 goto out;
1824 } 1871 }
1825 1872
1826 rtnl_lock();
1827 err = drv->ops->del_mpath(&drv->wiphy, dev, dst); 1873 err = drv->ops->del_mpath(&drv->wiphy, dev, dst);
1828 rtnl_unlock();
1829 1874
1830 out: 1875 out:
1831 cfg80211_put_dev(drv); 1876 cfg80211_put_dev(drv);
1832 dev_put(dev); 1877 dev_put(dev);
1878 out_rtnl:
1879 rtnl_unlock();
1880
1833 return err; 1881 return err;
1834} 1882}
1835 1883
@@ -1862,22 +1910,25 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
1862 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); 1910 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
1863 } 1911 }
1864 1912
1913 rtnl_lock();
1914
1865 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1915 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1866 if (err) 1916 if (err)
1867 return err; 1917 goto out_rtnl;
1868 1918
1869 if (!drv->ops->change_bss) { 1919 if (!drv->ops->change_bss) {
1870 err = -EOPNOTSUPP; 1920 err = -EOPNOTSUPP;
1871 goto out; 1921 goto out;
1872 } 1922 }
1873 1923
1874 rtnl_lock();
1875 err = drv->ops->change_bss(&drv->wiphy, dev, &params); 1924 err = drv->ops->change_bss(&drv->wiphy, dev, &params);
1876 rtnl_unlock();
1877 1925
1878 out: 1926 out:
1879 cfg80211_put_dev(drv); 1927 cfg80211_put_dev(drv);
1880 dev_put(dev); 1928 dev_put(dev);
1929 out_rtnl:
1930 rtnl_unlock();
1931
1881 return err; 1932 return err;
1882} 1933}
1883 1934
@@ -1972,10 +2023,12 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
1972 struct nlattr *pinfoattr; 2023 struct nlattr *pinfoattr;
1973 struct sk_buff *msg; 2024 struct sk_buff *msg;
1974 2025
2026 rtnl_lock();
2027
1975 /* Look up our device */ 2028 /* Look up our device */
1976 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 2029 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1977 if (err) 2030 if (err)
1978 return err; 2031 goto out_rtnl;
1979 2032
1980 if (!drv->ops->get_mesh_params) { 2033 if (!drv->ops->get_mesh_params) {
1981 err = -EOPNOTSUPP; 2034 err = -EOPNOTSUPP;
@@ -1983,9 +2036,7 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
1983 } 2036 }
1984 2037
1985 /* Get the mesh params */ 2038 /* Get the mesh params */
1986 rtnl_lock();
1987 err = drv->ops->get_mesh_params(&drv->wiphy, dev, &cur_params); 2039 err = drv->ops->get_mesh_params(&drv->wiphy, dev, &cur_params);
1988 rtnl_unlock();
1989 if (err) 2040 if (err)
1990 goto out; 2041 goto out;
1991 2042
@@ -2034,13 +2085,16 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
2034 err = genlmsg_unicast(msg, info->snd_pid); 2085 err = genlmsg_unicast(msg, info->snd_pid);
2035 goto out; 2086 goto out;
2036 2087
2037nla_put_failure: 2088 nla_put_failure:
2038 genlmsg_cancel(msg, hdr); 2089 genlmsg_cancel(msg, hdr);
2039 err = -EMSGSIZE; 2090 err = -EMSGSIZE;
2040out: 2091 out:
2041 /* Cleanup */ 2092 /* Cleanup */
2042 cfg80211_put_dev(drv); 2093 cfg80211_put_dev(drv);
2043 dev_put(dev); 2094 dev_put(dev);
2095 out_rtnl:
2096 rtnl_unlock();
2097
2044 return err; 2098 return err;
2045} 2099}
2046 2100
@@ -2087,9 +2141,11 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
2087 parent_attr, nl80211_meshconf_params_policy)) 2141 parent_attr, nl80211_meshconf_params_policy))
2088 return -EINVAL; 2142 return -EINVAL;
2089 2143
2144 rtnl_lock();
2145
2090 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 2146 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
2091 if (err) 2147 if (err)
2092 return err; 2148 goto out_rtnl;
2093 2149
2094 if (!drv->ops->set_mesh_params) { 2150 if (!drv->ops->set_mesh_params) {
2095 err = -EOPNOTSUPP; 2151 err = -EOPNOTSUPP;
@@ -2136,14 +2192,15 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
2136 nla_get_u16); 2192 nla_get_u16);
2137 2193
2138 /* Apply changes */ 2194 /* Apply changes */
2139 rtnl_lock();
2140 err = drv->ops->set_mesh_params(&drv->wiphy, dev, &cfg, mask); 2195 err = drv->ops->set_mesh_params(&drv->wiphy, dev, &cfg, mask);
2141 rtnl_unlock();
2142 2196
2143 out: 2197 out:
2144 /* cleanup */ 2198 /* cleanup */
2145 cfg80211_put_dev(drv); 2199 cfg80211_put_dev(drv);
2146 dev_put(dev); 2200 dev_put(dev);
2201 out_rtnl:
2202 rtnl_unlock();
2203
2147 return err; 2204 return err;
2148} 2205}
2149 2206
@@ -2310,19 +2367,22 @@ static int nl80211_set_mgmt_extra_ie(struct sk_buff *skb,
2310 params.ies_len = nla_len(info->attrs[NL80211_ATTR_IE]); 2367 params.ies_len = nla_len(info->attrs[NL80211_ATTR_IE]);
2311 } 2368 }
2312 2369
2370 rtnl_lock();
2371
2313 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 2372 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
2314 if (err) 2373 if (err)
2315 return err; 2374 goto out_rtnl;
2316 2375
2317 if (drv->ops->set_mgmt_extra_ie) { 2376 if (drv->ops->set_mgmt_extra_ie)
2318 rtnl_lock();
2319 err = drv->ops->set_mgmt_extra_ie(&drv->wiphy, dev, &params); 2377 err = drv->ops->set_mgmt_extra_ie(&drv->wiphy, dev, &params);
2320 rtnl_unlock(); 2378 else
2321 } else
2322 err = -EOPNOTSUPP; 2379 err = -EOPNOTSUPP;
2323 2380
2324 cfg80211_put_dev(drv); 2381 cfg80211_put_dev(drv);
2325 dev_put(dev); 2382 dev_put(dev);
2383 out_rtnl:
2384 rtnl_unlock();
2385
2326 return err; 2386 return err;
2327} 2387}
2328 2388
@@ -2339,9 +2399,11 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
2339 enum ieee80211_band band; 2399 enum ieee80211_band band;
2340 size_t ie_len; 2400 size_t ie_len;
2341 2401
2402 rtnl_lock();
2403
2342 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 2404 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
2343 if (err) 2405 if (err)
2344 return err; 2406 goto out_rtnl;
2345 2407
2346 wiphy = &drv->wiphy; 2408 wiphy = &drv->wiphy;
2347 2409
@@ -2350,11 +2412,9 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
2350 goto out; 2412 goto out;
2351 } 2413 }
2352 2414
2353 rtnl_lock();
2354
2355 if (drv->scan_req) { 2415 if (drv->scan_req) {
2356 err = -EBUSY; 2416 err = -EBUSY;
2357 goto out_unlock; 2417 goto out;
2358 } 2418 }
2359 2419
2360 if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { 2420 if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
@@ -2362,7 +2422,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
2362 n_channels++; 2422 n_channels++;
2363 if (!n_channels) { 2423 if (!n_channels) {
2364 err = -EINVAL; 2424 err = -EINVAL;
2365 goto out_unlock; 2425 goto out;
2366 } 2426 }
2367 } else { 2427 } else {
2368 for (band = 0; band < IEEE80211_NUM_BANDS; band++) 2428 for (band = 0; band < IEEE80211_NUM_BANDS; band++)
@@ -2376,7 +2436,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
2376 2436
2377 if (n_ssids > wiphy->max_scan_ssids) { 2437 if (n_ssids > wiphy->max_scan_ssids) {
2378 err = -EINVAL; 2438 err = -EINVAL;
2379 goto out_unlock; 2439 goto out;
2380 } 2440 }
2381 2441
2382 if (info->attrs[NL80211_ATTR_IE]) 2442 if (info->attrs[NL80211_ATTR_IE])
@@ -2390,7 +2450,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
2390 + ie_len, GFP_KERNEL); 2450 + ie_len, GFP_KERNEL);
2391 if (!request) { 2451 if (!request) {
2392 err = -ENOMEM; 2452 err = -ENOMEM;
2393 goto out_unlock; 2453 goto out;
2394 } 2454 }
2395 2455
2396 request->channels = (void *)((char *)request + sizeof(*request)); 2456 request->channels = (void *)((char *)request + sizeof(*request));
@@ -2461,11 +2521,12 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
2461 drv->scan_req = NULL; 2521 drv->scan_req = NULL;
2462 kfree(request); 2522 kfree(request);
2463 } 2523 }
2464 out_unlock:
2465 rtnl_unlock();
2466 out: 2524 out:
2467 cfg80211_put_dev(drv); 2525 cfg80211_put_dev(drv);
2468 dev_put(dev); 2526 dev_put(dev);
2527 out_rtnl:
2528 rtnl_unlock();
2529
2469 return err; 2530 return err;
2470} 2531}
2471 2532