]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ASoC: sma1307: Fix uevent string leaks in fault worker
authorCássio Gabriel <cassiogabrielcontato@gmail.com>
Tue, 9 Jun 2026 12:03:56 +0000 (09:03 -0300)
committerMark Brown <broonie@kernel.org>
Tue, 9 Jun 2026 17:41:45 +0000 (18:41 +0100)
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: 576c57e6b4c1 ("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>
sound/soc/codecs/sma1307.c

index 1de6bd1e4ee7ec2c95ac6ad1a4edf27cafe70cd4..c52fe95b30c6ad4f130c51500ce30b31967d519b 100644 (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) {