mirror of
https://github.com/torvalds/linux.git
synced 2026-10-10 20:38:02 +02:00
wifi: iwlwifi: mld: validate wake packet crypto overhead
Wake packet parsing only accounted for FCS and missed per-key IV/ICV overhead for protected data frames. Prevent size underflow and bad packet trimming when notifications are malformed or truncated. Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Link: https://patch.msgid.link/20260717172958.e06595623533.Ie09494b7e34e5872b750fd90e325648ee469d0da@changeid Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
This commit is contained in:
parent
905f57aefd
commit
c5cb9dd220
|
|
@ -59,6 +59,30 @@ struct iwl_mld_suspend_key_iter_data {
|
|||
__le32 bigtk_cipher;
|
||||
};
|
||||
|
||||
struct iwl_mld_wake_pkt_iter_data {
|
||||
bool multicast;
|
||||
u32 ivlen;
|
||||
u32 icvlen;
|
||||
};
|
||||
|
||||
static void
|
||||
iwl_mld_wake_pkt_key_iter(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key, void *_data)
|
||||
{
|
||||
struct iwl_mld_wake_pkt_iter_data *data = _data;
|
||||
bool is_group_key = !sta;
|
||||
|
||||
/* ignore anything that is not a PTK / GTK */
|
||||
if (key->keyidx > 3)
|
||||
return;
|
||||
if (is_group_key != data->multicast)
|
||||
return;
|
||||
|
||||
data->ivlen = key->iv_len;
|
||||
data->icvlen = key->icv_len;
|
||||
}
|
||||
|
||||
struct iwl_mld_mcast_key_data {
|
||||
u8 key[WOWLAN_KEY_MAX_SIZE];
|
||||
u8 len;
|
||||
|
|
@ -743,11 +767,17 @@ iwl_mld_set_wake_packet(struct iwl_mld *mld,
|
|||
struct cfg80211_wowlan_wakeup *wakeup,
|
||||
struct sk_buff **_pkt)
|
||||
{
|
||||
int pkt_bufsize = wowlan_status->wake_packet_bufsize;
|
||||
int expected_pktlen = wowlan_status->wake_packet_length;
|
||||
u32 pkt_bufsize = wowlan_status->wake_packet_bufsize;
|
||||
u32 expected_pktlen = wowlan_status->wake_packet_length;
|
||||
const u8 *pktdata = wowlan_status->wake_packet;
|
||||
const struct ieee80211_hdr *hdr = (const void *)pktdata;
|
||||
int truncated = expected_pktlen - pkt_bufsize;
|
||||
u32 truncated;
|
||||
|
||||
if (IWL_FW_CHECK(mld, pkt_bufsize < sizeof(*hdr),
|
||||
"pkt_bufsize is too short: %u\n", pkt_bufsize))
|
||||
return;
|
||||
|
||||
truncated = expected_pktlen - pkt_bufsize;
|
||||
|
||||
if (ieee80211_is_data(hdr->frame_control)) {
|
||||
int hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
||||
|
|
@ -758,9 +788,18 @@ iwl_mld_set_wake_packet(struct iwl_mld *mld,
|
|||
if (!pkt)
|
||||
return;
|
||||
|
||||
skb_put_data(pkt, pktdata, hdrlen);
|
||||
pktdata += hdrlen;
|
||||
pkt_bufsize -= hdrlen;
|
||||
if (ieee80211_has_protected(hdr->frame_control)) {
|
||||
struct iwl_mld_wake_pkt_iter_data iter_data = {
|
||||
.multicast =
|
||||
is_multicast_ether_addr(hdr->addr1),
|
||||
};
|
||||
|
||||
ieee80211_iter_keys(mld->hw, vif,
|
||||
iwl_mld_wake_pkt_key_iter,
|
||||
&iter_data);
|
||||
ivlen = iter_data.ivlen;
|
||||
icvlen += iter_data.icvlen;
|
||||
}
|
||||
|
||||
/* if truncated, FCS/ICV is (partially) gone */
|
||||
if (truncated >= icvlen) {
|
||||
|
|
@ -771,6 +810,13 @@ iwl_mld_set_wake_packet(struct iwl_mld *mld,
|
|||
truncated = 0;
|
||||
}
|
||||
|
||||
if (IWL_FW_CHECK(mld, pkt_bufsize <= hdrlen + ivlen + icvlen,
|
||||
"pkt_bufsize is too small %u\n", pkt_bufsize))
|
||||
return;
|
||||
|
||||
skb_put_data(pkt, pktdata, hdrlen);
|
||||
pktdata += hdrlen;
|
||||
pkt_bufsize -= hdrlen;
|
||||
pkt_bufsize -= ivlen + icvlen;
|
||||
pktdata += ivlen;
|
||||
|
||||
|
|
@ -792,6 +838,11 @@ iwl_mld_set_wake_packet(struct iwl_mld *mld,
|
|||
fcslen -= truncated;
|
||||
truncated = 0;
|
||||
}
|
||||
|
||||
if (IWL_FW_CHECK(mld, pkt_bufsize <= fcslen,
|
||||
"pkt_bufsize is too small %u\n", pkt_bufsize))
|
||||
return;
|
||||
|
||||
pkt_bufsize -= fcslen;
|
||||
wakeup->packet = wowlan_status->wake_packet;
|
||||
wakeup->packet_present_len = pkt_bufsize;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user