This looks like the wrong place to fix things - if this case is hit, don't we go on to call usb_eq_queue() which can't be valid if the gadget has been destroyed?
I don't see how cdev->gadget can be set to null without cdev being freed so is this actually a use-after-free not a simple null-dereference?
My guess is that somehow the gadget is being destroyed while the network interface is held open (we've seen similar issues in other, non-network, gadget functions), but I don't know enough about the network side of things to know how to cause that from userspace.
I'm still waiting on confirmation of whether this fixes things. So far we've seen it crash twice without the fix...
I don't know what triggers it - it's being triggered in some huge automated test framework. Whether the issue is lack of bind, or a too early gadget unbind... or something else...
As mentioned in the patch, I'm not entirely sure if this is the right fix... I certainly don't claim to understand the usb/gadget stack.
It does seem like usb_ep_queue() at least has some protections in place... though no idea if they're enough - and whether we'll hit a WARN_ON_ONCE now instead?
Honestly I don't even understand *why* we're sending out this speed notification out of ncm_close... (and if we do send speed notification of out ncm_close()... shouldn't it always just say speed 0?)