On Wed, Jan 11, 2023 at 9:51 AM Szymon Heidrich <szymon.heidrich@xxxxxxxxx> wrote: > > 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: 80f8c5b434f9 ("rndis_wlan: copy only useful data from rndis_command respond") > Signed-off-by: Szymon Heidrich <szymon.heidrich@xxxxxxxxx> > --- > V1 -> V2: Use size_t and min macro, fix netdev_dbg format > > drivers/net/wireless/rndis_wlan.c | 19 ++++++------------- > 1 file changed, 6 insertions(+), 13 deletions(-) > > diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c > index 82a7458e0..bf72e5fd3 100644 > --- a/drivers/net/wireless/rndis_wlan.c > +++ b/drivers/net/wireless/rndis_wlan.c > @@ -696,8 +696,8 @@ static int rndis_query_oid(struct usbnet *dev, u32 oid, void *data, int *len) > struct rndis_query *get; > struct rndis_query_c *get_c; > } u; > - int ret, buflen; > - int resplen, respoffs, copylen; > + int ret; > + size_t buflen, resplen, respoffs, copylen; > > buflen = *len + sizeof(*u.get); > if (buflen < CONTROL_BUFFER_SIZE) > @@ -732,22 +732,15 @@ static int rndis_query_oid(struct usbnet *dev, u32 oid, void *data, int *len) > > if (respoffs > buflen) { > /* Device returned data offset outside buffer, error. */ > - netdev_dbg(dev->net, "%s(%s): received invalid " > - "data offset: %d > %d\n", __func__, > - oid_to_string(oid), respoffs, buflen); > + netdev_dbg(dev->net, > + "%s(%s): received invalid data offset: %zu > %zu\n", > + __func__, oid_to_string(oid), respoffs, buflen); > > ret = -EINVAL; > goto exit_unlock; > } > > - if ((resplen + respoffs) > buflen) { > - /* Device would have returned more data if buffer would > - * have been big enough. Copy just the bits that we got. > - */ > - copylen = buflen - respoffs; > - } else { > - copylen = resplen; > - } > + copylen = min(resplen, buflen - respoffs); > > if (copylen > *len) > copylen = *len; Looks good to me. Reviewed-by: Alexander Duyck <alexanderduyck@xxxxxx>