Skip to content

Commit b870e73

Browse files
szymonhKalle Valo
authored andcommitted
wifi: rndis_wlan: Prevent buffer overflow in rndis_query_oid
Since resplen and respoffs are signed integers sufficiently large values of unsigned int len and offset members of RNDIS response will result in negative values of prior variables. This may be utilized to bypass implemented security checks to either extract memory contents by manipulating offset or overflow the data buffer via memcpy by manipulating both offset and len. Additionally assure that sum of resplen and respoffs does not overflow so buffer boundaries are kept. Fixes: 80f8c5b ("rndis_wlan: copy only useful data from rndis_command respond") Signed-off-by: Szymon Heidrich <[email protected]> Reviewed-by: Alexander Duyck <[email protected]> Signed-off-by: Kalle Valo <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent ed05cb1 commit b870e73

File tree

1 file changed

+6
-13
lines changed

1 file changed

+6
-13
lines changed

drivers/net/wireless/rndis_wlan.c

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -696,8 +696,8 @@ static int rndis_query_oid(struct usbnet *dev, u32 oid, void *data, int *len)
696696
struct rndis_query *get;
697697
struct rndis_query_c *get_c;
698698
} u;
699-
int ret, buflen;
700-
int resplen, respoffs, copylen;
699+
int ret;
700+
size_t buflen, resplen, respoffs, copylen;
701701

702702
buflen = *len + sizeof(*u.get);
703703
if (buflen < CONTROL_BUFFER_SIZE)
@@ -732,22 +732,15 @@ static int rndis_query_oid(struct usbnet *dev, u32 oid, void *data, int *len)
732732

733733
if (respoffs > buflen) {
734734
/* Device returned data offset outside buffer, error. */
735-
netdev_dbg(dev->net, "%s(%s): received invalid "
736-
"data offset: %d > %d\n", __func__,
737-
oid_to_string(oid), respoffs, buflen);
735+
netdev_dbg(dev->net,
736+
"%s(%s): received invalid data offset: %zu > %zu\n",
737+
__func__, oid_to_string(oid), respoffs, buflen);
738738

739739
ret = -EINVAL;
740740
goto exit_unlock;
741741
}
742742

743-
if ((resplen + respoffs) > buflen) {
744-
/* Device would have returned more data if buffer would
745-
* have been big enough. Copy just the bits that we got.
746-
*/
747-
copylen = buflen - respoffs;
748-
} else {
749-
copylen = resplen;
750-
}
743+
copylen = min(resplen, buflen - respoffs);
751744

752745
if (copylen > *len)
753746
copylen = *len;

0 commit comments

Comments
 (0)