From patchwork Thu Nov 17 12:08:13 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lee Jones X-Patchwork-Id: 21604 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp362783wrr; Thu, 17 Nov 2022 04:09:34 -0800 (PST) X-Google-Smtp-Source: AA0mqf7wEB7qnyGY6uV3gwsgIxCkWcSpJ/fi7ezU5TSGklQOCkLZVghvr92khHs1LDqPfJO2p5jh X-Received: by 2002:aa7:cb09:0:b0:463:ff10:4ff with SMTP id s9-20020aa7cb09000000b00463ff1004ffmr1923679edt.290.1668686974366; Thu, 17 Nov 2022 04:09:34 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1668686974; cv=none; d=google.com; s=arc-20160816; b=N1btzco5oXEiEN+do4LlkdBKQlLFw/JHMTV9mVcK4YFos+sgqt02nHJfSeheF1LR1U lXfsQnib5f60aYFzb2qCoee04A+SN1t4epsKxk/H8jtXwzoIplZHNnOORHoRhWb8YiC/ AjkcZ8I7Gc7mp0DETVkj+0rGqDEiApbpSik8s0KDxTRfxH+D5IBVU+gshV1oFZBMX2md +08KcuYqt7C+hA7rofDQax/vIdt7BvXidCciNM1JOgDAoxK49HABRqPqRYzecfsP4MqM f2loFYfGhEaCEmSm8m2WC3zfs4f2P3rIif2bqDKaFk8Wq3yTE+/mkTGR4HT1kLmKJJl5 zoXQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from:dkim-signature; bh=bLDmg3nraeIlizgHD0XSyJxhFbfpaoSiLJ3PNWRseds=; b=Ra2nGCBitGPAG1c84NrjJu+PPl9ZQMajqLAE5R6Buk1S950XWpKPY2jDPp5xyD3ztH MIsZ8hQzd5z9DHRVHvC2bC93j3lJJSwhSc1sG251BFzjw9IgcMM3T5E9uPg8CK4TYTZB uohBMAhESd8onGFf4Ks1tV93ViqbtoukXEXrR2wtgv0FEAUgIj68175z4c1/TXZbvtI/ Ds0uK8/7E/KaFlxBLvx/WPgf01zGFZPj4oetyLO5iXQAM99pFeIoWzqGJXJ7oxJpu8LK szk7fIKd0FZmrM4r0OEiqACD18BRObx+t8ngY4JOyosd6UuhYvPd62Gtcp4QsW6bAGyp dZwQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=WSjGOM+t; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id x10-20020a05640226ca00b0045fb7a04ce0si749639edd.148.2022.11.17.04.09.10; Thu, 17 Nov 2022 04:09:34 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=WSjGOM+t; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240143AbiKQMIr (ORCPT + 99 others); Thu, 17 Nov 2022 07:08:47 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38766 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240137AbiKQMIp (ORCPT ); Thu, 17 Nov 2022 07:08:45 -0500 Received: from sin.source.kernel.org (sin.source.kernel.org [IPv6:2604:1380:40e1:4800::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 44BA331FB3; Thu, 17 Nov 2022 04:08:42 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sin.source.kernel.org (Postfix) with ESMTPS id DE6DDCE1D56; Thu, 17 Nov 2022 12:08:38 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id D3620C433D6; Thu, 17 Nov 2022 12:08:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1668686917; bh=VGOY6CblI4x26pv4UpLJydIi/WK5ykAHqmG7x20RJnA=; h=From:To:Cc:Subject:Date:From; b=WSjGOM+trYZ/ytaSmAKqHRYxgzrz7ZJFduZdq+emlbiYqDbPmkV47wYHt99sPo25j Oui17QJrSjmWfp+VeWOz5pFWSYbRMKY/VkzJkpVYQfz3egkhmneZUigOO0KZjX1Mlx DSLe973bEgB15yKYA0CleBRQOU7hOc2SM1W9JZ1/+vNRhR9aCJKG2QHn+DrgP8UH3c UsGNdwq0HRdQLQ+D9T4bE1A2hJVt6H+R2l5FlpPlrebe0I73tTIP5ugn+U3slzNtw2 CfI2jB/6e0k+U7CcVrpIgVw0AI+9R9fYC0pS/NERqAiWEK/dSuYA2Pl6wi5gaF8F9a n2dbfpUjy625Q== From: Lee Jones To: lee@kernel.org, balbi@kernel.org, gregkh@linuxfoundation.org Cc: linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org Subject: [PATCH 1/1] usb: gadget: f_hid: Conduct proper refcounting on shared f_hidg pointer Date: Thu, 17 Nov 2022 12:08:13 +0000 Message-Id: <20221117120813.1257583-1-lee@kernel.org> X-Mailer: git-send-email 2.38.1.431.g37b22c650d-goog MIME-Version: 1.0 X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1749745112560066509?= X-GMAIL-MSGID: =?utf-8?q?1749745112560066509?= A reference to struct f_hidg is shared with this driver's associated character device handling component without provision for life-time handling. In some circumstances, this can lead to unwanted behaviour depending on the order in which things are torn down. Utilise, the reference counting functionality already provided by the implanted character device structure to ensure the struct f_hidg's memory is only freed once the character device handling has finished with it. Signed-off-by: Lee Jones Signed-off-by: John Keeping Signed-off-by: John Keeping --- drivers/usb/gadget/function/f_hid.c | 47 +++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c index ca0a7d9eaa34e..5da8f44d47d9d 100644 --- a/drivers/usb/gadget/function/f_hid.c +++ b/drivers/usb/gadget/function/f_hid.c @@ -77,6 +77,8 @@ struct f_hidg { struct usb_ep *in_ep; struct usb_ep *out_ep; + + bool gc; }; static inline struct f_hidg *func_to_hidg(struct usb_function *f) @@ -84,6 +86,11 @@ static inline struct f_hidg *func_to_hidg(struct usb_function *f) return container_of(f, struct f_hidg, func); } +static inline bool f_hidg_is_open(struct f_hidg *hidg) +{ + return !!kref_read(&hidg->cdev.kobj.kref); +} + /*-------------------------------------------------------------------------*/ /* Static descriptors */ @@ -273,6 +280,18 @@ static struct usb_gadget_strings *ct_func_strings[] = { NULL, }; +static void hidg_free_resources(struct f_hidg *hidg) +{ + struct f_hid_opts *opts = container_of(hidg->func.fi, struct f_hid_opts, func_inst); + + mutex_lock(&opts->lock); + kfree(hidg->report_desc); + kfree(hidg->set_report_buf); + kfree(hidg); + --opts->refcnt; + mutex_unlock(&opts->lock); +} + /*-------------------------------------------------------------------------*/ /* Char Device */ @@ -539,7 +558,16 @@ static __poll_t f_hidg_poll(struct file *file, poll_table *wait) static int f_hidg_release(struct inode *inode, struct file *fd) { + struct f_hidg *hidg = fd->private_data; + + if (hidg->gc) { + /* Gadget has already been disconnected and we are the last f_hidg user */ + cdev_del(&hidg->cdev); + hidg_free_resources(hidg); + } + fd->private_data = NULL; + return 0; } @@ -1239,17 +1267,16 @@ static struct usb_function_instance *hidg_alloc_inst(void) static void hidg_free(struct usb_function *f) { - struct f_hidg *hidg; - struct f_hid_opts *opts; + struct f_hidg *hidg = func_to_hidg(f); - hidg = func_to_hidg(f); - opts = container_of(f->fi, struct f_hid_opts, func_inst); - kfree(hidg->report_desc); - kfree(hidg->set_report_buf); - kfree(hidg); - mutex_lock(&opts->lock); - --opts->refcnt; - mutex_unlock(&opts->lock); + if (f_hidg_is_open(hidg)) + /* + * Gadget disconnected whilst an open dev node exists. + * Delay freeing resources until it closes. + */ + hidg->gc = true; + else + hidg_free_resources(hidg); } static void hidg_unbind(struct usb_configuration *c, struct usb_function *f)