ASoC: SOF: ipc-msg-injector: Cap the rmaining to count in IPC4 mode
authorPeter Ujfalusi <peter.ujfalusi@linux.intel.com>
Mon, 16 May 2022 09:24:42 +0000 (12:24 +0300)
committerMark Brown <broonie@kernel.org>
Tue, 17 May 2022 10:58:11 +0000 (11:58 +0100)
If user space provides smaller buffer than the IPC4 reply then it is
possible that we corrupt user space memory since the IPC4 dfs_read function
is not using the count directly in copy_to_user() due to the nature of
an IPC4 message.

Cap the remaining counter to make sure that we are not writing too much to
the user space provided buffer.

Add a check also to make sure that the buffer is at least the size of the
IPC4 header.

Fixes: 066c67624d8c: "ASoC: SOF: ipc-msg-injector: Add support for IPC4 messages"
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Link: https://lore.kernel.org/r/20220516092442.17027-1-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sof/sof-client-ipc-msg-injector.c

index c2480317730cc15354ee7d7bcda9aa49e4d2bb67..03490a4d4ae722f077b336057b07429901db7501 100644 (file)
@@ -76,12 +76,17 @@ static ssize_t sof_msg_inject_ipc4_dfs_read(struct file *file,
        struct sof_client_dev *cdev = file->private_data;
        struct sof_msg_inject_priv *priv = cdev->data;
        struct sof_ipc4_msg *ipc4_msg = priv->rx_buffer;
+       size_t header_size = sizeof(ipc4_msg->header_u64);
        size_t remaining;
 
        if (!ipc4_msg->header_u64 || !count || *ppos)
                return 0;
 
-       remaining = sizeof(ipc4_msg->header_u64);
+       /* we need space for the header at minimum (u64) */
+       if (count < header_size)
+               return -ENOSPC;
+
+       remaining = header_size;
 
        /* Only get large config have payload */
        if (SOF_IPC4_MSG_IS_MODULE_MSG(ipc4_msg->primary) &&
@@ -90,13 +95,15 @@ static ssize_t sof_msg_inject_ipc4_dfs_read(struct file *file,
 
        if (count > remaining)
                count = remaining;
+       else if (count < remaining)
+               remaining = count;
 
        /* copy the header first */
-       if (copy_to_user(buffer, &ipc4_msg->header_u64, sizeof(ipc4_msg->header_u64)))
+       if (copy_to_user(buffer, &ipc4_msg->header_u64, header_size))
                return -EFAULT;
 
-       *ppos += sizeof(ipc4_msg->header_u64);
-       remaining -= sizeof(ipc4_msg->header_u64);
+       *ppos += header_size;
+       remaining -= header_size;
 
        if (!remaining)
                return count;