]>
Commit | Line | Data |
---|---|---|
25d7dd99 JB |
1 | From 987a3b5cf7175916e2a4b6ea5b8e70f830dfe732 Mon Sep 17 00:00:00 2001 |
2 | From: Seunghun Han <kkamagui@gmail.com> | |
3 | Date: Wed, 19 Jul 2017 16:47:53 +0900 | |
4 | Subject: [PATCH] acpi: acpica: fix acpi operand cache leak in dswstate.c | |
5 | ||
6 | I found an ACPI cache leak in ACPI early termination and boot continuing case. | |
7 | ||
8 | When early termination occurs due to malicious ACPI table, Linux kernel | |
9 | terminates ACPI function and continues to boot process. While kernel terminates | |
10 | ACPI function, kmem_cache_destroy() reports Acpi-Operand cache leak. | |
11 | ||
12 | Boot log of ACPI operand cache leak is as follows: | |
13 | >[ 0.585957] ACPI: Added _OSI(Module Device) | |
14 | >[ 0.587218] ACPI: Added _OSI(Processor Device) | |
15 | >[ 0.588530] ACPI: Added _OSI(3.0 _SCP Extensions) | |
16 | >[ 0.589790] ACPI: Added _OSI(Processor Aggregator Device) | |
17 | >[ 0.591534] ACPI Error: Illegal I/O port address/length above 64K: C806E00000004002/0x2 (20170303/hwvalid-155) | |
18 | >[ 0.594351] ACPI Exception: AE_LIMIT, Unable to initialize fixed events (20170303/evevent-88) | |
19 | >[ 0.597858] ACPI: Unable to start the ACPI Interpreter | |
20 | >[ 0.599162] ACPI Error: Could not remove SCI handler (20170303/evmisc-281) | |
21 | >[ 0.601836] kmem_cache_destroy Acpi-Operand: Slab cache still has objects | |
22 | >[ 0.603556] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.12.0-rc5 #26 | |
23 | >[ 0.605159] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006 | |
24 | >[ 0.609177] Call Trace: | |
25 | >[ 0.610063] ? dump_stack+0x5c/0x81 | |
26 | >[ 0.611118] ? kmem_cache_destroy+0x1aa/0x1c0 | |
27 | >[ 0.612632] ? acpi_sleep_proc_init+0x27/0x27 | |
28 | >[ 0.613906] ? acpi_os_delete_cache+0xa/0x10 | |
29 | >[ 0.617986] ? acpi_ut_delete_caches+0x3f/0x7b | |
30 | >[ 0.619293] ? acpi_terminate+0xa/0x14 | |
31 | >[ 0.620394] ? acpi_init+0x2af/0x34f | |
32 | >[ 0.621616] ? __class_create+0x4c/0x80 | |
33 | >[ 0.623412] ? video_setup+0x7f/0x7f | |
34 | >[ 0.624585] ? acpi_sleep_proc_init+0x27/0x27 | |
35 | >[ 0.625861] ? do_one_initcall+0x4e/0x1a0 | |
36 | >[ 0.627513] ? kernel_init_freeable+0x19e/0x21f | |
37 | >[ 0.628972] ? rest_init+0x80/0x80 | |
38 | >[ 0.630043] ? kernel_init+0xa/0x100 | |
39 | >[ 0.631084] ? ret_from_fork+0x25/0x30 | |
40 | >[ 0.633343] vgaarb: loaded | |
41 | >[ 0.635036] EDAC MC: Ver: 3.0.0 | |
42 | >[ 0.638601] PCI: Probing PCI hardware | |
43 | >[ 0.639833] PCI host bridge to bus 0000:00 | |
44 | >[ 0.641031] pci_bus 0000:00: root bus resource [io 0x0000-0xffff] | |
45 | > ... Continue to boot and log is omitted ... | |
46 | ||
47 | I analyzed this memory leak in detail and found acpi_ds_obj_stack_pop_and_ | |
48 | delete() function miscalculated the top of the stack. acpi_ds_obj_stack_push() | |
49 | function uses walk_state->operand_index for start position of the top, but | |
50 | acpi_ds_obj_stack_pop_and_delete() function considers index 0 for it. | |
51 | Therefore, this causes acpi operand memory leak. | |
52 | ||
53 | This cache leak causes a security threat because an old kernel (<= 4.9) shows | |
54 | memory locations of kernel functions in stack dump. Some malicious users | |
55 | could use this information to neutralize kernel ASLR. | |
56 | ||
57 | I made a patch to fix ACPI operand cache leak. | |
58 | ||
59 | Signed-off-by: Seunghun Han <kkamagui@gmail.com> | |
60 | ||
61 | Github-Location: https://github.com/acpica/acpica/pull/295/commits/987a3b5cf7175916e2a4b6ea5b8e70f830dfe732 | |
62 | --- | |
63 | source/components/dispatcher/dsutils.c | 9 ++++++++- | |
64 | 1 file changed, 8 insertions(+), 1 deletion(-) | |
65 | ||
70586bb3 | 66 | Index: acpica-unix-20191213/source/components/dispatcher/dsutils.c |
25d7dd99 | 67 | =================================================================== |
70586bb3 JB |
68 | --- acpica-unix-20191213.orig/source/components/dispatcher/dsutils.c |
69 | +++ acpica-unix-20191213/source/components/dispatcher/dsutils.c | |
70 | @@ -759,6 +759,8 @@ AcpiDsCreateOperands ( | |
25d7dd99 JB |
71 | ACPI_PARSE_OBJECT *Arguments[ACPI_OBJ_NUM_OPERANDS]; |
72 | UINT32 ArgCount = 0; | |
73 | UINT32 Index = WalkState->NumOperands; | |
74 | + UINT32 PrevNumOperands = WalkState->NumOperands; | |
75 | + UINT32 NewNumOperands; | |
76 | UINT32 i; | |
77 | ||
78 | ||
70586bb3 | 79 | @@ -791,6 +793,7 @@ AcpiDsCreateOperands ( |
25d7dd99 JB |
80 | |
81 | /* Create the interpreter arguments, in reverse order */ | |
82 | ||
83 | + NewNumOperands = Index; | |
84 | Index--; | |
85 | for (i = 0; i < ArgCount; i++) | |
86 | { | |
70586bb3 | 87 | @@ -818,7 +821,11 @@ Cleanup: |
25d7dd99 JB |
88 | * pop everything off of the operand stack and delete those |
89 | * objects | |
90 | */ | |
91 | - AcpiDsObjStackPopAndDelete (ArgCount, WalkState); | |
92 | + WalkState->NumOperands = i; | |
93 | + AcpiDsObjStackPopAndDelete (NewNumOperands, WalkState); | |
94 | + | |
95 | + /* Restore operand count */ | |
96 | + WalkState->NumOperands = PrevNumOperands; | |
97 | ||
98 | ACPI_EXCEPTION ((AE_INFO, Status, "While creating Arg %u", Index)); | |
99 | return_ACPI_STATUS (Status); |