summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorMatt Fleming <matt@console-pimps.org>2009-10-10 16:03:11 +0100
committerMatt Fleming <matt@console-pimps.org>2009-10-11 17:12:28 +0100
commited4fe7f488008f38d5f423f0bcc736b1779d6ddc (patch)
tree9d569f812409f9738a99b6a0d398028e85512a28 /arch
parenta6a2f2ad67506090e332f440457553c0ec011d68 (diff)
downloadlinux-3.10-ed4fe7f488008f38d5f423f0bcc736b1779d6ddc.tar.gz
linux-3.10-ed4fe7f488008f38d5f423f0bcc736b1779d6ddc.tar.bz2
linux-3.10-ed4fe7f488008f38d5f423f0bcc736b1779d6ddc.zip
sh: Fix memory leak in dwarf_unwind_stack()
If we broke out of the while (1) loop because the return address of "frame" was zero, then "frame" needs to be free'd before we return. Signed-off-by: Matt Fleming <matt@console-pimps.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/sh/include/asm/dwarf.h1
-rw-r--r--arch/sh/kernel/dwarf.c22
2 files changed, 17 insertions, 6 deletions
diff --git a/arch/sh/include/asm/dwarf.h b/arch/sh/include/asm/dwarf.h
index aacdc746d07..eef87539963 100644
--- a/arch/sh/include/asm/dwarf.h
+++ b/arch/sh/include/asm/dwarf.h
@@ -376,6 +376,7 @@ static inline unsigned int DW_CFA_operand(unsigned long insn)
extern struct dwarf_frame *dwarf_unwind_stack(unsigned long,
struct dwarf_frame *);
+extern void dwarf_free_frame(struct dwarf_frame *);
extern int dwarf_parse_section(char *, char *, struct module *);
extern void dwarf_module_unload(struct module *);
diff --git a/arch/sh/kernel/dwarf.c b/arch/sh/kernel/dwarf.c
index 981315c6d65..ce8bff45d72 100644
--- a/arch/sh/kernel/dwarf.c
+++ b/arch/sh/kernel/dwarf.c
@@ -530,6 +530,16 @@ static int dwarf_cfa_execute_insns(unsigned char *insn_start,
}
/**
+ * dwarf_free_frame - free the memory allocated for @frame
+ * @frame: the frame to free
+ */
+void dwarf_free_frame(struct dwarf_frame *frame)
+{
+ dwarf_frame_free_regs(frame);
+ mempool_free(frame, dwarf_frame_pool);
+}
+
+/**
* dwarf_unwind_stack - recursively unwind the stack
* @pc: address of the function to unwind
* @prev: struct dwarf_frame of the previous stackframe on the callstack
@@ -649,8 +659,7 @@ struct dwarf_frame * dwarf_unwind_stack(unsigned long pc,
return frame;
bail:
- dwarf_frame_free_regs(frame);
- mempool_free(frame, dwarf_frame_pool);
+ dwarf_free_frame(frame);
return NULL;
}
@@ -837,10 +846,8 @@ static void dwarf_unwinder_dump(struct task_struct *task,
while (1) {
frame = dwarf_unwind_stack(return_addr, _frame);
- if (_frame) {
- dwarf_frame_free_regs(_frame);
- mempool_free(_frame, dwarf_frame_pool);
- }
+ if (_frame)
+ dwarf_free_frame(_frame);
_frame = frame;
@@ -850,6 +857,9 @@ static void dwarf_unwinder_dump(struct task_struct *task,
return_addr = frame->return_addr;
ops->address(data, return_addr, 1);
}
+
+ if (frame)
+ dwarf_free_frame(frame);
}
static struct unwinder dwarf_unwinder = {