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). rtllib_read_qos_param_element() copies a struct rtllib_info_element into a struct rtllib_qos_information_element, but is actually wanting to copy into the larger struct rtllib_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 rtllib_info_element { u8 id; u8 len; u8 data[]; } __packed; struct rtllib_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 rtllib_qos_parameter_info { struct rtllib_qos_information_element info_element; u8 reserved; struct rtllib_qos_ac_parameter ac_params_record[QOS_QUEUE_NUM]; } __packed; Cc: Darshan D V <darshandv10@xxxxxxxxx> Cc: Aditya Srivastava <yashsri421@xxxxxxxxx> Cc: devel@xxxxxxxxxxxxxxxxxxxx Cc: Larry Finger <Larry.Finger@xxxxxxxxxxxx> Signed-off-by: Kees Cook <keescook@xxxxxxxxxxxx> --- drivers/staging/rtl8192e/rtllib_crypt_ccmp.c | 4 +- drivers/staging/rtl8192e/rtllib_rx.c | 57 ++++++-------------- 2 files changed, 20 insertions(+), 41 deletions(-) diff --git a/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c b/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c index b60e2a109ce4..ed968c01c7ff 100644 --- a/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c +++ b/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c @@ -133,7 +133,9 @@ static int ccmp_init_iv_and_aad(struct rtllib_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/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c index c2209c033838..e3d0a361d370 100644 --- a/drivers/staging/rtl8192e/rtllib_rx.c +++ b/drivers/staging/rtl8192e/rtllib_rx.c @@ -1556,6 +1556,8 @@ static int rtllib_verify_qos_info(struct rtllib_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)) @@ -1570,57 +1572,32 @@ static int rtllib_verify_qos_info(struct rtllib_qos_information_element /* Parse a QoS parameter element */ -static int rtllib_read_qos_param_element(struct rtllib_qos_parameter_info - *element_param, - struct rtllib_info_element - *info_element) +static int rtllib_read_qos_param_element( + struct rtllib_qos_parameter_info *element_param, + struct rtllib_info_element *info_element) { - int ret = 0; - u16 size = sizeof(struct rtllib_qos_parameter_info) - 2; + size_t size = sizeof(*element_param); - if ((info_element == NULL) || (element_param == NULL)) + 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 = rtllib_verify_qos_info(&element_param->info_element, - QOS_OUI_PARAM_SUB_TYPE); - return ret; + memcpy(element_param, info_element, size); + return rtllib_verify_qos_info(&element_param->info_element, + QOS_OUI_PARAM_SUB_TYPE); } /* Parse a QoS information element */ -static int rtllib_read_qos_info_element(struct rtllib_qos_information_element - *element_info, - struct rtllib_info_element - *info_element) +static int rtllib_read_qos_info_element( + struct rtllib_qos_information_element *element_info, + struct rtllib_info_element *info_element) { - int ret = 0; - u16 size = sizeof(struct rtllib_qos_information_element) - 2; + size_t size = sizeof(*element_info); - if (element_info == NULL) + if (!element_info || !info_element || info_element->len != size - 2) return -1; - if (info_element == NULL) - 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 = rtllib_verify_qos_info(element_info, - QOS_OUI_INFO_SUB_TYPE); - return ret; + memcpy(element_info, info_element, size); + return rtllib_verify_qos_info(element_info, QOS_OUI_INFO_SUB_TYPE); } -- 2.30.2