1b78585135
As s390x was the only one remaining, it has now been excluded. This was best done with an update of the source tree to match upstream. This is turn caused additional patch updates. With s390x gone, all of the big-endian patches can be removed, simplifying things enormously. This is the biggest change. Several other patches that are no longer needed due to changes in Fedora builds (ld flags, for example), or that are no longer needed (such as armv7) have also been removed. Added three new patches to fix problems with dumping various tables, and removed all the remaining patches that no longer serve a purpose. Thanks to the contributors for PR#4 and PR#5 for the suggestions. These have all been incorporated even if they are not in exactly the same form. Signed-off-by: Al Stone <ahs3@ahs3.net> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
217 lines
8.5 KiB
Diff
217 lines
8.5 KiB
Diff
From 4a0243ecb4c94e2d73510d096c5ea4d0711fc6c0 Mon Sep 17 00:00:00 2001
|
|
From: Seunghun Han <kkamagui@gmail.com>
|
|
Date: Fri, 23 Jun 2017 14:19:48 +0900
|
|
Subject: [PATCH] acpi: acpica: fix acpi parse and parseext cache leaks
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
I'm Seunghun Han, and I work for National Security Research Institute of
|
|
South Korea.
|
|
|
|
I have been doing a research on ACPI and found an ACPI cache leak in ACPI
|
|
early abort cases.
|
|
|
|
Boot log of ACPI cache leak is as follows:
|
|
[ 0.352414] ACPI: Added _OSI(Module Device)
|
|
[ 0.353182] ACPI: Added _OSI(Processor Device)
|
|
[ 0.353182] ACPI: Added _OSI(3.0 _SCP Extensions)
|
|
[ 0.353182] ACPI: Added _OSI(Processor Aggregator Device)
|
|
[ 0.356028] ACPI: Unable to start the ACPI Interpreter
|
|
[ 0.356799] ACPI Error: Could not remove SCI handler (20170303/evmisc-281)
|
|
[ 0.360215] kmem_cache_destroy Acpi-State: Slab cache still has objects
|
|
[ 0.360648] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G W
|
|
4.12.0-rc4-next-20170608+ #10
|
|
[ 0.361273] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS
|
|
VirtualBox 12/01/2006
|
|
[ 0.361873] Call Trace:
|
|
[ 0.362243] ? dump_stack+0x5c/0x81
|
|
[ 0.362591] ? kmem_cache_destroy+0x1aa/0x1c0
|
|
[ 0.362944] ? acpi_sleep_proc_init+0x27/0x27
|
|
[ 0.363296] ? acpi_os_delete_cache+0xa/0x10
|
|
[ 0.363646] ? acpi_ut_delete_caches+0x6d/0x7b
|
|
[ 0.364000] ? acpi_terminate+0xa/0x14
|
|
[ 0.364000] ? acpi_init+0x2af/0x34f
|
|
[ 0.364000] ? __class_create+0x4c/0x80
|
|
[ 0.364000] ? video_setup+0x7f/0x7f
|
|
[ 0.364000] ? acpi_sleep_proc_init+0x27/0x27
|
|
[ 0.364000] ? do_one_initcall+0x4e/0x1a0
|
|
[ 0.364000] ? kernel_init_freeable+0x189/0x20a
|
|
[ 0.364000] ? rest_init+0xc0/0xc0
|
|
[ 0.364000] ? kernel_init+0xa/0x100
|
|
[ 0.364000] ? ret_from_fork+0x25/0x30
|
|
|
|
I analyzed this memory leak in detail. I found that “Acpi-State” cache and
|
|
“Acpi-Parse” cache were merged because the size of cache objects was same
|
|
slab cache size.
|
|
|
|
I finally found “Acpi-Parse” cache and “Acpi-ParseExt” cache were leaked
|
|
using SLAB_NEVER_MERGE flag in kmem_cache_create() function.
|
|
|
|
Real ACPI cache leak point is as follows:
|
|
[ 0.360101] ACPI: Added _OSI(Module Device)
|
|
[ 0.360101] ACPI: Added _OSI(Processor Device)
|
|
[ 0.360101] ACPI: Added _OSI(3.0 _SCP Extensions)
|
|
[ 0.361043] ACPI: Added _OSI(Processor Aggregator Device)
|
|
[ 0.364016] ACPI: Unable to start the ACPI Interpreter
|
|
[ 0.365061] ACPI Error: Could not remove SCI handler (20170303/evmisc-281)
|
|
[ 0.368174] kmem_cache_destroy Acpi-Parse: Slab cache still has objects
|
|
[ 0.369332] CPU: 1 PID: 1 Comm: swapper/0 Tainted: G W
|
|
4.12.0-rc4-next-20170608+ #8
|
|
[ 0.371256] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS
|
|
VirtualBox 12/01/2006
|
|
[ 0.372000] Call Trace:
|
|
[ 0.372000] ? dump_stack+0x5c/0x81
|
|
[ 0.372000] ? kmem_cache_destroy+0x1aa/0x1c0
|
|
[ 0.372000] ? acpi_sleep_proc_init+0x27/0x27
|
|
[ 0.372000] ? acpi_os_delete_cache+0xa/0x10
|
|
[ 0.372000] ? acpi_ut_delete_caches+0x56/0x7b
|
|
[ 0.372000] ? acpi_terminate+0xa/0x14
|
|
[ 0.372000] ? acpi_init+0x2af/0x34f
|
|
[ 0.372000] ? __class_create+0x4c/0x80
|
|
[ 0.372000] ? video_setup+0x7f/0x7f
|
|
[ 0.372000] ? acpi_sleep_proc_init+0x27/0x27
|
|
[ 0.372000] ? do_one_initcall+0x4e/0x1a0
|
|
[ 0.372000] ? kernel_init_freeable+0x189/0x20a
|
|
[ 0.372000] ? rest_init+0xc0/0xc0
|
|
[ 0.372000] ? kernel_init+0xa/0x100
|
|
[ 0.372000] ? ret_from_fork+0x25/0x30
|
|
[ 0.388039] kmem_cache_destroy Acpi-ParseExt: Slab cache still has objects
|
|
[ 0.389063] CPU: 1 PID: 1 Comm: swapper/0 Tainted: G W
|
|
4.12.0-rc4-next-20170608+ #8
|
|
[ 0.390557] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS
|
|
VirtualBox 12/01/2006
|
|
[ 0.392000] Call Trace:
|
|
[ 0.392000] ? dump_stack+0x5c/0x81
|
|
[ 0.392000] ? kmem_cache_destroy+0x1aa/0x1c0
|
|
[ 0.392000] ? acpi_sleep_proc_init+0x27/0x27
|
|
[ 0.392000] ? acpi_os_delete_cache+0xa/0x10
|
|
[ 0.392000] ? acpi_ut_delete_caches+0x6d/0x7b
|
|
[ 0.392000] ? acpi_terminate+0xa/0x14
|
|
[ 0.392000] ? acpi_init+0x2af/0x34f
|
|
[ 0.392000] ? __class_create+0x4c/0x80
|
|
[ 0.392000] ? video_setup+0x7f/0x7f
|
|
[ 0.392000] ? acpi_sleep_proc_init+0x27/0x27
|
|
[ 0.392000] ? do_one_initcall+0x4e/0x1a0
|
|
[ 0.392000] ? kernel_init_freeable+0x189/0x20a
|
|
[ 0.392000] ? rest_init+0xc0/0xc0
|
|
[ 0.392000] ? kernel_init+0xa/0x100
|
|
[ 0.392000] ? ret_from_fork+0x25/0x30
|
|
|
|
When early abort is occurred due to invalid ACPI information, Linux kernel
|
|
terminates ACPI by calling acpi_terminate() function. The function calls
|
|
acpi_ut_delete_caches() function to delete local caches (acpi_gbl_namespace_
|
|
cache, state_cache, operand_cache, ps_node_cache, ps_node_ext_cache).
|
|
|
|
But the deletion codes in acpi_ut_delete_caches() function only delete
|
|
slab caches using kmem_cache_destroy() function, therefore the cache
|
|
objects should be flushed before acpi_ut_delete_caches() function.
|
|
|
|
“Acpi-Parse” cache and “Acpi-ParseExt” cache are used in an AML parse
|
|
function, acpi_ps_parse_loop(). The function should have flush codes to
|
|
handle an error state due to invalid AML codes.
|
|
|
|
This cache leak has a security threat because an old kernel (<= 4.9) shows
|
|
memory locations of kernel functions in stack dump. Some malicious users
|
|
could use this information to neutralize kernel ASLR.
|
|
|
|
To fix ACPI cache leak for enhancing security, I made a patch which has
|
|
flush codes in acpi_ps_parse_loop() function.
|
|
|
|
I hope that this patch improves the security of Linux kernel.
|
|
|
|
Thank you.
|
|
|
|
Signed-off-by: Seunghun Han <kkamagui@gmail.com>
|
|
|
|
Github-Location: https://github.com/acpica/acpica/pull/278/commits/4a0243ecb4c94e2d73510d096c5ea4d0711fc6c0
|
|
|
|
---
|
|
source/components/parser/psobject.c | 44 ++++++++++++++-----------------------
|
|
1 file changed, 16 insertions(+), 28 deletions(-)
|
|
|
|
Index: acpica-unix2-20240321/source/components/parser/psobject.c
|
|
===================================================================
|
|
--- acpica-unix2-20240321.orig/source/components/parser/psobject.c
|
|
+++ acpica-unix2-20240321/source/components/parser/psobject.c
|
|
@@ -707,7 +707,8 @@ AcpiPsCompleteFinalOp (
|
|
ACPI_PARSE_OBJECT *Op,
|
|
ACPI_STATUS Status)
|
|
{
|
|
- ACPI_STATUS Status2;
|
|
+ ACPI_STATUS ReturnStatus = AE_OK;
|
|
+ BOOLEAN Ascending = TRUE;
|
|
|
|
|
|
ACPI_FUNCTION_TRACE_PTR (PsCompleteFinalOp, WalkState);
|
|
@@ -724,7 +725,7 @@ AcpiPsCompleteFinalOp (
|
|
{
|
|
if (Op)
|
|
{
|
|
- if (WalkState->AscendingCallback != NULL)
|
|
+ if (Ascending && WalkState->AscendingCallback != NULL)
|
|
{
|
|
WalkState->Op = Op;
|
|
WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
|
|
@@ -743,41 +744,28 @@ AcpiPsCompleteFinalOp (
|
|
|
|
if (Status == AE_CTRL_TERMINATE)
|
|
{
|
|
- Status = AE_OK;
|
|
-
|
|
- /* Clean up */
|
|
- do
|
|
- {
|
|
- if (Op)
|
|
- {
|
|
- Status2 = AcpiPsCompleteThisOp (WalkState, Op);
|
|
- if (ACPI_FAILURE (Status2))
|
|
- {
|
|
- return_ACPI_STATUS (Status2);
|
|
- }
|
|
- }
|
|
-
|
|
- AcpiPsPopScope (&(WalkState->ParserState), &Op,
|
|
- &WalkState->ArgTypes, &WalkState->ArgCount);
|
|
-
|
|
- } while (Op);
|
|
-
|
|
- return_ACPI_STATUS (Status);
|
|
+ Ascending = FALSE;
|
|
+ ReturnStatus = AE_CTRL_TERMINATE;
|
|
}
|
|
|
|
else if (ACPI_FAILURE (Status))
|
|
{
|
|
/* First error is most important */
|
|
|
|
- (void) AcpiPsCompleteThisOp (WalkState, Op);
|
|
- return_ACPI_STATUS (Status);
|
|
+ Ascending = FALSE;
|
|
+ ReturnStatus = Status;
|
|
}
|
|
}
|
|
|
|
- Status2 = AcpiPsCompleteThisOp (WalkState, Op);
|
|
- if (ACPI_FAILURE (Status2))
|
|
+ Status = AcpiPsCompleteThisOp (WalkState, Op);
|
|
+ if (ACPI_FAILURE (Status))
|
|
{
|
|
- return_ACPI_STATUS (Status2);
|
|
+ Ascending = FALSE;
|
|
+ if (ACPI_SUCCESS (ReturnStatus) ||
|
|
+ ReturnStatus == AE_CTRL_TERMINATE)
|
|
+ {
|
|
+ ReturnStatus = Status;
|
|
+ }
|
|
}
|
|
}
|
|
|
|
@@ -786,5 +774,5 @@ AcpiPsCompleteFinalOp (
|
|
|
|
} while (Op);
|
|
|
|
- return_ACPI_STATUS (Status);
|
|
+ return_ACPI_STATUS (ReturnStatus);
|
|
}
|