aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-12-14 06:20:27 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-12-15 14:45:45 -0500
commitbdd90d5e36a55271beb957b3d7ca3e29b2a90207 (patch)
tree79243e73e6c64217bc676507504b72a2d59fc096 /net/wireless
parentd83023daa219486e9aa139d423308a045bf0438b (diff)
cfg80211: validate nl80211 station handling better
The nl80211 station handling code is a bit messy and doesn't do a lot of validation. It seems like this could be an issue for drivers that don't use mac80211 to validate everything. As cfg80211 doesn't keep station state, move the validation of allowing supported_rates to change for TDLS only in station mode to mac80211. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/nl80211.c199
1 files changed, 112 insertions, 87 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index d86428145c3..b07c4fc4ae2 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2579,6 +2579,9 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
2579 params.ht_capa = 2579 params.ht_capa =
2580 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); 2580 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
2581 2581
2582 if (!rdev->ops->change_station)
2583 return -EOPNOTSUPP;
2584
2582 if (parse_station_flags(info, &params)) 2585 if (parse_station_flags(info, &params))
2583 return -EINVAL; 2586 return -EINVAL;
2584 2587
@@ -2590,73 +2593,84 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
2590 params.plink_state = 2593 params.plink_state =
2591 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]); 2594 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]);
2592 2595
2593 params.vlan = get_vlan(info, rdev);
2594 if (IS_ERR(params.vlan))
2595 return PTR_ERR(params.vlan);
2596
2597 /* validate settings */
2598 err = 0;
2599
2600 switch (dev->ieee80211_ptr->iftype) { 2596 switch (dev->ieee80211_ptr->iftype) {
2601 case NL80211_IFTYPE_AP: 2597 case NL80211_IFTYPE_AP:
2602 case NL80211_IFTYPE_AP_VLAN: 2598 case NL80211_IFTYPE_AP_VLAN:
2603 case NL80211_IFTYPE_P2P_GO: 2599 case NL80211_IFTYPE_P2P_GO:
2604 /* disallow mesh-specific things */ 2600 /* disallow mesh-specific things */
2605 if (params.plink_action) 2601 if (params.plink_action)
2606 err = -EINVAL; 2602 return -EINVAL;
2603
2604 /* TDLS can't be set, ... */
2605 if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
2606 return -EINVAL;
2607 /*
2608 * ... but don't bother the driver with it. This works around
2609 * a hostapd/wpa_supplicant issue -- it always includes the
2610 * TLDS_PEER flag in the mask even for AP mode.
2611 */
2612 params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
2613
2614 /* accept only the listed bits */
2615 if (params.sta_flags_mask &
2616 ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
2617 BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
2618 BIT(NL80211_STA_FLAG_WME) |
2619 BIT(NL80211_STA_FLAG_MFP)))
2620 return -EINVAL;
2621
2622 /* must be last in here for error handling */
2623 params.vlan = get_vlan(info, rdev);
2624 if (IS_ERR(params.vlan))
2625 return PTR_ERR(params.vlan);
2607 break; 2626 break;
2608 case NL80211_IFTYPE_P2P_CLIENT: 2627 case NL80211_IFTYPE_P2P_CLIENT:
2609 case NL80211_IFTYPE_STATION: 2628 case NL80211_IFTYPE_STATION:
2610 /* disallow things sta doesn't support */ 2629 /* disallow things sta doesn't support */
2611 if (params.plink_action) 2630 if (params.plink_action)
2612 err = -EINVAL; 2631 return -EINVAL;
2613 if (params.vlan)
2614 err = -EINVAL;
2615 if (params.supported_rates &&
2616 !(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
2617 err = -EINVAL;
2618 if (params.ht_capa) 2632 if (params.ht_capa)
2619 err = -EINVAL; 2633 return -EINVAL;
2620 if (params.listen_interval >= 0) 2634 if (params.listen_interval >= 0)
2621 err = -EINVAL; 2635 return -EINVAL;
2622 if (params.sta_flags_mask & 2636 /*
2623 ~(BIT(NL80211_STA_FLAG_AUTHORIZED) | 2637 * Don't allow userspace to change the TDLS_PEER flag,
2624 BIT(NL80211_STA_FLAG_TDLS_PEER))) 2638 * but silently ignore attempts to change it since we
2625 err = -EINVAL; 2639 * don't have state here to verify that it doesn't try
2626 /* can't change the TDLS bit */ 2640 * to change the flag.
2627 if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) && 2641 */
2628 (params.sta_flags_mask & BIT(NL80211_STA_FLAG_TDLS_PEER))) 2642 params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
2629 err = -EINVAL; 2643
2644 /* reject any changes other than AUTHORIZED */
2645 if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED))
2646 return -EINVAL;
2630 break; 2647 break;
2631 case NL80211_IFTYPE_MESH_POINT: 2648 case NL80211_IFTYPE_MESH_POINT:
2632 /* disallow things mesh doesn't support */ 2649 /* disallow things mesh doesn't support */
2633 if (params.vlan) 2650 if (params.vlan)
2634 err = -EINVAL; 2651 return -EINVAL;
2635 if (params.ht_capa) 2652 if (params.ht_capa)
2636 err = -EINVAL; 2653 return -EINVAL;
2637 if (params.listen_interval >= 0) 2654 if (params.listen_interval >= 0)
2638 err = -EINVAL; 2655 return -EINVAL;
2656 /*
2657 * No special handling for TDLS here -- the userspace
2658 * mesh code doesn't have this bug.
2659 */
2639 if (params.sta_flags_mask & 2660 if (params.sta_flags_mask &
2640 ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) | 2661 ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) |
2641 BIT(NL80211_STA_FLAG_MFP) | 2662 BIT(NL80211_STA_FLAG_MFP) |
2642 BIT(NL80211_STA_FLAG_AUTHORIZED))) 2663 BIT(NL80211_STA_FLAG_AUTHORIZED)))
2643 err = -EINVAL; 2664 return -EINVAL;
2644 break; 2665 break;
2645 default: 2666 default:
2646 err = -EINVAL; 2667 return -EOPNOTSUPP;
2647 } 2668 }
2648 2669
2649 if (err) 2670 /* be aware of params.vlan when changing code here */
2650 goto out;
2651
2652 if (!rdev->ops->change_station) {
2653 err = -EOPNOTSUPP;
2654 goto out;
2655 }
2656 2671
2657 err = rdev->ops->change_station(&rdev->wiphy, dev, mac_addr, &params); 2672 err = rdev->ops->change_station(&rdev->wiphy, dev, mac_addr, &params);
2658 2673
2659 out:
2660 if (params.vlan) 2674 if (params.vlan)
2661 dev_put(params.vlan); 2675 dev_put(params.vlan);
2662 2676
@@ -2711,70 +2725,81 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
2711 params.plink_action = 2725 params.plink_action =
2712 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); 2726 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
2713 2727
2728 if (!rdev->ops->add_station)
2729 return -EOPNOTSUPP;
2730
2714 if (parse_station_flags(info, &params)) 2731 if (parse_station_flags(info, &params))
2715 return -EINVAL; 2732 return -EINVAL;
2716 2733
2717 /* parse WME attributes if sta is WME capable */ 2734 switch (dev->ieee80211_ptr->iftype) {
2718 if ((rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) && 2735 case NL80211_IFTYPE_AP:
2719 (params.sta_flags_set & BIT(NL80211_STA_FLAG_WME)) && 2736 case NL80211_IFTYPE_AP_VLAN:
2720 info->attrs[NL80211_ATTR_STA_WME]) { 2737 case NL80211_IFTYPE_P2P_GO:
2721 struct nlattr *tb[NL80211_STA_WME_MAX + 1]; 2738 /* parse WME attributes if sta is WME capable */
2722 struct nlattr *nla; 2739 if ((rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) &&
2740 (params.sta_flags_set & BIT(NL80211_STA_FLAG_WME)) &&
2741 info->attrs[NL80211_ATTR_STA_WME]) {
2742 struct nlattr *tb[NL80211_STA_WME_MAX + 1];
2743 struct nlattr *nla;
2744
2745 nla = info->attrs[NL80211_ATTR_STA_WME];
2746 err = nla_parse_nested(tb, NL80211_STA_WME_MAX, nla,
2747 nl80211_sta_wme_policy);
2748 if (err)
2749 return err;
2723 2750
2724 nla = info->attrs[NL80211_ATTR_STA_WME]; 2751 if (tb[NL80211_STA_WME_UAPSD_QUEUES])
2725 err = nla_parse_nested(tb, NL80211_STA_WME_MAX, nla, 2752 params.uapsd_queues =
2726 nl80211_sta_wme_policy); 2753 nla_get_u8(tb[NL80211_STA_WME_UAPSD_QUEUES]);
2727 if (err) 2754 if (params.uapsd_queues &
2728 return err; 2755 ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
2756 return -EINVAL;
2729 2757
2730 if (tb[NL80211_STA_WME_UAPSD_QUEUES]) 2758 if (tb[NL80211_STA_WME_MAX_SP])
2731 params.uapsd_queues = 2759 params.max_sp =
2732 nla_get_u8(tb[NL80211_STA_WME_UAPSD_QUEUES]); 2760 nla_get_u8(tb[NL80211_STA_WME_MAX_SP]);
2733 if (params.uapsd_queues & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
2734 return -EINVAL;
2735 2761
2736 if (tb[NL80211_STA_WME_MAX_SP]) 2762 if (params.max_sp &
2737 params.max_sp = 2763 ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK)
2738 nla_get_u8(tb[NL80211_STA_WME_MAX_SP]); 2764 return -EINVAL;
2739 2765
2740 if (params.max_sp & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK) 2766 params.sta_modify_mask |= STATION_PARAM_APPLY_UAPSD;
2767 }
2768 /* TDLS peers cannot be added */
2769 if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
2741 return -EINVAL; 2770 return -EINVAL;
2771 /* but don't bother the driver with it */
2772 params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
2742 2773
2743 params.sta_modify_mask |= STATION_PARAM_APPLY_UAPSD; 2774 /* must be last in here for error handling */
2775 params.vlan = get_vlan(info, rdev);
2776 if (IS_ERR(params.vlan))
2777 return PTR_ERR(params.vlan);
2778 break;
2779 case NL80211_IFTYPE_MESH_POINT:
2780 /* TDLS peers cannot be added */
2781 if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
2782 return -EINVAL;
2783 break;
2784 case NL80211_IFTYPE_STATION:
2785 /* Only TDLS peers can be added */
2786 if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
2787 return -EINVAL;
2788 /* Can only add if TDLS ... */
2789 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS))
2790 return -EOPNOTSUPP;
2791 /* ... with external setup is supported */
2792 if (!(rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP))
2793 return -EOPNOTSUPP;
2794 break;
2795 default:
2796 return -EOPNOTSUPP;
2744 } 2797 }
2745 2798
2746 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && 2799 /* be aware of params.vlan when changing code here */
2747 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
2748 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&
2749 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO &&
2750 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION)
2751 return -EINVAL;
2752
2753 /*
2754 * Only managed stations can add TDLS peers, and only when the
2755 * wiphy supports external TDLS setup.
2756 */
2757 if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION &&
2758 !((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) &&
2759 (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) &&
2760 (rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP)))
2761 return -EINVAL;
2762
2763 params.vlan = get_vlan(info, rdev);
2764 if (IS_ERR(params.vlan))
2765 return PTR_ERR(params.vlan);
2766
2767 /* validate settings */
2768 err = 0;
2769
2770 if (!rdev->ops->add_station) {
2771 err = -EOPNOTSUPP;
2772 goto out;
2773 }
2774 2800
2775 err = rdev->ops->add_station(&rdev->wiphy, dev, mac_addr, &params); 2801 err = rdev->ops->add_station(&rdev->wiphy, dev, mac_addr, &params);
2776 2802
2777 out:
2778 if (params.vlan) 2803 if (params.vlan)
2779 dev_put(params.vlan); 2804 dev_put(params.vlan);
2780 return err; 2805 return err;