]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ACPICA: Improve argument parsing in acpi_ps_get_next_simple_arg()
authorikaros <void0red@gmail.com>
Wed, 27 May 2026 18:02:49 +0000 (20:02 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Wed, 27 May 2026 18:18:46 +0000 (20:18 +0200)
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 <void0red@gmail.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Link: https://patch.msgid.link/2008043.taCxCBeP46@rafael.j.wysocki
drivers/acpi/acpica/psargs.c

index 3526ea1094146a9fd39c68c79b7c951090977fca..064652d11d9aa7cd38c40a7bab4a38275e0eab22 100644 (file)
@@ -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: