diff options
author | Jan Beulich <jbeulich@novell.com> | 2006-12-06 20:14:13 -0500 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2006-12-06 20:14:13 -0500 |
commit | 359ad0d4015a9ab39243f2ebc4eb07915bd618b2 (patch) | |
tree | 90f05d8d9ab048029bfe1e451a012b4d5896aafe /arch | |
parent | eef5e0d185fc049bda11fa14ba286fbd357da896 (diff) |
[PATCH] unwinder: more sanity checks in Dwarf2 unwinder
Tighten the requirements on both input to and output from the Dwarf2
unwinder.
Signed-off-by: Jan Beulich <jbeulich@novell.com>
Signed-off-by: Andi Kleen <ak@suse.de>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/i386/kernel/traps.c | 7 | ||||
-rw-r--r-- | arch/x86_64/kernel/traps.c | 7 |
2 files changed, 14 insertions, 0 deletions
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 86d8476be4fe..c447807e2a45 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c | |||
@@ -161,12 +161,19 @@ dump_trace_unwind(struct unwind_frame_info *info, void *data) | |||
161 | { | 161 | { |
162 | struct ops_and_data *oad = (struct ops_and_data *)data; | 162 | struct ops_and_data *oad = (struct ops_and_data *)data; |
163 | int n = 0; | 163 | int n = 0; |
164 | unsigned long sp = UNW_SP(info); | ||
164 | 165 | ||
166 | if (arch_unw_user_mode(info)) | ||
167 | return -1; | ||
165 | while (unwind(info) == 0 && UNW_PC(info)) { | 168 | while (unwind(info) == 0 && UNW_PC(info)) { |
166 | n++; | 169 | n++; |
167 | oad->ops->address(oad->data, UNW_PC(info)); | 170 | oad->ops->address(oad->data, UNW_PC(info)); |
168 | if (arch_unw_user_mode(info)) | 171 | if (arch_unw_user_mode(info)) |
169 | break; | 172 | break; |
173 | if ((sp & ~(PAGE_SIZE - 1)) == (UNW_SP(info) & ~(PAGE_SIZE - 1)) | ||
174 | && sp > UNW_SP(info)) | ||
175 | break; | ||
176 | sp = UNW_SP(info); | ||
170 | } | 177 | } |
171 | return n; | 178 | return n; |
172 | } | 179 | } |
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index 9864d195c408..4fdd162f0bef 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c | |||
@@ -225,12 +225,19 @@ static int dump_trace_unwind(struct unwind_frame_info *info, void *context) | |||
225 | { | 225 | { |
226 | struct ops_and_data *oad = (struct ops_and_data *)context; | 226 | struct ops_and_data *oad = (struct ops_and_data *)context; |
227 | int n = 0; | 227 | int n = 0; |
228 | unsigned long sp = UNW_SP(info); | ||
228 | 229 | ||
230 | if (arch_unw_user_mode(info)) | ||
231 | return -1; | ||
229 | while (unwind(info) == 0 && UNW_PC(info)) { | 232 | while (unwind(info) == 0 && UNW_PC(info)) { |
230 | n++; | 233 | n++; |
231 | oad->ops->address(oad->data, UNW_PC(info)); | 234 | oad->ops->address(oad->data, UNW_PC(info)); |
232 | if (arch_unw_user_mode(info)) | 235 | if (arch_unw_user_mode(info)) |
233 | break; | 236 | break; |
237 | if ((sp & ~(PAGE_SIZE - 1)) == (UNW_SP(info) & ~(PAGE_SIZE - 1)) | ||
238 | && sp > UNW_SP(info)) | ||
239 | break; | ||
240 | sp = UNW_SP(info); | ||
234 | } | 241 | } |
235 | return n; | 242 | return n; |
236 | } | 243 | } |