OSDN Git Service

mwifiex: Prevent memory corruption handling keys
authorDan Carpenter <dan.carpenter@oracle.com>
Wed, 8 Jul 2020 11:58:57 +0000 (14:58 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 19 Aug 2020 06:14:57 +0000 (08:14 +0200)
[ Upstream commit e18696786548244914f36ec3c46ac99c53df99c3 ]

The length of the key comes from the network and it's a 16 bit number.  It
needs to be capped to prevent a buffer overflow.

Fixes: 5e6e3a92b9a4 ("wireless: mwifiex: initial commit for Marvell mwifiex driver")
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Acked-by: Ganapathi Bhat <ganapathi.bhat@nxp.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20200708115857.GA13729@mwanda
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c

index 69e3b62..797c2e9 100644 (file)
@@ -581,6 +581,11 @@ static int mwifiex_ret_802_11_key_material_v1(struct mwifiex_private *priv,
 {
        struct host_cmd_ds_802_11_key_material *key =
                                                &resp->params.key_material;
+       int len;
+
+       len = le16_to_cpu(key->key_param_set.key_len);
+       if (len > sizeof(key->key_param_set.key))
+               return -EINVAL;
 
        if (le16_to_cpu(key->action) == HostCmd_ACT_GEN_SET) {
                if ((le16_to_cpu(key->key_param_set.key_info) & KEY_MCAST)) {
@@ -594,9 +599,8 @@ static int mwifiex_ret_802_11_key_material_v1(struct mwifiex_private *priv,
 
        memset(priv->aes_key.key_param_set.key, 0,
               sizeof(key->key_param_set.key));
-       priv->aes_key.key_param_set.key_len = key->key_param_set.key_len;
-       memcpy(priv->aes_key.key_param_set.key, key->key_param_set.key,
-              le16_to_cpu(priv->aes_key.key_param_set.key_len));
+       priv->aes_key.key_param_set.key_len = cpu_to_le16(len);
+       memcpy(priv->aes_key.key_param_set.key, key->key_param_set.key, len);
 
        return 0;
 }
@@ -611,9 +615,14 @@ static int mwifiex_ret_802_11_key_material_v2(struct mwifiex_private *priv,
                                              struct host_cmd_ds_command *resp)
 {
        struct host_cmd_ds_802_11_key_material_v2 *key_v2;
-       __le16 len;
+       int len;
 
        key_v2 = &resp->params.key_material_v2;
+
+       len = le16_to_cpu(key_v2->key_param_set.key_params.aes.key_len);
+       if (len > WLAN_KEY_LEN_CCMP)
+               return -EINVAL;
+
        if (le16_to_cpu(key_v2->action) == HostCmd_ACT_GEN_SET) {
                if ((le16_to_cpu(key_v2->key_param_set.key_info) & KEY_MCAST)) {
                        mwifiex_dbg(priv->adapter, INFO, "info: key: GTK is set\n");
@@ -629,10 +638,9 @@ static int mwifiex_ret_802_11_key_material_v2(struct mwifiex_private *priv,
        memset(priv->aes_key_v2.key_param_set.key_params.aes.key, 0,
               WLAN_KEY_LEN_CCMP);
        priv->aes_key_v2.key_param_set.key_params.aes.key_len =
-                               key_v2->key_param_set.key_params.aes.key_len;
-       len = priv->aes_key_v2.key_param_set.key_params.aes.key_len;
+                               cpu_to_le16(len);
        memcpy(priv->aes_key_v2.key_param_set.key_params.aes.key,
-              key_v2->key_param_set.key_params.aes.key, le16_to_cpu(len));
+              key_v2->key_param_set.key_params.aes.key, len);
 
        return 0;
 }