Skip to content

Commit a9effd6

Browse files
ZheyuMaPatchew Applier
authored and
Patchew Applier
committed
hw/gpio/aspeed: Add reg_table_size to AspeedGPIOClass
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_size 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 Signed-off-by: Zheyu Ma <zheyuma97@gmail.com> Reviewed-by: Andrew Jeffery <andrew@codeconstruct.com.au> Message-Id: <20240619183638.4073070-1-zheyuma97@gmail.com>
1 parent 80748eb commit a9effd6

File tree

2 files changed

+18
-0
lines changed

2 files changed

+18
-0
lines changed

hw/gpio/aspeed_gpio.c

+17
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,12 @@ static uint64_t aspeed_gpio_read(void *opaque, hwaddr offset, uint32_t size)
559559
return debounce_value;
560560
}
561561

562+
if (idx >= agc->reg_table_size) {
563+
qemu_log_mask(LOG_GUEST_ERROR, "%s: idx 0x%" PRIx64 " out of bounds\n",
564+
__func__, idx);
565+
return 0;
566+
}
567+
562568
reg = &agc->reg_table[idx];
563569
if (reg->set_idx >= agc->nr_gpio_sets) {
564570
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,
785791
return;
786792
}
787793

794+
if (idx >= agc->reg_table_size) {
795+
qemu_log_mask(LOG_GUEST_ERROR, "%s: idx 0x%" PRIx64 " out of bounds\n",
796+
__func__, idx);
797+
return;
798+
}
799+
788800
reg = &agc->reg_table[idx];
789801
if (reg->set_idx >= agc->nr_gpio_sets) {
790802
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)
11171129
agc->nr_gpio_pins = 216;
11181130
agc->nr_gpio_sets = 7;
11191131
agc->reg_table = aspeed_3_3v_gpios;
1132+
agc->reg_table_size = GPIO_3_3V_REG_ARRAY_SIZE;
11201133
}
11211134

11221135
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)
11271140
agc->nr_gpio_pins = 228;
11281141
agc->nr_gpio_sets = 8;
11291142
agc->reg_table = aspeed_3_3v_gpios;
1143+
agc->reg_table_size = GPIO_3_3V_REG_ARRAY_SIZE;
11301144
}
11311145

11321146
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)
11371151
agc->nr_gpio_pins = 208;
11381152
agc->nr_gpio_sets = 7;
11391153
agc->reg_table = aspeed_3_3v_gpios;
1154+
agc->reg_table_size = GPIO_3_3V_REG_ARRAY_SIZE;
11401155
}
11411156

11421157
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)
11471162
agc->nr_gpio_pins = 36;
11481163
agc->nr_gpio_sets = 2;
11491164
agc->reg_table = aspeed_1_8v_gpios;
1165+
agc->reg_table_size = GPIO_1_8V_REG_ARRAY_SIZE;
11501166
}
11511167

11521168
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)
11571173
agc->nr_gpio_pins = 151;
11581174
agc->nr_gpio_sets = 6;
11591175
agc->reg_table = aspeed_3_3v_gpios;
1176+
agc->reg_table_size = GPIO_3_3V_REG_ARRAY_SIZE;
11601177
}
11611178

11621179
static const TypeInfo aspeed_gpio_info = {

include/hw/gpio/aspeed_gpio.h

+1
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ struct AspeedGPIOClass {
7575
uint32_t nr_gpio_pins;
7676
uint32_t nr_gpio_sets;
7777
const AspeedGPIOReg *reg_table;
78+
uint32_t reg_table_size;
7879
};
7980

8081
struct AspeedGPIOState {

0 commit comments

Comments
 (0)