[PATCH AUTOSEL 6.18-5.10] ACPICA: Add package limit checks in parser functions

From: Sasha Levin

Date: Mon Aug 31 2026 - 12:18:04 EST


From: ikaros <void0red@xxxxxxxxx>

[ Upstream commit d27d48a528e437aed690f977e69a6fe73fe82ab5 ]

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@xxxxxxxxx>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@xxxxxxxxx>
Link: https://patch.msgid.link/3212937.CbtlEUcBR6@rafael.j.wysocki
Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>
---

LLM Generated explanations, may be completely bogus:

The background git searches finished. Both came back empty:

- No commit matching **"Add package limit"** in this tree
- No commits from author **ikaros**
- No related fixes for **"Clamp PackageEnd"**, **"package limit"**, or
**"package end"**

That confirms the package-limit checks are not in **6.18.44** yet. The
earlier analysis stands: this is a small, maintainer-reviewed bounds-
check fix for a real ACPI parser OOB read, and it should be backported.

**YES**

drivers/acpi/acpica/nsxfname.c | 4 ++++
drivers/acpi/acpica/psargs.c | 4 ++++
drivers/acpi/acpica/psloop.c | 25 +++++++++++++++++++++++++
drivers/acpi/acpica/psparse.c | 8 ++++++++
4 files changed, 41 insertions(+)

diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c
index 1db831545ec8c..821fb4930e9d8 100644
--- a/drivers/acpi/acpica/nsxfname.c
+++ b/drivers/acpi/acpica/nsxfname.c
@@ -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++;
diff --git a/drivers/acpi/acpica/psargs.c b/drivers/acpi/acpica/psargs.c
index 064652d11d9aa..34d887e2211ac 100644
--- a/drivers/acpi/acpica/psargs.c
+++ b/drivers/acpi/acpica/psargs.c
@@ -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:
diff --git a/drivers/acpi/acpica/psloop.c b/drivers/acpi/acpica/psloop.c
index 35111ff2526b1..7c3caf0ccab62 100644
--- a/drivers/acpi/acpica/psloop.c
+++ b/drivers/acpi/acpica/psloop.c
@@ -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;
}
diff --git a/drivers/acpi/acpica/psparse.c b/drivers/acpi/acpica/psparse.c
index 55a416e56fd83..b4f21a8988795 100644
--- a/drivers/acpi/acpica/psparse.c
+++ b/drivers/acpi/acpica/psparse.c
@@ -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;

--
2.53.0