From nobody Fri Oct 2 06:58:33 2026 Received: from mail-pj1-f54.google.com (mail-pj1-f54.google.com [209.85.216.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7E444423EBA for ; Tue, 4 Aug 2026 07:44:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785829479; cv=none; b=GOtIaLX2uX1rIARhQ4oorXzzMSRZFQifYKxqJ2zz6+EUOGGmSRFPIPLw4O1jRo525u54wAzfen6G2jkwS7CaXa9f3WnVihE5Oyf4SM7nxzGlcAgq4ufLvCFnWZYahpZZE8HEGe2ffzrLhNEohBi8iUz/K9k/gkvUKIws19AorrM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785829479; c=relaxed/simple; bh=esbXX7i5X1gADRKgX80SvnOuJl3IXoEgbmVlwa26+zo=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=DfxO9CfFTDi0A9B7V2SkWR5beI+1HtWmPsspeE1o1JAiW7Ksua6FOfcjaHJmTT99eAMc8HJdNfqn+k6c8bwNaIEhuM1a5On+BSS4KQOHuUkQ5+dXo4HKoQpt5CB3bVzDJgmLy9g9iqHEPQeBkeDwFnVsPzYjj5BCsODIhfNlHoU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=IaW/p7we; arc=none smtp.client-ip=209.85.216.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="IaW/p7we" Received: by mail-pj1-f54.google.com with SMTP id 98e67ed59e1d1-381c51fde6bso4643121a91.2 for ; Tue, 04 Aug 2026 00:44:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785829478; x=1786434278; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=fTXWfWyOkl0xOSzBDPDeUohi0rPwGKQbDvqXhmbLPPY=; b=IaW/p7weYGjHBq/tWkQ/mIHB52uyAHr6yBNjEOXIKMnrIUqbyWCYPdA+PuMu4BBeyE btBhmslahSKRiLdxk9A/i/bJ6TTWqrSU9fqzxDvvtkNNrqlrly8UUteYv6m7nntkGSlu kRyZ+dqCYvUMVEEeXbYDYvqmvNxGxPRsfBshHVUpJCEhrmHLE/2WdWPlIEnTMv2v0kwm nAl0MlfpNBczMsuenTGNo+ZV9m+RFQAzT9ak6oJr3R7SDid6K+Qa/ZxxYIiIXFQc4UxI 6lWAQOo1ofD23ybsdwmpmRCKM2KfX0vPiFkvFnrZHaDjCHDj0Rpt1fNFrEjZWclRBi/g A/lw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785829478; x=1786434278; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=fTXWfWyOkl0xOSzBDPDeUohi0rPwGKQbDvqXhmbLPPY=; b=DUse7V0McvT3Hb5JjrFIrU1W2a8yIx+N9yWkKWISuxTLSv/v7HXkhwv7UTdNQe37pl N1Iwx8bayd3pY1TrPceCH99ahWGgQz4TzKUkUmyxRq0AddwdlSeC73TXxq/9kEkokqcr eJ28WJaVHlp/aXsRyZW+pQSiQc2DlUJzr7zuqburfy4abcBBTChxn7lQ6ijuvZythT6F F88JKzP5MwhT8wA/SnXD7MCr215o/SStvvcyAhGLz8Fgx4hB2QnyS5eTKXumCA5sUTEo MnLmgtrJ6rWNVRxQ/NFgz2VsRDYO78hMCx7Gu5pcYtobNww5DUKvjtvkDssVTFt7GPZ0 KRaA== X-Forwarded-Encrypted: i=1; AHgh+Rpiduu0G4v0CiHEuV6z4QwGYyJIQh3SemzkcSqu/tcFqEtkzoFxnH8okFSAVpfeRgU33nUu1xkYX6CGsGM=@vger.kernel.org X-Gm-Message-State: AOJu0YyPH3KkkGRj/Sbziy5H/Pewtxtxm3M4VEVTea3Cdo6VYSyBlYvC PfH7KTW4DVAAi2BkDEtPUlUlkUIn24Oa4rMsrEi6FvdlrjDnZRQSABKghTyt4dfOSIY= X-Gm-Gg: AR+sD13hajzj0qH51D3kqOQnNFoPsLcyEO6bwxfxRKRR/GO+HuV4RZnQKTHfjJ8VmSS m08mWXgX6tyzBUPn16VNKo3eAXwrfboSiwJQsIMCAOH5/uDXdo+T5WuWSNKJKfjKVdUdxDtwOWt 2ETEdD4ea1R9a6ZTfPpB7KjV4DBvGhduz6vVsD/8+bXV6826G1bX+KDHtdbYKUxYTABs7bcdk09 m9TVavn3J2e+1KBwc1lC3eSlFFqUxXwewtFnTaaQ6JzYa34epnlKY1a+gOWEgOLOoYDBYru3H0X 0lalGp/PVulxhXstI+PCg/uLhJbl1BCItunaWjJWJS2bGLXgVaAQPPkFlpnrIO1LeNn1sUD8aPH /vNP8siiyNZht6riX+3j9AFiIgGVwTX8BemhE7XHF3UjXwLFuMwU0DNMgBfYgbdaKXv64PeHPrb 0Ee3vM0047NL7FNS0dsrZc6dIQuNvCrguJRx904CxnQEd4BRf2+2NLuZVos910jID4cZO4MgbDJ pa7TMy2dY6X7g== X-Received: by 2002:a17:90b:48c9:b0:382:5c31:1f8a with SMTP id 98e67ed59e1d1-38fbc511c3emr11893259a91.27.1785829477748; Tue, 04 Aug 2026 00:44:37 -0700 (PDT) Received: from ML-GYSUBT565.ECARX.COM.CN ([101.47.164.95]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-38fb2b551b9sm2985830a91.2.2026.08.04.00.44.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 04 Aug 2026 00:44:37 -0700 (PDT) From: Nguyen Quang Le Kien To: gregkh@linuxfoundation.org Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, syzbot+098999e05b6b877c01b3@syzkaller.appspotmail.com, Nguyen Quang Le Kien Subject: [PATCH v2] usb: gadget: f_phonet: fix use-after-free in pn_bind Date: Tue, 4 Aug 2026 15:44:32 +0800 Message-Id: <20260804074432.2906951-1-khiemtranzo532001@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <2026080431-paragraph-caloric-0aae@gregkh> References: <2026080431-paragraph-caloric-0aae@gregkh> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" pn_bind() and phonet_free_inst() race on opts->bound and opts->net. If configfs removes the function instance while pn_bind() is between the !bound check and setting bound =3D true, free_inst() frees opts->net and pn_bind() then writes to net->dev.parent via gphonet_set_gadget(). The existing "no race condition" comment was wrong: configfs_rmdir() can run independently of the composite bind sequence. Add a mutex to f_phonet_opts and use scoped_guard(mutex) in both pn_bind() and phonet_free_inst() to serialize access to ->bound and ->net. Add a kernel-doc comment describing what the lock protects, and destroy the mutex before freeing opts. Fixes: 00a2430ff07d ("usb: gadget: Gadget directory cleanup - group usb fun= ctions") Reported-by: syzbot+098999e05b6b877c01b3@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=3D098999e05b6b877c01b3 Signed-off-by: Nguyen Quang Le Kien --- v2: - use scoped_guard(mutex) instead of open-coded lock/unlock - add kernel-doc comment on struct f_phonet_opts describing what @lock protects - add explicit #include - call mutex_destroy() before kfree(opts) - remove stale "no race condition" comment; explain why it was wrong in the commit message --- drivers/usb/gadget/function/f_phonet.c | 34 +++++++++++++------------- drivers/usb/gadget/function/u_phonet.h | 10 ++++++++ 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/drivers/usb/gadget/function/f_phonet.c b/drivers/usb/gadget/fu= nction/f_phonet.c index b1ee9a7c2..350579747 100644 --- a/drivers/usb/gadget/function/f_phonet.c +++ b/drivers/usb/gadget/function/f_phonet.c @@ -12,6 +12,7 @@ #include #include #include +#include =20 #include #include @@ -499,19 +500,14 @@ static int pn_bind(struct usb_configuration *c, struc= t usb_function *f) =20 phonet_opts =3D container_of(f->fi, struct f_phonet_opts, func_inst); =20 - /* - * in drivers/usb/gadget/configfs.c:configfs_composite_bind() - * configurations are bound in sequence with list_for_each_entry, - * in each configuration its functions are bound in sequence - * with list_for_each_entry, so we assume no race condition - * with regard to phonet_opts->bound access - */ - if (!phonet_opts->bound) { - gphonet_set_gadget(phonet_opts->net, gadget); - status =3D gphonet_register_netdev(phonet_opts->net); - if (status) - return status; - phonet_opts->bound =3D true; + scoped_guard(mutex, &phonet_opts->lock) { + if (!phonet_opts->bound) { + gphonet_set_gadget(phonet_opts->net, gadget); + status =3D gphonet_register_netdev(phonet_opts->net); + if (status) + return status; + phonet_opts->bound =3D true; + } } =20 /* Reserve interface IDs */ @@ -621,10 +617,13 @@ static void phonet_free_inst(struct usb_function_inst= ance *f) struct f_phonet_opts *opts; =20 opts =3D container_of(f, struct f_phonet_opts, func_inst); - if (opts->bound) - gphonet_cleanup(opts->net); - else - free_netdev(opts->net); + scoped_guard(mutex, &opts->lock) { + if (opts->bound) + gphonet_cleanup(opts->net); + else + free_netdev(opts->net); + } + mutex_destroy(&opts->lock); kfree(opts); } =20 @@ -636,6 +635,7 @@ static struct usb_function_instance *phonet_alloc_inst(= void) if (!opts) return ERR_PTR(-ENOMEM); =20 + mutex_init(&opts->lock); opts->func_inst.free_func_inst =3D phonet_free_inst; opts->net =3D gphonet_setup_default(); if (IS_ERR(opts->net)) { diff --git a/drivers/usb/gadget/function/u_phonet.h b/drivers/usb/gadget/fu= nction/u_phonet.h index ff62ca22c..54fadfe64 100644 --- a/drivers/usb/gadget/function/u_phonet.h +++ b/drivers/usb/gadget/function/u_phonet.h @@ -8,11 +8,21 @@ #ifndef __U_PHONET_H #define __U_PHONET_H =20 +#include #include #include =20 +/** + * struct f_phonet_opts - Phonet function instance options + * @func_inst: USB function instance + * @lock: protects @bound and @net against concurrent access from + * pn_bind() vs phonet_free_inst() during configfs teardown + * @bound: true once pn_bind() has successfully registered @net + * @net: net_device owned by this function instance + */ struct f_phonet_opts { struct usb_function_instance func_inst; + struct mutex lock; bool bound; struct net_device *net; }; --=20 2.34.1