2022-04-18 12:58:51

by Veerendranath Jakkam

[permalink] [raw]
Subject: [PATCH] cfg80211: Add support for sending more than two AKMs in crypto settings

Add support to indicate maximum number of AKMs allowed in
NL80211_CMD_CONNECT, NL80211_CMD_ASSOCIATE and NL80211_CMD_START_AP.
If the driver doesn't indicate the capability, maximum limit is set to
the legacy value i.e. NL80211_MAX_NR_AKM_SUITE.

Signed-off-by: Veerendranath Jakkam <[email protected]>
---
drivers/net/wireless/ath/wil6210/cfg80211.c | 3 +--
drivers/net/wireless/quantenna/qtnfmac/commands.c | 6 ++++--
include/net/cfg80211.h | 6 +++++-
include/uapi/linux/nl80211.h | 15 +++++++++++++++
net/wireless/core.c | 11 +++++++++++
net/wireless/nl80211.c | 15 +++++++++++++--
net/wireless/sme.c | 20 +++++++++++++++++++-
net/wireless/wext-compat.c | 8 ++++++++
8 files changed, 76 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index 764d1d1..ac40fe2 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -1073,8 +1073,7 @@ static void wil_print_crypto(struct wil6210_priv *wil,
c->ciphers_pairwise[i]);
wil_dbg_misc(wil, "}\n");
wil_dbg_misc(wil, "AKM suites [%d] {\n", c->n_akm_suites);
- n = min_t(int, c->n_akm_suites, ARRAY_SIZE(c->akm_suites));
- for (i = 0; i < n; i++)
+ for (i = 0; i < c->n_akm_suites; i++)
wil_dbg_misc(wil, " [%d] = 0x%08x\n", i,
c->akm_suites[i]);
wil_dbg_misc(wil, "}\n");
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index c68563c..866355ae 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -281,7 +281,8 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif,
aen->ciphers_pairwise[i] =
cpu_to_le32(s->crypto.ciphers_pairwise[i]);
aen->n_akm_suites = cpu_to_le32(s->crypto.n_akm_suites);
- for (i = 0; i < QLINK_MAX_NR_AKM_SUITES; i++)
+ for (i = 0; i < min(QLINK_MAX_NR_AKM_SUITES, s->crypto.n_akm_suites);
+ i++)
aen->akm_suites[i] = cpu_to_le32(s->crypto.akm_suites[i]);
aen->control_port = s->crypto.control_port;
aen->control_port_no_encrypt = s->crypto.control_port_no_encrypt;
@@ -2134,7 +2135,8 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif,

aen->n_akm_suites = cpu_to_le32(sme->crypto.n_akm_suites);

- for (i = 0; i < QLINK_MAX_NR_AKM_SUITES; i++)
+ for (i = 0; i < min(QLINK_MAX_NR_AKM_SUITES, s->crypto.n_akm_suites);
+ i++)
aen->akm_suites[i] = cpu_to_le32(sme->crypto.akm_suites[i]);

aen->control_port = sme->crypto.control_port;
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 6871338..48c7ab1 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1112,7 +1112,7 @@ struct cfg80211_crypto_settings {
int n_ciphers_pairwise;
u32 ciphers_pairwise[NL80211_MAX_NR_CIPHER_SUITES];
int n_akm_suites;
- u32 akm_suites[NL80211_MAX_NR_AKM_SUITES];
+ u32 *akm_suites;
bool control_port;
__be16 control_port_ethertype;
bool control_port_no_encrypt;
@@ -5129,6 +5129,9 @@ struct wiphy_iftype_akm_suites {
* @ema_max_profile_periodicity: maximum profile periodicity supported by
* the driver. Setting this field to a non-zero value indicates that the
* driver supports enhanced multi-BSSID advertisements (EMA AP).
+ * @max_num_akm_suites: maximum supported number of AKM suites for
+ * configuration through %NL80211_CMD_CONNECT, %NL80211_CMD_ASSOCIATE and
+ * %NL80211_CMD_START_AP.
*/
struct wiphy {
struct mutex mtx;
@@ -5275,6 +5278,7 @@ struct wiphy {

u8 mbssid_max_interfaces;
u8 ema_max_profile_periodicity;
+ u16 max_num_akm_suites;

char priv[] __aligned(NETDEV_ALIGN);
};
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 0568a79..00fa5ea 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2663,6 +2663,13 @@ enum nl80211_commands {
* association request when used with NL80211_CMD_NEW_STATION). Can be set
* only if %NL80211_STA_FLAG_WME is set.
*
+ * @NL80211_ATTR_MAX_NUM_AKM_SUITES: U16 attribute. Indicates maximum number of
+ * AKM suites allowed for %NL80211_CMD_CONNECT, %NL80211_CMD_ASSOCIATE and
+ * %NL80211_CMD_START_AP. If this attribute is not present userspace shall
+ * consider maximum number of AKM suites supported as
+ * %NL80211_MAX_NR_AKM_SUITES which is the legacy maximum number prior to
+ * the introduction of this attribute.
+ *
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -3175,6 +3182,8 @@ enum nl80211_attrs {

NL80211_ATTR_EHT_CAPABILITY,

+ NL80211_ATTR_MAX_NUM_AKM_SUITES,
+
/* add attributes here, update the policy in nl80211.c */

__NL80211_ATTR_AFTER_LAST,
@@ -3229,6 +3238,12 @@ enum nl80211_attrs {
#define NL80211_HE_MIN_CAPABILITY_LEN 16
#define NL80211_HE_MAX_CAPABILITY_LEN 54
#define NL80211_MAX_NR_CIPHER_SUITES 5
+
+/*
+ * NL80211_MAX_NR_AKM_SUITES is obsolete and not used for indicating maximum
+ * number of supported AKM suites. Instead, maximum number of supported AKM
+ * suites is indicated using %NL80211_ATTR_MAX_NUM_AKM_SUITES attribute.
+ */
#define NL80211_MAX_NR_AKM_SUITES 2
#define NL80211_EHT_MIN_CAPABILITY_LEN 13
#define NL80211_EHT_MAX_CAPABILITY_LEN 51
diff --git a/net/wireless/core.c b/net/wireless/core.c
index f08d4b3..282cabc 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -913,6 +913,15 @@ int wiphy_register(struct wiphy *wiphy)
return -EINVAL;
#endif

+ /*
+ * Maximum number of AKM suites allowed for NL80211_CMD_CONECT,
+ * NL80211_CMD_ASSOCIATE and NL80211_CMD_START_AP, must be at least
+ * NL80211_MAX_NR_AKM_SUITES to avoid issues with legacy userspace.
+ */
+ if (WARN_ON(wiphy->max_num_akm_suites &&
+ wiphy->max_num_akm_suites < NL80211_MAX_NR_AKM_SUITES))
+ return -EINVAL;
+
/* check and set up bitrates */
ieee80211_set_bitrate_flags(wiphy);

@@ -1154,6 +1163,8 @@ static void _cfg80211_unregister_wdev(struct wireless_dev *wdev,
#ifdef CONFIG_CFG80211_WEXT
kfree_sensitive(wdev->wext.keys);
wdev->wext.keys = NULL;
+ kfree(wdev->wext.connect.crypto.akm_suites);
+ wdev->wext.connect.crypto.akm_suites = NULL;
#endif
/* only initialized if we have a netdev */
if (wdev->netdev)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 711061c..4b7cbd5 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -790,6 +790,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
NLA_POLICY_RANGE(NLA_BINARY,
NL80211_EHT_MIN_CAPABILITY_LEN,
NL80211_EHT_MAX_CAPABILITY_LEN),
+ [NL80211_ATTR_MAX_NUM_AKM_SUITES] = { .type = NLA_U16 },
};

/* policy for the key attributes */
@@ -2889,6 +2890,12 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
if (nl80211_put_mbssid_support(&rdev->wiphy, msg))
goto nla_put_failure;

+ if (nla_put_u16(msg, NL80211_ATTR_MAX_NUM_AKM_SUITES,
+ rdev->wiphy.max_num_akm_suites ?
+ rdev->wiphy.max_num_akm_suites :
+ NL80211_MAX_NR_AKM_SUITES))
+ goto nla_put_failure;
+
/* done */
state->split_start = 0;
break;
@@ -10253,6 +10260,7 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
if (info->attrs[NL80211_ATTR_AKM_SUITES]) {
void *data;
int len;
+ int max_num_akm_suites = NL80211_MAX_NR_AKM_SUITES;

data = nla_data(info->attrs[NL80211_ATTR_AKM_SUITES]);
len = nla_len(info->attrs[NL80211_ATTR_AKM_SUITES]);
@@ -10261,10 +10269,13 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
if (len % sizeof(u32))
return -EINVAL;

- if (settings->n_akm_suites > NL80211_MAX_NR_AKM_SUITES)
+ if (rdev->wiphy.max_num_akm_suites)
+ max_num_akm_suites = rdev->wiphy.max_num_akm_suites;
+
+ if (settings->n_akm_suites > max_num_akm_suites)
return -EINVAL;

- memcpy(settings->akm_suites, data, len);
+ settings->akm_suites = data;
}

if (info->attrs[NL80211_ATTR_PMK]) {
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index ff4d48fc..1ff9513 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -57,6 +57,7 @@ static void cfg80211_sme_free(struct wireless_dev *wdev)
return;

kfree(wdev->conn->ie);
+ kfree(wdev->conn->params.crypto.akm_suites);
kfree(wdev->conn);
wdev->conn = NULL;
}
@@ -537,7 +538,8 @@ static int cfg80211_sme_connect(struct wireless_dev *wdev,
return -ENOMEM;

/*
- * Copy all parameters, and treat explicitly IEs, BSSID, SSID.
+ * Copy all parameters, and treat explicitly IEs, BSSID, SSID,
+ * AKM SUITES.
*/
memcpy(&wdev->conn->params, connect, sizeof(*connect));
if (connect->bssid) {
@@ -563,6 +565,22 @@ static int cfg80211_sme_connect(struct wireless_dev *wdev,
wdev->conn->auto_auth = false;
}

+ if (connect->crypto.n_akm_suites) {
+ wdev->conn->params.crypto.akm_suites =
+ kcalloc(connect->crypto.n_akm_suites, sizeof(u32),
+ GFP_KERNEL);
+ if (!wdev->conn->params.crypto.akm_suites) {
+ cfg80211_sme_free(wdev);
+ return -ENOMEM;
+ }
+
+ wdev->conn->params.crypto.n_akm_suites =
+ connect->crypto.n_akm_suites;
+ memcpy(wdev->conn->params.crypto.akm_suites,
+ connect->crypto.akm_suites,
+ sizeof(u32) * connect->crypto.n_akm_suites);
+ }
+
wdev->conn->params.ssid = wdev->ssid;
wdev->conn->params.ssid_len = wdev->ssid_len;

diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index a32065d..0d262e9 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -1102,6 +1102,14 @@ static int cfg80211_set_key_mgt(struct wireless_dev *wdev, u32 key_mgt)
IW_AUTH_KEY_MGMT_PSK))
return -EINVAL;

+ if (!wdev->wext.connect.crypto.akm_suites) {
+ wdev->wext.connect.crypto.akm_suites =
+ kcalloc(NL80211_MAX_NR_AKM_SUITES, sizeof(u32),
+ GFP_KERNEL);
+ if (!wdev->wext.connect.crypto.akm_suites)
+ return -ENOMEM;
+ }
+
if (key_mgt & IW_AUTH_KEY_MGMT_802_1X) {
wdev->wext.connect.crypto.akm_suites[nr_akm_suites] =
WLAN_AKM_SUITE_8021X;
--
2.7.4


2022-04-19 08:38:21

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH] cfg80211: Add support for sending more than two AKMs in crypto settings

Hi Veerendranath,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on wireless-next/main]
[also build test ERROR on wireless/main v5.18-rc3 next-20220414]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url: https://github.com/intel-lab-lkp/linux/commits/Veerendranath-Jakkam/cfg80211-Add-support-for-sending-more-than-two-AKMs-in-crypto-settings/20220418-203101
base: https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git main
config: mips-allyesconfig (https://download.01.org/0day-ci/archive/20220419/[email protected]/config)
compiler: mips-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/a90fd9fa52075529ae10224239a5b2c1ce156e34
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Veerendranath-Jakkam/cfg80211-Add-support-for-sending-more-than-two-AKMs-in-crypto-settings/20220418-203101
git checkout a90fd9fa52075529ae10224239a5b2c1ce156e34
# save the config file to linux build tree
mkdir build_dir
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=mips SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <[email protected]>

All errors (new ones prefixed by >>):

In file included from include/linux/kernel.h:26,
from include/linux/skbuff.h:13,
from drivers/net/wireless/quantenna/qtnfmac/commands.c:5:
drivers/net/wireless/quantenna/qtnfmac/commands.c: In function 'qtnf_cmd_send_connect':
>> drivers/net/wireless/quantenna/qtnfmac/commands.c:2138:54: error: 's' undeclared (first use in this function)
2138 | for (i = 0; i < min(QLINK_MAX_NR_AKM_SUITES, s->crypto.n_akm_suites);
| ^
include/linux/minmax.h:20:46: note: in definition of macro '__typecheck'
20 | (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1)))
| ^
include/linux/minmax.h:36:31: note: in expansion of macro '__safe_cmp'
36 | __builtin_choose_expr(__safe_cmp(x, y), \
| ^~~~~~~~~~
include/linux/minmax.h:45:25: note: in expansion of macro '__careful_cmp'
45 | #define min(x, y) __careful_cmp(x, y, <)
| ^~~~~~~~~~~~~
drivers/net/wireless/quantenna/qtnfmac/commands.c:2138:25: note: in expansion of macro 'min'
2138 | for (i = 0; i < min(QLINK_MAX_NR_AKM_SUITES, s->crypto.n_akm_suites);
| ^~~
drivers/net/wireless/quantenna/qtnfmac/commands.c:2138:54: note: each undeclared identifier is reported only once for each function it appears in
2138 | for (i = 0; i < min(QLINK_MAX_NR_AKM_SUITES, s->crypto.n_akm_suites);
| ^
include/linux/minmax.h:20:46: note: in definition of macro '__typecheck'
20 | (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1)))
| ^
include/linux/minmax.h:36:31: note: in expansion of macro '__safe_cmp'
36 | __builtin_choose_expr(__safe_cmp(x, y), \
| ^~~~~~~~~~
include/linux/minmax.h:45:25: note: in expansion of macro '__careful_cmp'
45 | #define min(x, y) __careful_cmp(x, y, <)
| ^~~~~~~~~~~~~
drivers/net/wireless/quantenna/qtnfmac/commands.c:2138:25: note: in expansion of macro 'min'
2138 | for (i = 0; i < min(QLINK_MAX_NR_AKM_SUITES, s->crypto.n_akm_suites);
| ^~~
>> include/linux/minmax.h:36:9: error: first argument to '__builtin_choose_expr' not a constant
36 | __builtin_choose_expr(__safe_cmp(x, y), \
| ^~~~~~~~~~~~~~~~~~~~~
include/linux/minmax.h:45:25: note: in expansion of macro '__careful_cmp'
45 | #define min(x, y) __careful_cmp(x, y, <)
| ^~~~~~~~~~~~~
drivers/net/wireless/quantenna/qtnfmac/commands.c:2138:25: note: in expansion of macro 'min'
2138 | for (i = 0; i < min(QLINK_MAX_NR_AKM_SUITES, s->crypto.n_akm_suites);
| ^~~


vim +/s +2138 drivers/net/wireless/quantenna/qtnfmac/commands.c

2071
2072 int qtnf_cmd_send_connect(struct qtnf_vif *vif,
2073 struct cfg80211_connect_params *sme)
2074 {
2075 struct sk_buff *cmd_skb;
2076 struct qlink_cmd_connect *cmd;
2077 struct qlink_auth_encr *aen;
2078 int ret;
2079 int i;
2080 u32 connect_flags = 0;
2081
2082 cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
2083 QLINK_CMD_CONNECT,
2084 sizeof(*cmd));
2085 if (!cmd_skb)
2086 return -ENOMEM;
2087
2088 cmd = (struct qlink_cmd_connect *)cmd_skb->data;
2089
2090 ether_addr_copy(cmd->bssid, vif->bssid);
2091
2092 if (sme->bssid_hint)
2093 ether_addr_copy(cmd->bssid_hint, sme->bssid_hint);
2094 else
2095 eth_zero_addr(cmd->bssid_hint);
2096
2097 if (sme->prev_bssid)
2098 ether_addr_copy(cmd->prev_bssid, sme->prev_bssid);
2099 else
2100 eth_zero_addr(cmd->prev_bssid);
2101
2102 if ((sme->bg_scan_period >= 0) &&
2103 (sme->bg_scan_period <= SHRT_MAX))
2104 cmd->bg_scan_period = cpu_to_le16(sme->bg_scan_period);
2105 else
2106 cmd->bg_scan_period = cpu_to_le16(-1); /* use default value */
2107
2108 if (sme->flags & ASSOC_REQ_DISABLE_HT)
2109 connect_flags |= QLINK_STA_CONNECT_DISABLE_HT;
2110 if (sme->flags & ASSOC_REQ_DISABLE_VHT)
2111 connect_flags |= QLINK_STA_CONNECT_DISABLE_VHT;
2112 if (sme->flags & ASSOC_REQ_USE_RRM)
2113 connect_flags |= QLINK_STA_CONNECT_USE_RRM;
2114
2115 cmd->flags = cpu_to_le32(connect_flags);
2116 memcpy(&cmd->ht_capa, &sme->ht_capa, sizeof(cmd->ht_capa));
2117 memcpy(&cmd->ht_capa_mask, &sme->ht_capa_mask,
2118 sizeof(cmd->ht_capa_mask));
2119 memcpy(&cmd->vht_capa, &sme->vht_capa, sizeof(cmd->vht_capa));
2120 memcpy(&cmd->vht_capa_mask, &sme->vht_capa_mask,
2121 sizeof(cmd->vht_capa_mask));
2122 cmd->pbss = sme->pbss;
2123
2124 aen = &cmd->aen;
2125 aen->auth_type = sme->auth_type;
2126 aen->privacy = !!sme->privacy;
2127 cmd->mfp = sme->mfp;
2128 aen->wpa_versions = cpu_to_le32(sme->crypto.wpa_versions);
2129 aen->cipher_group = cpu_to_le32(sme->crypto.cipher_group);
2130 aen->n_ciphers_pairwise = cpu_to_le32(sme->crypto.n_ciphers_pairwise);
2131
2132 for (i = 0; i < QLINK_MAX_NR_CIPHER_SUITES; i++)
2133 aen->ciphers_pairwise[i] =
2134 cpu_to_le32(sme->crypto.ciphers_pairwise[i]);
2135
2136 aen->n_akm_suites = cpu_to_le32(sme->crypto.n_akm_suites);
2137
> 2138 for (i = 0; i < min(QLINK_MAX_NR_AKM_SUITES, s->crypto.n_akm_suites);
2139 i++)
2140 aen->akm_suites[i] = cpu_to_le32(sme->crypto.akm_suites[i]);
2141
2142 aen->control_port = sme->crypto.control_port;
2143 aen->control_port_no_encrypt =
2144 sme->crypto.control_port_no_encrypt;
2145 aen->control_port_ethertype =
2146 cpu_to_le16(be16_to_cpu(sme->crypto.control_port_ethertype));
2147
2148 qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, sme->ssid,
2149 sme->ssid_len);
2150
2151 if (sme->ie_len != 0)
2152 qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_ASSOC_REQ,
2153 sme->ie, sme->ie_len);
2154
2155 if (sme->channel)
2156 qtnf_cmd_channel_tlv_add(cmd_skb, sme->channel);
2157
2158 qtnf_bus_lock(vif->mac->bus);
2159 ret = qtnf_cmd_send(vif->mac->bus, cmd_skb);
2160 qtnf_bus_unlock(vif->mac->bus);
2161
2162 return ret;
2163 }
2164

--
0-DAY CI Kernel Test Service
https://01.org/lkp