On Thu, Apr 14, 2022 at 10:12:23PM +0800, Wang Cheng wrote:
> Due to the case that "requesttype == 0x01 && status <= 0"
> isn't handled in r8712_usbctrl_vendorreq(),
> "data" (drivers/staging/rtl8712/usb_ops.c:32)
> will be returned without initialization.
>
> When "tmpU1b" (drivers/staging/rtl8712/usb_intf.c:395)
> is 0, mac[6] (usb_intf.c:394) won't be initialized,
> which leads to accessing uninit-value on usb_intf.c:541.
These line numbers are sort of useless because everyone is on a
different git hash.
>
> Reported-and-tested-by: [email protected]
> Signed-off-by: Wang Cheng <[email protected]>
> ---
> drivers/staging/rtl8712/usb_intf.c | 6 +++---
> drivers/staging/rtl8712/usb_ops_linux.c | 14 ++++++++------
> 2 files changed, 11 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c
> index ee4c61f85a07..50dcd3ecb685 100644
> --- a/drivers/staging/rtl8712/usb_intf.c
> +++ b/drivers/staging/rtl8712/usb_intf.c
> @@ -538,13 +538,13 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf,
> } else {
> AutoloadFail = false;
> }
> - if (((mac[0] == 0xff) && (mac[1] == 0xff) &&
> + if ((!AutoloadFail) ||
> + ((mac[0] == 0xff) && (mac[1] == 0xff) &&
> (mac[2] == 0xff) && (mac[3] == 0xff) &&
> (mac[4] == 0xff) && (mac[5] == 0xff)) ||
> ((mac[0] == 0x00) && (mac[1] == 0x00) &&
> (mac[2] == 0x00) && (mac[3] == 0x00) &&
> - (mac[4] == 0x00) && (mac[5] == 0x00)) ||
> - (!AutoloadFail)) {
> + (mac[4] == 0x00) && (mac[5] == 0x00))) {
> mac[0] = 0x00;
> mac[1] = 0xe0;
> mac[2] = 0x4c;
This is a separate fix from the rest of the patch. Send it by itself.
> diff --git a/drivers/staging/rtl8712/usb_ops_linux.c b/drivers/staging/rtl8712/usb_ops_linux.c
> index f984a5ab2c6f..e321ca4453ca 100644
> --- a/drivers/staging/rtl8712/usb_ops_linux.c
> +++ b/drivers/staging/rtl8712/usb_ops_linux.c
> @@ -495,12 +495,14 @@ int r8712_usbctrl_vendorreq(struct intf_priv *pintfpriv, u8 request, u16 value,
> }
> status = usb_control_msg(udev, pipe, request, reqtype, value, index,
> pIo_buf, len, 500);
> - if (status > 0) { /* Success this control transfer. */
> - if (requesttype == 0x01) {
> - /* For Control read transfer, we have to copy the read
> - * data from pIo_buf to pdata.
> - */
> - memcpy(pdata, pIo_buf, status);
> + /* For Control read transfer, copy the read data from pIo_buf to pdata
> + * when control transfer success; otherwise init *pdata with 0.
> + */
> + if (requesttype == 0x01) {
> + if (status > 0)
> + memcpy(pdata, pIo_buf, status);
> + else
> + *(u32 *)pdata = 0;
> }
This isn't really correct. In many cases status is "len" is less than 4.
I'm slightly surprised that nothing complains about that as an
uninitialized access. But then another problem is that "status" can be
less than "len".
A better fix instead of setting pdata to zero would be to add error
checking in the callers and then change this code to use
usb_control_msg_send/recv(). Probably just initialize "data" in the
callers as well.
regards,
dan carpenter
On Thu, Apr 14, 2022 at 06:42:15PM +0300, Dan Carpenter wrote:
> > diff --git a/drivers/staging/rtl8712/usb_ops_linux.c b/drivers/staging/rtl8712/usb_ops_linux.c
> > index f984a5ab2c6f..e321ca4453ca 100644
> > --- a/drivers/staging/rtl8712/usb_ops_linux.c
> > +++ b/drivers/staging/rtl8712/usb_ops_linux.c
> > @@ -495,12 +495,14 @@ int r8712_usbctrl_vendorreq(struct intf_priv *pintfpriv, u8 request, u16 value,
> > }
> > status = usb_control_msg(udev, pipe, request, reqtype, value, index,
> > pIo_buf, len, 500);
> > - if (status > 0) { /* Success this control transfer. */
> > - if (requesttype == 0x01) {
> > - /* For Control read transfer, we have to copy the read
> > - * data from pIo_buf to pdata.
> > - */
> > - memcpy(pdata, pIo_buf, status);
> > + /* For Control read transfer, copy the read data from pIo_buf to pdata
> > + * when control transfer success; otherwise init *pdata with 0.
> > + */
> > + if (requesttype == 0x01) {
> > + if (status > 0)
> > + memcpy(pdata, pIo_buf, status);
> > + else
> > + *(u32 *)pdata = 0;
> > }
>
> This isn't really correct. In many cases status is "len" is less than 4.
> I'm slightly surprised that nothing complains about that as an
> uninitialized access. But then another problem is that "status" can be
> less than "len".
>
> A better fix instead of setting pdata to zero would be to add error
> checking in the callers and then change this code to use
> usb_control_msg_send/recv(). Probably just initialize "data" in the
> callers as well.
A different, less good option would be to, still add error handling in
the callers, but do:
status = usb_control_msg();
if (status < 0)
goto free;
if (status != len) {
status = -EREMOTEIO;
goto free;
}
if (requesttype == 0x01)
memcpy(pdata, pIo_buf, status);
status = 0;
free:
kfree(palloc_buf);
return status;
regards,
dan carpenter
Hi Dan, thx for your review.
On 22/04/14 06:42PM, Dan Carpenter wrote:
> On Thu, Apr 14, 2022 at 10:12:23PM +0800, Wang Cheng wrote:
> > Due to the case that "requesttype == 0x01 && status <= 0"
> > isn't handled in r8712_usbctrl_vendorreq(),
> > "data" (drivers/staging/rtl8712/usb_ops.c:32)
> > will be returned without initialization.
> >
> > When "tmpU1b" (drivers/staging/rtl8712/usb_intf.c:395)
> > is 0, mac[6] (usb_intf.c:394) won't be initialized,
> > which leads to accessing uninit-value on usb_intf.c:541.
>
> These line numbers are sort of useless because everyone is on a
> different git hash.
I will correct this.
>
> >
> > Reported-and-tested-by: [email protected]
> > Signed-off-by: Wang Cheng <[email protected]>
> > ---
> > drivers/staging/rtl8712/usb_intf.c | 6 +++---
> > drivers/staging/rtl8712/usb_ops_linux.c | 14 ++++++++------
> > 2 files changed, 11 insertions(+), 9 deletions(-)
> >
> > diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c
> > index ee4c61f85a07..50dcd3ecb685 100644
> > --- a/drivers/staging/rtl8712/usb_intf.c
> > +++ b/drivers/staging/rtl8712/usb_intf.c
> > @@ -538,13 +538,13 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf,
> > } else {
> > AutoloadFail = false;
> > }
> > - if (((mac[0] == 0xff) && (mac[1] == 0xff) &&
> > + if ((!AutoloadFail) ||
> > + ((mac[0] == 0xff) && (mac[1] == 0xff) &&
> > (mac[2] == 0xff) && (mac[3] == 0xff) &&
> > (mac[4] == 0xff) && (mac[5] == 0xff)) ||
> > ((mac[0] == 0x00) && (mac[1] == 0x00) &&
> > (mac[2] == 0x00) && (mac[3] == 0x00) &&
> > - (mac[4] == 0x00) && (mac[5] == 0x00)) ||
> > - (!AutoloadFail)) {
> > + (mac[4] == 0x00) && (mac[5] == 0x00))) {
> > mac[0] = 0x00;
> > mac[1] = 0xe0;
> > mac[2] = 0x4c;
>
> This is a separate fix from the rest of the patch. Send it by itself.
Ah, thought to send a patch series.
>
>
> > diff --git a/drivers/staging/rtl8712/usb_ops_linux.c b/drivers/staging/rtl8712/usb_ops_linux.c
> > index f984a5ab2c6f..e321ca4453ca 100644
> > --- a/drivers/staging/rtl8712/usb_ops_linux.c
> > +++ b/drivers/staging/rtl8712/usb_ops_linux.c
> > @@ -495,12 +495,14 @@ int r8712_usbctrl_vendorreq(struct intf_priv *pintfpriv, u8 request, u16 value,
> > }
> > status = usb_control_msg(udev, pipe, request, reqtype, value, index,
> > pIo_buf, len, 500);
> > - if (status > 0) { /* Success this control transfer. */
> > - if (requesttype == 0x01) {
> > - /* For Control read transfer, we have to copy the read
> > - * data from pIo_buf to pdata.
> > - */
> > - memcpy(pdata, pIo_buf, status);
> > + /* For Control read transfer, copy the read data from pIo_buf to pdata
> > + * when control transfer success; otherwise init *pdata with 0.
> > + */
> > + if (requesttype == 0x01) {
> > + if (status > 0)
> > + memcpy(pdata, pIo_buf, status);
> > + else
> > + *(u32 *)pdata = 0;
> > }
>
> This isn't really correct. In many cases status is "len" is less than 4.
> I'm slightly surprised that nothing complains about that as an
> uninitialized access. But then another problem is that "status" can be
> less than "len".
Sorry, I should explain it clearly. If I did right, watching "status"
with gdb while running syzkaller reproducer, "status" returns from
usb_control_msg() is -71. In which case, *pdata won't be touched in
r8712_usbctrl_vendorreq(). As a result, "data" in
usb_read8()/usb_read16()/usb_read32() will be returned without
initialization. I think that is why kmsan reports:
Local variable data created at:
usb_read8+0x5d/0x130 drivers/staging/rtl8712/usb_ops.c:33
r8712_read8+0xa5/0xd0 drivers/staging/rtl8712/rtl8712_io.c:29
>
> A better fix instead of setting pdata to zero would be to add error
> checking in the callers and then change this code to use
> usb_control_msg_send/recv(). Probably just initialize "data" in the
> callers as well.
I tried something similar which also works fine, but I think this patch
does't fix it at root.
https://syzkaller.appspot.com/text?tag=Patch&x=15be2970f00000
>
> regards,
> dan carpenter
>
thanks,
-- w