usb: f_gsi: Fix the error path in gsi_update_function_bind_params
Currently if usb_ep_autoconfig fails, we go ahead and free the requests and buffers even before allocation this. This can lead to potential kernel panics. Prevent this by fixing the failure path in gsi_update_function_bind_params(). While at it, introduce a new function gsi_assign_string_ids() to reduce the cyclomatic complexity. Change-Id: I545be5db3d3bec0e13e29a7854ba6dff210936e2 Signed-off-by: Prashanth K <quic_prashk@quicinc.com> Signed-off-by: Udipto Goswami <quic_ugoswami@quicinc.com>
This commit is contained in:
parent
49626d70d0
commit
c62967c152
1 changed files with 27 additions and 10 deletions
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022,2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
|
@ -2652,13 +2652,11 @@ static int gsi_func_suspend(struct usb_function *f, u8 options)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int gsi_update_function_bind_params(struct f_gsi *gsi,
|
||||
|
||||
static int gsi_assign_string_ids(struct f_gsi *gsi,
|
||||
struct usb_composite_dev *cdev,
|
||||
struct gsi_function_bind_info *info)
|
||||
{
|
||||
struct usb_ep *ep;
|
||||
struct usb_cdc_notification *event;
|
||||
struct usb_function *f = &gsi->function;
|
||||
int status;
|
||||
|
||||
if (info->ctrl_str_idx >= 0 && info->ctrl_desc) {
|
||||
|
|
@ -2714,6 +2712,23 @@ static int gsi_update_function_bind_params(struct f_gsi *gsi,
|
|||
if (info->data_nop_desc)
|
||||
info->data_nop_desc->bInterfaceNumber = gsi->data_id;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int gsi_update_function_bind_params(struct f_gsi *gsi,
|
||||
struct usb_composite_dev *cdev,
|
||||
struct gsi_function_bind_info *info)
|
||||
{
|
||||
struct usb_ep *ep;
|
||||
struct usb_cdc_notification *event;
|
||||
struct usb_function *f = &gsi->function;
|
||||
int status;
|
||||
|
||||
status = gsi_assign_string_ids(gsi, cdev, info);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
/* allocate instance-specific endpoints */
|
||||
if (info->fs_in_desc) {
|
||||
ep = usb_ep_autoconfig(cdev->gadget, info->fs_in_desc);
|
||||
|
|
@ -2748,7 +2763,7 @@ static int gsi_update_function_bind_params(struct f_gsi *gsi,
|
|||
gsi->c_port.notify_req->buf =
|
||||
kmalloc(info->notify_buf_len, GFP_KERNEL);
|
||||
if (!gsi->c_port.notify_req->buf)
|
||||
goto fail;
|
||||
goto free_req;
|
||||
|
||||
gsi->c_port.notify_req->length = info->notify_buf_len;
|
||||
gsi->c_port.notify_req->context = gsi;
|
||||
|
|
@ -2801,15 +2816,17 @@ static int gsi_update_function_bind_params(struct f_gsi *gsi,
|
|||
status = usb_assign_descriptors(f, info->fs_desc_hdr, info->hs_desc_hdr,
|
||||
info->ss_desc_hdr, info->ss_desc_hdr);
|
||||
if (status)
|
||||
goto fail;
|
||||
goto free_req_buf;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (gsi->c_port.notify_req) {
|
||||
free_req_buf:
|
||||
if (gsi->c_port.notify_req && gsi->c_port.notify_req->buf)
|
||||
kfree(gsi->c_port.notify_req->buf);
|
||||
free_req:
|
||||
if (gsi->c_port.notify_req)
|
||||
usb_ep_free_request(gsi->c_port.notify, gsi->c_port.notify_req);
|
||||
}
|
||||
fail:
|
||||
/* we might as well release our claims on endpoints */
|
||||
if (gsi->c_port.notify)
|
||||
gsi->c_port.notify->driver_data = NULL;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue