lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Tue, 10 Jan 2023 11:39:17 -0800
From:   Alexander H Duyck <alexander.duyck@...il.com>
To:     Szymon Heidrich <szymon.heidrich@...il.com>, kvalo@...nel.org,
        jussi.kivilinna@....fi, davem@...emloft.net
Cc:     edumazet@...gle.com, kuba@...nel.org, pabeni@...hat.com,
        linux-wireless@...r.kernel.org, netdev@...r.kernel.org,
        linux-kernel@...r.kernel.org
Subject: Re: [PATCH] rndis_wlan: Prevent buffer overflow in rndis_query_oid

On Tue, 2023-01-10 at 18:30 +0100, Szymon Heidrich 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@...il.com>
> ---
>  drivers/net/wireless/rndis_wlan.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
> index 82a7458e0..d7fc05328 100644
> --- a/drivers/net/wireless/rndis_wlan.c
> +++ b/drivers/net/wireless/rndis_wlan.c
> @@ -697,7 +697,7 @@ static int rndis_query_oid(struct usbnet *dev, u32 oid, void *data, int *len)
>  		struct rndis_query_c	*get_c;
>  	} u;
>  	int ret, buflen;
> -	int resplen, respoffs, copylen;
> +	u32 resplen, respoffs, copylen;

Rather than a u32 why not just make it an size_t? The advantage is that
is the native type for all the memory allocation and copying that takes
place in the function so it would avoid having to cast between u32 and
size_t.

Also why not move buflen over to the unsigned integer category with the
other values you stated were at risk of overflow?

>  
>  	buflen = *len + sizeof(*u.get);
>  	if (buflen < CONTROL_BUFFER_SIZE)

For example, this line here is comparing buflen to a fixed constant. If
we are concerned about overflows this could be triggering an integer
overflow resulting in truncation assuming *len is close to the roll-
over threshold.

By converting to a size_t we would most likely end up blowing up on the
kmalloc and instead returning an -ENOMEM.

> @@ -740,7 +740,7 @@ static int rndis_query_oid(struct usbnet *dev, u32 oid, void *data, int *len)

Also with any type change such as this I believe you would also need to
update the netdev_dbg statement that displays respoffs and the like to
account for the fact that you are now using an unsigned value.
Otherwise I believe %d will display the value as a signed integer
value.

>  			goto exit_unlock;
>  		}
>  
> -		if ((resplen + respoffs) > buflen) {
> +		if (resplen > (buflen - respoffs)) {
>  			/* Device would have returned more data if buffer would
>  			 * have been big enough. Copy just the bits that we got.
>  			 */

Actually you should be able to simplfy this further. Assuming resplen,
buflen and respoffs all the same type this entire if statement could be
broken down into:
		copylen = min(resplen, buflen - respoffs);


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ