summaryrefslogtreecommitdiff
path: root/drivers/staging/rtl8192u
diff options
context:
space:
mode:
authorKees Cook <keescook@chromium.org>2021-08-06 13:12:07 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-08-10 12:09:35 +0200
commit1b3c6cccda3f012ffab8287f1d6151492055340e (patch)
tree2773fb227e9a708feafc992484db17ff7fef9774 /drivers/staging/rtl8192u
parentada0e6dbbb098350e0cb7fd32672ba4fd98500fc (diff)
staging: rtl8192u: Avoid field-overflowing memcpy()
In preparation for FORTIFY_SOURCE performing compile-time and run-time field bounds checking for memcpy(), memmove(), and memset(), avoid intentionally writing across neighboring fields. Split the 3 addr memcpy() into 3 memcpy() calls so the compiler doesn't think an overflowing memcpy() happens against the addr1 field (the neighbors are intended to be copied as well). ieee80211_read_qos_param_element() copies a struct ieee80211_info_element into a struct ieee80211_qos_information_element, but is actually wanting to copy into the larger struct ieee80211_qos_parameter_info (the contents of ac_params_record[] is later examined). Refactor the routine to perform centralized checks, and copy the entire contents directly (since the id and len members match the elementID and length members): struct ieee80211_info_element { u8 id; u8 len; u8 data[]; } __packed; struct ieee80211_qos_information_element { u8 elementID; u8 length; u8 qui[QOS_OUI_LEN]; u8 qui_type; u8 qui_subtype; u8 version; u8 ac_info; } __packed; struct ieee80211_qos_parameter_info { struct ieee80211_qos_information_element info_element; u8 reserved; struct ieee80211_qos_ac_parameter ac_params_record[QOS_QUEUE_NUM]; } __packed; Additionally replace old-style zero-element arrays with flexible arrays. Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Pascal Terjan <pterjan@google.com> Cc: Christophe JAILLET <christophe.jaillet@wanadoo.fr> Cc: devel@driverdev.osuosl.org Signed-off-by: Kees Cook <keescook@chromium.org> Link: https://lore.kernel.org/r/20210806201208.2871467-1-keescook@chromium.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/rtl8192u')
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211.h4
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c4
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c49
3 files changed, 19 insertions, 38 deletions
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h
index 7903c777a417..15207dc1f5c5 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h
@@ -303,7 +303,7 @@ struct ieee_param {
struct {
u32 len;
u8 reserved[32];
- u8 data[0];
+ u8 data[];
} wpa_ie;
struct{
int command;
@@ -316,7 +316,7 @@ struct ieee_param {
u8 idx;
u8 seq[8]; /* sequence counter (set: RX, get: TX) */
u16 key_len;
- u8 key[0];
+ u8 key[];
} crypt;
} u;
};
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c
index c241cf484023..ccff385cf1f8 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c
@@ -141,7 +141,9 @@ static int ccmp_init_iv_and_aad(struct rtl_80211_hdr_4addr *hdr,
pos = (u8 *)hdr;
aad[0] = pos[0] & 0x8f;
aad[1] = pos[1] & 0xc7;
- memcpy(aad + 2, hdr->addr1, 3 * ETH_ALEN);
+ memcpy(&aad[2], &hdr->addr1, ETH_ALEN);
+ memcpy(&aad[8], &hdr->addr2, ETH_ALEN);
+ memcpy(&aad[14], &hdr->addr3, ETH_ALEN);
pos = (u8 *)&hdr->seq_ctl;
aad[20] = pos[0] & 0x0f;
aad[21] = 0; /* all bits masked */
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
index b0e01ee65f7f..b58e75932ecd 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
@@ -1310,7 +1310,8 @@ static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };
static int ieee80211_verify_qos_info(struct ieee80211_qos_information_element
*info_element, int sub_type)
{
-
+ if (info_element->elementID != QOS_ELEMENT_ID)
+ return -1;
if (info_element->qui_subtype != sub_type)
return -1;
if (memcmp(info_element->qui, qos_oui, QOS_OUI_LEN))
@@ -1327,27 +1328,18 @@ static int ieee80211_verify_qos_info(struct ieee80211_qos_information_element
/*
* Parse a QoS parameter element
*/
-static int ieee80211_read_qos_param_element(struct ieee80211_qos_parameter_info
- *element_param, struct ieee80211_info_element
- *info_element)
+static int ieee80211_read_qos_param_element(
+ struct ieee80211_qos_parameter_info *element_param,
+ struct ieee80211_info_element *info_element)
{
- int ret = 0;
- u16 size = sizeof(struct ieee80211_qos_parameter_info) - 2;
+ size_t size = sizeof(*element_param);
- if (!info_element || !element_param)
+ if (!element_param || !info_element || info_element->len != size - 2)
return -1;
- if (info_element->id == QOS_ELEMENT_ID && info_element->len == size) {
- memcpy(element_param->info_element.qui, info_element->data,
- info_element->len);
- element_param->info_element.elementID = info_element->id;
- element_param->info_element.length = info_element->len;
- } else
- ret = -1;
- if (ret == 0)
- ret = ieee80211_verify_qos_info(&element_param->info_element,
- QOS_OUI_PARAM_SUB_TYPE);
- return ret;
+ memcpy(element_param, info_element, size);
+ return ieee80211_verify_qos_info(&element_param->info_element,
+ QOS_OUI_PARAM_SUB_TYPE);
}
/*
@@ -1357,26 +1349,13 @@ static int ieee80211_read_qos_info_element(
struct ieee80211_qos_information_element *element_info,
struct ieee80211_info_element *info_element)
{
- int ret = 0;
- u16 size = sizeof(struct ieee80211_qos_information_element) - 2;
+ size_t size = sizeof(*element_info);
- if (!element_info)
+ if (!element_info || !info_element || info_element->len != size - 2)
return -1;
- if (!info_element)
- return -1;
-
- if ((info_element->id == QOS_ELEMENT_ID) && (info_element->len == size)) {
- memcpy(element_info->qui, info_element->data,
- info_element->len);
- element_info->elementID = info_element->id;
- element_info->length = info_element->len;
- } else
- ret = -1;
- if (ret == 0)
- ret = ieee80211_verify_qos_info(element_info,
- QOS_OUI_INFO_SUB_TYPE);
- return ret;
+ memcpy(element_info, info_element, size);
+ return ieee80211_verify_qos_info(element_info, QOS_OUI_INFO_SUB_TYPE);
}