]> git.pld-linux.org Git - packages/acpica.git/blob - cve-2017-13694.patch
- updated tests
[packages/acpica.git] / cve-2017-13694.patch
1 From 4a0243ecb4c94e2d73510d096c5ea4d0711fc6c0 Mon Sep 17 00:00:00 2001
2 From: Seunghun Han <kkamagui@gmail.com>
3 Date: Fri, 23 Jun 2017 14:19:48 +0900
4 Subject: [PATCH] acpi: acpica: fix acpi parse and parseext cache leaks
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 I'm Seunghun Han, and I work for National Security Research Institute of
10 South Korea.
11
12 I have been doing a research on ACPI and found an ACPI cache leak in ACPI
13 early abort cases.
14
15 Boot log of ACPI cache leak is as follows:
16 [    0.352414] ACPI: Added _OSI(Module Device)
17 [    0.353182] ACPI: Added _OSI(Processor Device)
18 [    0.353182] ACPI: Added _OSI(3.0 _SCP Extensions)
19 [    0.353182] ACPI: Added _OSI(Processor Aggregator Device)
20 [    0.356028] ACPI: Unable to start the ACPI Interpreter
21 [    0.356799] ACPI Error: Could not remove SCI handler (20170303/evmisc-281)
22 [    0.360215] kmem_cache_destroy Acpi-State: Slab cache still has objects
23 [    0.360648] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W
24 4.12.0-rc4-next-20170608+ #10
25 [    0.361273] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS
26 VirtualBox 12/01/2006
27 [    0.361873] Call Trace:
28 [    0.362243]  ? dump_stack+0x5c/0x81
29 [    0.362591]  ? kmem_cache_destroy+0x1aa/0x1c0
30 [    0.362944]  ? acpi_sleep_proc_init+0x27/0x27
31 [    0.363296]  ? acpi_os_delete_cache+0xa/0x10
32 [    0.363646]  ? acpi_ut_delete_caches+0x6d/0x7b
33 [    0.364000]  ? acpi_terminate+0xa/0x14
34 [    0.364000]  ? acpi_init+0x2af/0x34f
35 [    0.364000]  ? __class_create+0x4c/0x80
36 [    0.364000]  ? video_setup+0x7f/0x7f
37 [    0.364000]  ? acpi_sleep_proc_init+0x27/0x27
38 [    0.364000]  ? do_one_initcall+0x4e/0x1a0
39 [    0.364000]  ? kernel_init_freeable+0x189/0x20a
40 [    0.364000]  ? rest_init+0xc0/0xc0
41 [    0.364000]  ? kernel_init+0xa/0x100
42 [    0.364000]  ? ret_from_fork+0x25/0x30
43
44 I analyzed this memory leak in detail. I found that “Acpi-State” cache and
45 “Acpi-Parse” cache were merged because the size of cache objects was same
46 slab cache size.
47
48 I finally found “Acpi-Parse” cache and “Acpi-ParseExt” cache were leaked
49 using SLAB_NEVER_MERGE flag in kmem_cache_create() function.
50
51 Real ACPI cache leak point is as follows:
52 [    0.360101] ACPI: Added _OSI(Module Device)
53 [    0.360101] ACPI: Added _OSI(Processor Device)
54 [    0.360101] ACPI: Added _OSI(3.0 _SCP Extensions)
55 [    0.361043] ACPI: Added _OSI(Processor Aggregator Device)
56 [    0.364016] ACPI: Unable to start the ACPI Interpreter
57 [    0.365061] ACPI Error: Could not remove SCI handler (20170303/evmisc-281)
58 [    0.368174] kmem_cache_destroy Acpi-Parse: Slab cache still has objects
59 [    0.369332] CPU: 1 PID: 1 Comm: swapper/0 Tainted: G        W
60 4.12.0-rc4-next-20170608+ #8
61 [    0.371256] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS
62 VirtualBox 12/01/2006
63 [    0.372000] Call Trace:
64 [    0.372000]  ? dump_stack+0x5c/0x81
65 [    0.372000]  ? kmem_cache_destroy+0x1aa/0x1c0
66 [    0.372000]  ? acpi_sleep_proc_init+0x27/0x27
67 [    0.372000]  ? acpi_os_delete_cache+0xa/0x10
68 [    0.372000]  ? acpi_ut_delete_caches+0x56/0x7b
69 [    0.372000]  ? acpi_terminate+0xa/0x14
70 [    0.372000]  ? acpi_init+0x2af/0x34f
71 [    0.372000]  ? __class_create+0x4c/0x80
72 [    0.372000]  ? video_setup+0x7f/0x7f
73 [    0.372000]  ? acpi_sleep_proc_init+0x27/0x27
74 [    0.372000]  ? do_one_initcall+0x4e/0x1a0
75 [    0.372000]  ? kernel_init_freeable+0x189/0x20a
76 [    0.372000]  ? rest_init+0xc0/0xc0
77 [    0.372000]  ? kernel_init+0xa/0x100
78 [    0.372000]  ? ret_from_fork+0x25/0x30
79 [    0.388039] kmem_cache_destroy Acpi-ParseExt: Slab cache still has objects
80 [    0.389063] CPU: 1 PID: 1 Comm: swapper/0 Tainted: G        W
81 4.12.0-rc4-next-20170608+ #8
82 [    0.390557] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS
83 VirtualBox 12/01/2006
84 [    0.392000] Call Trace:
85 [    0.392000]  ? dump_stack+0x5c/0x81
86 [    0.392000]  ? kmem_cache_destroy+0x1aa/0x1c0
87 [    0.392000]  ? acpi_sleep_proc_init+0x27/0x27
88 [    0.392000]  ? acpi_os_delete_cache+0xa/0x10
89 [    0.392000]  ? acpi_ut_delete_caches+0x6d/0x7b
90 [    0.392000]  ? acpi_terminate+0xa/0x14
91 [    0.392000]  ? acpi_init+0x2af/0x34f
92 [    0.392000]  ? __class_create+0x4c/0x80
93 [    0.392000]  ? video_setup+0x7f/0x7f
94 [    0.392000]  ? acpi_sleep_proc_init+0x27/0x27
95 [    0.392000]  ? do_one_initcall+0x4e/0x1a0
96 [    0.392000]  ? kernel_init_freeable+0x189/0x20a
97 [    0.392000]  ? rest_init+0xc0/0xc0
98 [    0.392000]  ? kernel_init+0xa/0x100
99 [    0.392000]  ? ret_from_fork+0x25/0x30
100
101 When early abort is occurred due to invalid ACPI information, Linux kernel
102 terminates ACPI by calling acpi_terminate() function. The function calls
103 acpi_ut_delete_caches() function to delete local caches (acpi_gbl_namespace_
104 cache, state_cache, operand_cache, ps_node_cache, ps_node_ext_cache).
105
106 But the deletion codes in acpi_ut_delete_caches() function only delete
107 slab caches using kmem_cache_destroy() function, therefore the cache
108 objects should be flushed before acpi_ut_delete_caches() function.
109
110 “Acpi-Parse” cache and “Acpi-ParseExt” cache are used in an AML parse
111 function, acpi_ps_parse_loop(). The function should have flush codes to
112 handle an error state due to invalid AML codes.
113
114 This cache leak has a security threat because an old kernel (<= 4.9) shows
115 memory locations of kernel functions in stack dump. Some malicious users
116 could use this information to neutralize kernel ASLR.
117
118 To fix ACPI cache leak for enhancing security, I made a patch which has
119 flush codes in acpi_ps_parse_loop() function.
120
121 I hope that this patch improves the security of Linux kernel.
122
123 Thank you.
124
125 Signed-off-by: Seunghun Han <kkamagui@gmail.com>
126
127 Github-Location: https://github.com/acpica/acpica/pull/278/commits/4a0243ecb4c94e2d73510d096c5ea4d0711fc6c0
128
129 ---
130  source/components/parser/psobject.c | 44 ++++++++++++++-----------------------
131  1 file changed, 16 insertions(+), 28 deletions(-)
132
133 Index: acpica-unix-20191213/source/components/parser/psobject.c
134 ===================================================================
135 --- acpica-unix-20191213.orig/source/components/parser/psobject.c
136 +++ acpica-unix-20191213/source/components/parser/psobject.c
137 @@ -707,7 +707,8 @@ AcpiPsCompleteFinalOp (
138      ACPI_PARSE_OBJECT       *Op,
139      ACPI_STATUS             Status)
140  {
141 -    ACPI_STATUS             Status2;
142 +    ACPI_STATUS             ReturnStatus = AE_OK;
143 +    BOOLEAN                 Ascending = TRUE;
144  
145  
146      ACPI_FUNCTION_TRACE_PTR (PsCompleteFinalOp, WalkState);
147 @@ -724,7 +725,7 @@ AcpiPsCompleteFinalOp (
148      {
149          if (Op)
150          {
151 -            if (WalkState->AscendingCallback != NULL)
152 +            if (Ascending && WalkState->AscendingCallback != NULL)
153              {
154                  WalkState->Op = Op;
155                  WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
156 @@ -743,41 +744,28 @@ AcpiPsCompleteFinalOp (
157  
158                  if (Status == AE_CTRL_TERMINATE)
159                  {
160 -                    Status = AE_OK;
161 -
162 -                    /* Clean up */
163 -                    do
164 -                    {
165 -                        if (Op)
166 -                        {
167 -                            Status2 = AcpiPsCompleteThisOp (WalkState, Op);
168 -                            if (ACPI_FAILURE (Status2))
169 -                            {
170 -                                return_ACPI_STATUS (Status2);
171 -                            }
172 -                        }
173 -
174 -                        AcpiPsPopScope (&(WalkState->ParserState), &Op,
175 -                            &WalkState->ArgTypes, &WalkState->ArgCount);
176 -
177 -                    } while (Op);
178 -
179 -                    return_ACPI_STATUS (Status);
180 +                    Ascending = FALSE;
181 +                    ReturnStatus = AE_CTRL_TERMINATE;
182                  }
183  
184                  else if (ACPI_FAILURE (Status))
185                  {
186                      /* First error is most important */
187  
188 -                    (void) AcpiPsCompleteThisOp (WalkState, Op);
189 -                    return_ACPI_STATUS (Status);
190 +                    Ascending = FALSE;
191 +                    ReturnStatus = Status;
192                  }
193              }
194  
195 -            Status2 = AcpiPsCompleteThisOp (WalkState, Op);
196 -            if (ACPI_FAILURE (Status2))
197 +            Status = AcpiPsCompleteThisOp (WalkState, Op);
198 +            if (ACPI_FAILURE (Status))
199              {
200 -                return_ACPI_STATUS (Status2);
201 +                Ascending = FALSE;
202 +                if (ACPI_SUCCESS (ReturnStatus) ||
203 +                    ReturnStatus == AE_CTRL_TERMINATE)
204 +                {
205 +                    ReturnStatus = Status;
206 +                }
207              }
208          }
209  
210 @@ -786,5 +774,5 @@ AcpiPsCompleteFinalOp (
211  
212      } while (Op);
213  
214 -    return_ACPI_STATUS (Status);
215 +    return_ACPI_STATUS (ReturnStatus);
216  }
This page took 0.071799 seconds and 3 git commands to generate.