221a602
From patchwork Wed Jul 19 07:07:23 2017
221a602
Content-Type: text/plain; charset="utf-8"
221a602
MIME-Version: 1.0
221a602
Content-Transfer-Encoding: 7bit
221a602
Subject: acpi: acpica: fix acpi operand cache leak in nseval.c
221a602
From: Seunghun Han <kkamagui@gmail.com>
221a602
X-Patchwork-Id: 9850567
221a602
Message-Id: <1500448043-137615-1-git-send-email-kkamagui@gmail.com>
221a602
To: Lv Zheng <lv.zheng@intel.com>
221a602
Cc: Robert Moore <robert.moore@intel.com>,
221a602
 "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>,
221a602
 linux-acpi@vger.kernel.org, devel@acpica.org,
221a602
 linux-kernel@vger.kernel.org, security@kernel.org,
221a602
 Seunghun Han <kkamagui@gmail.com>
221a602
Date: Wed, 19 Jul 2017 16:07:23 +0900
221a602
221a602
I found an ACPI cache leak in ACPI early termination and boot continuing case.
221a602
221a602
When early termination occurs due to malicious ACPI table, Linux kernel
221a602
terminates ACPI function and continues to boot process. While kernel terminates
221a602
ACPI function, kmem_cache_destroy() reports Acpi-Operand cache leak.
221a602
221a602
Boot log of ACPI operand cache leak is as follows:
221a602
>[    0.464168] ACPI: Added _OSI(Module Device)
221a602
>[    0.467022] ACPI: Added _OSI(Processor Device)
221a602
>[    0.469376] ACPI: Added _OSI(3.0 _SCP Extensions)
221a602
>[    0.471647] ACPI: Added _OSI(Processor Aggregator Device)
221a602
>[    0.477997] ACPI Error: Null stack entry at ffff880215c0aad8 (20170303/exresop-174)
221a602
>[    0.482706] ACPI Exception: AE_AML_INTERNAL, While resolving operands for [OpcodeName unavailable] (20170303/dswexec-461)
221a602
>[    0.487503] ACPI Error: Method parse/execution failed [\DBG] (Node ffff88021710ab40), AE_AML_INTERNAL (20170303/psparse-543)
221a602
>[    0.492136] ACPI Error: Method parse/execution failed [\_SB._INI] (Node ffff88021710a618), AE_AML_INTERNAL (20170303/psparse-543)
221a602
>[    0.497683] ACPI: Interpreter enabled
221a602
>[    0.499385] ACPI: (supports S0)
221a602
>[    0.501151] ACPI: Using IOAPIC for interrupt routing
221a602
>[    0.503342] ACPI Error: Null stack entry at ffff880215c0aad8 (20170303/exresop-174)
221a602
>[    0.506522] ACPI Exception: AE_AML_INTERNAL, While resolving operands for [OpcodeName unavailable] (20170303/dswexec-461)
221a602
>[    0.510463] ACPI Error: Method parse/execution failed [\DBG] (Node ffff88021710ab40), AE_AML_INTERNAL (20170303/psparse-543)
221a602
>[    0.514477] ACPI Error: Method parse/execution failed [\_PIC] (Node ffff88021710ab18), AE_AML_INTERNAL (20170303/psparse-543)
221a602
>[    0.518867] ACPI Exception: AE_AML_INTERNAL, Evaluating _PIC (20170303/bus-991)
221a602
>[    0.522384] kmem_cache_destroy Acpi-Operand: Slab cache still has objects
221a602
>[    0.524597] CPU: 1 PID: 1 Comm: swapper/0 Not tainted 4.12.0-rc5 #26
221a602
>[    0.526795] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
221a602
>[    0.529668] Call Trace:
221a602
>[    0.530811]  ? dump_stack+0x5c/0x81
221a602
>[    0.532240]  ? kmem_cache_destroy+0x1aa/0x1c0
221a602
>[    0.533905]  ? acpi_os_delete_cache+0xa/0x10
221a602
>[    0.535497]  ? acpi_ut_delete_caches+0x3f/0x7b
221a602
>[    0.537237]  ? acpi_terminate+0xa/0x14
221a602
>[    0.538701]  ? acpi_init+0x2af/0x34f
221a602
>[    0.540008]  ? acpi_sleep_proc_init+0x27/0x27
221a602
>[    0.541593]  ? do_one_initcall+0x4e/0x1a0
221a602
>[    0.543008]  ? kernel_init_freeable+0x19e/0x21f
221a602
>[    0.546202]  ? rest_init+0x80/0x80
221a602
>[    0.547513]  ? kernel_init+0xa/0x100
221a602
>[    0.548817]  ? ret_from_fork+0x25/0x30
221a602
>[    0.550587] vgaarb: loaded
221a602
>[    0.551716] EDAC MC: Ver: 3.0.0
221a602
>[    0.553744] PCI: Probing PCI hardware
221a602
>[    0.555038] PCI host bridge to bus 0000:00
221a602
> ... Continue to boot and log is omitted ...
221a602
221a602
I analyzed this memory leak in detail and found acpi_ns_evaluate() function
221a602
only removes info->return_object in AE_CTRL_RETURN_VALUE case. But, when errors
221a602
occur, the status value is not AE_CTRL_RETURN_VALUE, and info->return_object is
221a602
also not null. Therefore, this causes acpi operand memory leak.
221a602
221a602
This cache leak causes a security threat because an old kernel (<= 4.9) shows
221a602
memory locations of kernel functions in stack dump. Some malicious users
221a602
could use this information to neutralize kernel ASLR.
221a602
221a602
I made a patch to fix ACPI operand cache leak.
221a602
221a602
Signed-off-by: Seunghun Han <kkamagui@gmail.com>
221a602
---
221a602
 drivers/acpi/acpica/nseval.c | 8 ++++++++
221a602
 1 file changed, 8 insertions(+)
221a602
221a602
diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c
221a602
index d22167c..f13d3cf 100644
221a602
--- a/drivers/acpi/acpica/nseval.c
221a602
+++ b/drivers/acpi/acpica/nseval.c
221a602
@@ -308,6 +308,14 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info)
221a602
 		/* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */
221a602
 
221a602
 		status = AE_OK;
221a602
+	} else if (ACPI_FAILURE(status)) {
221a602
+
221a602
+		/* If return_object exists, delete it */
221a602
+
221a602
+		if (info->return_object) {
221a602
+			acpi_ut_remove_reference(info->return_object);
221a602
+			info->return_object = NULL;
221a602
+		}
221a602
 	}
221a602
 
221a602
 	ACPI_DEBUG_PRINT((ACPI_DB_NAMES,