From 87511bb878b2fc6618bee71add5c28c4e3d36d60 Mon Sep 17 00:00:00 2001 From: Zheyu Ma Date: Thu, 20 Jun 2024 16:02:39 +0200 Subject: [PATCH 1/6] hw/gpio/aspeed: Add reg_table_count to AspeedGPIOClass MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ASan detected a global-buffer-overflow error in the aspeed_gpio_read() function. This issue occurred when reading beyond the bounds of the reg_table. To enhance the safety and maintainability of the Aspeed GPIO code, this commit introduces a reg_table_count member to the AspeedGPIOClass structure. This change ensures that the size of the GPIO register table is explicitly tracked and initialized, reducing the risk of errors if new register tables are introduced in the future. Reproducer: cat << EOF | qemu-system-aarch64 -display none \ -machine accel=qtest, -m 512M -machine ast1030-evb -qtest stdio readq 0x7e780272 EOF ASAN log indicating the issue: ==2602930==ERROR: AddressSanitizer: global-buffer-overflow on address 0x55a5da29e128 at pc 0x55a5d700dc62 bp 0x7fff096c4e90 sp 0x7fff096c4e88 READ of size 2 at 0x55a5da29e128 thread T0 #0 0x55a5d700dc61 in aspeed_gpio_read hw/gpio/aspeed_gpio.c:564:14 #1 0x55a5d933f3ab in memory_region_read_accessor system/memory.c:445:11 #2 0x55a5d92fba40 in access_with_adjusted_size system/memory.c:573:18 #3 0x55a5d92f842c in memory_region_dispatch_read1 system/memory.c:1426:16 #4 0x55a5d92f7b68 in memory_region_dispatch_read system/memory.c:1459:9 #5 0x55a5d9376ad1 in flatview_read_continue_step system/physmem.c:2836:18 #6 0x55a5d9376399 in flatview_read_continue system/physmem.c:2877:19 #7 0x55a5d93775b8 in flatview_read system/physmem.c:2907:12 Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2355 Signed-off-by: Zheyu Ma Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Andrew Jeffery --- hw/gpio/aspeed_gpio.c | 17 +++++++++++++++++ include/hw/gpio/aspeed_gpio.h | 1 + 2 files changed, 18 insertions(+) diff --git a/hw/gpio/aspeed_gpio.c b/hw/gpio/aspeed_gpio.c index c1781e2ba3..6474bb8de5 100644 --- a/hw/gpio/aspeed_gpio.c +++ b/hw/gpio/aspeed_gpio.c @@ -559,6 +559,12 @@ static uint64_t aspeed_gpio_read(void *opaque, hwaddr offset, uint32_t size) return debounce_value; } + if (idx >= agc->reg_table_count) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: idx 0x%" PRIx64 " out of bounds\n", + __func__, idx); + return 0; + } + reg = &agc->reg_table[idx]; if (reg->set_idx >= agc->nr_gpio_sets) { qemu_log_mask(LOG_GUEST_ERROR, "%s: no getter for offset 0x%" @@ -785,6 +791,12 @@ static void aspeed_gpio_write(void *opaque, hwaddr offset, uint64_t data, return; } + if (idx >= agc->reg_table_count) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: idx 0x%" PRIx64 " out of bounds\n", + __func__, idx); + return; + } + reg = &agc->reg_table[idx]; if (reg->set_idx >= agc->nr_gpio_sets) { qemu_log_mask(LOG_GUEST_ERROR, "%s: no setter for offset 0x%" @@ -1117,6 +1129,7 @@ static void aspeed_gpio_ast2400_class_init(ObjectClass *klass, void *data) agc->nr_gpio_pins = 216; agc->nr_gpio_sets = 7; agc->reg_table = aspeed_3_3v_gpios; + agc->reg_table_count = GPIO_3_3V_REG_ARRAY_SIZE; } static void aspeed_gpio_2500_class_init(ObjectClass *klass, void *data) @@ -1127,6 +1140,7 @@ static void aspeed_gpio_2500_class_init(ObjectClass *klass, void *data) agc->nr_gpio_pins = 228; agc->nr_gpio_sets = 8; agc->reg_table = aspeed_3_3v_gpios; + agc->reg_table_count = GPIO_3_3V_REG_ARRAY_SIZE; } static void aspeed_gpio_ast2600_3_3v_class_init(ObjectClass *klass, void *data) @@ -1137,6 +1151,7 @@ static void aspeed_gpio_ast2600_3_3v_class_init(ObjectClass *klass, void *data) agc->nr_gpio_pins = 208; agc->nr_gpio_sets = 7; agc->reg_table = aspeed_3_3v_gpios; + agc->reg_table_count = GPIO_3_3V_REG_ARRAY_SIZE; } static void aspeed_gpio_ast2600_1_8v_class_init(ObjectClass *klass, void *data) @@ -1147,6 +1162,7 @@ static void aspeed_gpio_ast2600_1_8v_class_init(ObjectClass *klass, void *data) agc->nr_gpio_pins = 36; agc->nr_gpio_sets = 2; agc->reg_table = aspeed_1_8v_gpios; + agc->reg_table_count = GPIO_1_8V_REG_ARRAY_SIZE; } static void aspeed_gpio_1030_class_init(ObjectClass *klass, void *data) @@ -1157,6 +1173,7 @@ static void aspeed_gpio_1030_class_init(ObjectClass *klass, void *data) agc->nr_gpio_pins = 151; agc->nr_gpio_sets = 6; agc->reg_table = aspeed_3_3v_gpios; + agc->reg_table_count = GPIO_3_3V_REG_ARRAY_SIZE; } static const TypeInfo aspeed_gpio_info = { diff --git a/include/hw/gpio/aspeed_gpio.h b/include/hw/gpio/aspeed_gpio.h index 904eecf62c..90a12ae318 100644 --- a/include/hw/gpio/aspeed_gpio.h +++ b/include/hw/gpio/aspeed_gpio.h @@ -75,6 +75,7 @@ struct AspeedGPIOClass { uint32_t nr_gpio_pins; uint32_t nr_gpio_sets; const AspeedGPIOReg *reg_table; + unsigned reg_table_count; }; struct AspeedGPIOState { From 56a37eda93edafabcc4de0184b88d082ede6dec1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Mon, 24 Jun 2024 19:29:18 +0200 Subject: [PATCH 2/6] aspeed: Deprecate the tacoma-bmc machine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tacoma-bmc machine was a board including an AST2600 SoC based BMC and a witherspoon like OpenPOWER system. It was used for bring up of the AST2600 SoC in labs. It can be easily replaced by the rainier-bmc machine which is part of a real product offering. Signed-off-by: Cédric Le Goater Reviewed-by: Philippe Mathieu-Daudé --- docs/about/deprecated.rst | 8 ++++++++ hw/arm/aspeed.c | 2 ++ 2 files changed, 10 insertions(+) diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index ff3da68208..5d9e4d8de7 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -256,6 +256,14 @@ images are not available, OpenWRT dropped support in 2019, U-Boot in 2017, Linux also is dropping support in 2024. It is time to let go of this ancient hardware and focus on newer CPUs and platforms. +Arm ``tacoma-bmc`` machine (since 9.1) +'''''''''''''''''''''''''''''''''''''''' + +The ``tacoma-bmc`` machine was a board including an AST2600 SoC based +BMC and a witherspoon like OpenPOWER system. It was used for bring up +of the AST2600 SoC in labs. It can be easily replaced by the +``rainier-bmc`` machine which is a real product. + Backend options --------------- diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 40dc0e4c76..53a4f665d0 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -1379,6 +1379,8 @@ static void aspeed_machine_tacoma_class_init(ObjectClass *oc, void *data) amc->i2c_init = witherspoon_bmc_i2c_init; /* Same board layout */ mc->default_ram_size = 1 * GiB; aspeed_machine_class_init_cpus_defaults(mc); + + mc->deprecation_reason = "Please use the similar 'rainier-bmc' machine"; }; static void aspeed_machine_g220a_class_init(ObjectClass *oc, void *data) From 61578d1e806d7271813c870e31160a7b21eab508 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 25 Jun 2024 08:37:43 +0200 Subject: [PATCH 3/6] aspeed/sdmc: Check RAM size value at realize time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The RAM size of the SDMC device is validated for the SoC and set when the Aspeed machines are initialized and then later used by several SoC implementations. However, the SDMC model never checks that the RAM size has been actually set before being used. Do that at realize. Signed-off-by: Cédric Le Goater Reviewed-by: Jamin_lin < jamin_lin@aspeedtech.com> --- hw/misc/aspeed_sdmc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c index 93e2e29ead..44da085e10 100644 --- a/hw/misc/aspeed_sdmc.c +++ b/hw/misc/aspeed_sdmc.c @@ -271,6 +271,12 @@ static void aspeed_sdmc_realize(DeviceState *dev, Error **errp) AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s); assert(asc->max_ram_size < 4 * GiB || asc->is_bus64bit); + + if (!s->ram_size) { + error_setg(errp, "RAM size is not set"); + return; + } + s->max_ram_size = asc->max_ram_size; memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sdmc_ops, s, From 5c065dfc71b84179a9aec2d283bb57b5a5675b0b Mon Sep 17 00:00:00 2001 From: Jamin Lin Date: Tue, 25 Jun 2024 15:07:39 +0800 Subject: [PATCH 4/6] aspeed/soc: Fix possible divide by zero MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Coverity reports a possible DIVIDE_BY_ZERO issue regarding the "ram_size" object property. This can not happen because RAM has predefined valid sizes per SoC. Nevertheless, add a test to close the issue. Fixes: Coverity CID 1547113 Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater [ clg: Rewrote commit log ] Signed-off-by: Cédric Le Goater --- hw/arm/aspeed_ast27x0.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c index b6876b4862..18e6a8b10c 100644 --- a/hw/arm/aspeed_ast27x0.c +++ b/hw/arm/aspeed_ast27x0.c @@ -211,6 +211,8 @@ static void aspeed_ram_capacity_write(void *opaque, hwaddr addr, uint64_t data, ram_size = object_property_get_uint(OBJECT(&s->sdmc), "ram-size", &error_abort); + assert(ram_size > 0); + /* * Emulate ddr capacity hardware behavior. * If writes the data to the address which is beyond the ram size, From 50c527b9ef58086dc377a0fa5e3053d16fc5728e Mon Sep 17 00:00:00 2001 From: Jamin Lin Date: Tue, 25 Jun 2024 15:07:40 +0800 Subject: [PATCH 5/6] aspeed/sdmc: Remove extra R_MAIN_STATUS case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Coverity reports that the newly added 'case R_MAIN_STATUS' is DEADCODE because it can not be reached. This is because R_MAIN_STATUS is handled before in the "Unprotected registers" switch statement. Remove it. Fixes: Coverity CID 1547112 Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater [ clg: Rewrote commit log ] Signed-off-by: Cédric Le Goater --- hw/misc/aspeed_sdmc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c index 44da085e10..ebf139cb5c 100644 --- a/hw/misc/aspeed_sdmc.c +++ b/hw/misc/aspeed_sdmc.c @@ -595,7 +595,6 @@ static void aspeed_2700_sdmc_write(AspeedSDMCState *s, uint32_t reg, case R_INT_STATUS: case R_INT_CLEAR: case R_INT_MASK: - case R_MAIN_STATUS: case R_ERR_STATUS: case R_ECC_FAIL_STATUS: case R_ECC_FAIL_ADDR: From 5b0961f7ad6790f473623703834351b6e43fbaa6 Mon Sep 17 00:00:00 2001 From: Jamin Lin Date: Wed, 19 Jun 2024 18:01:01 +0800 Subject: [PATCH 6/6] hw/net:ftgmac100: fix coding style MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix coding style issues from checkpatch.pl Test command: ./scripts/checkpatch.pl --no-tree -f hw/net/ftgmac100.c Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater --- hw/net/ftgmac100.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c index 74b6c3d9a7..25e4c0cd5b 100644 --- a/hw/net/ftgmac100.c +++ b/hw/net/ftgmac100.c @@ -238,7 +238,8 @@ typedef struct { */ #define FTGMAC100_MAX_FRAME_SIZE 9220 -/* Limits depending on the type of the frame +/* + * Limits depending on the type of the frame * * 9216 for Jumbo frames (+ 4 for VLAN) * 1518 for other frames (+ 4 for VLAN) @@ -533,8 +534,10 @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring, break; } - /* record transmit flags as they are valid only on the first - * segment */ + /* + * record transmit flags as they are valid only on the first + * segment + */ if (bd.des0 & FTGMAC100_TXDES0_FTS) { flags = bd.des1; } @@ -639,7 +642,8 @@ static bool ftgmac100_can_receive(NetClientState *nc) */ static uint32_t ftgmac100_rxpoll(FTGMAC100State *s) { - /* Polling times : + /* + * Polling times : * * Speed TIME_SEL=0 TIME_SEL=1 *