]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ASoC: SOF: ipc4-topology: Correct the allocation size for bytes controls
authorPeter Ujfalusi <peter.ujfalusi@linux.intel.com>
Wed, 17 Dec 2025 14:39:39 +0000 (16:39 +0200)
committerMark Brown <broonie@kernel.org>
Wed, 17 Dec 2025 16:35:45 +0000 (16:35 +0000)
The size of the data behind of scontrol->ipc_control_data for bytes
controls is:
[1] sizeof(struct sof_ipc4_control_data) + // kernel only struct
[2] sizeof(struct sof_abi_hdr)) + payload

The max_size specifies the size of [2] and it is coming from topology.

Change the function to take this into account and allocate adequate amount
of memory behind scontrol->ipc_control_data.

With the change we will allocate [1] amount more memory to be able to hold
the full size of data.

Fixes: a382082ff74b ("ASoC: SOF: ipc4-topology: Add support for TPLG_CTL_BYTES")
Cc: stable@vger.kernel.org
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Link: https://patch.msgid.link/20251217143945.2667-3-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sof/ipc4-topology.c

index 221e9d4052b8f0ef823def6c8e31f22d0b857839..4272d84679ac1f1d44aa202deedb6bbd1a500e27 100644 (file)
@@ -2855,22 +2855,41 @@ static int sof_ipc4_control_load_bytes(struct snd_sof_dev *sdev, struct snd_sof_
        struct sof_ipc4_msg *msg;
        int ret;
 
-       if (scontrol->max_size < (sizeof(*control_data) + sizeof(struct sof_abi_hdr))) {
-               dev_err(sdev->dev, "insufficient size for a bytes control %s: %zu.\n",
+       /*
+        * The max_size is coming from topology and indicates the maximum size
+        * of sof_abi_hdr plus the payload, which excludes the local only
+        * 'struct sof_ipc4_control_data'
+        */
+       if (scontrol->max_size < sizeof(struct sof_abi_hdr)) {
+               dev_err(sdev->dev,
+                       "insufficient maximum size for a bytes control %s: %zu.\n",
                        scontrol->name, scontrol->max_size);
                return -EINVAL;
        }
 
-       if (scontrol->priv_size > scontrol->max_size - sizeof(*control_data)) {
-               dev_err(sdev->dev, "scontrol %s bytes data size %zu exceeds max %zu.\n",
-                       scontrol->name, scontrol->priv_size,
-                       scontrol->max_size - sizeof(*control_data));
+       if (scontrol->priv_size > scontrol->max_size) {
+               dev_err(sdev->dev,
+                       "bytes control %s initial data size %zu exceeds max %zu.\n",
+                       scontrol->name, scontrol->priv_size, scontrol->max_size);
+               return -EINVAL;
+       }
+
+       if (scontrol->priv_size < sizeof(struct sof_abi_hdr)) {
+               dev_err(sdev->dev,
+                       "bytes control %s initial data size %zu is insufficient.\n",
+                       scontrol->name, scontrol->priv_size);
                return -EINVAL;
        }
 
-       scontrol->size = sizeof(struct sof_ipc4_control_data) + scontrol->priv_size;
+       /*
+        * The used size behind the cdata pointer, which can be smaller than
+        * the maximum size
+        */
+       scontrol->size = sizeof(*control_data) + scontrol->priv_size;
 
-       scontrol->ipc_control_data = kzalloc(scontrol->max_size, GFP_KERNEL);
+       /* Allocate the cdata: local struct size + maximum payload size */
+       scontrol->ipc_control_data = kzalloc(sizeof(*control_data) + scontrol->max_size,
+                                            GFP_KERNEL);
        if (!scontrol->ipc_control_data)
                return -ENOMEM;