public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: patches@lists.linux.dev, stable@vger.kernel.org
Cc: wangdicheng <wangdicheng@kylinos.cn>,
	Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>,
	lgirdwood@gmail.com, perex@perex.cz, tiwai@suse.com,
	linux-sound@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH AUTOSEL 7.0-6.6] ASoC: aw88395: Fix kernel panic caused by invalid GPIO error pointer
Date: Tue,  5 May 2026 05:51:37 -0400	[thread overview]
Message-ID: <20260505095149.512052-21-sashal@kernel.org> (raw)
In-Reply-To: <20260505095149.512052-1-sashal@kernel.org>

From: wangdicheng <wangdicheng@kylinos.cn>

[ Upstream commit 241ee17ecb6be210f7b231b2a81bfb68871950d0 ]

In aw88395_i2c_probe(), if `devm_gpiod_get_optional()` fails, it returns
an ERR_PTR() error pointer. The current code only prints a message and
continues execution, leaving `aw88395->reset_gpio` as an invalid pointer.

Later, in `aw88395_hw_reset()`, this invalid pointer is passed to
`gpiod_set_value_cansleep()`, which dereferences it and causes a kernel
panic.

For optional GPIOs, `devm_gpiod_get_optional()` returns NULL if the GPIO
is not defined in the DT, which is safe. If it returns an ERR_PTR, it
means a real error occurred (e.g., -EPROBE_DEFER) and the probe must be
aborted.

Also, since the GPIO is optional, remove the dev_err() log in
aw88395_hw_reset() when the GPIO is missing to match the optional
semantics. This also fixes a potential NULL pointer dereference as
aw_pa is not initialized when aw88395_hw_reset() is called.

Signed-off-by: wangdicheng <wangdicheng@kylinos.cn>
Link: https://patch.msgid.link/20260428023408.46420-1-wangdich9700@163.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

## Phase Walkthrough
Step 1.1 Record: Subsystem `ASoC: aw88395`; action verb `Fix`; claimed
intent is preventing probe/reset crashes from invalid or missing
optional reset GPIO handling.

Step 1.2 Record: Tags found: `Signed-off-by: wangdicheng
<wangdicheng@kylinos.cn>`, `Link:
https://patch.msgid.link/20260428023408.46420-1-wangdich9700@163.com`,
`Signed-off-by: Mark Brown <broonie@kernel.org>`. No `Fixes:`,
`Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Acked-by:`, or `Cc:
stable`.

Step 1.3 Record: Commit body describes `devm_gpiod_get_optional()`
returning `ERR_PTR`, current code logging and continuing, then
`aw88395_hw_reset()` using the bad pointer. Verified an additional body
claim: `aw_pa` is uninitialized when `aw88395_hw_reset()` is called, so
the old missing-GPIO `dev_err(aw88395->aw_pa->dev, ...)` path can
dereference NULL.

Step 1.4 Record: This is a real bug fix despite also changing logging:
it fixes probe error handling and removes a pre-initialization NULL
dereference path.

Step 2.1 Record: One file changed: `sound/soc/codecs/aw88395/aw88395.c`,
4 insertions and 5 deletions. Modified functions: `aw88395_hw_reset()`
and `aw88395_i2c_probe()`. Scope is single-file surgical driver fix.

Step 2.2 Record: Hunk 1 changes missing reset GPIO from logging through
`aw88395->aw_pa->dev` to silent no-op. Hunk 2 changes
`IS_ERR(reset_gpio)` from “log and continue” to `return
dev_err_probe(...)`.

Step 2.3 Record: Bug categories: NULL pointer dereference in probe/reset
when optional GPIO is absent; probe error handling bug for `ERR_PTR`
values such as `-EPROBE_DEFER`. I could not verify the commit’s exact
claim that `gpiod_set_value_cansleep()` dereferences an `ERR_PTR`,
because current and checked stable gpiolib validate error pointers
before use.

Step 2.4 Record: Fix quality is good: minimal, contained, follows common
`devm_gpiod_get_optional()` patterns, and uses existing
`dev_err_probe()`. Regression risk is low; the behavior change is to
fail probe on real GPIO acquisition errors and stop logging through an
uninitialized pointer.

Step 3.1 Record: `git blame` shows the buggy lines were introduced by
`62fc25fbab5f4`, “ASoC: codecs: Add i2c and codec registration for
aw88395...”, first contained in `v6.3`.

Step 3.2 Record: No `Fixes:` tag, so there was no tagged introducing
commit to follow; blame identifies `62fc25fbab5f4` as the origin.

Step 3.3 Record: Recent file history shows normal aw88395 codec churn
and no prerequisite patch for this fix. On `fixes-next`, the candidate
`241ee17ecb6b` is the direct relevant change to this file.

Step 3.4 Record: `git log --author=wangdicheng` found no other local
aw88395/codecs commits by this author. Maintainer Mark Brown applied the
patch.

Step 3.5 Record: No dependent commits found. `dev_err_probe()` and the
touched code exist in the checked stable trees; the patch applies
cleanly to representative stable tags.

Step 4.1 Record: `b4 dig -c 241ee17ecb6b` matched the lore submission
`20260428023408.46420-1-wangdich9700@163.com`. `b4 dig -a` found v1 and
v2; v2 is the committed/applied version.

Step 4.2 Record: `b4 dig -w` shows recipients included Mark Brown,
Takashi Iwai, `linux-sound`, and `linux-kernel`.

Step 4.3 Record: No `Reported-by` or external bug report tag. The Link
points to the patch thread. WebFetch of lore was blocked by Anubis, but
b4 successfully retrieved the mboxes.

Step 4.4 Record: v1 changed only the `IS_ERR()` handling. Mark Brown
replied that it looked OK but noted the missing-GPIO `dev_err()` bug. v2
removed that `dev_err()` and was applied by Mark Brown to
`broonie/sound.git for-7.1` as `241ee17ecb6b`.

Step 4.5 Record: Stable-specific lore search through WebFetch was
blocked by Anubis; no stable-specific discussion was verified.

Step 5.1 Record: Modified functions are `aw88395_hw_reset()` and
`aw88395_i2c_probe()`.

Step 5.2 Record: `aw88395_hw_reset()` is called only from
`aw88395_i2c_probe()` in this file. `aw88395_i2c_probe()` is registered
as `.probe` in `aw88395_i2c_driver`.

Step 5.3 Record: Key callees include `devm_gpiod_get_optional()`,
`gpiod_set_value_cansleep()`, `devm_regmap_init_i2c()`, and later
`aw88395_init()`.

Step 5.4 Record: Call chain is I2C driver registration via
`module_i2c_driver()` -> I2C core `i2c_device_probe()` ->
`driver->probe(client)` -> `aw88395_i2c_probe()` ->
`aw88395_hw_reset()`. Trigger is device probe, not an unprivileged
syscall path.

Step 5.5 Record: Similar codec patterns usually return on
`IS_ERR(devm_gpiod_get_optional())`; `aw88166.c`, `wcd937x.c`,
`tlv320dac33.c`, and others show this local convention.

Step 6.1 Record: The driver does not exist in `v5.15` or `v6.1`. The
buggy code exists in `v6.3`, `v6.6`, `v6.12`, `v6.19`, and `v7.0`.

Step 6.2 Record: `git apply --check` passed on current `v7.0.3`;
temporary worktree checks passed cleanly on `v6.6`, `v6.12`, and
`v6.19`.

Step 6.3 Record: No related fix for this aw88395 reset GPIO issue was
found in checked `master`/file history; current stable checkout still
has the old code.

Step 7.1 Record: Subsystem is ALSA SoC codec driver under
`sound/soc/codecs`; criticality is driver-specific/peripheral, but
failure mode is severe for affected hardware.

Step 7.2 Record: aw88395 file history shows moderate ongoing maintenance
since the driver was added in v6.3.

Step 8.1 Record: Affected users are systems using the Awinic AW88395 I2C
codec driver.

Step 8.2 Record: Trigger is probe with missing optional reset GPIO, or
real GPIO acquisition failure such as deferred probe. Unprivileged users
cannot directly trigger this through a normal syscall path based on the
traced call chain.

Step 8.3 Record: Verified failure mode is probe-time NULL dereference
through `aw88395->aw_pa->dev` when `reset_gpio` is NULL before
`aw88395_init()` initializes `aw_pa`. Severity: HIGH/CRITICAL for
affected systems.

Step 8.4 Record: Benefit is high for affected hardware because it
prevents probe-time crash/misprobe. Risk is low: 9-line single-driver
change, no ABI/API changes, clean apply to representative stable trees.

Step 9.1 Record: Evidence for backporting: real NULL deref, correct
handling of `ERR_PTR`, maintainer feedback led to v2, maintainer
applied, small clean patch, affected code present in stable v6.6+.
Evidence against: no explicit reporter/test tag; exact `ERR_PTR` panic
claim was not verified because gpiolib validates error pointers.
Unresolved: no stable-specific lore discussion verified due WebFetch
blocking.

Step 9.2 Record: Stable rules: obviously correct yes; fixes real bug
yes; important issue yes, probe-time crash/oops; small and contained
yes; no new feature/API yes; applies to stable yes for checked
v6.6/v6.12/v6.19/v7.0.

Step 9.3 Record: No automatic exception category applies; this is not a
device ID, quirk, DT-only, build, or documentation patch.

Step 9.4 Record: Decision is backport. The verified NULL dereference
plus probe error handling fix outweigh the low regression risk.

## Verification
- [Phase 1] Parsed commit `241ee17ecb6be210f7b231b2a81bfb68871950d0`
  locally and confirmed tags/message.
- [Phase 2] Inspected patch and current source around
  `aw88395_hw_reset()` and `aw88395_i2c_probe()`.
- [Phase 2] Checked `drivers/gpio/gpiolib.c`: `validate_desc()` handles
  NULL and `IS_ERR()` descriptors before `gpiod_set_value_cansleep()`
  continues.
- [Phase 3] `git blame` traced both changed areas to `62fc25fbab5f4`,
  first present in `v6.3`.
- [Phase 4] `b4 dig` found v1/v2; v1 reviewer feedback from Mark Brown
  requested addressing the optional GPIO logging bug; v2 was applied.
- [Phase 5] Traced caller registration through `.probe`,
  `module_i2c_driver()`, and I2C core `driver->probe(client)`.
- [Phase 6] Verified code absent in `v5.15`/`v6.1`, present in `v6.3+`,
  and cleanly applying to `v6.6`, `v6.12`, `v6.19`, and current
  `v7.0.3`.
- [Phase 8] Verified `aw88395_malloc_init()` uses `devm_kzalloc()`, so
  `aw_pa` is NULL until later `aw88395_init()`.

**YES**

 sound/soc/codecs/aw88395/aw88395.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/sound/soc/codecs/aw88395/aw88395.c b/sound/soc/codecs/aw88395/aw88395.c
index 3602b5b9f7d77..dd09bac652f7f 100644
--- a/sound/soc/codecs/aw88395/aw88395.c
+++ b/sound/soc/codecs/aw88395/aw88395.c
@@ -456,8 +456,6 @@ static void aw88395_hw_reset(struct aw88395 *aw88395)
 		usleep_range(AW88395_1000_US, AW88395_1000_US + 10);
 		gpiod_set_value_cansleep(aw88395->reset_gpio, 1);
 		usleep_range(AW88395_1000_US, AW88395_1000_US + 10);
-	} else {
-		dev_err(aw88395->aw_pa->dev, "%s failed", __func__);
 	}
 }
 
@@ -522,9 +520,10 @@ static int aw88395_i2c_probe(struct i2c_client *i2c)
 	i2c_set_clientdata(i2c, aw88395);
 
 	aw88395->reset_gpio = devm_gpiod_get_optional(&i2c->dev, "reset", GPIOD_OUT_LOW);
-	if (IS_ERR(aw88395->reset_gpio))
-		dev_info(&i2c->dev, "reset gpio not defined\n");
-
+	if (IS_ERR(aw88395->reset_gpio)) {
+		return dev_err_probe(&i2c->dev, PTR_ERR(aw88395->reset_gpio),
+				"failed to get reset gpio\n");
+	}
 	/* hardware reset */
 	aw88395_hw_reset(aw88395);
 
-- 
2.53.0


  parent reply	other threads:[~2026-05-05  9:52 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-05  9:51 [PATCH AUTOSEL 7.0-5.10] ALSA: hda: Avoid WARN_ON() for HDMI chmap slot checks Sasha Levin
2026-05-05  9:51 ` [PATCH AUTOSEL 7.0-6.1] nvmet-tcp: check INIT_FAILED before nvmet_req_uninit in digest error path Sasha Levin
2026-05-05  9:51 ` [PATCH AUTOSEL 7.0] drm/amd/pm: Update emit clock logic Sasha Levin
2026-05-05  9:51 ` [PATCH AUTOSEL 7.0] smb: client: change allocation requirements in smb2_compound_op Sasha Levin
2026-05-05  9:51 ` [PATCH AUTOSEL 7.0-6.18] btrfs: handle -EAGAIN from btrfs_duplicate_item and refresh stale leaf pointer Sasha Levin
2026-05-05  9:51 ` [PATCH AUTOSEL 7.0-5.10] nvme: add missing MODULE_ALIAS for fabrics transports Sasha Levin
2026-05-05  9:51 ` [PATCH AUTOSEL 7.0] dpll: export __dpll_pin_change_ntf() for use under dpll_lock Sasha Levin
2026-05-05  9:51 ` [PATCH AUTOSEL 7.0-5.10] nvme-core: fix parameter name in comment Sasha Levin
2026-05-05  9:51 ` [PATCH AUTOSEL 7.0-5.10] nvme: add quirk NVME_QUIRK_IGNORE_DEV_SUBNQN for 144d:a808 (Samsung PM981/983/970 EVO Plus ) Sasha Levin
2026-05-05  9:51 ` [PATCH AUTOSEL 7.0] ASoC: spacemit: move hw constraints from hw_params to startup Sasha Levin
2026-05-05  9:51 ` [PATCH AUTOSEL 7.0-5.10] ALSA: usb-audio: apply quirk for Playstation PDP Riffmaster Sasha Levin
2026-05-05  9:51 ` [PATCH AUTOSEL 7.0-6.18] nvmet-tcp: Don't clear tls_key when freeing sq Sasha Levin
2026-05-05  9:51 ` [PATCH AUTOSEL 7.0-5.10] rculist: add list_splice_rcu() for private lists Sasha Levin
2026-05-05  9:51 ` [PATCH AUTOSEL 7.0] ALSA: hda/realtek: enable mute LED support on ThinkBook 16p Sasha Levin
2026-05-05  9:51 ` [PATCH AUTOSEL 7.0-6.18] mailbox: cix: Add IRQF_NO_SUSPEND to mailbox interrupt Sasha Levin
2026-05-05  9:51 ` [PATCH AUTOSEL 7.0-6.12] ASoC: codecs: wcd937x: fix AUX PA sequencing and mixer controls Sasha Levin
2026-05-05  9:51 ` [PATCH AUTOSEL 7.0-6.18] btrfs: replace ASSERT with proper error handling in stripe lookup fallback Sasha Levin
2026-05-05  9:51 ` [PATCH AUTOSEL 7.0-5.10] btrfs: handle unexpected free-space-tree key types Sasha Levin
2026-05-05  9:51 ` [PATCH AUTOSEL 7.0-6.18] md/raid5: Fix UAF on IO across the reshape position Sasha Levin
2026-05-05  9:51 ` [PATCH AUTOSEL 7.0-6.6] btrfs: apply first key check for readahead when possible Sasha Levin
2026-05-05  9:51 ` Sasha Levin [this message]
2026-05-05  9:51 ` [PATCH AUTOSEL 7.0-6.12] nvme-tcp: teardown circular locking fixes Sasha Levin
2026-05-05  9:51 ` [PATCH AUTOSEL 7.0-6.18] btrfs: fix wrong min_objectid in btrfs_previous_item() call Sasha Levin
2026-05-05  9:51 ` [PATCH AUTOSEL 7.0-6.18] btrfs: check return value of btrfs_partially_delete_raid_extent() Sasha Levin
2026-05-05  9:51 ` [PATCH AUTOSEL 7.0-6.18] btrfs: fix raid stripe search missing entries at leaf boundaries Sasha Levin
2026-05-05  9:51 ` [PATCH AUTOSEL 7.0-6.18] btrfs: copy devid in btrfs_partially_delete_raid_extent() Sasha Levin
2026-05-05  9:51 ` [PATCH AUTOSEL 7.0-6.18] nvme-multipath: put module reference when delayed removal work is canceled Sasha Levin
2026-05-05  9:51 ` [PATCH AUTOSEL 7.0] btrfs: abort transaction in do_remap_reloc_trans() on failure Sasha Levin
2026-05-05  9:51 ` [PATCH AUTOSEL 7.0] drm/amdkfd: check if vm ready in svm map and unmap to gpu Sasha Levin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260505095149.512052-21-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=broonie@kernel.org \
    --cc=lgirdwood@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-sound@vger.kernel.org \
    --cc=patches@lists.linux.dev \
    --cc=perex@perex.cz \
    --cc=stable@vger.kernel.org \
    --cc=tiwai@suse.com \
    --cc=wangdicheng@kylinos.cn \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox