2016-06-16 13:23:50

by Amitkumar Karwar

[permalink] [raw]
Subject: [PATCH 1/6] mwifiex: Fix an issue spotted by KASAN

From: Ganapathi Bhat <[email protected]>

When an association command is sent to firmware but the process is
killed before the command response arrives, driver will try to
access bss_desc which is already freed. This issue is fixed by
checking return value of bss_start.

Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/marvell/mwifiex/join.c | 12 ++++++++++++
drivers/net/wireless/marvell/mwifiex/sta_ioctl.c | 4 ++++
2 files changed, 16 insertions(+)

diff --git a/drivers/net/wireless/marvell/mwifiex/join.c b/drivers/net/wireless/marvell/mwifiex/join.c
index a4b773d..1c7b006 100644
--- a/drivers/net/wireless/marvell/mwifiex/join.c
+++ b/drivers/net/wireless/marvell/mwifiex/join.c
@@ -647,6 +647,12 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
const u8 *ie_ptr;
struct ieee80211_ht_operation *assoc_resp_ht_oper;

+ if (!priv->attempted_bss_desc) {
+ mwifiex_dbg(priv->adapter, ERROR,
+ "ASSOC_RESP: failed, association terminated by host\n");
+ goto done;
+ }
+
assoc_rsp = (struct ieee_types_assoc_rsp *) &resp->params;

cap_info = le16_to_cpu(assoc_rsp->cap_info_bitmap);
@@ -1270,6 +1276,12 @@ int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,
u16 cmd = le16_to_cpu(resp->command);
u8 result;

+ if (!priv->attempted_bss_desc) {
+ mwifiex_dbg(priv->adapter, ERROR,
+ "ADHOC_RESP: failed, association terminated by host\n");
+ goto done;
+ }
+
if (cmd == HostCmd_CMD_802_11_AD_HOC_START)
result = start_result->result;
else
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c
index 8e08626..2ba5397 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c
@@ -426,6 +426,10 @@ done:
if (bss_desc)
kfree(bss_desc->beacon_buf);
kfree(bss_desc);
+
+ if (ret < 0)
+ priv->attempted_bss_desc = NULL;
+
return ret;
}

--
1.9.1



2016-06-16 13:29:55

by Amitkumar Karwar

[permalink] [raw]
Subject: [PATCH 5/6] mwifiex: fix AP unable to start in VHT40 problem

This patch populates secondary channel offset and downloads it to
firmware to fix the problem.

Signed-off-by: Amitkumar Karwar <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
---
drivers/net/wireless/marvell/mwifiex/ioctl.h | 2 ++
drivers/net/wireless/marvell/mwifiex/uap_cmd.c | 30 ++++++++++++++++++++++++--
2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/ioctl.h b/drivers/net/wireless/marvell/mwifiex/ioctl.h
index a5a48c1..f5b8fd1 100644
--- a/drivers/net/wireless/marvell/mwifiex/ioctl.h
+++ b/drivers/net/wireless/marvell/mwifiex/ioctl.h
@@ -83,6 +83,8 @@ struct wep_key {
#define MWIFIEX_AUTH_MODE_AUTO 0xFF
#define BAND_CONFIG_BG 0x00
#define BAND_CONFIG_A 0x01
+#define MWIFIEX_SEC_CHAN_BELOW 0x30
+#define MWIFIEX_SEC_CHAN_ABOVE 0x10
#define MWIFIEX_SUPPORTED_RATES 14
#define MWIFIEX_SUPPORTED_RATES_EXT 32
#define MWIFIEX_TDLS_SUPPORTED_RATES 8
diff --git a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c
index f79d00d..a7e9f54 100644
--- a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c
+++ b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c
@@ -19,6 +19,7 @@

#include "main.h"
#include "11ac.h"
+#include "11n.h"

/* This function parses security related parameters from cfg80211_ap_settings
* and sets into FW understandable bss_config structure.
@@ -521,9 +522,9 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
tlv += sizeof(struct host_cmd_tlv_rates) + i;
}
if (bss_cfg->channel &&
- ((bss_cfg->band_cfg == BAND_CONFIG_BG &&
+ (((bss_cfg->band_cfg & BIT(0)) == BAND_CONFIG_BG &&
bss_cfg->channel <= MAX_CHANNEL_BAND_BG) ||
- (bss_cfg->band_cfg == BAND_CONFIG_A &&
+ ((bss_cfg->band_cfg & BIT(0)) == BAND_CONFIG_A &&
bss_cfg->channel <= MAX_CHANNEL_BAND_A))) {
chan_band = (struct host_cmd_tlv_channel_band *)tlv;
chan_band->header.type = cpu_to_le16(TLV_TYPE_CHANNELBANDLIST);
@@ -833,6 +834,31 @@ void mwifiex_uap_set_channel(struct mwifiex_private *priv,
config_bands |= BAND_AAC;
}

+ switch (chandef.width) {
+ case NL80211_CHAN_WIDTH_5:
+ case NL80211_CHAN_WIDTH_10:
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ case NL80211_CHAN_WIDTH_20:
+ break;
+ case NL80211_CHAN_WIDTH_40:
+ if (chandef.center_freq1 < chandef.chan->center_freq)
+ bss_cfg->band_cfg |= MWIFIEX_SEC_CHAN_BELOW;
+ else
+ bss_cfg->band_cfg |= MWIFIEX_SEC_CHAN_ABOVE;
+ break;
+ case NL80211_CHAN_WIDTH_80:
+ case NL80211_CHAN_WIDTH_80P80:
+ case NL80211_CHAN_WIDTH_160:
+ bss_cfg->band_cfg |=
+ mwifiex_get_sec_chan_offset(bss_cfg->channel) << 4;
+ break;
+ default:
+ mwifiex_dbg(priv->adapter,
+ WARN, "Unknown channel width: %d\n",
+ chandef.width);
+ break;
+ }
+
priv->adapter->config_bands = config_bands;

if (old_bands != config_bands) {
--
1.9.1


2016-06-29 15:54:30

by Kalle Valo

[permalink] [raw]
Subject: Re: [1/6] mwifiex: Fix an issue spotted by KASAN

Amitkumar Karwar <[email protected]> wrote:
> From: Ganapathi Bhat <[email protected]>
>
> When an association command is sent to firmware but the process is
> killed before the command response arrives, driver will try to
> access bss_desc which is already freed. This issue is fixed by
> checking return value of bss_start.
>
> Signed-off-by: Amitkumar Karwar <[email protected]>

Thanks, 6 patches applied to wireless-drivers-next.git:

4699fc3f2dcb mwifiex: Fix an issue spotted by KASAN
a9c790ba23eb mwifiex: factor out mwifiex_cancel_scan
dec277f781ce mwifiex: cancel pending scan during disconnect
437322ea2a36 mwifiex: fix system hang problem after resume
568fb26ec8be mwifiex: fix AP unable to start in VHT40 problem
7311ea850079 mwifiex: fix AP start problem for newly added interface

--
Sent by pwcli
https://patchwork.kernel.org/patch/9180805/


2016-06-16 13:31:21

by Amitkumar Karwar

[permalink] [raw]
Subject: [PATCH 6/6] mwifiex: fix AP start problem for newly added interface

It's been observed that if interface type is changed from managed to
__ap, AP can be successfully started. But there is a problem if new
ap interface is added.

The problem got resolved after sending appropriate commands to firmware
in add_interface handler.

Signed-off-by: Amitkumar Karwar <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
---
drivers/net/wireless/marvell/mwifiex/cfg80211.c | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index cd50425..81ff8bb 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -2775,6 +2775,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
struct mwifiex_private *priv;
struct net_device *dev;
void *mdev_priv;
+ int ret;

if (!adapter)
return ERR_PTR(-EFAULT);
@@ -2900,6 +2901,13 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
mwifiex_init_priv_params(priv, dev);
priv->netdev = dev;

+ ret = mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
+ HostCmd_ACT_GEN_SET, 0, NULL, true);
+ return ERR_PTR(ret);
+
+ ret = mwifiex_sta_init_cmd(priv, false, false);
+ return ERR_PTR(ret);
+
mwifiex_setup_ht_caps(&wiphy->bands[NL80211_BAND_2GHZ]->ht_cap, priv);
if (adapter->is_hw_11ac_capable)
mwifiex_setup_vht_caps(
--
1.9.1


2016-06-16 13:27:21

by Amitkumar Karwar

[permalink] [raw]
Subject: [PATCH 4/6] mwifiex: fix system hang problem after resume

On some platforms, driver is unable to wakeup firmware after system resume
due to a problem at MMC subsystem. Triggering card reset in this case has
a race with card removal from MMC which causes system hang. This patch
resolves the problem by not triggering card reset.

Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/marvell/mwifiex/init.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c
index fbaf490..d39f72a3 100644
--- a/drivers/net/wireless/marvell/mwifiex/init.c
+++ b/drivers/net/wireless/marvell/mwifiex/init.c
@@ -60,7 +60,7 @@ static void wakeup_timer_fn(unsigned long data)
adapter->hw_status = MWIFIEX_HW_STATUS_RESET;
mwifiex_cancel_all_pending_cmd(adapter);

- if (adapter->if_ops.card_reset)
+ if (adapter->if_ops.card_reset && !adapter->hs_activated)
adapter->if_ops.card_reset(adapter);
}

--
1.9.1


2016-06-16 13:24:57

by Amitkumar Karwar

[permalink] [raw]
Subject: [PATCH 2/6] mwifiex: factor out mwifiex_cancel_scan

From: Xinming Hu <[email protected]>

This patch creates common function mwifiex_cancel_scan to remove
duplication of code.

Signed-off-by: Xinming Hu <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/marvell/mwifiex/cmdevt.c | 40 ++-------------------------
drivers/net/wireless/marvell/mwifiex/main.h | 1 +
drivers/net/wireless/marvell/mwifiex/scan.c | 26 +++++++++++++++++
3 files changed, 29 insertions(+), 38 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
index 6bc2011..c29f26d 100644
--- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
@@ -1020,8 +1020,6 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
{
struct cmd_ctrl_node *cmd_node = NULL, *tmp_node;
unsigned long flags, cmd_flags;
- struct mwifiex_private *priv;
- int i;

spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
/* Cancel current cmd */
@@ -1046,23 +1044,7 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);

- mwifiex_cancel_pending_scan_cmd(adapter);
-
- if (adapter->scan_processing) {
- spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
- adapter->scan_processing = false;
- spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
- for (i = 0; i < adapter->priv_num; i++) {
- priv = adapter->priv[i];
- if (!priv)
- continue;
- if (priv->scan_request) {
- mwifiex_dbg(adapter, WARN, "info: aborting scan\n");
- cfg80211_scan_done(priv->scan_request, 1);
- priv->scan_request = NULL;
- }
- }
- }
+ mwifiex_cancel_scan(adapter);
}

/*
@@ -1080,8 +1062,6 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
{
struct cmd_ctrl_node *cmd_node = NULL;
unsigned long cmd_flags;
- struct mwifiex_private *priv;
- int i;

if ((adapter->curr_cmd) &&
(adapter->curr_cmd->wait_q_enabled)) {
@@ -1101,23 +1081,7 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
mwifiex_recycle_cmd_node(adapter, cmd_node);
}

- mwifiex_cancel_pending_scan_cmd(adapter);
-
- if (adapter->scan_processing) {
- spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
- adapter->scan_processing = false;
- spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
- for (i = 0; i < adapter->priv_num; i++) {
- priv = adapter->priv[i];
- if (!priv)
- continue;
- if (priv->scan_request) {
- mwifiex_dbg(adapter, WARN, "info: aborting scan\n");
- cfg80211_scan_done(priv->scan_request, 1);
- priv->scan_request = NULL;
- }
- }
- }
+ mwifiex_cancel_scan(adapter);
}

/*
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index 39bb5bc..9f6bb40 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -1056,6 +1056,7 @@ int mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter);
void mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter);
void mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter);
void mwifiex_cancel_pending_scan_cmd(struct mwifiex_adapter *adapter);
+void mwifiex_cancel_scan(struct mwifiex_adapter *adapter);

void mwifiex_recycle_cmd_node(struct mwifiex_adapter *adapter,
struct cmd_ctrl_node *cmd_node);
diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c
index bc5e52c..e331122 100644
--- a/drivers/net/wireless/marvell/mwifiex/scan.c
+++ b/drivers/net/wireless/marvell/mwifiex/scan.c
@@ -2001,6 +2001,32 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
return;
}

+void mwifiex_cancel_scan(struct mwifiex_adapter *adapter)
+{
+ struct mwifiex_private *priv;
+ unsigned long cmd_flags;
+ int i;
+
+ mwifiex_cancel_pending_scan_cmd(adapter);
+
+ if (adapter->scan_processing) {
+ spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
+ adapter->scan_processing = false;
+ spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
+ for (i = 0; i < adapter->priv_num; i++) {
+ priv = adapter->priv[i];
+ if (!priv)
+ continue;
+ if (priv->scan_request) {
+ mwifiex_dbg(adapter, INFO,
+ "info: aborting scan\n");
+ cfg80211_scan_done(priv->scan_request, 1);
+ priv->scan_request = NULL;
+ }
+ }
+ }
+}
+
/*
* This function handles the command response of scan.
*
--
1.9.1


2016-06-16 13:26:09

by Amitkumar Karwar

[permalink] [raw]
Subject: [PATCH 3/6] mwifiex: cancel pending scan during disconnect

From: Xinming Hu <[email protected]>

It is obeserved that sometimes scan operation will block the disconnect
during system suspend. It's ok to cancel ongoing scan in this case. It
reduces unnecessary system suspend delay.

Signed-off-by: Xinming Hu <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/marvell/mwifiex/cfg80211.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index 313115e..cd50425 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -1695,6 +1695,9 @@ static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy,
struct cfg80211_beacon_data *data)
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+ struct mwifiex_adapter *adapter = priv->adapter;
+
+ mwifiex_cancel_scan(adapter);

if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) {
mwifiex_dbg(priv->adapter, ERROR,
--
1.9.1