diff mbox series

net: usbnet: Fix potential NULL pointer dereference

Message ID 20231101123559.210756-1-renmingshuai@huawei.com (mailing list archive)
State Changes Requested
Delegated to: Netdev Maintainers
Headers show
Series net: usbnet: Fix potential NULL pointer dereference | expand

Checks

Context Check Description
netdev/series_format warning Single patches do not need cover letters; Target tree name not specified in the subject
netdev/tree_selection success Guessed tree name to be net-next
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 1344 this patch: 1344
netdev/cc_maintainers warning 4 maintainers not CCed: edumazet@google.com kuba@kernel.org pabeni@redhat.com linux-usb@vger.kernel.org
netdev/build_clang success Errors and warnings before: 1369 this patch: 1369
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 1369 this patch: 1369
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 11 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

renmingshuai Nov. 1, 2023, 12:35 p.m. UTC
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(+)

Comments

renmingshuai Nov. 1, 2023, 12:55 p.m. UTC | #1
>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
Jakub Kicinski Nov. 2, 2023, 4:38 a.m. UTC | #2
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.
renmingshuai Nov. 2, 2023, 9:06 a.m. UTC | #3
>> >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().
Oliver Neukum Nov. 6, 2023, 10:18 a.m. UTC | #4
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
Bjørn Mork Nov. 6, 2023, 10:55 a.m. UTC | #5
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
Oliver Neukum Nov. 6, 2023, 12:53 p.m. UTC | #6
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
Oliver Neukum Nov. 6, 2023, 12:59 p.m. UTC | #7
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
diff mbox series

Patch

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;