iwlwifi: mvm: validate firmware sync response size
We send some data to the firmware and expect to get it back, but we shouldn't really trust the firmware on this. Check the size of all the data we send down to avoid using bad or just uninitialized data when the firmware doesn't respond right. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com> Link: https://lore.kernel.org/r/iwlwifi.20201209231352.a5a8173f16c7.I4fa68bb2b1c7dcc52ddd381c4042722d27c4a34d@changeid Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
This commit is contained in:
committed by
Luca Coelho
parent
e4475583b5
commit
b570e5b059
@@ -747,10 +747,18 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||||
struct iwl_rxq_sync_notification *notif;
|
struct iwl_rxq_sync_notification *notif;
|
||||||
struct iwl_mvm_internal_rxq_notif *internal_notif;
|
struct iwl_mvm_internal_rxq_notif *internal_notif;
|
||||||
|
u32 len = iwl_rx_packet_payload_len(pkt);
|
||||||
|
|
||||||
notif = (void *)pkt->data;
|
notif = (void *)pkt->data;
|
||||||
internal_notif = (void *)notif->payload;
|
internal_notif = (void *)notif->payload;
|
||||||
|
|
||||||
|
if (WARN_ONCE(len < sizeof(*notif) + sizeof(*internal_notif),
|
||||||
|
"invalid notification size %d (%d)",
|
||||||
|
len, (int)(sizeof(*notif) + sizeof(*internal_notif))))
|
||||||
|
return;
|
||||||
|
/* remove only the firmware header, we want all of our payload below */
|
||||||
|
len -= sizeof(*notif);
|
||||||
|
|
||||||
if (internal_notif->sync &&
|
if (internal_notif->sync &&
|
||||||
mvm->queue_sync_cookie != internal_notif->cookie) {
|
mvm->queue_sync_cookie != internal_notif->cookie) {
|
||||||
WARN_ONCE(1, "Received expired RX queue sync message\n");
|
WARN_ONCE(1, "Received expired RX queue sync message\n");
|
||||||
@@ -759,11 +767,22 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||||||
|
|
||||||
switch (internal_notif->type) {
|
switch (internal_notif->type) {
|
||||||
case IWL_MVM_RXQ_EMPTY:
|
case IWL_MVM_RXQ_EMPTY:
|
||||||
|
WARN_ONCE(len != sizeof(*internal_notif),
|
||||||
|
"invalid empty notification size %d (%d)",
|
||||||
|
len, (int)sizeof(*internal_notif));
|
||||||
break;
|
break;
|
||||||
case IWL_MVM_RXQ_NOTIF_DEL_BA:
|
case IWL_MVM_RXQ_NOTIF_DEL_BA:
|
||||||
|
if (WARN_ONCE(len != sizeof(struct iwl_mvm_rss_sync_notif),
|
||||||
|
"invalid delba notification size %d (%d)",
|
||||||
|
len, (int)sizeof(struct iwl_mvm_rss_sync_notif)))
|
||||||
|
break;
|
||||||
iwl_mvm_del_ba(mvm, queue, (void *)internal_notif->data);
|
iwl_mvm_del_ba(mvm, queue, (void *)internal_notif->data);
|
||||||
break;
|
break;
|
||||||
case IWL_MVM_RXQ_NSSN_SYNC:
|
case IWL_MVM_RXQ_NSSN_SYNC:
|
||||||
|
if (WARN_ONCE(len != sizeof(struct iwl_mvm_rss_sync_notif),
|
||||||
|
"invalid nssn sync notification size %d (%d)",
|
||||||
|
len, (int)sizeof(struct iwl_mvm_rss_sync_notif)))
|
||||||
|
break;
|
||||||
iwl_mvm_nssn_sync(mvm, napi, queue,
|
iwl_mvm_nssn_sync(mvm, napi, queue,
|
||||||
(void *)internal_notif->data);
|
(void *)internal_notif->data);
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user