Skip to content

Commit 263e22d

Browse files
Zhengzengkaictmarinas
authored andcommitted
ACPI: GTDT: Tighten the check for the array of platform timer structures
As suggested by Marc and Lorenzo, first we need to check whether the platform_timer entry pointer is within gtdt bounds (< gtdt_end) before de-referencing what it points at to detect the length of the platform timer struct and then check that the length of current platform_timer struct is also valid, i.e. the length is not zero and within gtdt_end. Now next_platform_timer() only checks against gtdt_end for the entry of subsequent platform timer without checking the length of it and will not report error if the check failed and the existing check in function acpi_gtdt_init() is also not enough. Modify the for_each_platform_timer() iterator and use it combined with a dedicated check function platform_timer_valid() to do the check against table length (gtdt_end) for each element of platform timer array in function acpi_gtdt_init(), making sure that both their entry and length actually fit in the table. Suggested-by: Lorenzo Pieralisi <[email protected]> Co-developed-by: Marc Zyngier <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Signed-off-by: Zheng Zengkai <[email protected]> Reviewed-by: Lorenzo Pieralisi <[email protected]> Reviewed-by: Hanjun Guo <[email protected]> Tested-by: Hanjun Guo <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Catalin Marinas <[email protected]>
1 parent 525fd6a commit 263e22d

File tree

1 file changed

+20
-9
lines changed

1 file changed

+20
-9
lines changed

drivers/acpi/arm64/gtdt.c

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,25 @@ struct acpi_gtdt_descriptor {
3636

3737
static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata;
3838

39-
static inline __init void *next_platform_timer(void *platform_timer)
39+
static __init bool platform_timer_valid(void *platform_timer)
4040
{
4141
struct acpi_gtdt_header *gh = platform_timer;
4242

43-
platform_timer += gh->length;
44-
if (platform_timer < acpi_gtdt_desc.gtdt_end)
45-
return platform_timer;
43+
return (platform_timer >= (void *)(acpi_gtdt_desc.gtdt + 1) &&
44+
platform_timer < acpi_gtdt_desc.gtdt_end &&
45+
gh->length != 0 &&
46+
platform_timer + gh->length <= acpi_gtdt_desc.gtdt_end);
47+
}
48+
49+
static __init void *next_platform_timer(void *platform_timer)
50+
{
51+
struct acpi_gtdt_header *gh = platform_timer;
4652

47-
return NULL;
53+
return platform_timer + gh->length;
4854
}
4955

5056
#define for_each_platform_timer(_g) \
51-
for (_g = acpi_gtdt_desc.platform_timer; _g; \
57+
for (_g = acpi_gtdt_desc.platform_timer; platform_timer_valid(_g);\
5258
_g = next_platform_timer(_g))
5359

5460
static inline bool is_timer_block(void *platform_timer)
@@ -157,6 +163,7 @@ int __init acpi_gtdt_init(struct acpi_table_header *table,
157163
{
158164
void *platform_timer;
159165
struct acpi_table_gtdt *gtdt;
166+
int cnt = 0;
160167

161168
gtdt = container_of(table, struct acpi_table_gtdt, header);
162169
acpi_gtdt_desc.gtdt = gtdt;
@@ -176,12 +183,16 @@ int __init acpi_gtdt_init(struct acpi_table_header *table,
176183
return 0;
177184
}
178185

179-
platform_timer = (void *)gtdt + gtdt->platform_timer_offset;
180-
if (platform_timer < (void *)table + sizeof(struct acpi_table_gtdt)) {
186+
acpi_gtdt_desc.platform_timer = (void *)gtdt + gtdt->platform_timer_offset;
187+
for_each_platform_timer(platform_timer)
188+
cnt++;
189+
190+
if (cnt != gtdt->platform_timer_count) {
191+
acpi_gtdt_desc.platform_timer = NULL;
181192
pr_err(FW_BUG "invalid timer data.\n");
182193
return -EINVAL;
183194
}
184-
acpi_gtdt_desc.platform_timer = platform_timer;
195+
185196
if (platform_timer_count)
186197
*platform_timer_count = gtdt->platform_timer_count;
187198

0 commit comments

Comments
 (0)