[PATCH RFC] usb: legacy: ncm: Fix potential NPE in gncm_bind

From: Kuen-Han Tsai

Date: Sat Feb 14 2026 - 02:01:14 EST


Commit 56a512a9b410 ("usb: gadget: f_ncm: align net_device lifecycle
with bind/unbind") deferred the allocation of the net_device. This
change can lead to a NULL pointer dereference in the legacy NCM driver
as it attempts to access the net_device before it's fully initialized.

Store the provided qmult, host_addr, and dev_addr into the struct
ncm_opts->net_opts during gncm_bind(). These values will be properly
applied to the net_device when it is allocated and configured later in
the binding process by the NCM function driver.

Fixes: 56a512a9b410 ("usb: gadget: f_ncm: align net_device lifecycle with bind/unbind")
Cc: stable@xxxxxxxxxx
Signed-off-by: Kuen-Han Tsai <khtsai@xxxxxxxxxx>
---
Hi Greg,

I have been working on a series of changes to align the net_device
lifecycle with the bind/unbind process across various USB gadget
function drivers. The goal is to solve the long-standing "lifetime
mismatch" problem where the network interface could outlive its parent
gadget device, leading to dangling symbolic links.

Recently, Commit 56a512a9b410 ("usb: gadget: f_ncm: align net_device
lifecycle with bind/unbind") was accepted to address this for the NCM
driver. However, during the process of adapting this same architecture
to f_subset, f_eem, f_ecm, and f_rndis, I discovered that this approach
regresses the legacy NCM driver (g_ncm).

Specifically, the legacy driver attempts to access the net_device during
its own binding process before the NCM function driver has been fully
bound. This can result in a NULL pointer dereference.

I am submitting the following patch as a fix for the g_ncm regression by
caching the configuration (qmult, host_addr, dev_addr) in opts_net until
the network device is ready. Please note that while I have verified the
logic and ensured the code builds, I do not have the physical hardware
required to perform a full functional test with the legacy g_ncm driver.

Beyond this specific fix, I would like to request the guidance on how to
proceed with the remaining network function drivers:

1. Deprecation: Can we consider the legacy drivers obsolete? If so,
we could prioritize the lifecycle fix for the configfs framework.

2. Compatibility: Should we continue to adapt the lifecycle concept to
all drivers while strictly maintaining backward compatibility for
legacy function drivers?

I would appreciate your feedback on the preferred direction before I
proceed with the patchsets for the other USB function drivers.
---
drivers/usb/gadget/legacy/ncm.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/gadget/legacy/ncm.c b/drivers/usb/gadget/legacy/ncm.c
index 0f1b45e3abd1a1ead7b2776be10a2a5747960136..bf00f9d76a5323b298869b4210c5bf99b1ab7f9c 100644
--- a/drivers/usb/gadget/legacy/ncm.c
+++ b/drivers/usb/gadget/legacy/ncm.c
@@ -15,8 +15,10 @@
/* #define DEBUG */
/* #define VERBOSE_DEBUG */

+#include <linux/hex.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/string.h>
#include <linux/usb/composite.h>

#include "u_ether.h"
@@ -129,6 +131,7 @@ static int gncm_bind(struct usb_composite_dev *cdev)
struct usb_gadget *gadget = cdev->gadget;
struct f_ncm_opts *ncm_opts;
int status;
+ u8 mac[ETH_ALEN];

f_ncm_inst = usb_get_function_instance("ncm");
if (IS_ERR(f_ncm_inst))
@@ -136,11 +139,15 @@ static int gncm_bind(struct usb_composite_dev *cdev)

ncm_opts = container_of(f_ncm_inst, struct f_ncm_opts, func_inst);

- gether_set_qmult(ncm_opts->net, qmult);
- if (!gether_set_host_addr(ncm_opts->net, host_addr))
+ ncm_opts->net_opts.qmult = qmult;
+ if (mac_pton(host_addr, mac)) {
+ memcpy(&ncm_opts->net_opts.host_mac, mac, ETH_ALEN);
pr_info("using host ethernet address: %s", host_addr);
- if (!gether_set_dev_addr(ncm_opts->net, dev_addr))
+ }
+ if (mac_pton(dev_addr, mac)) {
+ memcpy(&ncm_opts->net_opts.dev_mac, mac, ETH_ALEN);
pr_info("using self ethernet address: %s", dev_addr);
+ }

/* Allocate string descriptor numbers ... note that string
* contents can be overridden by the composite_dev glue.

---
base-commit: da87d45b195148d670ab995367d52aa9e8a9a1fa
change-id: 20260214-legacy-ncm-8c001295b343

Best regards,
--
Kuen-Han Tsai <khtsai@xxxxxxxxxx>