From nobody Fri Oct 2 05:30:26 2026 Received: from mail-pg1-f169.google.com (mail-pg1-f169.google.com [209.85.215.169]) (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 428B43C456F for ; Wed, 5 Aug 2026 04:13:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785903205; cv=none; b=PLFLHMoO4tiBf0BFCLoR/gGtqjVlCGvt0cAktrnOJ5hnkehvHFJDkok4mfmTn7eLuBkhtoyrxVLsSp68MWTe2MdAJsD1wDtIosB519XwwX8ro6QE7bzwSEbkFNReAdRAuIa+T28qtc2uLLNMk+4tzjseNyCQYMOk58n4KlN1r3o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785903205; c=relaxed/simple; bh=G6y86Bnl9pH5Yy5pJthkcZYErCAbB9k9Prmrewimk/c=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=PGgQEw/rjcbAn1cPdcE7c+M0k0b4o3IpzEkRRE3yy+ToE7kSL9yw8ckrMLKjtHdEBlVTqEPHT8EPJn7t4Dq4w2WD0rODNMurqQzaWk+E7Svxqxd7bAfNCcvX2Zppi5YgDwd0QDJBvRgeutBN0uuc7zjTavqvG31iIP0uNvq1VWs= 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=Yb18BwOX; arc=none smtp.client-ip=209.85.215.169 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="Yb18BwOX" Received: by mail-pg1-f169.google.com with SMTP id 41be03b00d2f7-c9e7391839cso491470a12.0 for ; Tue, 04 Aug 2026 21:13:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785903203; x=1786508003; 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=Z14pFBM+gRuEL1nL/itnWoFwr8ux+8wC7KVMIdZnv9w=; b=Yb18BwOXGe2DflIgpzVyEFNXpf6tJVkXD+1Ghepimlj6P9gqXQLUtr8yystahIdQPE 8PYivTb3f8L7gDw1I5VlINsvxQrIljFP9ivlJUXRZdqn3gZicyZtJjV0uzCvndoc7Nhs RBk6OjEhp/MjCOXfUFq5enGKPt44Cjz6SbVBfaUKKaOSjANiilFlpMcMqpwvtgmfqEve k4aBpokNdujuEw2M7HzzGMBM1LTEEqH0EpLlbqXenDor4z+fpY+xHcKtlgzTDoD9aXjo xq7hzxmgPXHsH6MTGowhjM+DI1HMRKMkhUM70IAnFJRdxSMccnYLRBbxDU2LL0gDZG56 WR7A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785903203; x=1786508003; 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=Z14pFBM+gRuEL1nL/itnWoFwr8ux+8wC7KVMIdZnv9w=; b=fe2mBbhKdneO3p33sERafYGFik8fA/R/0k4SEnSm5zLw61bXA3Nv/np66cHvHXfTvf FQcn1qEs7OzGRuInAnT2wQk2u59cLz3NDy5hkibgAfzQk7ORDHIeNzTL9GmAj1EIbbgf rjS77EpV3AGayv6dkjkMVIFfQi5DEzEbQk8vZAf2Rg7s2X9M8SS2kUOsc1q5pekR3Mju vuOgWSxCQ5mS4YB2i/yvamN3HYFWCIdqIMQhtlVi2wS1iyJHujlL54eQ2LFiWMHHmDL6 ed3RRBxmxJko2QBU1AtaYP09oUMaSQddGgkJhJmkj/R3JijBGNw9+/nRGQv2Cojc/XuP JU4Q== X-Forwarded-Encrypted: i=1; AHgh+RofY1zAp/RNjHEchv/qC9wgAvZHYt0nHCB22kqK8789xSvxO/UHZ+iQ4GMUBm1IJHQOm1m1oZf48yYxS6Y=@vger.kernel.org X-Gm-Message-State: AOJu0YzzO/PweyYDYovU7gCcLktjvsoWOuokOSDPxg/sjB/yTEXruzIK L8jcG24wv85vqtXar9ePBaKBva/Vh3UvXc/4Ip/NG57bjwDuO4dQfvvY X-Gm-Gg: AR+sD11XCm+TqfAonX5Lxo3Ls088j9x/nFPHgkd0EHwE2b0Sc9yFJQTXPc1tfy8SOze STVdWDOXgmFW9cta6GYoCu3c3G04VcpglJVG76PxmN5Q3+ulklGHMw2x71aJVOW9NQ5ZgGUwaV5 jnwGnr14Pl7P+sqOCovgtkc/4ktaMHkBRys+CHSzqYdY94vPQlVTar439I0MqJjEn0ZQf795Tqq f3bgFbw594x98huIA8vMuCyNPOfBNa5wyBYEEdIc93ZJOyezbsmodNXNa4lRx+96PC0PTDrZY6S ZO77BJiUfEFD3pOIwiI2R7HGODi+/Mkyv+Fk2XvBvqtrDiyyMGgL9d9Car3wJWjZO2OU70XAhk4 JTb533A2OzZt4NOK8VZeRFbRaqzu73457Yn4Ny/CKG/X+5wfLwoOM7NZoFtQxl+Cc5Vcrc/PML2 yq/cBbyvGtb69SniJJq+o64/EWjQ2SbtsFYFvJcSotN6ClSTjieGv/OevrslsY5Dwfz4+r1oD+X U9WMd6+qsyTIA== X-Received: by 2002:a05:6a21:3294:b0:39c:126c:93b5 with SMTP id adf61e73a8af0-3cb85e5402emr3945302637.21.1785903203521; Tue, 04 Aug 2026 21:13:23 -0700 (PDT) Received: from ML-GYSUBT565.ECARX.COM.CN ([101.47.164.95]) by smtp.gmail.com with ESMTPSA id a92af1059eb24-13fca908068sm8238608c88.12.2026.08.04.21.13.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 04 Aug 2026 21:13:23 -0700 (PDT) From: Nguyen Quang Le Kien To: gregkh@linuxfoundation.org Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Nguyen Quang Le Kien , syzbot+098999e05b6b877c01b3@syzkaller.appspotmail.com Subject: [PATCH v3] usb: gadget: f_phonet: fix use-after-free in pn_bind Date: Wed, 5 Aug 2026 12:13:19 +0800 Message-Id: <20260805041319.3197126-1-khiemtranzo532001@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260804074432.2906951-1-khiemtranzo532001@gmail.com> References: <20260804074432.2906951-1-khiemtranzo532001@gmail.com> 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 old "no race condition" comment was wrong - configfs_rmdir() can run in parallel with the composite bind path. Add a mutex to f_phonet_opts, use scoped_guard(mutex) in both paths, add kernel-doc on the struct, 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 --- v3: drop the redundant #include in f_phonet.c - u_phonet.h already includes it. v2: scoped_guard(mutex) instead of open-coded lock/unlock; kernel-doc on the struct; mutex_destroy(); remove the wrong comment. --- drivers/usb/gadget/function/f_phonet.c | 33 +++++++++++++------------- drivers/usb/gadget/function/u_phonet.h | 10 ++++++++ 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/drivers/usb/gadget/function/f_phonet.c b/drivers/usb/gadget/fu= nction/f_phonet.c index b1ee9a7c2..e14ee91a8 100644 --- a/drivers/usb/gadget/function/f_phonet.c +++ b/drivers/usb/gadget/function/f_phonet.c @@ -499,19 +499,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 +616,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 +634,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