Al Stone 1b212f
From 987a3b5cf7175916e2a4b6ea5b8e70f830dfe732 Mon Sep 17 00:00:00 2001
Al Stone 1b212f
From: Seunghun Han <kkamagui@gmail.com>
Al Stone 1b212f
Date: Wed, 19 Jul 2017 16:47:53 +0900
Al Stone 1b212f
Subject: [PATCH] acpi: acpica: fix acpi operand cache leak in dswstate.c
Al Stone 1b212f
Al Stone 1b212f
I found an ACPI cache leak in ACPI early termination and boot continuing case.
Al Stone 1b212f
Al Stone 1b212f
When early termination occurs due to malicious ACPI table, Linux kernel
Al Stone 1b212f
terminates ACPI function and continues to boot process. While kernel terminates
Al Stone 1b212f
ACPI function, kmem_cache_destroy() reports Acpi-Operand cache leak.
Al Stone 1b212f
Al Stone 1b212f
Boot log of ACPI operand cache leak is as follows:
Al Stone 1b212f
>[    0.585957] ACPI: Added _OSI(Module Device)
Al Stone 1b212f
>[    0.587218] ACPI: Added _OSI(Processor Device)
Al Stone 1b212f
>[    0.588530] ACPI: Added _OSI(3.0 _SCP Extensions)
Al Stone 1b212f
>[    0.589790] ACPI: Added _OSI(Processor Aggregator Device)
Al Stone 1b212f
>[    0.591534] ACPI Error: Illegal I/O port address/length above 64K: C806E00000004002/0x2 (20170303/hwvalid-155)
Al Stone 1b212f
>[    0.594351] ACPI Exception: AE_LIMIT, Unable to initialize fixed events (20170303/evevent-88)
Al Stone 1b212f
>[    0.597858] ACPI: Unable to start the ACPI Interpreter
Al Stone 1b212f
>[    0.599162] ACPI Error: Could not remove SCI handler (20170303/evmisc-281)
Al Stone 1b212f
>[    0.601836] kmem_cache_destroy Acpi-Operand: Slab cache still has objects
Al Stone 1b212f
>[    0.603556] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.12.0-rc5 #26
Al Stone 1b212f
>[    0.605159] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
Al Stone 1b212f
>[    0.609177] Call Trace:
Al Stone 1b212f
>[    0.610063]  ? dump_stack+0x5c/0x81
Al Stone 1b212f
>[    0.611118]  ? kmem_cache_destroy+0x1aa/0x1c0
Al Stone 1b212f
>[    0.612632]  ? acpi_sleep_proc_init+0x27/0x27
Al Stone 1b212f
>[    0.613906]  ? acpi_os_delete_cache+0xa/0x10
Al Stone 1b212f
>[    0.617986]  ? acpi_ut_delete_caches+0x3f/0x7b
Al Stone 1b212f
>[    0.619293]  ? acpi_terminate+0xa/0x14
Al Stone 1b212f
>[    0.620394]  ? acpi_init+0x2af/0x34f
Al Stone 1b212f
>[    0.621616]  ? __class_create+0x4c/0x80
Al Stone 1b212f
>[    0.623412]  ? video_setup+0x7f/0x7f
Al Stone 1b212f
>[    0.624585]  ? acpi_sleep_proc_init+0x27/0x27
Al Stone 1b212f
>[    0.625861]  ? do_one_initcall+0x4e/0x1a0
Al Stone 1b212f
>[    0.627513]  ? kernel_init_freeable+0x19e/0x21f
Al Stone 1b212f
>[    0.628972]  ? rest_init+0x80/0x80
Al Stone 1b212f
>[    0.630043]  ? kernel_init+0xa/0x100
Al Stone 1b212f
>[    0.631084]  ? ret_from_fork+0x25/0x30
Al Stone 1b212f
>[    0.633343] vgaarb: loaded
Al Stone 1b212f
>[    0.635036] EDAC MC: Ver: 3.0.0
Al Stone 1b212f
>[    0.638601] PCI: Probing PCI hardware
Al Stone 1b212f
>[    0.639833] PCI host bridge to bus 0000:00
Al Stone 1b212f
>[    0.641031] pci_bus 0000:00: root bus resource [io  0x0000-0xffff]
Al Stone 1b212f
> ... Continue to boot and log is omitted ...
Al Stone 1b212f
Al Stone 1b212f
I analyzed this memory leak in detail and found acpi_ds_obj_stack_pop_and_
Al Stone 1b212f
delete() function miscalculated the top of the stack. acpi_ds_obj_stack_push()
Al Stone 1b212f
function uses walk_state->operand_index for start position of the top, but
Al Stone 1b212f
acpi_ds_obj_stack_pop_and_delete() function considers index 0 for it.
Al Stone 1b212f
Therefore, this causes acpi operand memory leak.
Al Stone 1b212f
Al Stone 1b212f
This cache leak causes a security threat because an old kernel (<= 4.9) shows
Al Stone 1b212f
memory locations of kernel functions in stack dump. Some malicious users
Al Stone 1b212f
could use this information to neutralize kernel ASLR.
Al Stone 1b212f
Al Stone 1b212f
I made a patch to fix ACPI operand cache leak.
Al Stone 1b212f
Al Stone 1b212f
Signed-off-by: Seunghun Han <kkamagui@gmail.com>
Al Stone 1b212f
Al Stone 1b212f
Github-Location: https://github.com/acpica/acpica/pull/295/commits/987a3b5cf7175916e2a4b6ea5b8e70f830dfe732
Al Stone 1b212f
---
Al Stone 1b212f
 source/components/dispatcher/dsutils.c | 9 ++++++++-
Al Stone 1b212f
 1 file changed, 8 insertions(+), 1 deletion(-)
Al Stone 1b212f
Al Stone 1b212f
Index: acpica-unix2-20180209/source/components/dispatcher/dsutils.c
Al Stone 1b212f
===================================================================
Al Stone 1b212f
--- acpica-unix2-20180209.orig/source/components/dispatcher/dsutils.c
Al Stone 1b212f
+++ acpica-unix2-20180209/source/components/dispatcher/dsutils.c
Al Stone 1b212f
@@ -761,6 +761,8 @@ AcpiDsCreateOperands (
Al Stone 1b212f
     ACPI_PARSE_OBJECT       *Arguments[ACPI_OBJ_NUM_OPERANDS];
Al Stone 1b212f
     UINT32                  ArgCount = 0;
Al Stone 1b212f
     UINT32                  Index = WalkState->NumOperands;
Al Stone 1b212f
+    UINT32                  PrevNumOperands = WalkState->NumOperands;
Al Stone 1b212f
+    UINT32                  NewNumOperands;
Al Stone 1b212f
     UINT32                  i;
Al Stone 1b212f
 
Al Stone 1b212f
 
Al Stone 1b212f
@@ -793,6 +795,7 @@ AcpiDsCreateOperands (
Al Stone 1b212f
 
Al Stone 1b212f
     /* Create the interpreter arguments, in reverse order */
Al Stone 1b212f
 
Al Stone 1b212f
+    NewNumOperands = Index;
Al Stone 1b212f
     Index--;
Al Stone 1b212f
     for (i = 0; i < ArgCount; i++)
Al Stone 1b212f
     {
Al Stone 1b212f
@@ -820,7 +823,11 @@ Cleanup:
Al Stone 1b212f
      * pop everything off of the operand stack and delete those
Al Stone 1b212f
      * objects
Al Stone 1b212f
      */
Al Stone 1b212f
-    AcpiDsObjStackPopAndDelete (ArgCount, WalkState);
Al Stone 1b212f
+    WalkState->NumOperands = i;
Al Stone 1b212f
+    AcpiDsObjStackPopAndDelete (NewNumOperands, WalkState);
Al Stone 1b212f
+
Al Stone 1b212f
+    /* Restore operand count */
Al Stone 1b212f
+    WalkState->NumOperands = PrevNumOperands;
Al Stone 1b212f
 
Al Stone 1b212f
     ACPI_EXCEPTION ((AE_INFO, Status, "While creating Arg %u", Index));
Al Stone 1b212f
     return_ACPI_STATUS (Status);