Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

staging: rtl8192e: 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).

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@gmail.com>
Cc: Aditya Srivastava <yashsri421@gmail.com>
Cc: devel@driverdev.osuosl.org
Cc: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/20210806201106.2871169-1-keescook@chromium.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Kees Cook and committed by
Greg Kroah-Hartman
ada0e6db 69c92a74

+20 -41
+3 -1
drivers/staging/rtl8192e/rtllib_crypt_ccmp.c
··· 133 133 pos = (u8 *) hdr; 134 134 aad[0] = pos[0] & 0x8f; 135 135 aad[1] = pos[1] & 0xc7; 136 - memcpy(aad + 2, hdr->addr1, 3 * ETH_ALEN); 136 + memcpy(&aad[2], &hdr->addr1, ETH_ALEN); 137 + memcpy(&aad[8], &hdr->addr2, ETH_ALEN); 138 + memcpy(&aad[14], &hdr->addr3, ETH_ALEN); 137 139 pos = (u8 *) &hdr->seq_ctl; 138 140 aad[20] = pos[0] & 0x0f; 139 141 aad[21] = 0; /* all bits masked */
+17 -40
drivers/staging/rtl8192e/rtllib_rx.c
··· 1556 1556 *info_element, int sub_type) 1557 1557 { 1558 1558 1559 + if (info_element->elementID != QOS_ELEMENT_ID) 1560 + return -1; 1559 1561 if (info_element->qui_subtype != sub_type) 1560 1562 return -1; 1561 1563 if (memcmp(info_element->qui, qos_oui, QOS_OUI_LEN)) ··· 1572 1570 1573 1571 1574 1572 /* Parse a QoS parameter element */ 1575 - static int rtllib_read_qos_param_element(struct rtllib_qos_parameter_info 1576 - *element_param, 1577 - struct rtllib_info_element 1578 - *info_element) 1573 + static int rtllib_read_qos_param_element( 1574 + struct rtllib_qos_parameter_info *element_param, 1575 + struct rtllib_info_element *info_element) 1579 1576 { 1580 - int ret = 0; 1581 - u16 size = sizeof(struct rtllib_qos_parameter_info) - 2; 1577 + size_t size = sizeof(*element_param); 1582 1578 1583 - if ((info_element == NULL) || (element_param == NULL)) 1579 + if (!element_param || !info_element || info_element->len != size - 2) 1584 1580 return -1; 1585 1581 1586 - if (info_element->id == QOS_ELEMENT_ID && info_element->len == size) { 1587 - memcpy(element_param->info_element.qui, info_element->data, 1588 - info_element->len); 1589 - element_param->info_element.elementID = info_element->id; 1590 - element_param->info_element.length = info_element->len; 1591 - } else 1592 - ret = -1; 1593 - if (ret == 0) 1594 - ret = rtllib_verify_qos_info(&element_param->info_element, 1595 - QOS_OUI_PARAM_SUB_TYPE); 1596 - return ret; 1582 + memcpy(element_param, info_element, size); 1583 + return rtllib_verify_qos_info(&element_param->info_element, 1584 + QOS_OUI_PARAM_SUB_TYPE); 1597 1585 } 1598 1586 1599 1587 /* Parse a QoS information element */ 1600 - static int rtllib_read_qos_info_element(struct rtllib_qos_information_element 1601 - *element_info, 1602 - struct rtllib_info_element 1603 - *info_element) 1588 + static int rtllib_read_qos_info_element( 1589 + struct rtllib_qos_information_element *element_info, 1590 + struct rtllib_info_element *info_element) 1604 1591 { 1605 - int ret = 0; 1606 - u16 size = sizeof(struct rtllib_qos_information_element) - 2; 1592 + size_t size = sizeof(*element_info); 1607 1593 1608 - if (element_info == NULL) 1609 - return -1; 1610 - if (info_element == NULL) 1594 + if (!element_info || !info_element || info_element->len != size - 2) 1611 1595 return -1; 1612 1596 1613 - if ((info_element->id == QOS_ELEMENT_ID) && 1614 - (info_element->len == size)) { 1615 - memcpy(element_info->qui, info_element->data, 1616 - info_element->len); 1617 - element_info->elementID = info_element->id; 1618 - element_info->length = info_element->len; 1619 - } else 1620 - ret = -1; 1621 - 1622 - if (ret == 0) 1623 - ret = rtllib_verify_qos_info(element_info, 1624 - QOS_OUI_INFO_SUB_TYPE); 1625 - return ret; 1597 + memcpy(element_info, info_element, size); 1598 + return rtllib_verify_qos_info(element_info, QOS_OUI_INFO_SUB_TYPE); 1626 1599 } 1627 1600 1628 1601