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
next prev parent reply other threads:[~2026-05-05 9:52 UTC|newest]
Thread overview: 30+ 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 ` 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.