ASoC: sma1307: Fix uevent string leaks in fault worker

sma1307_check_fault_worker() stores dynamically allocated uevent strings in
envp[0]. Several fault conditions are checked in sequence, so a later fault
can overwrite envp[0] before the final kfree() and leak the previous
allocation.

The same flow can leave an OT1 volume entry in envp[1] while envp[0]
has been overwritten by a later non-OT1 fault, causing an inconsistent
uevent payload.

Use static STATUS strings and a stack buffer for the optional VOLUME entry.
This removes the allocations from the worker and keeps VOLUME tied only
to the OT1 events that produce it.

Fixes: 576c57e6b4 ("ASoC: sma1307: Add driver for Iron Device SMA1307")
Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
Link: https://patch.msgid.link/20260609-asoc-sma1307-uevent-leak-v1-1-cd7f5b062ab7@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Cássio Gabriel 2026-06-09 09:03:56 -03:00 committed by Mark Brown
parent 9f0b311829
commit a750ca72af
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0

View File

@ -1592,6 +1592,7 @@ static void sma1307_check_fault_worker(struct work_struct *work)
struct sma1307_priv *sma1307 =
container_of(work, struct sma1307_priv, check_fault_work.work);
unsigned int status1_val, status2_val;
char volume[sizeof("VOLUME=0x12345678")];
char *envp[3] = { NULL, NULL, NULL };
if (sma1307->tsdw_cnt)
@ -1607,7 +1608,7 @@ static void sma1307_check_fault_worker(struct work_struct *work)
if (~status1_val & SMA1307_OT1_OK_STATUS) {
dev_crit(sma1307->dev,
"%s: OT1(Over Temperature Level 1)\n", __func__);
envp[0] = kasprintf(GFP_KERNEL, "STATUS=OT1");
envp[0] = "STATUS=OT1";
if (sma1307->sw_ot1_prot) {
/* Volume control (Current Volume -3dB) */
if ((sma1307->cur_vol + 6) <= 0xFA) {
@ -1615,8 +1616,9 @@ static void sma1307_check_fault_worker(struct work_struct *work)
regmap_write(sma1307->regmap,
SMA1307_0A_SPK_VOL,
sma1307->cur_vol);
envp[1] = kasprintf(GFP_KERNEL,
"VOLUME=0x%02X", sma1307->cur_vol);
snprintf(volume, sizeof(volume),
"VOLUME=0x%02X", sma1307->cur_vol);
envp[1] = volume;
}
}
sma1307->tsdw_cnt++;
@ -1625,48 +1627,53 @@ static void sma1307_check_fault_worker(struct work_struct *work)
SMA1307_0A_SPK_VOL, sma1307->init_vol);
sma1307->tsdw_cnt = 0;
sma1307->cur_vol = sma1307->init_vol;
envp[0] = kasprintf(GFP_KERNEL, "STATUS=OT1_CLEAR");
envp[1] = kasprintf(GFP_KERNEL,
"VOLUME=0x%02X", sma1307->cur_vol);
envp[0] = "STATUS=OT1_CLEAR";
snprintf(volume, sizeof(volume), "VOLUME=0x%02X",
sma1307->cur_vol);
envp[1] = volume;
}
if (~status1_val & SMA1307_OT2_OK_STATUS) {
dev_crit(sma1307->dev,
"%s: OT2(Over Temperature Level 2)\n", __func__);
envp[0] = kasprintf(GFP_KERNEL, "STATUS=OT2");
envp[0] = "STATUS=OT2";
envp[1] = NULL;
}
if (status1_val & SMA1307_UVLO_STATUS) {
dev_crit(sma1307->dev,
"%s: UVLO(Under Voltage Lock Out)\n", __func__);
envp[0] = kasprintf(GFP_KERNEL, "STATUS=UVLO");
envp[0] = "STATUS=UVLO";
envp[1] = NULL;
}
if (status1_val & SMA1307_OVP_BST_STATUS) {
dev_crit(sma1307->dev,
"%s: OVP_BST(Over Voltage Protection)\n", __func__);
envp[0] = kasprintf(GFP_KERNEL, "STATUS=OVP_BST");
envp[0] = "STATUS=OVP_BST";
envp[1] = NULL;
}
if (status2_val & SMA1307_OCP_SPK_STATUS) {
dev_crit(sma1307->dev,
"%s: OCP_SPK(Over Current Protect SPK)\n", __func__);
envp[0] = kasprintf(GFP_KERNEL, "STATUS=OCP_SPK");
envp[0] = "STATUS=OCP_SPK";
envp[1] = NULL;
}
if (status2_val & SMA1307_OCP_BST_STATUS) {
dev_crit(sma1307->dev,
"%s: OCP_BST(Over Current Protect Boost)\n", __func__);
envp[0] = kasprintf(GFP_KERNEL, "STATUS=OCP_BST");
envp[0] = "STATUS=OCP_BST";
envp[1] = NULL;
}
if (status2_val & SMA1307_CLK_MON_STATUS) {
dev_crit(sma1307->dev,
"%s: CLK_FAULT(No clock input)\n", __func__);
envp[0] = kasprintf(GFP_KERNEL, "STATUS=CLK_FAULT");
envp[0] = "STATUS=CLK_FAULT";
envp[1] = NULL;
}
if (envp[0] != NULL) {
if (kobject_uevent_env(sma1307->kobj, KOBJ_CHANGE, envp))
dev_err(sma1307->dev,
"%s: Error sending uevent\n", __func__);
kfree(envp[0]);
kfree(envp[1]);
}
if (sma1307->check_fault_status) {