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