[PATCH] net: usbnet: Fix potential NULL pointer dereference

Ren Mingshuai posted 1 patch 2 years, 2 months ago
drivers/net/usb/usbnet.c | 5 +++++
1 file changed, 5 insertions(+)
[PATCH] net: usbnet: Fix potential NULL pointer dereference
Posted by Ren Mingshuai 2 years, 2 months ago
23ba07991dad said SKB can be NULL without describing the triggering
scenario. Always Check it before dereference to void potential NULL
pointer dereference.
Fix smatch warning:
drivers/net/usb/usbnet.c:1380 usbnet_start_xmit() error: we previously assumed 'skb' could be null (see line 1359)

Signed-off-by: Ren Mingshuai <renmingshuai@huawei.com>
---
 drivers/net/usb/usbnet.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 64a9a80b2309..386cb1a4ff03 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1374,6 +1374,11 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
 		}
 	}
 
+	if (!skb) {
+		netif_dbg(dev, tx_err, dev->net, "tx skb is NULL\n");
+		goto drop;
+	}
+
 	if (!(urb = usb_alloc_urb (0, GFP_ATOMIC))) {
 		netif_dbg(dev, tx_err, dev->net, "no urb\n");
 		goto drop;
-- 
2.33.0
Re: [PATCH] net: usbnet: Fix potential NULL pointer dereference
Posted by Ren Mingshuai 2 years, 2 months ago
>23ba07991dad said SKB can be NULL without describing the triggering
>scenario. Always Check it before dereference to void potential NULL
>pointer dereference.
I've tried to find out the scenarios where SKB is NULL, but failed.
It seems impossible for SKB to be NULL. If SKB can be NULL, please tell
me the reason and I'd be very grateful.

>Fix smatch warning:
>drivers/net/usb/usbnet.c:1380 usbnet_start_xmit() error: we previously assumed 'skb' could be null (see line 1359)
>
>Signed-off-by: Ren Mingshuai <renmingshuai@huawei.com>
>---
> drivers/net/usb/usbnet.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
>diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
>index 64a9a80b2309..386cb1a4ff03 100644
>--- a/drivers/net/usb/usbnet.c
>+++ b/drivers/net/usb/usbnet.c
>@@ -1374,6 +1374,11 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
>                }
>        }
>
>+       if (!skb) {
>+               netif_dbg(dev, tx_err, dev->net, "tx skb is NULL\n");
>+               goto drop;
>+       }
>+
>        if (!(urb = usb_alloc_urb (0, GFP_ATOMIC))) {
>                netif_dbg(dev, tx_err, dev->net, "no urb\n");
>                goto drop;
>--
>2.33.0
Re: [PATCH] net: usbnet: Fix potential NULL pointer dereference
Posted by Jakub Kicinski 2 years, 1 month ago
On Wed, 1 Nov 2023 20:55:11 +0800 Ren Mingshuai wrote:
> >23ba07991dad said SKB can be NULL without describing the triggering
> >scenario. Always Check it before dereference to void potential NULL
> >pointer dereference.  
> I've tried to find out the scenarios where SKB is NULL, but failed.
> It seems impossible for SKB to be NULL. If SKB can be NULL, please tell
> me the reason and I'd be very grateful.

What do you mean? Grepping the function name shows call sites with NULL
getting passed as skb.
Re: [PATCH] net: usbnet: Fix potential NULL pointer dereference
Posted by Ren Mingshuai 2 years, 1 month ago
>> >23ba07991dad said SKB can be NULL without describing the triggering 
>> >scenario. Always Check it before dereference to void potential NULL 
>> >pointer dereference.
>> I've tried to find out the scenarios where SKB is NULL, but failed.
>> It seems impossible for SKB to be NULL. If SKB can be NULL, please 
>> tell me the reason and I'd be very grateful.
>
>What do you mean? Grepping the function name shows call sites with NULL getting passed as skb.

Yes And I just learned that during the cdc_ncm_driver.probe, it is possible to pass a NULL SKB to usbnet_start_xmit().
Re: [PATCH] net: usbnet: Fix potential NULL pointer dereference
Posted by Oliver Neukum 2 years, 1 month ago
On 02.11.23 10:06, Ren Mingshuai wrote:

>> What do you mean? Grepping the function name shows call sites with NULL getting passed as skb.

You may see that we do check skb != NULL before we timestamp it.
But later in the process we depend skb == NULL implying that tx_fixup != NULL

That is the combination that must not happen. If it happens, though
simply bailing out seems to the wrong answer.
  
> Yes And I just learned that during the cdc_ncm_driver.probe, it is possible to pass a NULL SKB to usbnet_start_xmit().

How can that happen? And if it happens is tx_fixup set?

	Regards
		Oliver
Re: [PATCH] net: usbnet: Fix potential NULL pointer dereference
Posted by Oliver Neukum 2 years, 1 month ago

On 02.11.23 10:06, Ren Mingshuai wrote:
>>>> 23ba07991dad said SKB can be NULL without describing the triggering
>>>> scenario. Always Check it before dereference to void potential NULL
>>>> pointer dereference.
>>> I've tried to find out the scenarios where SKB is NULL, but failed.
>>> It seems impossible for SKB to be NULL. If SKB can be NULL, please
>>> tell me the reason and I'd be very grateful.
>>
>> What do you mean? Grepping the function name shows call sites with NULL getting passed as skb.
> 
> Yes And I just learned that during the cdc_ncm_driver.probe, it is possible to pass a NULL SKB to usbnet_start_xmit().

Hi,

yes it looks like NCM does funky things, but what does that mean?

ndp_to_end_store()

         /* flush pending data before changing flag */
         netif_tx_lock_bh(dev->net);
         usbnet_start_xmit(NULL, dev->net);
         spin_lock_bh(&ctx->mtx);
         if (enable)

expects some odd semantics from it. The proposed patch simply
increases the drop counter, which is by itself questionable, as
we drop nothing.

But it definitely does no IO, so we flush nothing.
That is, we clearly have bug(s) but the patch only papers over
them.
And frankly, the basic question needs to be answered:
Are you allowed to call ndo_start_xmit() with a NULL skb?

My understanding until now was that you must not.

	Regards
		Oliver
Re: [PATCH] net: usbnet: Fix potential NULL pointer dereference
Posted by Bjørn Mork 2 years, 1 month ago
Oliver Neukum <oneukum@suse.com> writes:

> yes it looks like NCM does funky things, but what does that mean?
>
> ndp_to_end_store()
>
>         /* flush pending data before changing flag */
>         netif_tx_lock_bh(dev->net);
>         usbnet_start_xmit(NULL, dev->net);
>         spin_lock_bh(&ctx->mtx);
>         if (enable)
>
> expects some odd semantics from it. The proposed patch simply
> increases the drop counter, which is by itself questionable, as
> we drop nothing.
>
> But it definitely does no IO, so we flush nothing.
> That is, we clearly have bug(s) but the patch only papers over
> them.
> And frankly, the basic question needs to be answered:
> Are you allowed to call ndo_start_xmit() with a NULL skb?
>
> My understanding until now was that you must not.

Yuck.  I see that I'm to blame for that code, so I've tried to figure
out what the idea behind it could possibly have been.

I believe that code is based on the (safe?) assumption that the struct
usbnet driver_info->tx_fixup points to cdc_ncm_tx_fixup().  And
cdc_ncm_tx_fixup does lots of weird stuff, including special handling of
NULL skb. It might return a valid skb for further processing by
usbnet_start_xmit().  If it doesn't, then we jump straight to
"not_drop", like we do when cdc_ncm_tx_fixup decides to eat the passed
skb.

But "funky" is i precise description of all this...  If someone feels
like it, then all that open coded skb queing inside cdc_ncm should be
completely rewritten.



Bjørn
Re: [PATCH] net: usbnet: Fix potential NULL pointer dereference
Posted by Oliver Neukum 2 years, 1 month ago
On 06.11.23 11:55, Bjørn Mork wrote:

> I believe that code is based on the (safe?) assumption that the struct
> usbnet driver_info->tx_fixup points to cdc_ncm_tx_fixup().  And

That seems to be a correct assumption, but one that is far from obvious.
Could you add a big, fat comment?

> cdc_ncm_tx_fixup does lots of weird stuff, including special handling of
> NULL skb. It might return a valid skb for further processing by
> usbnet_start_xmit().  If it doesn't, then we jump straight to
> "not_drop", like we do when cdc_ncm_tx_fixup decides to eat the passed
> skb.
> 
> But "funky" is i precise description of all this...  If someone feels
> like it, then all that open coded skb queing inside cdc_ncm should be
> completely rewritten.

I understand what you mean, but I need a generic answer. Can you call
ndo_start_xmit() with skb == NULL?

	Regards
		Oliver