From: "Philippe Mathieu-Daudé" <philmd@linaro.org>
To: qemu-devel@nongnu.org
Cc: "Philippe Mathieu-Daudé" <philmd@linaro.org>,
"Richard Henderson" <richard.henderson@linaro.org>,
"Beniamino Galvani" <b.galvani@gmail.com>,
"Peter Maydell" <peter.maydell@linaro.org>,
"Strahinja Jankovic" <strahinja.p.jankovic@gmail.com>,
"Bin Meng" <bmeng.cn@gmail.com>,
qemu-arm@nongnu.org, qemu-block@nongnu.org
Subject: [PULL 03/13] hw/sd/sdbus: Provide buffer size to sdbus_do_command()
Date: Tue, 5 Aug 2025 19:31:24 +0200 [thread overview]
Message-ID: <20250805173135.38045-4-philmd@linaro.org> (raw)
In-Reply-To: <20250805173135.38045-1-philmd@linaro.org>
We provide to sdbus_do_command() a pointer to a buffer to be
filled with a varying number of bytes. By not providing the
buffer size, the callee can not check the buffer is big enough.
Pass the buffer size as argument to follow good practices.
sdbus_do_command() doesn't return any error, only the size filled
in the buffer. Convert the returned type to unsigned and remove
the few unreachable lines in callers.
This allow to check for possible overflow in sd_do_command().
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20250804133406.17456-4-philmd@linaro.org>
---
include/hw/sd/sd.h | 23 +++++++++++++++++++++--
hw/sd/allwinner-sdhost.c | 7 ++-----
hw/sd/bcm2835_sdhost.c | 7 ++-----
hw/sd/core.c | 5 +++--
hw/sd/omap_mmc.c | 5 +++--
hw/sd/pl181.c | 6 ++----
hw/sd/sd.c | 6 ++++--
hw/sd/sdhci.c | 6 +++---
hw/sd/ssi-sd.c | 12 +++++++-----
9 files changed, 47 insertions(+), 30 deletions(-)
diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
index d6bad175131..55d363f58fb 100644
--- a/include/hw/sd/sd.h
+++ b/include/hw/sd/sd.h
@@ -96,7 +96,17 @@ struct SDCardClass {
DeviceClass parent_class;
/*< public >*/
- int (*do_command)(SDState *sd, SDRequest *req, uint8_t *response);
+ /**
+ * Process a SD command request.
+ * @sd: card
+ * @req: command request
+ * @resp: buffer to receive the command response
+ * @respsz: size of @resp buffer
+ *
+ * Return: size of the response
+ */
+ size_t (*do_command)(SDState *sd, SDRequest *req,
+ uint8_t *resp, size_t respsz);
/**
* Write a byte to a SD card.
* @sd: card
@@ -153,7 +163,16 @@ struct SDBusClass {
void sdbus_set_voltage(SDBus *sdbus, uint16_t millivolts);
uint8_t sdbus_get_dat_lines(SDBus *sdbus);
bool sdbus_get_cmd_line(SDBus *sdbus);
-int sdbus_do_command(SDBus *sd, SDRequest *req, uint8_t *response);
+/**
+ * sdbus_do_command: Process a SD command request
+ * @sd: card
+ * @req: command request
+ * @resp: buffer to receive the command response
+ * @respsz: size of @resp buffer
+ *
+ * Return: size of the response
+ */
+size_t sdbus_do_command(SDBus *sd, SDRequest *req, uint8_t *resp, size_t respsz);
/**
* Write a byte to a SD bus.
* @sd: bus
diff --git a/hw/sd/allwinner-sdhost.c b/hw/sd/allwinner-sdhost.c
index b31da5c399c..9d61b372e70 100644
--- a/hw/sd/allwinner-sdhost.c
+++ b/hw/sd/allwinner-sdhost.c
@@ -233,7 +233,7 @@ static void allwinner_sdhost_send_command(AwSdHostState *s)
{
SDRequest request;
uint8_t resp[16];
- int rlen;
+ size_t rlen;
/* Auto clear load flag */
s->command &= ~SD_CMDR_LOAD;
@@ -246,10 +246,7 @@ static void allwinner_sdhost_send_command(AwSdHostState *s)
request.arg = s->command_arg;
/* Send request to SD bus */
- rlen = sdbus_do_command(&s->sdbus, &request, resp);
- if (rlen < 0) {
- goto error;
- }
+ rlen = sdbus_do_command(&s->sdbus, &request, resp, sizeof(resp));
/* If the command has a response, store it in the response registers */
if ((s->command & SD_CMDR_RESPONSE)) {
diff --git a/hw/sd/bcm2835_sdhost.c b/hw/sd/bcm2835_sdhost.c
index 29debdf59e4..f7cef7bb1cd 100644
--- a/hw/sd/bcm2835_sdhost.c
+++ b/hw/sd/bcm2835_sdhost.c
@@ -113,15 +113,12 @@ static void bcm2835_sdhost_send_command(BCM2835SDHostState *s)
{
SDRequest request;
uint8_t rsp[16];
- int rlen;
+ size_t rlen;
request.cmd = s->cmd & SDCMD_CMD_MASK;
request.arg = s->cmdarg;
- rlen = sdbus_do_command(&s->sdbus, &request, rsp);
- if (rlen < 0) {
- goto error;
- }
+ rlen = sdbus_do_command(&s->sdbus, &request, rsp, sizeof(rsp));
if (!(s->cmd & SDCMD_NO_RESPONSE)) {
if (rlen == 0 || (rlen == 4 && (s->cmd & SDCMD_LONG_RESPONSE))) {
goto error;
diff --git a/hw/sd/core.c b/hw/sd/core.c
index 4b30218b520..d3c9017445e 100644
--- a/hw/sd/core.c
+++ b/hw/sd/core.c
@@ -90,7 +90,8 @@ void sdbus_set_voltage(SDBus *sdbus, uint16_t millivolts)
}
}
-int sdbus_do_command(SDBus *sdbus, SDRequest *req, uint8_t *response)
+size_t sdbus_do_command(SDBus *sdbus, SDRequest *req,
+ uint8_t *resp, size_t respsz)
{
SDState *card = get_card(sdbus);
@@ -98,7 +99,7 @@ int sdbus_do_command(SDBus *sdbus, SDRequest *req, uint8_t *response)
if (card) {
SDCardClass *sc = SDMMC_COMMON_GET_CLASS(card);
- return sc->do_command(card, req, response);
+ return sc->do_command(card, req, resp, respsz);
}
return 0;
diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c
index b7648d41cc5..5a1d25defaa 100644
--- a/hw/sd/omap_mmc.c
+++ b/hw/sd/omap_mmc.c
@@ -130,7 +130,8 @@ static void omap_mmc_command(OMAPMMCState *host, int cmd, int dir,
sd_rsp_type_t resptype, int init)
{
uint32_t rspstatus, mask;
- int rsplen, timeout;
+ size_t rsplen;
+ int timeout;
SDRequest request;
uint8_t response[16];
@@ -157,7 +158,7 @@ static void omap_mmc_command(OMAPMMCState *host, int cmd, int dir,
request.arg = host->arg;
request.crc = 0; /* FIXME */
- rsplen = sdbus_do_command(&host->sdbus, &request, response);
+ rsplen = sdbus_do_command(&host->sdbus, &request, response, sizeof(response));
/* TODO: validate CRCs */
switch (resptype) {
diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
index b8fc9f86f13..5d56ead4d91 100644
--- a/hw/sd/pl181.c
+++ b/hw/sd/pl181.c
@@ -173,14 +173,12 @@ static void pl181_do_command(PL181State *s)
{
SDRequest request;
uint8_t response[16];
- int rlen;
+ size_t rlen;
request.cmd = s->cmd & PL181_CMD_INDEX;
request.arg = s->cmdarg;
trace_pl181_command_send(request.cmd, request.arg);
- rlen = sdbus_do_command(&s->sdbus, &request, response);
- if (rlen < 0)
- goto error;
+ rlen = sdbus_do_command(&s->sdbus, &request, response, sizeof(response));
if (s->cmd & PL181_CMD_RESPONSE) {
if (rlen == 0 || (rlen == 4 && (s->cmd & PL181_CMD_LONGRESP)))
goto error;
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 76ce54664f2..069107a2e70 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -2166,8 +2166,9 @@ static bool cmd_valid_while_locked(SDState *sd, unsigned cmd)
return cmd_class == 0 || cmd_class == 7;
}
-static int sd_do_command(SDState *sd, SDRequest *req,
- uint8_t *response) {
+static size_t sd_do_command(SDState *sd, SDRequest *req,
+ uint8_t *response, size_t respsz)
+{
int last_state;
sd_rsp_type_t rtype;
int rsplen;
@@ -2231,6 +2232,7 @@ static int sd_do_command(SDState *sd, SDRequest *req,
send_response:
rsplen = sd_response_size(sd, rtype);
+ assert(rsplen <= respsz);
switch (rtype) {
case sd_r1:
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 226ff133ff9..3c897e54b72 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -337,7 +337,7 @@ static void sdhci_send_command(SDHCIState *s)
{
SDRequest request;
uint8_t response[16];
- int rlen;
+ size_t rlen;
bool timeout = false;
s->errintsts = 0;
@@ -346,7 +346,7 @@ static void sdhci_send_command(SDHCIState *s)
request.arg = s->argument;
trace_sdhci_send_command(request.cmd, request.arg);
- rlen = sdbus_do_command(&s->sdbus, &request, response);
+ rlen = sdbus_do_command(&s->sdbus, &request, response, sizeof(response));
if (s->cmdreg & SDHC_CMD_RESPONSE) {
if (rlen == 4) {
@@ -400,7 +400,7 @@ static void sdhci_end_transfer(SDHCIState *s)
request.cmd = 0x0C;
request.arg = 0;
trace_sdhci_end_transfer(request.cmd, request.arg);
- sdbus_do_command(&s->sdbus, &request, response);
+ sdbus_do_command(&s->sdbus, &request, response, sizeof(response));
/* Auto CMD12 response goes to the upper Response register */
s->rspreg[3] = ldl_be_p(response);
}
diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c
index 6c90a86ab41..3025f8f15f4 100644
--- a/hw/sd/ssi-sd.c
+++ b/hw/sd/ssi-sd.c
@@ -146,8 +146,9 @@ static uint32_t ssi_sd_transfer(SSIPeripheral *dev, uint32_t val)
/* manually issue cmd12 to stop the transfer */
request.cmd = 12;
request.arg = 0;
- s->arglen = sdbus_do_command(&s->sdbus, &request, longresp);
- if (s->arglen <= 0) {
+ s->arglen = sdbus_do_command(&s->sdbus, &request,
+ longresp, sizeof(longresp));
+ if (s->arglen == 0) {
s->arglen = 1;
/* a zero value indicates the card is busy */
s->response[0] = 0;
@@ -171,8 +172,9 @@ static uint32_t ssi_sd_transfer(SSIPeripheral *dev, uint32_t val)
request.cmd = s->cmd;
request.arg = ldl_be_p(s->cmdarg);
DPRINTF("CMD%d arg 0x%08x\n", s->cmd, request.arg);
- s->arglen = sdbus_do_command(&s->sdbus, &request, longresp);
- if (s->arglen <= 0) {
+ s->arglen = sdbus_do_command(&s->sdbus, &request,
+ longresp, sizeof(longresp));
+ if (s->arglen == 0) {
s->arglen = 1;
s->response[0] = 4;
DPRINTF("SD command failed\n");
@@ -333,7 +335,7 @@ static int ssi_sd_post_load(void *opaque, int version_id)
return -EINVAL;
}
if (s->mode == SSI_SD_CMDARG &&
- (s->arglen < 0 || s->arglen >= ARRAY_SIZE(s->cmdarg))) {
+ (s->arglen >= ARRAY_SIZE(s->cmdarg))) {
return -EINVAL;
}
if (s->mode == SSI_SD_RESPONSE &&
--
2.49.0
next prev parent reply other threads:[~2025-08-05 17:32 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-05 17:31 [PULL 00/13] Misc HW patches for 2025-08-05 Philippe Mathieu-Daudé
2025-08-05 17:31 ` [PULL 01/13] hw/sd/sdcard: Do not ignore errors in sd_cmd_to_sendingdata() Philippe Mathieu-Daudé
2025-08-05 17:31 ` [PULL 02/13] hw/sd/sdcard: Factor sd_response_size() out Philippe Mathieu-Daudé
2025-08-05 17:31 ` Philippe Mathieu-Daudé [this message]
2025-08-05 17:31 ` [PULL 04/13] hw/sd/sdcard: Fill SPI response bits in card code Philippe Mathieu-Daudé
2025-08-05 17:31 ` [PULL 05/13] hw/sd/sdcard: Implement SPI R2 return value Philippe Mathieu-Daudé
2025-08-05 17:31 ` [PULL 06/13] hw/sd/sdcard: Use complete SEND_OP_COND implementation in SPI mode Philippe Mathieu-Daudé
2025-08-05 17:31 ` [PULL 07/13] hw/sd/sdcard: Allow using SWITCH_FUNCTION in more SPI states Philippe Mathieu-Daudé
2025-08-05 17:31 ` [PULL 08/13] hw/sd/sdcard: Factor spi_cmd_SEND_CxD() out Philippe Mathieu-Daudé
2025-08-05 17:31 ` [PULL 09/13] hw/sd/sdcard: Disable checking STBY mode in SPI SEND_CSD/CID Philippe Mathieu-Daudé
2025-08-05 17:31 ` [PULL 10/13] hw/sd/sdcard: Remove SDState::mode field Philippe Mathieu-Daudé
2025-08-05 17:31 ` [PULL 11/13] tests/functional: Test SD cards in SPI mode (using sifive_u machine) Philippe Mathieu-Daudé
2025-08-06 17:58 ` Pierrick Bouvier
2025-08-05 17:31 ` [PULL 12/13] target/i386/cpu: Move addressable ID encoding out of compat property in CPUID[0x1] Philippe Mathieu-Daudé
2025-08-05 17:31 ` [PULL 13/13] hw/i386/microvm: Explicitly select ACPI_PCI Philippe Mathieu-Daudé
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250805173135.38045-4-philmd@linaro.org \
--to=philmd@linaro.org \
--cc=b.galvani@gmail.com \
--cc=bmeng.cn@gmail.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-arm@nongnu.org \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=richard.henderson@linaro.org \
--cc=strahinja.p.jankovic@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).