From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1794591396; b=NxOoI07bOGNePk7i+IHgYAJTorFM2BSkdQN9EEDpXbwTVc8i0K5WfBj1hjhAqTkGjcCy vs4feaWTc5AvdizflTSCk/fzOVlptWc2CX88wrtfc8dhwQAAnmbN9mH98ZqwS4xXxjnfg ufEEjhNtJ0IRNiUXrFRjXf5drelyr2NyMPrGh/pEA0Mzg+jWlE5GcgfZyZ4GiR5JIdPm2 oxMHu6zo9dBtKAtwxT1bscC5wVHmW2X2TA5OgkyjPTmp+aAgu0K1ATdfdE/V4oOM06xx8 weo4j6zunwru+RDb/1qkEF/eDeKANWwYCrhsWDV9o/jh0Ol2oS4h+daujnoJ1VaTgGw== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1794591396; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:User-Agent:X-stable:X-Patchwork-Hint: MIME-Version:Content-Transfer-Encoding; bh=OZMWfcla9r8uZQXwOrTETvhnybyedKED7iZAzoTJFgo=; b=RaJGLUrcZKuux/ZrbxzDB9mFCYw4c4oPaUOP6KBWpuVlXShpqZoVSoJKzfRyZ7SrWk6o 1sjO5MtsEMCy7QQt9ji/SowcNcGmcrYAciqCoyEqpaL5t3ZXNGCuXP4FM3CHwgeKEK+LI tUdT9RsKOptdrEgr4jJ6e0kutZ+gHpqqBDxbUsiyRbehmYKK57yfvubehGpiKu4vQ4sR5 VKVdc0SbA5YVMwYKDxW7xwiC0z8kdYFS0PBqcsa0u/SvlJZx6YirIKAgA/Civ/8UzY6o6 PwhhfLMt0z6IVsR1K9kDL33rV4ubXCYtiwAN7eYzSTTy69ZL5LBby/zicwT+EPr+EYQ== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=linuxfoundation.org header.i=@linuxfoundation.org header.a=rsa-sha256 header.s=korg header.b=Tx4NN83Y; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C35616079D44; Fri, 13 Nov 2026 17:36:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.a=rsa-sha256 header.s=korg header.b=Tx4NN83Y Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6FE781F000C4; Fri, 13 Nov 2026 17:36:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1794591396; bh=OZMWfcla9r8uZQXwOrTETvhnybyedKED7iZAzoTJFgo=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Tx4NN83YP+8bvwehswHfo362dX2mvOtydHWnacp4uruclNb4sOSpm1Ii/BzA0q9VK lTQjlahkvusHlNzkUYPsCzJ/EXDGvaah5SAdwIZnhccAnqAoDahicd6HsmuiB7ojW/ DZkmH+n1FSRhVMCl9AArSm/U9q9jKlvoP91PqMFw= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Weibin Liu , Mark Brown , Sasha Levin Subject: [PATCH 6.12 495/670] spi: cadence-xspi: reject SDMA transfers larger than the requested length Date: Fri, 13 Nov 2026 10:50:59 -0500 Message-ID: <20261113153828.705208661@linuxfoundation.org> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261113153811.177190860@linuxfoundation.org> References: <20261113153811.177190860@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore X-Mailing-List: stable@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 6.12-stable review patch. If anyone has any objections, please let me know. ------------------ From: Weibin Liu [ Upstream commit ea9854a169e9c1437df8829bea21c2f2e80b137c ] The XSPI controller reports the size of the slave-DMA transaction through SDMA_SIZE_REG. Both SDMA handlers take this register at face value and copy the reported number of bytes between the SDMA FIFO and the transfer buffers, without checking it against the length of the transfer that was actually requested. While cdns_xspi_adjust_mem_op_size() clamps the size of the operations issued by the SPI core, the device can still report a bigger SDMA size than what was programmed, which makes the handlers read from or write to memory beyond the end of the transfer buffers. Track the number of bytes requested for the current data phase in a new sdma_xfer_len field, set by cdns_xspi_send_stig_command() and by the Marvell b0 transfer path, and reject any SDMA size that exceeds it. Fixes: a16cc8077627 ("spi: cadence: add support for Cadence XSPI controller") Cc: stable@vger.kernel.org # 5.16+ Signed-off-by: Weibin Liu Link: https://patch.msgid.link/20260929081146.41041-2-liuwb@xiaopeng.com Signed-off-by: Mark Brown [ sashal: adjusted context for direct SDMA I/O calls instead of helper functions ] Signed-off-by: Sasha Levin --- drivers/spi/spi-cadence-xspi.c | 36 +++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/drivers/spi/spi-cadence-xspi.c b/drivers/spi/spi-cadence-xspi.c index c12930ce67472..ca6af39e977a4 100644 --- a/drivers/spi/spi-cadence-xspi.c +++ b/drivers/spi/spi-cadence-xspi.c @@ -332,6 +332,7 @@ struct cdns_xspi_dev { int irq; int cur_cs; unsigned int sdmasize; + unsigned int sdma_xfer_len; struct completion cmd_complete; struct completion auto_cmd_complete; @@ -344,7 +345,7 @@ struct cdns_xspi_dev { u8 hw_num_banks; const struct cdns_xspi_driver_data *driver_data; - void (*sdma_handler)(struct cdns_xspi_dev *cdns_xspi); + int (*sdma_handler)(struct cdns_xspi_dev *cdns_xspi); void (*set_interrupts_handler)(struct cdns_xspi_dev *cdns_xspi, bool enabled); bool xfer_in_progress; @@ -445,7 +446,7 @@ static int cdns_xspi_controller_init(struct cdns_xspi_dev *cdns_xspi) return 0; } -static void cdns_xspi_sdma_handle(struct cdns_xspi_dev *cdns_xspi) +static int cdns_xspi_sdma_handle(struct cdns_xspi_dev *cdns_xspi) { u32 sdma_size, sdma_trd_info; u8 sdma_dir; @@ -454,6 +455,13 @@ static void cdns_xspi_sdma_handle(struct cdns_xspi_dev *cdns_xspi) sdma_trd_info = readl(cdns_xspi->iobase + CDNS_XSPI_SDMA_TRD_INFO_REG); sdma_dir = FIELD_GET(CDNS_XSPI_SDMA_DIR, sdma_trd_info); + if (sdma_size > cdns_xspi->sdma_xfer_len) { + dev_err(cdns_xspi->dev, + "SDMA size %u exceeds the requested length %u\n", + sdma_size, cdns_xspi->sdma_xfer_len); + return -EINVAL; + } + switch (sdma_dir) { case CDNS_XSPI_SDMA_DIR_READ: ioread8_rep(cdns_xspi->sdmabase, @@ -465,6 +473,8 @@ static void cdns_xspi_sdma_handle(struct cdns_xspi_dev *cdns_xspi) cdns_xspi->out_buffer, sdma_size); break; } + + return 0; } static int cdns_xspi_send_stig_command(struct cdns_xspi_dev *cdns_xspi, @@ -510,6 +520,7 @@ static int cdns_xspi_send_stig_command(struct cdns_xspi_dev *cdns_xspi, cdns_xspi->in_buffer = op->data.buf.in; cdns_xspi->out_buffer = op->data.buf.out; + cdns_xspi->sdma_xfer_len = op->data.nbytes; cdns_xspi_trigger_command(cdns_xspi, cmd_regs); @@ -518,7 +529,11 @@ static int cdns_xspi_send_stig_command(struct cdns_xspi_dev *cdns_xspi, cdns_xspi->set_interrupts_handler(cdns_xspi, false); return -EIO; } - cdns_xspi->sdma_handler(cdns_xspi); + ret = cdns_xspi->sdma_handler(cdns_xspi); + if (ret) { + cdns_xspi->set_interrupts_handler(cdns_xspi, false); + return ret; + } } wait_for_completion(&cdns_xspi->cmd_complete); @@ -900,7 +915,7 @@ static void m_iowriteq(void __iomem *addr, const void *buf, int len) } } -static void marvell_xspi_sdma_handle(struct cdns_xspi_dev *cdns_xspi) +static int marvell_xspi_sdma_handle(struct cdns_xspi_dev *cdns_xspi) { u32 sdma_size, sdma_trd_info; u8 sdma_dir; @@ -909,6 +924,13 @@ static void marvell_xspi_sdma_handle(struct cdns_xspi_dev *cdns_xspi) sdma_trd_info = readl(cdns_xspi->iobase + CDNS_XSPI_SDMA_TRD_INFO_REG); sdma_dir = FIELD_GET(CDNS_XSPI_SDMA_DIR, sdma_trd_info); + if (sdma_size > cdns_xspi->sdma_xfer_len) { + dev_err(cdns_xspi->dev, + "SDMA size %u exceeds the requested length %u\n", + sdma_size, cdns_xspi->sdma_xfer_len); + return -EINVAL; + } + switch (sdma_dir) { case CDNS_XSPI_SDMA_DIR_READ: m_ioreadq(cdns_xspi->sdmabase, @@ -920,6 +942,8 @@ static void marvell_xspi_sdma_handle(struct cdns_xspi_dev *cdns_xspi) cdns_xspi->out_buffer, sdma_size); break; } + + return 0; } static const struct spi_controller_mem_ops marvell_xspi_mem_ops = { @@ -1084,9 +1108,11 @@ static int cdns_xspi_transfer_one_message_b0(struct spi_controller *controller, cdns_xspi_prepare_transfer(cs, 1, current_transfer_len - 1, cmd_regs); cdns_xspi_trigger_command(cdns_xspi, cmd_regs); + cdns_xspi->sdma_xfer_len = current_transfer_len - 1; if (!cdns_xspi_is_sdma_ready(cdns_xspi, true)) return -EIO; - cdns_xspi->sdma_handler(cdns_xspi); + if (cdns_xspi->sdma_handler(cdns_xspi)) + return -EIO; if (!cdns_xspi_is_stig_ready(cdns_xspi, true)) return -EIO; -- 2.53.0