From nobody Fri Apr 17 07:44:39 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E81A8346763; Mon, 23 Feb 2026 06:17:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771827468; cv=none; b=juHKfuYvb3wriEFSK4K1uNHyU2aOKXpXorSuQjZTF2dEXZ3Kf/iQ7FL9d9QT+lbstMMzi4y58k0kHIjU0ilepL57n/0SWMUthUtb9TBLKv6LY9dh6hJlJ1+svjX2+n6wAVBEMqs21oiy17IjOYtzpzDLnj6bkzY347kiVwTIKEY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771827468; c=relaxed/simple; bh=POrU04cCpey+W4zQF5H63Ny+cH4s0q8KfDFXXNLfiJg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=K1CL8CfvJDcCujXX+TkKGeBoQBAoDg60/Smm5MGdlDzeKehq2Q4MbKqa9QmkPmJDjLLohjjLfuJTKdCDiyZFJms87A9d8WmHC3C/XTCkt4uBeqqA2jGFBtV1dDfYA48yL2eQjaYcYFU644Y2h1LYJlM0Z33ONdzmUNfZWcxC13o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ej/s1ACG; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ej/s1ACG" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 33F92C116C6; Mon, 23 Feb 2026 06:17:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771827467; bh=POrU04cCpey+W4zQF5H63Ny+cH4s0q8KfDFXXNLfiJg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ej/s1ACGInIOZCvEwGzR6CT10nq7F6Ne7gb0wn1cwXXJODddfaVOvUdDPhJ6GboRG LtA/7AKWgvw5OPS8YmrP96t+C6EGT63/DZQol4XU+yGTiSowwEXfV1Nht3m+mUbPyb HmGRehkEYUG0EB5buajV5Lq0fNOEJsm+B2EvIvHXicCeyU6qEBHArgQNyXVfU+B+yv XK79H1YoklsLa0eQNeFQvFtMROLc0jnTVRfiEcQvUDz094Y2Uz3U9skwhzWQU5Phzg 7u2yR8+WrGMCBEZBkpG9Y0IEsd5onUBelx4Fnkv1OZwspvxRXQeWbcW6XBLYGYMEPW K0VDgwBh7Ic0g== From: Tzung-Bi Shih To: Bartosz Golaszewski , Linus Walleij Cc: Shuah Khan , linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-kselftest@vger.kernel.org, tzungbi@kernel.org Subject: [PATCH v4 1/6] gpio: Access `gpio_bus_type` in gpiochip_setup_dev() Date: Mon, 23 Feb 2026 14:17:21 +0800 Message-ID: <20260223061726.82161-2-tzungbi@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260223061726.82161-1-tzungbi@kernel.org> References: <20260223061726.82161-1-tzungbi@kernel.org> 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" To make the intent clear, access `gpio_bus_type` only when it's ready in gpiochip_setup_dev(). Reviewed-by: Linus Walleij Signed-off-by: Tzung-Bi Shih --- v4: - Add R-b tag. v3: https://lore.kernel.org/all/20260213092958.864411-2-tzungbi@kernel.org - No changes. v2: https://lore.kernel.org/all/20260203061059.975605-2-tzungbi@kernel.org - No changes. v1: https://lore.kernel.org/all/20260116081036.352286-7-tzungbi@kernel.org drivers/gpio/gpiolib.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index f77d5121a8a8..0a73561060dd 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -901,6 +901,8 @@ static int gpiochip_setup_dev(struct gpio_device *gdev) struct fwnode_handle *fwnode =3D dev_fwnode(&gdev->dev); int ret; =20 + gdev->dev.bus =3D &gpio_bus_type; + /* * If fwnode doesn't belong to another device, it's safe to clear its * initialized flag. @@ -1082,7 +1084,6 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, = void *data, * then make sure they get free():ed there. */ gdev->dev.type =3D &gpio_dev_type; - gdev->dev.bus =3D &gpio_bus_type; gdev->dev.parent =3D gc->parent; device_set_node(&gdev->dev, gpiochip_choose_fwnode(gc)); =20 @@ -1220,8 +1221,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, = void *data, * we get a device node entry in sysfs under * /sys/bus/gpio/devices/gpiochipN/dev that can be used for * coldplug of device nodes and other udev business. - * We can do this only if gpiolib has been initialized. - * Otherwise, defer until later. + * We can do this only if gpiolib has been initialized + * (i.e., `gpio_bus_type` is ready). Otherwise, defer until later. */ if (gpiolib_initialized) { ret =3D gpiochip_setup_dev(gdev); --=20 2.51.0 From nobody Fri Apr 17 07:44:39 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B0435346A1F; Mon, 23 Feb 2026 06:17:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771827469; cv=none; b=U4kGtVM1aj+ogJFTIO8nYlq0YPtBK5L64NH7vp3sR400rxKraQGipA6Wq1M9a4OQ0xAnvitwfAsXhrcJabEWbjQetTpNRW3eqQzUqZ86OKNph+LiSkGAh5YSb8XNSlLGx3TaxotTm023qEby/WPR5p/TNaoL7ObYXO94/Ub6NO8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771827469; c=relaxed/simple; bh=BAPg3VOsJBISwCCY0+rT3CoAIrhM+BvyViRvuu7W41M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YarRGoN9Xuu2HXLStprJOBmmKg1AlGCuZ6YRYRiTAnj/TPtMz0zEDXlElWxGNzvpg+hKQDN+yZWSY+RrNWvtz4bPAla4U2VsCJIG6GqWx5Nm6nUJtFU+0zC+XIcXyIlsYgW2jgciO6myitcW4rnXHCUy7zQ0AO9N0OWRWj+J/Wg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=fLWjVfL2; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="fLWjVfL2" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EC5FEC19423; Mon, 23 Feb 2026 06:17:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771827469; bh=BAPg3VOsJBISwCCY0+rT3CoAIrhM+BvyViRvuu7W41M=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fLWjVfL2oFoybhC4KL+nSLOyvjUZjqoiTVG2iWuT3eOqL0Y1ehJlnAruQciQc4x0u XJB9I5UKWJSpQjFs+Y2q3gL4JqOk6T5VH+PqPPiO5KKp8F3AvWlETMBNlATapyUc0G E/cTovEGqNxAo6Kp4gpPCWKIk0s5tcAWTMB6n4hvSbywECA+Vx0N7vfnzIiBqESaEs vXT/ChRSUH8SPu5t/mgpmQ8Fmui/byvoUePu0RV8ayxL51uKuELNovUcsOCo02DmpV 8hbwTqsmg+JPmHs5JWLF0XE+Nxyb8OkHzBcVnG/H1xlSKX0nJZ8AJWT4WORc1HLSqB AOAoW8HSvfQcw== From: Tzung-Bi Shih To: Bartosz Golaszewski , Linus Walleij Cc: Shuah Khan , linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-kselftest@vger.kernel.org, tzungbi@kernel.org Subject: [PATCH v4 2/6] gpio: Remove redundant check for struct gpio_chip Date: Mon, 23 Feb 2026 14:17:22 +0800 Message-ID: <20260223061726.82161-3-tzungbi@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260223061726.82161-1-tzungbi@kernel.org> References: <20260223061726.82161-1-tzungbi@kernel.org> 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" gpiolib_dbg_show() is only called by gpiolib_seq_show() which has ensured the struct gpio_chip. Remove the redundant check in gpiolib_dbg_show(). Reviewed-by: Linus Walleij Signed-off-by: Tzung-Bi Shih --- v4: - Add R-b tag. v3: https://lore.kernel.org/all/20260213092958.864411-3-tzungbi@kernel.org - No changes. v2: https://lore.kernel.org/all/20260203061059.975605-3-tzungbi@kernel.org - No changes. v1: https://lore.kernel.org/all/20260116081036.352286-8-tzungbi@kernel.org drivers/gpio/gpiolib.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 0a73561060dd..08a3697dbd5a 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -5312,23 +5312,14 @@ core_initcall(gpiolib_dev_init); =20 #ifdef CONFIG_DEBUG_FS =20 -static void gpiolib_dbg_show(struct seq_file *s, struct gpio_device *gdev) +static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *gc) { bool active_low, is_irq, is_out; struct gpio_desc *desc; unsigned int gpio =3D 0; - struct gpio_chip *gc; unsigned long flags; int value; =20 - guard(srcu)(&gdev->srcu); - - gc =3D srcu_dereference(gdev->chip, &gdev->srcu); - if (!gc) { - seq_puts(s, "Underlying GPIO chip is gone\n"); - return; - } - for_each_gpio_desc(gc, desc) { guard(srcu)(&desc->gdev->desc_srcu); flags =3D READ_ONCE(desc->flags); @@ -5441,7 +5432,7 @@ static int gpiolib_seq_show(struct seq_file *s, void = *v) if (gc->dbg_show) gc->dbg_show(s, gc); else - gpiolib_dbg_show(s, gdev); + gpiolib_dbg_show(s, gc); =20 return 0; } --=20 2.51.0 From nobody Fri Apr 17 07:44:39 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 614CF347BA5; Mon, 23 Feb 2026 06:17:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771827471; cv=none; b=BxKR2/+b0d/hPcyTvQbS6O6H/I7HBWfy0Sik8hn61ziClRN6zPA+kZ594qOMU+AhmRbQjQ0ilsy2W8s9SmSGf8jPcJWoeajK9J+4bT6BxosFcVts6ht35EMNA3s9TbmfygnLTAceNc8d4SI0A3xi5Vh5ESr9b6l/FvQd+92HR5k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771827471; c=relaxed/simple; bh=yD2pG/K68/APLZzFaGWMD+tmK+JmbviTLcJrVMHoTUE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YGyYeViV615iF/hHEmAXMXXlMOQyN0h/EJZwkd3nrvnJ7539IIgaSOuNJf80KPBCnLL1eSTjFS43MT+RKQgfU2az4M7EmeOit1cBDl/B5BYP0R3ZWu9Y6/YTFk5kMBUKsDmlQiZ7LgYzFEB6t7+767ctTYC3uuHsmG45tRr09o0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UpWNVy/t; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="UpWNVy/t" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B0B99C2BC87; Mon, 23 Feb 2026 06:17:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771827471; bh=yD2pG/K68/APLZzFaGWMD+tmK+JmbviTLcJrVMHoTUE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UpWNVy/tC3eOjOfg8ZlrJiHhQMTSw7mNTSw0rJOWVtShuZp8VUoEN5AotWkix4Da1 r+HOusIoy3AJKN4fnV658aIIwQOYgRxKRN32+lTt/GdbB0NPeGWt4ttTnrVWZ8jUWq NmQrIFT/PCGPV4sAEk/p/S2gvzB7x7tjhzUdxANdRHLhYtQYrB6kGY8SY4V8tZKcvM nxqAdz2QxP4LmRxV0QcsYf/MLAdxwxbl+sazB119vzAadLNovywxrzv+xrX59h1JiA HYh+ERU+g7BYxadMWJw54AXKujIimId1VlN87wUFdflIWcJJhjYTs/zuTkjpAfPb9O OG9FUSt/ih5tg== From: Tzung-Bi Shih To: Bartosz Golaszewski , Linus Walleij Cc: Shuah Khan , linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-kselftest@vger.kernel.org, tzungbi@kernel.org Subject: [PATCH v4 3/6] gpio: sysfs: Remove redundant check for struct gpio_chip Date: Mon, 23 Feb 2026 14:17:23 +0800 Message-ID: <20260223061726.82161-4-tzungbi@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260223061726.82161-1-tzungbi@kernel.org> References: <20260223061726.82161-1-tzungbi@kernel.org> 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" gpiochip_sysfs_unregister() is only called by gpiochip_remove() where the struct gpio_chip is ensured. Remove the redundant check. Reviewed-by: Linus Walleij Signed-off-by: Tzung-Bi Shih --- v4: - Add R-b tag. - To be consistent, rename `chip` -> `gc`. v3: https://lore.kernel.org/all/20260213092958.864411-4-tzungbi@kernel.org - Pass struct gpio_chip * only. v2: https://lore.kernel.org/all/20260203061059.975605-4-tzungbi@kernel.org - No changes. v1: https://lore.kernel.org/all/20260116081036.352286-9-tzungbi@kernel.org drivers/gpio/gpiolib-sysfs.c | 11 +++-------- drivers/gpio/gpiolib-sysfs.h | 4 ++-- drivers/gpio/gpiolib.c | 2 +- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index 270e8060e761..1c25a7dd3db4 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -1053,11 +1053,11 @@ int gpiochip_sysfs_register(struct gpio_device *gde= v) return 0; } =20 -void gpiochip_sysfs_unregister(struct gpio_device *gdev) +void gpiochip_sysfs_unregister(struct gpio_chip *gc) { + struct gpio_device *gdev =3D gc->gpiodev; struct gpiodev_data *data; struct gpio_desc *desc; - struct gpio_chip *chip; =20 guard(mutex)(&sysfs_lock); =20 @@ -1065,13 +1065,8 @@ void gpiochip_sysfs_unregister(struct gpio_device *g= dev) if (!data) return; =20 - guard(srcu)(&gdev->srcu); - chip =3D srcu_dereference(gdev->chip, &gdev->srcu); - if (!chip) - return; - /* unregister gpiod class devices owned by sysfs */ - for_each_gpio_desc_with_flag(chip, desc, GPIOD_FLAG_SYSFS) { + for_each_gpio_desc_with_flag(gc, desc, GPIOD_FLAG_SYSFS) { gpiod_unexport_unlocked(desc); gpiod_free(desc); } diff --git a/drivers/gpio/gpiolib-sysfs.h b/drivers/gpio/gpiolib-sysfs.h index b794b396d6a5..fd5db5384681 100644 --- a/drivers/gpio/gpiolib-sysfs.h +++ b/drivers/gpio/gpiolib-sysfs.h @@ -8,7 +8,7 @@ struct gpio_device; #ifdef CONFIG_GPIO_SYSFS =20 int gpiochip_sysfs_register(struct gpio_device *gdev); -void gpiochip_sysfs_unregister(struct gpio_device *gdev); +void gpiochip_sysfs_unregister(struct gpio_chip *gc); =20 #else =20 @@ -17,7 +17,7 @@ static inline int gpiochip_sysfs_register(struct gpio_dev= ice *gdev) return 0; } =20 -static inline void gpiochip_sysfs_unregister(struct gpio_device *gdev) +static inline void gpiochip_sysfs_unregister(struct gpio_chip *gc) { } =20 diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 08a3697dbd5a..d5070c538ba5 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1285,7 +1285,7 @@ void gpiochip_remove(struct gpio_chip *gc) struct gpio_device *gdev =3D gc->gpiodev; =20 /* FIXME: should the legacy sysfs handling be moved to gpio_device? */ - gpiochip_sysfs_unregister(gdev); + gpiochip_sysfs_unregister(gc); gpiochip_free_hogs(gc); gpiochip_free_remaining_irqs(gc); =20 --=20 2.51.0 From nobody Fri Apr 17 07:44:39 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 00FD1348889; Mon, 23 Feb 2026 06:17:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771827473; cv=none; b=VusRuPfn+3T3e4DqNyWLEZM1kjbRFDbfzKR6zzPf2v7N//5dI1p/mopeMm3NqvXFEUCPjMqMrYGEQTwIOgAF56PTtr4b7ijBMOXsbDoIPmopCzxeETX5swGvU2eQvCqJVapyJLN/GYcvZxV85GZuwKYyC4iF3Z/6jlOoFOH9Lbw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771827473; c=relaxed/simple; bh=ndt6VgQG8rMzKlDaZB5HulAjbnNY2Y9JIC1Ii/WSyW0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MCJ24ExdV4m8KmiIHDdFk/ZTRa3tCA4fBuaWUlV0EexlJ/bPQpYeXsKtPNe7k3fm7LEaUOHNvurdE9yh0Ni9y3oWrQTjIh2M01FFdMCx+VgC/Wlgh8pEBORQF1viXDk5jDq85CZDKvDyTYnwh6uGODwzKDnQ8nQH4j8q1lWshxI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=tzVybFTX; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="tzVybFTX" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 75B90C2BC86; Mon, 23 Feb 2026 06:17:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771827472; bh=ndt6VgQG8rMzKlDaZB5HulAjbnNY2Y9JIC1Ii/WSyW0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=tzVybFTXF53e0CysCSnd6ImU9V89wP4/I4iWYcnhr73B6ZB8E9EPnsO6831UrfPpB ZyYJScuMjzMWdKG9YiqZ9b2I/vBxRCmPUjUBRKIfrItGZ4GMS+pjfzweVCJ5ftWU5h MFd0JZfk9+Nc1HnPxXAu3zAuYI7WZEspBLkCLXPzInT2+4oVoEwgz1KT2MWsnV72Bt Ak9tDg1ZMWZnWslEpyhkZGjocrNENeISF6ca3CVSwEObQQ23/lM+TvlHckn11Q2e31 DI/JX7312D+eXlMZu8tZ06ayDnjvYi1Vo6GSjOZDkzrxML+DqmTkmdD82Xodn0Xttx gTcXDmgzhPDfg== From: Tzung-Bi Shih To: Bartosz Golaszewski , Linus Walleij Cc: Shuah Khan , linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-kselftest@vger.kernel.org, tzungbi@kernel.org Subject: [PATCH v4 4/6] gpio: Ensure struct gpio_chip for gpiochip_setup_dev() Date: Mon, 23 Feb 2026 14:17:24 +0800 Message-ID: <20260223061726.82161-5-tzungbi@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260223061726.82161-1-tzungbi@kernel.org> References: <20260223061726.82161-1-tzungbi@kernel.org> 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" Ensure struct gpio_chip for gpiochip_setup_dev(). This eliminates a few checks for struct gpio_chip. Signed-off-by: Tzung-Bi Shih --- v4: - To be consistent, rename `chip` -> `gc`. - Add lockdep checks. v3: https://lore.kernel.org/all/20260213092958.864411-5-tzungbi@kernel.org - Pass struct gpio_chip * only. v2: https://lore.kernel.org/all/20260203061059.975605-5-tzungbi@kernel.org - No changes. v1: https://lore.kernel.org/all/20260116081036.352286-10-tzungbi@kernel.org drivers/gpio/gpiolib-cdev.c | 14 ++++---------- drivers/gpio/gpiolib-cdev.h | 2 +- drivers/gpio/gpiolib-sysfs.c | 21 ++++++++------------- drivers/gpio/gpiolib-sysfs.h | 4 ++-- drivers/gpio/gpiolib.c | 24 +++++++++++++++++------- 5 files changed, 32 insertions(+), 33 deletions(-) diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index 73ae77f0f213..a154b04e9316 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -2782,11 +2782,13 @@ static const struct file_operations gpio_fileops = =3D { #endif }; =20 -int gpiolib_cdev_register(struct gpio_device *gdev, dev_t devt) +int gpiolib_cdev_register(struct gpio_chip *gc, dev_t devt) { - struct gpio_chip *gc; + struct gpio_device *gdev =3D gc->gpiodev; int ret; =20 + lockdep_assert_held(&gdev->srcu); + cdev_init(&gdev->chrdev, &gpio_fileops); gdev->chrdev.owner =3D THIS_MODULE; gdev->dev.devt =3D MKDEV(MAJOR(devt), gdev->id); @@ -2802,14 +2804,6 @@ int gpiolib_cdev_register(struct gpio_device *gdev, = dev_t devt) return ret; } =20 - guard(srcu)(&gdev->srcu); - gc =3D srcu_dereference(gdev->chip, &gdev->srcu); - if (!gc) { - cdev_device_del(&gdev->chrdev, &gdev->dev); - destroy_workqueue(gdev->line_state_wq); - return -ENODEV; - } - gpiochip_dbg(gc, "added GPIO chardev (%d:%d)\n", MAJOR(devt), gdev->id); =20 return 0; diff --git a/drivers/gpio/gpiolib-cdev.h b/drivers/gpio/gpiolib-cdev.h index b42644cbffb8..4a9cb3335d99 100644 --- a/drivers/gpio/gpiolib-cdev.h +++ b/drivers/gpio/gpiolib-cdev.h @@ -7,7 +7,7 @@ =20 struct gpio_device; =20 -int gpiolib_cdev_register(struct gpio_device *gdev, dev_t devt); +int gpiolib_cdev_register(struct gpio_chip *gc, dev_t devt); void gpiolib_cdev_unregister(struct gpio_device *gdev); =20 #endif /* GPIOLIB_CDEV_H */ diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index 1c25a7dd3db4..748a3eb1bf35 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -983,13 +983,15 @@ void gpiod_unexport(struct gpio_desc *desc) } EXPORT_SYMBOL_GPL(gpiod_unexport); =20 -int gpiochip_sysfs_register(struct gpio_device *gdev) +int gpiochip_sysfs_register(struct gpio_chip *gc) { + struct gpio_device *gdev =3D gc->gpiodev; struct gpiodev_data *data; - struct gpio_chip *chip; struct device *parent; int err; =20 + lockdep_assert_held(&gdev->srcu); + /* * Many systems add gpio chips for SOC support very early, * before driver model support is available. In those cases we @@ -999,18 +1001,12 @@ int gpiochip_sysfs_register(struct gpio_device *gdev) if (!class_is_registered(&gpio_class)) return 0; =20 - guard(srcu)(&gdev->srcu); - - chip =3D srcu_dereference(gdev->chip, &gdev->srcu); - if (!chip) - return -ENODEV; - /* * For sysfs backward compatibility we need to preserve this * preferred parenting to the gpio_chip parent field, if set. */ - if (chip->parent) - parent =3D chip->parent; + if (gc->parent) + parent =3D gc->parent; else parent =3D &gdev->dev; =20 @@ -1029,7 +1025,7 @@ int gpiochip_sysfs_register(struct gpio_device *gdev) MKDEV(0, 0), data, gpiochip_groups, GPIOCHIP_NAME "%d", - chip->base); + gc->base); if (IS_ERR(data->cdev_base)) { err =3D PTR_ERR(data->cdev_base); kfree(data); @@ -1085,10 +1081,9 @@ void gpiochip_sysfs_unregister(struct gpio_chip *gc) */ static int gpiofind_sysfs_register(struct gpio_chip *gc, const void *data) { - struct gpio_device *gdev =3D gc->gpiodev; int ret; =20 - ret =3D gpiochip_sysfs_register(gdev); + ret =3D gpiochip_sysfs_register(gc); if (ret) gpiochip_err(gc, "failed to register the sysfs entry: %d\n", ret); =20 diff --git a/drivers/gpio/gpiolib-sysfs.h b/drivers/gpio/gpiolib-sysfs.h index fd5db5384681..d0998de043a2 100644 --- a/drivers/gpio/gpiolib-sysfs.h +++ b/drivers/gpio/gpiolib-sysfs.h @@ -7,12 +7,12 @@ struct gpio_device; =20 #ifdef CONFIG_GPIO_SYSFS =20 -int gpiochip_sysfs_register(struct gpio_device *gdev); +int gpiochip_sysfs_register(struct gpio_chip *gc); void gpiochip_sysfs_unregister(struct gpio_chip *gc); =20 #else =20 -static inline int gpiochip_sysfs_register(struct gpio_device *gdev) +static inline int gpiochip_sysfs_register(struct gpio_chip *gc) { return 0; } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index d5070c538ba5..44635e9a29c3 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -881,14 +881,14 @@ static const struct device_type gpio_dev_type =3D { }; =20 #ifdef CONFIG_GPIO_CDEV -#define gcdev_register(gdev, devt) gpiolib_cdev_register((gdev), (devt)) +#define gcdev_register(gc, devt) gpiolib_cdev_register((gc), (devt)) #define gcdev_unregister(gdev) gpiolib_cdev_unregister((gdev)) #else /* * gpiolib_cdev_register() indirectly calls device_add(), which is still * required even when cdev is not selected. */ -#define gcdev_register(gdev, devt) device_add(&(gdev)->dev) +#define gcdev_register(gc, devt) device_add(&(gc)->gpiodev->dev) #define gcdev_unregister(gdev) device_del(&(gdev)->dev) #endif =20 @@ -896,8 +896,9 @@ static const struct device_type gpio_dev_type =3D { * An initial reference count has been held in gpiochip_add_data_with_key(= ). * The caller should drop the reference via gpio_device_put() on errors. */ -static int gpiochip_setup_dev(struct gpio_device *gdev) +static int gpiochip_setup_dev(struct gpio_chip *gc) { + struct gpio_device *gdev =3D gc->gpiodev; struct fwnode_handle *fwnode =3D dev_fwnode(&gdev->dev); int ret; =20 @@ -910,11 +911,11 @@ static int gpiochip_setup_dev(struct gpio_device *gde= v) if (fwnode && !fwnode->dev) fwnode_dev_initialized(fwnode, false); =20 - ret =3D gcdev_register(gdev, gpio_devt); + ret =3D gcdev_register(gc, gpio_devt); if (ret) return ret; =20 - ret =3D gpiochip_sysfs_register(gdev); + ret =3D gpiochip_sysfs_register(gc); if (ret) goto err_remove_device; =20 @@ -961,13 +962,22 @@ static void machine_gpiochip_add(struct gpio_chip *gc) static void gpiochip_setup_devs(void) { struct gpio_device *gdev; + struct gpio_chip *gc; int ret; =20 guard(srcu)(&gpio_devices_srcu); =20 list_for_each_entry_srcu(gdev, &gpio_devices, list, srcu_read_lock_held(&gpio_devices_srcu)) { - ret =3D gpiochip_setup_dev(gdev); + guard(srcu)(&gdev->srcu); + + gc =3D srcu_dereference(gdev->chip, &gdev->srcu); + if (!gc) { + dev_err(&gdev->dev, "Underlying GPIO chip is gone\n"); + continue; + } + + ret =3D gpiochip_setup_dev(gc); if (ret) { gpio_device_put(gdev); dev_err(&gdev->dev, @@ -1225,7 +1235,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, = void *data, * (i.e., `gpio_bus_type` is ready). Otherwise, defer until later. */ if (gpiolib_initialized) { - ret =3D gpiochip_setup_dev(gdev); + ret =3D gpiochip_setup_dev(gc); if (ret) goto err_teardown_shared; } --=20 2.51.0 From nobody Fri Apr 17 07:44:39 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 493B7349AF9; Mon, 23 Feb 2026 06:17:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771827475; cv=none; b=uEtwoVRdSQDutLe8/bScPTcdIf/o6Xiq0t7KA8PYoAqW6vGsCCGcvhUjp2J45FU8Rr3OxEKAuGuSmqEVj9T5GIX1ElzRvq0tsSkLHDYxYa399dbh/xFtvYuJ/wKL2dMgHbY+ip9jCzWjUAqPBDuA+X4jHMiZFrQXXT7o9McKIfk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771827475; c=relaxed/simple; bh=rEKOvY8ban5EFD4115du6UZcdU8moboolpkVYP28tpc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lhXqgByfXYLALM0DQ0QnDW5VJUZzRO8+VeL/go/iybjDxh2Boo9hYIuur5MIrne4RYBdGtDDtVrwR1UOMqw+IZN/OO/rrIftsav4fO7eDqYZsfkSw3dDBtCe/pmxrF9/gY+ts2SzFV/KY+l6t7EZkyW1IwLzBEq/qODtwCYKY64= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=d98GpjG6; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="d98GpjG6" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3A05BC116C6; Mon, 23 Feb 2026 06:17:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771827474; bh=rEKOvY8ban5EFD4115du6UZcdU8moboolpkVYP28tpc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=d98GpjG6oJzpMGXNHMLajGl2fX9aAK/wONoPctySqBL/J/t7qbjy+U/WEVnoottny CWjyJ04Wy8SebEaohpLT+lAtst36PXFDc39BOUmdo2tVVvHqkCb+7rl5PFOC1b/PIu u6AveVx0Yboan9badnKh7G0WM4DttRsdtalW8AUgXwRGaZVDHCukiByaQ28pDxjF7M 67sEEWdphwPo1I66qnCVy9kN6pHN6qDNmWuEWNhftVix0NKBTOZrZ0SN8imU1imhDu PcXEzq416l4Qc6CSFTkSW8ozGhhHOzBC4YGu+10bCl7VMu1zOO/pg7ufnAeO9A++9O QSvmSJno3OUwA== From: Tzung-Bi Shih To: Bartosz Golaszewski , Linus Walleij Cc: Shuah Khan , linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-kselftest@vger.kernel.org, tzungbi@kernel.org Subject: [PATCH v4 5/6] gpio: cdev: Don't check struct gpio_chip in gpio_chrdev_open() Date: Mon, 23 Feb 2026 14:17:25 +0800 Message-ID: <20260223061726.82161-6-tzungbi@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260223061726.82161-1-tzungbi@kernel.org> References: <20260223061726.82161-1-tzungbi@kernel.org> 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" It's harmless even if: chrdev_open() and cdev_device_del() run at the same time, and gpio_chrdev_open() gets called after the underlying GPIO chip has gone. The subsequent file operations check the availability of struct gpio_chip anyway. Don't check struct gpio_chip in gpio_chrdev_open(). Reviewed-by: Linus Walleij Signed-off-by: Tzung-Bi Shih --- v4: - Add R-b tag. v3: https://lore.kernel.org/all/20260213092958.864411-6-tzungbi@kernel.org - No changes. v2: https://lore.kernel.org/all/20260203061059.975605-6-tzungbi@kernel.org - No changes. v1: https://lore.kernel.org/all/20260116081036.352286-11-tzungbi@kernel.org drivers/gpio/gpiolib-cdev.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index a154b04e9316..475ad185f915 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -2689,12 +2689,6 @@ static int gpio_chrdev_open(struct inode *inode, str= uct file *file) struct gpio_chardev_data *cdev; int ret =3D -ENOMEM; =20 - guard(srcu)(&gdev->srcu); - - /* Fail on open if the backing gpiochip is gone */ - if (!rcu_access_pointer(gdev->chip)) - return -ENODEV; - cdev =3D kzalloc(sizeof(*cdev), GFP_KERNEL); if (!cdev) return -ENOMEM; --=20 2.51.0 From nobody Fri Apr 17 07:44:39 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C50F73469F4; Mon, 23 Feb 2026 06:17:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771827476; cv=none; b=e9BEKyMwBKftayptepnnIYl9g2Iyu0AeUpju99GzL1Eri2a8clQoj8PrG1pLABmiSYcLd85WsK9aihnaAKCLgXwIZEmVtRq0yB15ZH5nLUiJmGZLbSX49ZY/1MCA5kKPBb2i6SVHwkPbna+GelDnJxMMlvAC0pxDBqPEkw2r2Ig= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771827476; c=relaxed/simple; bh=JpdZrqFMvn1I2wIDO5c75qXXq2BiDGaqMTs3XgagMI8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pSYbyVSZLc7J3ayPVwgl6MGgrNL+mLvdLmx85jCmeUxux31A+G9K/xvQFZfo366GPObTnQTsz+XpQn9n4i/6Wzremb2RZzKW0DtTpU9lz9xMr6Zgtf3CmVKzcrrHKjULt10UhWEcB4UauZtXXs8ml6WuPtaAvjfX6haGN82+0aw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=b2ROXckC; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="b2ROXckC" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5406DC19421; Mon, 23 Feb 2026 06:17:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771827476; bh=JpdZrqFMvn1I2wIDO5c75qXXq2BiDGaqMTs3XgagMI8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=b2ROXckCh/FxEs57Uygr+JWe0jpWcjSEGzMbPH3yNxLJyrHCWBBQdrrS+gKjVW6Zt V2/Q8J8MZ2rEspFhBY4xQ7/gmzy/QC9WGu+taZLzyXwsZt1xZ1FLCptEcGTdQjAGGv P8xmWAJzXpN7D0aL+Bf9LW1gltALpoDcicjiDljFsgs74KNIToQW6uDr2y9Mhyklur mZKc3uikvRyekbPNpgFB5H4eYC7giG0i1WhAYMwYgcRZAjsyaSUEAh3thgsfh3I1Qw FgXpkfKd22957fFJTrm7+WhgOJlgTHqeuQ+ClECGpUQBLWqJn+d2L5Wf7uy/RM1DUp sKlAsX1U6zY5g== From: Tzung-Bi Shih To: Bartosz Golaszewski , Linus Walleij Cc: Shuah Khan , linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-kselftest@vger.kernel.org, tzungbi@kernel.org Subject: [PATCH v4 6/6] selftests: gpio: Add gpio-cdev-uaf tests Date: Mon, 23 Feb 2026 14:17:26 +0800 Message-ID: <20260223061726.82161-7-tzungbi@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260223061726.82161-1-tzungbi@kernel.org> References: <20260223061726.82161-1-tzungbi@kernel.org> 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" Add tests for gpiolib-cdev to make sure accessing to dangling resources via the opening file descriptor won't crash the system after the underlying resource providers have gone. Reviewed-by: Linus Walleij Signed-off-by: Tzung-Bi Shih --- v4: - Add R-b tag. v3: https://lore.kernel.org/all/20260213092958.864411-7-tzungbi@kernel.org - No changes. v2: https://lore.kernel.org/all/20260203061059.975605-7-tzungbi@kernel.org - Remove fdinfo test which is redundant. v1: https://lore.kernel.org/all/20260116081036.352286-12-tzungbi@kernel.org tools/testing/selftests/gpio/Makefile | 5 +- tools/testing/selftests/gpio/gpio-cdev-uaf.c | 292 ++++++++++++++++++ tools/testing/selftests/gpio/gpio-cdev-uaf.sh | 63 ++++ 3 files changed, 358 insertions(+), 2 deletions(-) create mode 100644 tools/testing/selftests/gpio/gpio-cdev-uaf.c create mode 100755 tools/testing/selftests/gpio/gpio-cdev-uaf.sh diff --git a/tools/testing/selftests/gpio/Makefile b/tools/testing/selftest= s/gpio/Makefile index 7bfe315f7001..741ab21e1260 100644 --- a/tools/testing/selftests/gpio/Makefile +++ b/tools/testing/selftests/gpio/Makefile @@ -1,8 +1,9 @@ # SPDX-License-Identifier: GPL-2.0 =20 -TEST_PROGS :=3D gpio-mockup.sh gpio-sim.sh gpio-aggregator.sh +TEST_PROGS :=3D gpio-mockup.sh gpio-sim.sh gpio-aggregator.sh gpio-cdev-ua= f.sh TEST_FILES :=3D gpio-mockup-sysfs.sh -TEST_GEN_PROGS_EXTENDED :=3D gpio-mockup-cdev gpio-chip-info gpio-line-name +TEST_GEN_PROGS_EXTENDED :=3D gpio-mockup-cdev gpio-chip-info gpio-line-nam= e \ + gpio-cdev-uaf CFLAGS +=3D -O2 -g -Wall $(KHDR_INCLUDES) =20 include ../lib.mk diff --git a/tools/testing/selftests/gpio/gpio-cdev-uaf.c b/tools/testing/s= elftests/gpio/gpio-cdev-uaf.c new file mode 100644 index 000000000000..765d3cc4f0ef --- /dev/null +++ b/tools/testing/selftests/gpio/gpio-cdev-uaf.c @@ -0,0 +1,292 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * GPIO character device helper for UAF tests. + * + * Copyright 2026 Google LLC + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CONFIGFS_DIR "/sys/kernel/config/gpio-sim" +#define PROCFS_DIR "/proc" + +static void print_usage(void) +{ + printf("usage:\n"); + printf(" gpio-cdev-uaf [chip|handle|event|req] [poll|read|ioctl]\n"); +} + +static int _create_chip(const char *name, int create) +{ + char path[64]; + + snprintf(path, sizeof(path), CONFIGFS_DIR "/%s", name); + + if (create) + return mkdir(path, 0755); + else + return rmdir(path); +} + +static int create_chip(const char *name) +{ + return _create_chip(name, 1); +} + +static void remove_chip(const char *name) +{ + _create_chip(name, 0); +} + +static int _create_bank(const char *chip_name, const char *name, int creat= e) +{ + char path[64]; + + snprintf(path, sizeof(path), CONFIGFS_DIR "/%s/%s", chip_name, name); + + if (create) + return mkdir(path, 0755); + else + return rmdir(path); +} + +static int create_bank(const char *chip_name, const char *name) +{ + return _create_bank(chip_name, name, 1); +} + +static void remove_bank(const char *chip_name, const char *name) +{ + _create_bank(chip_name, name, 0); +} + +static int _enable_chip(const char *name, int enable) +{ + char path[64]; + int fd, ret; + + snprintf(path, sizeof(path), CONFIGFS_DIR "/%s/live", name); + + fd =3D open(path, O_WRONLY); + if (fd =3D=3D -1) + return fd; + + if (enable) + ret =3D write(fd, "1", 1); + else + ret =3D write(fd, "0", 1); + + close(fd); + return ret =3D=3D 1 ? 0 : -1; +} + +static int enable_chip(const char *name) +{ + return _enable_chip(name, 1); +} + +static void disable_chip(const char *name) +{ + _enable_chip(name, 0); +} + +static int open_chip(const char *chip_name, const char *bank_name) +{ + char path[64], dev_name[32]; + int ret, fd; + + ret =3D create_chip(chip_name); + if (ret) { + fprintf(stderr, "failed to create chip\n"); + return ret; + } + + ret =3D create_bank(chip_name, bank_name); + if (ret) { + fprintf(stderr, "failed to create bank\n"); + goto err_remove_chip; + } + + ret =3D enable_chip(chip_name); + if (ret) { + fprintf(stderr, "failed to enable chip\n"); + goto err_remove_bank; + } + + snprintf(path, sizeof(path), CONFIGFS_DIR "/%s/%s/chip_name", + chip_name, bank_name); + + fd =3D open(path, O_RDONLY); + if (fd =3D=3D -1) { + ret =3D fd; + fprintf(stderr, "failed to open %s\n", path); + goto err_disable_chip; + } + + ret =3D read(fd, dev_name, sizeof(dev_name) - 1); + close(fd); + if (ret =3D=3D -1) { + fprintf(stderr, "failed to read %s\n", path); + goto err_disable_chip; + } + dev_name[ret] =3D '\0'; + if (ret && dev_name[ret - 1] =3D=3D '\n') + dev_name[ret - 1] =3D '\0'; + + snprintf(path, sizeof(path), "/dev/%s", dev_name); + + fd =3D open(path, O_RDWR); + if (fd =3D=3D -1) { + ret =3D fd; + fprintf(stderr, "failed to open %s\n", path); + goto err_disable_chip; + } + + return fd; +err_disable_chip: + disable_chip(chip_name); +err_remove_bank: + remove_bank(chip_name, bank_name); +err_remove_chip: + remove_chip(chip_name); + return ret; +} + +static void close_chip(const char *chip_name, const char *bank_name) +{ + disable_chip(chip_name); + remove_bank(chip_name, bank_name); + remove_chip(chip_name); +} + +static int test_poll(int fd) +{ + struct pollfd pfds; + + pfds.fd =3D fd; + pfds.events =3D POLLIN; + pfds.revents =3D 0; + + if (poll(&pfds, 1, 0) =3D=3D -1) + return -1; + + return (pfds.revents & ~(POLLHUP | POLLERR)) ? -1 : 0; +} + +static int test_read(int fd) +{ + char data; + + if (read(fd, &data, 1) =3D=3D -1 && errno =3D=3D ENODEV) + return 0; + return -1; +} + +static int test_ioctl(int fd) +{ + if (ioctl(fd, 0, NULL) =3D=3D -1 && errno =3D=3D ENODEV) + return 0; + return -1; +} + +int main(int argc, char **argv) +{ + int cfd, fd, ret; + int (*test_func)(int); + + if (argc !=3D 3) { + print_usage(); + return EXIT_FAILURE; + } + + if (strcmp(argv[1], "chip") =3D=3D 0 || + strcmp(argv[1], "event") =3D=3D 0 || + strcmp(argv[1], "req") =3D=3D 0) { + if (strcmp(argv[2], "poll") && + strcmp(argv[2], "read") && + strcmp(argv[2], "ioctl")) { + fprintf(stderr, "unknown command: %s\n", argv[2]); + return EXIT_FAILURE; + } + } else if (strcmp(argv[1], "handle") =3D=3D 0) { + if (strcmp(argv[2], "ioctl")) { + fprintf(stderr, "unknown command: %s\n", argv[2]); + return EXIT_FAILURE; + } + } else { + fprintf(stderr, "unknown command: %s\n", argv[1]); + return EXIT_FAILURE; + } + + if (strcmp(argv[2], "poll") =3D=3D 0) + test_func =3D test_poll; + else if (strcmp(argv[2], "read") =3D=3D 0) + test_func =3D test_read; + else /* strcmp(argv[2], "ioctl") =3D=3D 0 */ + test_func =3D test_ioctl; + + cfd =3D open_chip("chip", "bank"); + if (cfd =3D=3D -1) { + fprintf(stderr, "failed to open chip\n"); + return EXIT_FAILURE; + } + + /* Step 1: Hold a FD to the test target. */ + if (strcmp(argv[1], "chip") =3D=3D 0) { + fd =3D cfd; + } else if (strcmp(argv[1], "handle") =3D=3D 0) { + struct gpiohandle_request req =3D {0}; + + req.lines =3D 1; + if (ioctl(cfd, GPIO_GET_LINEHANDLE_IOCTL, &req) =3D=3D -1) { + fprintf(stderr, "failed to get handle FD\n"); + goto err_close_chip; + } + + close(cfd); + fd =3D req.fd; + } else if (strcmp(argv[1], "event") =3D=3D 0) { + struct gpioevent_request req =3D {0}; + + if (ioctl(cfd, GPIO_GET_LINEEVENT_IOCTL, &req) =3D=3D -1) { + fprintf(stderr, "failed to get event FD\n"); + goto err_close_chip; + } + + close(cfd); + fd =3D req.fd; + } else { /* strcmp(argv[1], "req") =3D=3D 0 */ + struct gpio_v2_line_request req =3D {0}; + + req.num_lines =3D 1; + if (ioctl(cfd, GPIO_V2_GET_LINE_IOCTL, &req) =3D=3D -1) { + fprintf(stderr, "failed to get req FD\n"); + goto err_close_chip; + } + + close(cfd); + fd =3D req.fd; + } + + /* Step 2: Free the chip. */ + close_chip("chip", "bank"); + + /* Step 3: Access the dangling FD to trigger UAF. */ + ret =3D test_func(fd); + close(fd); + return ret ? EXIT_FAILURE : EXIT_SUCCESS; +err_close_chip: + close(cfd); + close_chip("chip", "bank"); + return EXIT_FAILURE; +} diff --git a/tools/testing/selftests/gpio/gpio-cdev-uaf.sh b/tools/testing/= selftests/gpio/gpio-cdev-uaf.sh new file mode 100755 index 000000000000..6e47533019cf --- /dev/null +++ b/tools/testing/selftests/gpio/gpio-cdev-uaf.sh @@ -0,0 +1,63 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright 2026 Google LLC + +BASE_DIR=3D`dirname $0` +MODULE=3D"gpio-cdev-uaf" + +fail() { + echo "$*" >&2 + echo "GPIO $MODULE test FAIL" + exit 1 +} + +skip() { + echo "$*" >&2 + echo "GPIO $MODULE test SKIP" + exit 4 +} + +# Load the gpio-sim module. This will pull in configfs if needed too. +modprobe gpio-sim || skip "unable to load the gpio-sim module" +# Make sure configfs is mounted at /sys/kernel/config. Wait a bit if neede= d. +for _ in `seq 5`; do + mountpoint -q /sys/kernel/config && break + mount -t configfs none /sys/kernel/config + sleep 0.1 +done +mountpoint -q /sys/kernel/config || \ + skip "configfs not mounted at /sys/kernel/config" + +echo "1. GPIO" + +echo "1.1. poll" +$BASE_DIR/gpio-cdev-uaf chip poll || fail "failed to test chip poll" +echo "1.2. read" +$BASE_DIR/gpio-cdev-uaf chip read || fail "failed to test chip read" +echo "1.3. ioctl" +$BASE_DIR/gpio-cdev-uaf chip ioctl || fail "failed to test chip ioctl" + +echo "2. linehandle" + +echo "2.1. ioctl" +$BASE_DIR/gpio-cdev-uaf handle ioctl || fail "failed to test handle ioctl" + +echo "3. lineevent" + +echo "3.1. read" +$BASE_DIR/gpio-cdev-uaf event read || fail "failed to test event read" +echo "3.2. poll" +$BASE_DIR/gpio-cdev-uaf event poll || fail "failed to test event poll" +echo "3.3. ioctl" +$BASE_DIR/gpio-cdev-uaf event ioctl || fail "failed to test event ioctl" + +echo "4. linereq" + +echo "4.1. read" +$BASE_DIR/gpio-cdev-uaf req read || fail "failed to test req read" +echo "4.2. poll" +$BASE_DIR/gpio-cdev-uaf req poll || fail "failed to test req poll" +echo "4.3. ioctl" +$BASE_DIR/gpio-cdev-uaf req ioctl || fail "failed to test req ioctl" + +echo "GPIO $MODULE test PASS" --=20 2.51.0