From patchwork Mon Mar 22 21:11:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Shevchenko X-Patchwork-Id: 12156223 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.9 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B77EFC433DB for ; Mon, 22 Mar 2021 21:12:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7C09261924 for ; Mon, 22 Mar 2021 21:12:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230439AbhCVVMO (ORCPT ); Mon, 22 Mar 2021 17:12:14 -0400 Received: from mga05.intel.com ([192.55.52.43]:18052 "EHLO mga05.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229526AbhCVVLn (ORCPT ); Mon, 22 Mar 2021 17:11:43 -0400 IronPort-SDR: 10jgB+8kIi30/1/1FwYYe2yWT3sWIJKQsRq9O2IZF5FuopBxusU9MN4L4qI0hc0fcuKEBYEp7V l0LiuXl7rWnQ== X-IronPort-AV: E=McAfee;i="6000,8403,9931"; a="275450701" X-IronPort-AV: E=Sophos;i="5.81,269,1610438400"; d="scan'208";a="275450701" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Mar 2021 14:11:43 -0700 IronPort-SDR: 8Fe0dVdtS7ZdHq4akg4ZfIPAaIDyOFMlySbFM+g0Ui2U4RlNVLgK3KRFu7CE8DKF9X1ZZgwZXA WIsUBMhx38fw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.81,269,1610438400"; d="scan'208";a="592752295" Received: from black.fi.intel.com ([10.237.72.28]) by orsmga005.jf.intel.com with ESMTP; 22 Mar 2021 14:11:41 -0700 Received: by black.fi.intel.com (Postfix, from userid 1003) id 35590E7; Mon, 22 Mar 2021 23:11:55 +0200 (EET) From: Andy Shevchenko To: Andy Shevchenko , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Felipe Balbi , Greg Kroah-Hartman , Linus Walleij Subject: [PATCH v1 2/6] usb: gardet: pch_udc: Check if driver is present before calling ->setup() Date: Mon, 22 Mar 2021 23:11:45 +0200 Message-Id: <20210322211149.6658-2-andriy.shevchenko@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210322211149.6658-1-andriy.shevchenko@linux.intel.com> References: <20210322211149.6658-1-andriy.shevchenko@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Since we have a separate routine for VBUS sense, the interrupt may occur before gadget driver is present. Hence, ->setup() call may oops the kernel: [ 55.245843] BUG: kernel NULL pointer dereference, address: 00000010 ... [ 55.245843] EIP: pch_udc_isr.cold+0x162/0x33f ... [ 55.245843] [ 55.245843] ? pch_udc_svc_data_out+0x160/0x160 Check if driver is present before calling ->setup(). Fixes: f646cf94520e ("USB device driver of Topcliff PCH") Signed-off-by: Andy Shevchenko --- drivers/usb/gadget/udc/pch_udc.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/drivers/usb/gadget/udc/pch_udc.c b/drivers/usb/gadget/udc/pch_udc.c index 2e2dca391007..5bb83a2705ad 100644 --- a/drivers/usb/gadget/udc/pch_udc.c +++ b/drivers/usb/gadget/udc/pch_udc.c @@ -2298,6 +2298,21 @@ static void pch_udc_svc_data_out(struct pch_udc_dev *dev, int ep_num) pch_udc_set_dma(dev, DMA_DIR_RX); } +static int pch_udc_gadget_setup(struct pch_udc_dev *dev) + __must_hold(&dev->lock) +{ + int rc; + + /* In some cases we can get an interrupt before driver gets setup */ + if (!dev->driver) + return -ESHUTDOWN; + + spin_unlock(&dev->lock); + rc = dev->driver->setup(&dev->gadget, &dev->setup_data); + spin_lock(&dev->lock); + return rc; +} + /** * pch_udc_svc_control_in() - Handle Control IN endpoint interrupts * @dev: Reference to the device structure @@ -2369,15 +2384,12 @@ static void pch_udc_svc_control_out(struct pch_udc_dev *dev) dev->gadget.ep0 = &dev->ep[UDC_EP0IN_IDX].ep; else /* OUT */ dev->gadget.ep0 = &ep->ep; - spin_lock(&dev->lock); /* If Mass storage Reset */ if ((dev->setup_data.bRequestType == 0x21) && (dev->setup_data.bRequest == 0xFF)) dev->prot_stall = 0; /* call gadget with setup data received */ - setup_supported = dev->driver->setup(&dev->gadget, - &dev->setup_data); - spin_unlock(&dev->lock); + setup_supported = pch_udc_gadget_setup(dev); if (dev->setup_data.bRequestType & USB_DIR_IN) { ep->td_data->status = (ep->td_data->status & @@ -2625,9 +2637,7 @@ static void pch_udc_svc_intf_interrupt(struct pch_udc_dev *dev) dev->ep[i].halted = 0; } dev->stall = 0; - spin_unlock(&dev->lock); - dev->driver->setup(&dev->gadget, &dev->setup_data); - spin_lock(&dev->lock); + pch_udc_gadget_setup(dev); } /** @@ -2662,9 +2672,7 @@ static void pch_udc_svc_cfg_interrupt(struct pch_udc_dev *dev) dev->stall = 0; /* call gadget zero with setup data received */ - spin_unlock(&dev->lock); - dev->driver->setup(&dev->gadget, &dev->setup_data); - spin_lock(&dev->lock); + pch_udc_gadget_setup(dev); } /**