diff options
author | Kees Cook <keescook@chromium.org> | 2021-08-06 13:12:07 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2021-08-10 12:09:35 +0200 |
commit | 1b3c6cccda3f012ffab8287f1d6151492055340e (patch) | |
tree | 2773fb227e9a708feafc992484db17ff7fef9774 /drivers/staging/rtl8192u | |
parent | ada0e6dbbb098350e0cb7fd32672ba4fd98500fc (diff) | |
download | lwn-1b3c6cccda3f012ffab8287f1d6151492055340e.tar.gz lwn-1b3c6cccda3f012ffab8287f1d6151492055340e.zip |
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.h | 4 | ||||
-rw-r--r-- | drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c | 4 | ||||
-rw-r--r-- | drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c | 49 |
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); } |