]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.17-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 20 Oct 2025 08:46:55 +0000 (10:46 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 20 Oct 2025 08:46:55 +0000 (10:46 +0200)
added patches:
usb-gadget-f_acm-refactor-bind-path-to-use-__free.patch
usb-gadget-f_ecm-refactor-bind-path-to-use-__free.patch
usb-gadget-f_ncm-refactor-bind-path-to-use-__free.patch

queue-6.17/series
queue-6.17/usb-gadget-f_acm-refactor-bind-path-to-use-__free.patch [new file with mode: 0644]
queue-6.17/usb-gadget-f_ecm-refactor-bind-path-to-use-__free.patch [new file with mode: 0644]
queue-6.17/usb-gadget-f_ncm-refactor-bind-path-to-use-__free.patch [new file with mode: 0644]

index df69ba3bf1267e6f06837b8d5cd4da0dc50ca4b3..2204bc893e0ce71cb62c395bc475a6d6c6f250a9 100644 (file)
@@ -51,3 +51,6 @@ media-nxp-imx8-isi-m2m-fix-streaming-cleanup-on-release.patch
 usb-gadget-store-endpoint-pointer-in-usb_request.patch
 usb-gadget-introduce-free_usb_request-helper.patch
 usb-gadget-f_rndis-refactor-bind-path-to-use-__free.patch
+usb-gadget-f_acm-refactor-bind-path-to-use-__free.patch
+usb-gadget-f_ecm-refactor-bind-path-to-use-__free.patch
+usb-gadget-f_ncm-refactor-bind-path-to-use-__free.patch
diff --git a/queue-6.17/usb-gadget-f_acm-refactor-bind-path-to-use-__free.patch b/queue-6.17/usb-gadget-f_acm-refactor-bind-path-to-use-__free.patch
new file mode 100644 (file)
index 0000000..3d693cb
--- /dev/null
@@ -0,0 +1,173 @@
+From stable+bounces-187738-greg=kroah.com@vger.kernel.org Sat Oct 18 02:17:57 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Oct 2025 20:17:48 -0400
+Subject: usb: gadget: f_acm: Refactor bind path to use __free()
+To: stable@vger.kernel.org
+Cc: Kuen-Han Tsai <khtsai@google.com>, stable@kernel.org, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251018001748.76008-3-sashal@kernel.org>
+
+From: Kuen-Han Tsai <khtsai@google.com>
+
+[ Upstream commit 47b2116e54b4a854600341487e8b55249e926324 ]
+
+After an bind/unbind cycle, the acm->notify_req is left stale. If a
+subsequent bind fails, the unified error label attempts to free this
+stale request, leading to a NULL pointer dereference when accessing
+ep->ops->free_request.
+
+Refactor the error handling in the bind path to use the __free()
+automatic cleanup mechanism.
+
+Unable to handle kernel NULL pointer dereference at virtual address 0000000000000020
+Call trace:
+ usb_ep_free_request+0x2c/0xec
+ gs_free_req+0x30/0x44
+ acm_bind+0x1b8/0x1f4
+ usb_add_function+0xcc/0x1f0
+ configfs_composite_bind+0x468/0x588
+ gadget_bind_driver+0x104/0x270
+ really_probe+0x190/0x374
+ __driver_probe_device+0xa0/0x12c
+ driver_probe_device+0x3c/0x218
+ __device_attach_driver+0x14c/0x188
+ bus_for_each_drv+0x10c/0x168
+ __device_attach+0xfc/0x198
+ device_initial_probe+0x14/0x24
+ bus_probe_device+0x94/0x11c
+ device_add+0x268/0x48c
+ usb_add_gadget+0x198/0x28c
+ dwc3_gadget_init+0x700/0x858
+ __dwc3_set_mode+0x3cc/0x664
+ process_scheduled_works+0x1d8/0x488
+ worker_thread+0x244/0x334
+ kthread+0x114/0x1bc
+ ret_from_fork+0x10/0x20
+
+Fixes: 1f1ba11b6494 ("usb gadget: issue notifications from ACM function")
+Cc: stable@kernel.org
+Signed-off-by: Kuen-Han Tsai <khtsai@google.com>
+Link: https://lore.kernel.org/r/20250916-ready-v1-4-4997bf277548@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Link: https://lore.kernel.org/r/20250916-ready-v1-4-4997bf277548@google.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/function/f_acm.c |   42 ++++++++++++++++--------------------
+ 1 file changed, 19 insertions(+), 23 deletions(-)
+
+--- a/drivers/usb/gadget/function/f_acm.c
++++ b/drivers/usb/gadget/function/f_acm.c
+@@ -11,12 +11,15 @@
+ /* #define VERBOSE_DEBUG */
++#include <linux/cleanup.h>
+ #include <linux/slab.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/device.h>
+ #include <linux/err.h>
++#include <linux/usb/gadget.h>
++
+ #include "u_serial.h"
+@@ -613,6 +616,7 @@ acm_bind(struct usb_configuration *c, st
+       struct usb_string       *us;
+       int                     status;
+       struct usb_ep           *ep;
++      struct usb_request      *request __free(free_usb_request) = NULL;
+       /* REVISIT might want instance-specific strings to help
+        * distinguish instances ...
+@@ -630,7 +634,7 @@ acm_bind(struct usb_configuration *c, st
+       /* allocate instance-specific interface IDs, and patch descriptors */
+       status = usb_interface_id(c, f);
+       if (status < 0)
+-              goto fail;
++              return status;
+       acm->ctrl_id = status;
+       acm_iad_descriptor.bFirstInterface = status;
+@@ -639,43 +643,41 @@ acm_bind(struct usb_configuration *c, st
+       status = usb_interface_id(c, f);
+       if (status < 0)
+-              goto fail;
++              return status;
+       acm->data_id = status;
+       acm_data_interface_desc.bInterfaceNumber = status;
+       acm_union_desc.bSlaveInterface0 = status;
+       acm_call_mgmt_descriptor.bDataInterface = status;
+-      status = -ENODEV;
+-
+       /* allocate instance-specific endpoints */
+       ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_in_desc);
+       if (!ep)
+-              goto fail;
++              return -ENODEV;
+       acm->port.in = ep;
+       ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_out_desc);
+       if (!ep)
+-              goto fail;
++              return -ENODEV;
+       acm->port.out = ep;
+       ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_notify_desc);
+       if (!ep)
+-              goto fail;
++              return -ENODEV;
+       acm->notify = ep;
+       acm_iad_descriptor.bFunctionProtocol = acm->bInterfaceProtocol;
+       acm_control_interface_desc.bInterfaceProtocol = acm->bInterfaceProtocol;
+       /* allocate notification */
+-      acm->notify_req = gs_alloc_req(ep,
+-                      sizeof(struct usb_cdc_notification) + 2,
+-                      GFP_KERNEL);
+-      if (!acm->notify_req)
+-              goto fail;
++      request = gs_alloc_req(ep,
++                             sizeof(struct usb_cdc_notification) + 2,
++                             GFP_KERNEL);
++      if (!request)
++              return -ENODEV;
+-      acm->notify_req->complete = acm_cdc_notify_complete;
+-      acm->notify_req->context = acm;
++      request->complete = acm_cdc_notify_complete;
++      request->context = acm;
+       /* support all relevant hardware speeds... we expect that when
+        * hardware is dual speed, all bulk-capable endpoints work at
+@@ -692,7 +694,9 @@ acm_bind(struct usb_configuration *c, st
+       status = usb_assign_descriptors(f, acm_fs_function, acm_hs_function,
+                       acm_ss_function, acm_ss_function);
+       if (status)
+-              goto fail;
++              return status;
++
++      acm->notify_req = no_free_ptr(request);
+       dev_dbg(&cdev->gadget->dev,
+               "acm ttyGS%d: IN/%s OUT/%s NOTIFY/%s\n",
+@@ -700,14 +704,6 @@ acm_bind(struct usb_configuration *c, st
+               acm->port.in->name, acm->port.out->name,
+               acm->notify->name);
+       return 0;
+-
+-fail:
+-      if (acm->notify_req)
+-              gs_free_req(acm->notify, acm->notify_req);
+-
+-      ERROR(cdev, "%s/%p: can't bind, err %d\n", f->name, f, status);
+-
+-      return status;
+ }
+ static void acm_unbind(struct usb_configuration *c, struct usb_function *f)
diff --git a/queue-6.17/usb-gadget-f_ecm-refactor-bind-path-to-use-__free.patch b/queue-6.17/usb-gadget-f_ecm-refactor-bind-path-to-use-__free.patch
new file mode 100644 (file)
index 0000000..94eb6fc
--- /dev/null
@@ -0,0 +1,158 @@
+From sashal@kernel.org Sat Oct 18 02:45:33 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Oct 2025 20:45:26 -0400
+Subject: usb: gadget: f_ecm: Refactor bind path to use __free()
+To: stable@vger.kernel.org
+Cc: Kuen-Han Tsai <khtsai@google.com>, stable@kernel.org, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251018004526.94714-3-sashal@kernel.org>
+
+From: Kuen-Han Tsai <khtsai@google.com>
+
+[ Upstream commit 42988380ac67c76bb9dff8f77d7ef3eefd50b7b5 ]
+
+After an bind/unbind cycle, the ecm->notify_req is left stale. If a
+subsequent bind fails, the unified error label attempts to free this
+stale request, leading to a NULL pointer dereference when accessing
+ep->ops->free_request.
+
+Refactor the error handling in the bind path to use the __free()
+automatic cleanup mechanism.
+
+Fixes: da741b8c56d6 ("usb ethernet gadget: split CDC Ethernet function")
+Cc: stable@kernel.org
+Signed-off-by: Kuen-Han Tsai <khtsai@google.com>
+Link: https://lore.kernel.org/r/20250916-ready-v1-5-4997bf277548@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Link: https://lore.kernel.org/r/20250916-ready-v1-5-4997bf277548@google.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/function/f_ecm.c |   48 +++++++++++++++---------------------
+ 1 file changed, 20 insertions(+), 28 deletions(-)
+
+--- a/drivers/usb/gadget/function/f_ecm.c
++++ b/drivers/usb/gadget/function/f_ecm.c
+@@ -8,6 +8,7 @@
+ /* #define VERBOSE_DEBUG */
++#include <linux/cleanup.h>
+ #include <linux/slab.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+@@ -15,6 +16,8 @@
+ #include <linux/etherdevice.h>
+ #include <linux/string_choices.h>
++#include <linux/usb/gadget.h>
++
+ #include "u_ether.h"
+ #include "u_ether_configfs.h"
+ #include "u_ecm.h"
+@@ -678,6 +681,7 @@ ecm_bind(struct usb_configuration *c, st
+       struct usb_ep           *ep;
+       struct f_ecm_opts       *ecm_opts;
++      struct usb_request      *request __free(free_usb_request) = NULL;
+       if (!can_support_ecm(cdev->gadget))
+               return -EINVAL;
+@@ -711,7 +715,7 @@ ecm_bind(struct usb_configuration *c, st
+       /* allocate instance-specific interface IDs */
+       status = usb_interface_id(c, f);
+       if (status < 0)
+-              goto fail;
++              return status;
+       ecm->ctrl_id = status;
+       ecm_iad_descriptor.bFirstInterface = status;
+@@ -720,24 +724,22 @@ ecm_bind(struct usb_configuration *c, st
+       status = usb_interface_id(c, f);
+       if (status < 0)
+-              goto fail;
++              return status;
+       ecm->data_id = status;
+       ecm_data_nop_intf.bInterfaceNumber = status;
+       ecm_data_intf.bInterfaceNumber = status;
+       ecm_union_desc.bSlaveInterface0 = status;
+-      status = -ENODEV;
+-
+       /* allocate instance-specific endpoints */
+       ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_in_desc);
+       if (!ep)
+-              goto fail;
++              return -ENODEV;
+       ecm->port.in_ep = ep;
+       ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_out_desc);
+       if (!ep)
+-              goto fail;
++              return -ENODEV;
+       ecm->port.out_ep = ep;
+       /* NOTE:  a status/notification endpoint is *OPTIONAL* but we
+@@ -746,20 +748,18 @@ ecm_bind(struct usb_configuration *c, st
+        */
+       ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_notify_desc);
+       if (!ep)
+-              goto fail;
++              return -ENODEV;
+       ecm->notify = ep;
+-      status = -ENOMEM;
+-
+       /* allocate notification request and buffer */
+-      ecm->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL);
+-      if (!ecm->notify_req)
+-              goto fail;
+-      ecm->notify_req->buf = kmalloc(ECM_STATUS_BYTECOUNT, GFP_KERNEL);
+-      if (!ecm->notify_req->buf)
+-              goto fail;
+-      ecm->notify_req->context = ecm;
+-      ecm->notify_req->complete = ecm_notify_complete;
++      request = usb_ep_alloc_request(ep, GFP_KERNEL);
++      if (!request)
++              return -ENOMEM;
++      request->buf = kmalloc(ECM_STATUS_BYTECOUNT, GFP_KERNEL);
++      if (!request->buf)
++              return -ENOMEM;
++      request->context = ecm;
++      request->complete = ecm_notify_complete;
+       /* support all relevant hardware speeds... we expect that when
+        * hardware is dual speed, all bulk-capable endpoints work at
+@@ -778,7 +778,7 @@ ecm_bind(struct usb_configuration *c, st
+       status = usb_assign_descriptors(f, ecm_fs_function, ecm_hs_function,
+                       ecm_ss_function, ecm_ss_function);
+       if (status)
+-              goto fail;
++              return status;
+       /* NOTE:  all that is done without knowing or caring about
+        * the network link ... which is unavailable to this code
+@@ -788,20 +788,12 @@ ecm_bind(struct usb_configuration *c, st
+       ecm->port.open = ecm_open;
+       ecm->port.close = ecm_close;
++      ecm->notify_req = no_free_ptr(request);
++
+       DBG(cdev, "CDC Ethernet: IN/%s OUT/%s NOTIFY/%s\n",
+                       ecm->port.in_ep->name, ecm->port.out_ep->name,
+                       ecm->notify->name);
+       return 0;
+-
+-fail:
+-      if (ecm->notify_req) {
+-              kfree(ecm->notify_req->buf);
+-              usb_ep_free_request(ecm->notify, ecm->notify_req);
+-      }
+-
+-      ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
+-
+-      return status;
+ }
+ static inline struct f_ecm_opts *to_f_ecm_opts(struct config_item *item)
diff --git a/queue-6.17/usb-gadget-f_ncm-refactor-bind-path-to-use-__free.patch b/queue-6.17/usb-gadget-f_ncm-refactor-bind-path-to-use-__free.patch
new file mode 100644 (file)
index 0000000..fb3e8a4
--- /dev/null
@@ -0,0 +1,230 @@
+From stable+bounces-187728-greg=kroah.com@vger.kernel.org Sat Oct 18 01:43:25 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Oct 2025 19:43:14 -0400
+Subject: usb: gadget: f_ncm: Refactor bind path to use __free()
+To: stable@vger.kernel.org
+Cc: Kuen-Han Tsai <khtsai@google.com>, stable@kernel.org, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251017234314.52983-3-sashal@kernel.org>
+
+From: Kuen-Han Tsai <khtsai@google.com>
+
+[ Upstream commit 75a5b8d4ddd4eb6b16cb0b475d14ff4ae64295ef ]
+
+After an bind/unbind cycle, the ncm->notify_req is left stale. If a
+subsequent bind fails, the unified error label attempts to free this
+stale request, leading to a NULL pointer dereference when accessing
+ep->ops->free_request.
+
+Refactor the error handling in the bind path to use the __free()
+automatic cleanup mechanism.
+
+Unable to handle kernel NULL pointer dereference at virtual address 0000000000000020
+Call trace:
+ usb_ep_free_request+0x2c/0xec
+ ncm_bind+0x39c/0x3dc
+ usb_add_function+0xcc/0x1f0
+ configfs_composite_bind+0x468/0x588
+ gadget_bind_driver+0x104/0x270
+ really_probe+0x190/0x374
+ __driver_probe_device+0xa0/0x12c
+ driver_probe_device+0x3c/0x218
+ __device_attach_driver+0x14c/0x188
+ bus_for_each_drv+0x10c/0x168
+ __device_attach+0xfc/0x198
+ device_initial_probe+0x14/0x24
+ bus_probe_device+0x94/0x11c
+ device_add+0x268/0x48c
+ usb_add_gadget+0x198/0x28c
+ dwc3_gadget_init+0x700/0x858
+ __dwc3_set_mode+0x3cc/0x664
+ process_scheduled_works+0x1d8/0x488
+ worker_thread+0x244/0x334
+ kthread+0x114/0x1bc
+ ret_from_fork+0x10/0x20
+
+Fixes: 9f6ce4240a2b ("usb: gadget: f_ncm.c added")
+Cc: stable@kernel.org
+Signed-off-by: Kuen-Han Tsai <khtsai@google.com>
+Link: https://lore.kernel.org/r/20250916-ready-v1-3-4997bf277548@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Link: https://lore.kernel.org/r/20250916-ready-v1-3-4997bf277548@google.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/function/f_ncm.c |   78 +++++++++++++++---------------------
+ 1 file changed, 33 insertions(+), 45 deletions(-)
+
+--- a/drivers/usb/gadget/function/f_ncm.c
++++ b/drivers/usb/gadget/function/f_ncm.c
+@@ -11,6 +11,7 @@
+  * Copyright (C) 2008 Nokia Corporation
+  */
++#include <linux/cleanup.h>
+ #include <linux/kernel.h>
+ #include <linux/interrupt.h>
+ #include <linux/module.h>
+@@ -20,6 +21,7 @@
+ #include <linux/string_choices.h>
+ #include <linux/usb/cdc.h>
++#include <linux/usb/gadget.h>
+ #include "u_ether.h"
+ #include "u_ether_configfs.h"
+@@ -1436,18 +1438,18 @@ static int ncm_bind(struct usb_configura
+       struct usb_ep           *ep;
+       struct f_ncm_opts       *ncm_opts;
++      struct usb_os_desc_table        *os_desc_table __free(kfree) = NULL;
++      struct usb_request              *request __free(free_usb_request) = NULL;
++
+       if (!can_support_ecm(cdev->gadget))
+               return -EINVAL;
+       ncm_opts = container_of(f->fi, struct f_ncm_opts, func_inst);
+       if (cdev->use_os_string) {
+-              f->os_desc_table = kzalloc(sizeof(*f->os_desc_table),
+-                                         GFP_KERNEL);
+-              if (!f->os_desc_table)
++              os_desc_table = kzalloc(sizeof(*os_desc_table), GFP_KERNEL);
++              if (!os_desc_table)
+                       return -ENOMEM;
+-              f->os_desc_n = 1;
+-              f->os_desc_table[0].os_desc = &ncm_opts->ncm_os_desc;
+       }
+       mutex_lock(&ncm_opts->lock);
+@@ -1459,16 +1461,15 @@ static int ncm_bind(struct usb_configura
+       mutex_unlock(&ncm_opts->lock);
+       if (status)
+-              goto fail;
++              return status;
+       ncm_opts->bound = true;
+       us = usb_gstrings_attach(cdev, ncm_strings,
+                                ARRAY_SIZE(ncm_string_defs));
+-      if (IS_ERR(us)) {
+-              status = PTR_ERR(us);
+-              goto fail;
+-      }
++      if (IS_ERR(us))
++              return PTR_ERR(us);
++
+       ncm_control_intf.iInterface = us[STRING_CTRL_IDX].id;
+       ncm_data_nop_intf.iInterface = us[STRING_DATA_IDX].id;
+       ncm_data_intf.iInterface = us[STRING_DATA_IDX].id;
+@@ -1478,20 +1479,16 @@ static int ncm_bind(struct usb_configura
+       /* allocate instance-specific interface IDs */
+       status = usb_interface_id(c, f);
+       if (status < 0)
+-              goto fail;
++              return status;
+       ncm->ctrl_id = status;
+       ncm_iad_desc.bFirstInterface = status;
+       ncm_control_intf.bInterfaceNumber = status;
+       ncm_union_desc.bMasterInterface0 = status;
+-      if (cdev->use_os_string)
+-              f->os_desc_table[0].if_id =
+-                      ncm_iad_desc.bFirstInterface;
+-
+       status = usb_interface_id(c, f);
+       if (status < 0)
+-              goto fail;
++              return status;
+       ncm->data_id = status;
+       ncm_data_nop_intf.bInterfaceNumber = status;
+@@ -1500,35 +1497,31 @@ static int ncm_bind(struct usb_configura
+       ecm_desc.wMaxSegmentSize = cpu_to_le16(ncm_opts->max_segment_size);
+-      status = -ENODEV;
+-
+       /* allocate instance-specific endpoints */
+       ep = usb_ep_autoconfig(cdev->gadget, &fs_ncm_in_desc);
+       if (!ep)
+-              goto fail;
++              return -ENODEV;
+       ncm->port.in_ep = ep;
+       ep = usb_ep_autoconfig(cdev->gadget, &fs_ncm_out_desc);
+       if (!ep)
+-              goto fail;
++              return -ENODEV;
+       ncm->port.out_ep = ep;
+       ep = usb_ep_autoconfig(cdev->gadget, &fs_ncm_notify_desc);
+       if (!ep)
+-              goto fail;
++              return -ENODEV;
+       ncm->notify = ep;
+-      status = -ENOMEM;
+-
+       /* allocate notification request and buffer */
+-      ncm->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL);
+-      if (!ncm->notify_req)
+-              goto fail;
+-      ncm->notify_req->buf = kmalloc(NCM_STATUS_BYTECOUNT, GFP_KERNEL);
+-      if (!ncm->notify_req->buf)
+-              goto fail;
+-      ncm->notify_req->context = ncm;
+-      ncm->notify_req->complete = ncm_notify_complete;
++      request = usb_ep_alloc_request(ep, GFP_KERNEL);
++      if (!request)
++              return -ENOMEM;
++      request->buf = kmalloc(NCM_STATUS_BYTECOUNT, GFP_KERNEL);
++      if (!request->buf)
++              return -ENOMEM;
++      request->context = ncm;
++      request->complete = ncm_notify_complete;
+       /*
+        * support all relevant hardware speeds... we expect that when
+@@ -1548,7 +1541,7 @@ static int ncm_bind(struct usb_configura
+       status = usb_assign_descriptors(f, ncm_fs_function, ncm_hs_function,
+                       ncm_ss_function, ncm_ss_function);
+       if (status)
+-              goto fail;
++              return status;
+       /*
+        * NOTE:  all that is done without knowing or caring about
+@@ -1561,23 +1554,18 @@ static int ncm_bind(struct usb_configura
+       hrtimer_setup(&ncm->task_timer, ncm_tx_timeout, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT);
++      if (cdev->use_os_string) {
++              os_desc_table[0].os_desc = &ncm_opts->ncm_os_desc;
++              os_desc_table[0].if_id = ncm_iad_desc.bFirstInterface;
++              f->os_desc_table = no_free_ptr(os_desc_table);
++              f->os_desc_n = 1;
++      }
++      ncm->notify_req = no_free_ptr(request);
++
+       DBG(cdev, "CDC Network: IN/%s OUT/%s NOTIFY/%s\n",
+                       ncm->port.in_ep->name, ncm->port.out_ep->name,
+                       ncm->notify->name);
+       return 0;
+-
+-fail:
+-      kfree(f->os_desc_table);
+-      f->os_desc_n = 0;
+-
+-      if (ncm->notify_req) {
+-              kfree(ncm->notify_req->buf);
+-              usb_ep_free_request(ncm->notify, ncm->notify_req);
+-      }
+-
+-      ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
+-
+-      return status;
+ }
+ static inline struct f_ncm_opts *to_f_ncm_opts(struct config_item *item)