2023-11-01 12:38:09

by Ren Mingshuai

[permalink] [raw]
Subject: [PATCH] net: usbnet: Fix potential NULL pointer dereference

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 <[email protected]>
---
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


2023-11-01 12:55:52

by Ren Mingshuai

[permalink] [raw]
Subject: Re: [PATCH] net: usbnet: Fix potential NULL pointer dereference

>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 <[email protected]>
>---
> 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

2023-11-02 04:38:43

by Jakub Kicinski

[permalink] [raw]
Subject: Re: [PATCH] net: usbnet: Fix potential NULL pointer dereference

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.

2023-11-02 09:25:35

by Ren Mingshuai

[permalink] [raw]
Subject: Re: [PATCH] net: usbnet: Fix potential NULL pointer dereference

>> >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().

2023-11-06 10:19:06

by Oliver Neukum

[permalink] [raw]
Subject: Re: [PATCH] net: usbnet: Fix potential NULL pointer dereference



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


2023-11-06 11:09:34

by Bjørn Mork

[permalink] [raw]
Subject: Re: [PATCH] net: usbnet: Fix potential NULL pointer dereference

Oliver Neukum <[email protected]> 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

2023-11-06 12:53:42

by Oliver Neukum

[permalink] [raw]
Subject: Re: [PATCH] net: usbnet: Fix potential NULL pointer dereference

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

2023-11-06 12:59:20

by Oliver Neukum

[permalink] [raw]
Subject: Re: [PATCH] net: usbnet: Fix potential NULL pointer dereference

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