Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

cfg80211/mac80211: Allow user space to register for station Rx authentication

To support Pre Association Security Negotiation (PASN) while already
associated to one AP, allow user space to register to Rx
authentication frames, so that the user space logic would be able to
receive/handle authentication frames from a different AP as part of
PASN.

Note that it is expected that user space would intelligently register
for Rx authentication frames, i.e., only when PASN is used and
configure a match filter only for PASN authentication algorithm, as
otherwise the MLME functionality of mac80211 would be broken.

Additionally, since some versions of the user space daemons wrongly
register to all types of authentication frames (which might result in
unexpected behavior) allow such registration if the request is for a
specific authentication algorithm number.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/20200131114529.894206-1-luca@coelho.fi
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Ilan Peer and committed by
Johannes Berg
ff74c51e f93d6b21

+46 -7
+13
net/mac80211/main.c
··· 416 416 }, 417 417 [NL80211_IFTYPE_STATION] = { 418 418 .tx = 0xffff, 419 + /* 420 + * To support Pre Association Security Negotiation (PASN) while 421 + * already associated to one AP, allow user space to register to 422 + * Rx authentication frames, so that the user space logic would 423 + * be able to receive/handle authentication frames from a 424 + * different AP as part of PASN. 425 + * It is expected that user space would intelligently register 426 + * for Rx authentication frames, i.e., only when PASN is used 427 + * and configure a match filter only for PASN authentication 428 + * algorithm, as otherwise the MLME functionality of mac80211 429 + * would be broken. 430 + */ 419 431 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | 432 + BIT(IEEE80211_STYPE_AUTH >> 4) | 420 433 BIT(IEEE80211_STYPE_PROBE_REQ >> 4), 421 434 }, 422 435 [NL80211_IFTYPE_AP] = {
+1 -1
net/wireless/core.h
··· 385 385 struct net_device *dev); 386 386 int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid, 387 387 u16 frame_type, const u8 *match_data, 388 - int match_len); 388 + int match_len, struct netlink_ext_ack *extack); 389 389 void cfg80211_mlme_unreg_wk(struct work_struct *wk); 390 390 void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid); 391 391 void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev);
+29 -4
net/wireless/mlme.c
··· 4 4 * 5 5 * Copyright (c) 2009, Jouni Malinen <j@w1.fi> 6 6 * Copyright (c) 2015 Intel Deutschland GmbH 7 + * Copyright (C) 2019 Intel Corporation 7 8 */ 8 9 9 10 #include <linux/kernel.h> ··· 471 470 472 471 int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid, 473 472 u16 frame_type, const u8 *match_data, 474 - int match_len) 473 + int match_len, struct netlink_ext_ack *extack) 475 474 { 476 475 struct wiphy *wiphy = wdev->wiphy; 477 476 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); ··· 482 481 if (!wdev->wiphy->mgmt_stypes) 483 482 return -EOPNOTSUPP; 484 483 485 - if ((frame_type & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT) 484 + if ((frame_type & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT) { 485 + NL_SET_ERR_MSG(extack, "frame type not management"); 486 486 return -EINVAL; 487 + } 487 488 488 - if (frame_type & ~(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) 489 + if (frame_type & ~(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) { 490 + NL_SET_ERR_MSG(extack, "Invalid frame type"); 489 491 return -EINVAL; 492 + } 490 493 491 494 mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4; 492 - if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].rx & BIT(mgmt_type))) 495 + if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].rx & BIT(mgmt_type))) { 496 + NL_SET_ERR_MSG(extack, 497 + "Registration to specific type not supported"); 493 498 return -EINVAL; 499 + } 500 + 501 + /* 502 + * To support Pre Association Security Negotiation (PASN), registration 503 + * for authentication frames should be supported. However, as some 504 + * versions of the user space daemons wrongly register to all types of 505 + * authentication frames (which might result in unexpected behavior) 506 + * allow such registration if the request is for a specific 507 + * authentication algorithm number. 508 + */ 509 + if (wdev->iftype == NL80211_IFTYPE_STATION && 510 + (frame_type & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_AUTH && 511 + !(match_data && match_len >= 2)) { 512 + NL_SET_ERR_MSG(extack, 513 + "Authentication algorithm number required"); 514 + return -EINVAL; 515 + } 494 516 495 517 nreg = kzalloc(sizeof(*reg) + match_len, GFP_KERNEL); 496 518 if (!nreg) ··· 528 504 continue; 529 505 530 506 if (memcmp(reg->match, match_data, mlen) == 0) { 507 + NL_SET_ERR_MSG(extack, "Match already configured"); 531 508 err = -EALREADY; 532 509 break; 533 510 }
+3 -2
net/wireless/nl80211.c
··· 10624 10624 return -EOPNOTSUPP; 10625 10625 10626 10626 return cfg80211_mlme_register_mgmt(wdev, info->snd_portid, frame_type, 10627 - nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]), 10628 - nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH])); 10627 + nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]), 10628 + nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]), 10629 + info->extack); 10629 10630 } 10630 10631 10631 10632 static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)