]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ACPICA: Add package limit checks in parser functions
authorikaros <void0red@gmail.com>
Wed, 27 May 2026 18:09:24 +0000 (20:09 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Wed, 27 May 2026 18:18:47 +0000 (20:18 +0200)
Add package limit checks in parser functions to prevent out-of-bounds
access.

Link: https://github.com/acpica/acpica/commit/b31b45af2122
Signed-off-by: ikaros <void0red@gmail.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Link: https://patch.msgid.link/3212937.CbtlEUcBR6@rafael.j.wysocki
drivers/acpi/acpica/nsxfname.c
drivers/acpi/acpica/psargs.c
drivers/acpi/acpica/psloop.c
drivers/acpi/acpica/psparse.c

index fabae9b08e3158d2dbb2504bde54615140b8d80d..b6534187cd43c49f898fa068714ec0a74cabf2ca 100644 (file)
@@ -512,6 +512,10 @@ acpi_status acpi_install_method(u8 *buffer)
 
        parser_state.aml += acpi_ps_get_opcode_size(opcode);
        parser_state.pkg_end = acpi_ps_get_next_package_end(&parser_state);
+       if ((parser_state.pkg_end > parser_state.aml_end) ||
+           (parser_state.pkg_end < parser_state.aml)) {
+               return (AE_AML_PACKAGE_LIMIT);
+       }
        path = acpi_ps_get_next_namestring(&parser_state);
 
        method_flags = *parser_state.aml++;
index cafd54fb5868f9f077fbf640b7362507fb6b326e..95d540bda4fbf068b166bca8babb4bee4999f3d0 100644 (file)
@@ -867,6 +867,10 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
 
                parser_state->pkg_end =
                    acpi_ps_get_next_package_end(parser_state);
+               if ((parser_state->pkg_end > parser_state->aml_end)
+                   || (parser_state->pkg_end < parser_state->aml)) {
+                       return_ACPI_STATUS(AE_AML_PACKAGE_LIMIT);
+               }
                break;
 
        case ARGP_FIELDLIST:
index e012495e2267c435bcd6c618d917d54f92b4356f..24a57f971c9673025a36728803ae89c3937a1bcb 100644 (file)
@@ -361,6 +361,13 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
                                        walk_state->parser_state.aml =
                                            acpi_ps_get_next_package_end
                                            (&walk_state->parser_state);
+                                       if ((walk_state->parser_state.aml >
+                                            walk_state->parser_state.aml_end)
+                                           || (walk_state->parser_state.aml <
+                                               walk_state->aml)) {
+                                               return_ACPI_STATUS
+                                                   (AE_AML_PACKAGE_LIMIT);
+                                       }
                                        walk_state->aml =
                                            walk_state->parser_state.aml;
                                }
@@ -421,6 +428,14 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
                                        parser_state->aml =
                                            acpi_ps_get_next_package_end
                                            (parser_state);
+                                       if ((parser_state->aml >
+                                            parser_state->aml_end)
+                                           || (parser_state->aml <
+                                               walk_state->control_state->
+                                               control.aml_predicate_start)) {
+                                               return_ACPI_STATUS
+                                                   (AE_AML_PACKAGE_LIMIT);
+                                       }
                                        walk_state->aml = parser_state->aml;
 
                                        ACPI_ERROR((AE_INFO,
@@ -436,6 +451,16 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
                                                walk_state->parser_state.aml =
                                                    acpi_ps_get_next_package_end
                                                    (parser_state);
+                                               if ((walk_state->parser_state.
+                                                    aml >
+                                                    walk_state->parser_state.
+                                                    aml_end)
+                                                   || (walk_state->
+                                                       parser_state.aml <
+                                                       walk_state->aml)) {
+                                                       return_ACPI_STATUS
+                                                           (AE_AML_PACKAGE_LIMIT);
+                                               }
                                                walk_state->aml =
                                                    parser_state->aml;
                                        }
index d9e4f33b6909075d55475faeec5a23e9be369029..29b57d2c4cc43d3ebdc474a8276d17601cd22dec 100644 (file)
@@ -300,6 +300,7 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state,
 {
        struct acpi_parse_state *parser_state = &walk_state->parser_state;
        acpi_status status = AE_CTRL_PENDING;
+       u8 *aml;
 
        ACPI_FUNCTION_TRACE_PTR(ps_next_parse_state, op);
 
@@ -344,7 +345,14 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state,
                 * Predicate of an IF was true, and we are at the matching ELSE.
                 * Just close out this package
                 */
+               aml = parser_state->aml;
+
                parser_state->aml = acpi_ps_get_next_package_end(parser_state);
+               if ((parser_state->aml > parser_state->aml_end) ||
+                   (parser_state->aml < aml)) {
+                       status = AE_AML_PACKAGE_LIMIT;
+                       break;
+               }
                status = AE_CTRL_PENDING;
                break;