From: ikaros Date: Wed, 27 May 2026 18:02:49 +0000 (+0200) Subject: ACPICA: Improve argument parsing in acpi_ps_get_next_simple_arg() X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=27d27e75ecb752a0b4da848c440bb3a88396ecba;p=thirdparty%2Flinux.git ACPICA: Improve argument parsing in acpi_ps_get_next_simple_arg() Improve argument parsing in acpi_ps_get_next_simple_arg() to handle remaining AML data safely. Link: https://github.com/acpica/acpica/commit/ecbb8bcfe301 Signed-off-by: ikaros Signed-off-by: Rafael J. Wysocki Link: https://patch.msgid.link/2008043.taCxCBeP46@rafael.j.wysocki --- diff --git a/drivers/acpi/acpica/psargs.c b/drivers/acpi/acpica/psargs.c index 3526ea1094146..064652d11d9aa 100644 --- a/drivers/acpi/acpica/psargs.c +++ b/drivers/acpi/acpica/psargs.c @@ -384,6 +384,8 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state, u32 length; u16 opcode; u8 *aml = parser_state->aml; + u32 remaining = (u32)ACPI_PTR_DIFF(parser_state->aml_end, aml); + u64 partial_value; ACPI_FUNCTION_TRACE_U32(ps_get_next_simple_arg, arg_type); @@ -393,8 +395,13 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state, /* Get 1 byte from the AML stream */ opcode = AML_BYTE_OP; - arg->common.value.integer = (u64) *aml; - length = 1; + if (remaining >= 1) { + arg->common.value.integer = (u64)*aml; + length = 1; + } else { + arg->common.value.integer = 0; + length = 0; + } break; case ARGP_WORDDATA: @@ -402,8 +409,19 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state, /* Get 2 bytes from the AML stream */ opcode = AML_WORD_OP; - ACPI_MOVE_16_TO_64(&arg->common.value.integer, aml); - length = 2; + if (remaining >= 2) { + ACPI_MOVE_16_TO_64(&arg->common.value.integer, aml); + length = 2; + } else { + arg->common.value.integer = 0; + length = 0; + if (remaining > 0) { + partial_value = 0; + memcpy(&partial_value, aml, remaining); + arg->common.value.integer = partial_value; + length = remaining; + } + } break; case ARGP_DWORDDATA: @@ -411,8 +429,19 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state, /* Get 4 bytes from the AML stream */ opcode = AML_DWORD_OP; - ACPI_MOVE_32_TO_64(&arg->common.value.integer, aml); - length = 4; + if (remaining >= 4) { + ACPI_MOVE_32_TO_64(&arg->common.value.integer, aml); + length = 4; + } else { + arg->common.value.integer = 0; + length = 0; + if (remaining > 0) { + partial_value = 0; + memcpy(&partial_value, aml, remaining); + arg->common.value.integer = partial_value; + length = remaining; + } + } break; case ARGP_QWORDDATA: @@ -420,8 +449,19 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state, /* Get 8 bytes from the AML stream */ opcode = AML_QWORD_OP; - ACPI_MOVE_64_TO_64(&arg->common.value.integer, aml); - length = 8; + if (remaining >= 8) { + ACPI_MOVE_64_TO_64(&arg->common.value.integer, aml); + length = 8; + } else { + arg->common.value.integer = 0; + length = 0; + if (remaining > 0) { + partial_value = 0; + memcpy(&partial_value, aml, remaining); + arg->common.value.integer = partial_value; + length = remaining; + } + } break; case ARGP_CHARLIST: @@ -434,10 +474,28 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state, /* Find the null terminator */ length = 0; - while (aml[length]) { + while ((length < remaining) && aml[length]) { + length++; + } + if (length < remaining) { + + /* Account for the terminating null */ length++; + } else { + /* + * No terminator found - add null at buffer boundary + * and report a warning + */ + ACPI_WARNING((AE_INFO, + "Invalid AML string: no null terminator, truncating at offset %u", + (u32)(aml - parser_state->aml))); + + /* Add null terminator at the boundary */ + if (remaining > 0) { + aml[remaining - 1] = 0; + length = remaining; + } } - length++; break; case ARGP_NAME: