diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2012-09-25 21:34:50 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-09-26 22:20:21 -0400 |
commit | f34f9d186df35e5c39163444c43b4fc6255e39c5 (patch) | |
tree | 4e66ee662fb2bd0c50c8b3aed27e9ce5c508059a /fs/binfmt_elf.c | |
parent | 260ef31135c2250ec01aa343192ec2a071b8e05f (diff) |
coredump: prevent double-free on an error path in core dumper
In !CORE_DUMP_USE_REGSET case, if elf_note_info_init fails to allocate
memory for info->fields, it frees already allocated stuff and returns
error to its caller, fill_note_info. Which in turn returns error to its
caller, elf_core_dump. Which jumps to cleanup label and calls
free_note_info, which will happily try to free all info->fields again.
BOOM.
This is the fix.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Cc: Venu Byravarasu <vbyravarasu@nvidia.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Diffstat (limited to 'fs/binfmt_elf.c')
-rw-r--r-- | fs/binfmt_elf.c | 19 |
1 files changed, 4 insertions, 15 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 1b52956afe33..0225fddf49b7 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -1696,30 +1696,19 @@ static int elf_note_info_init(struct elf_note_info *info) | |||
1696 | return 0; | 1696 | return 0; |
1697 | info->psinfo = kmalloc(sizeof(*info->psinfo), GFP_KERNEL); | 1697 | info->psinfo = kmalloc(sizeof(*info->psinfo), GFP_KERNEL); |
1698 | if (!info->psinfo) | 1698 | if (!info->psinfo) |
1699 | goto notes_free; | 1699 | return 0; |
1700 | info->prstatus = kmalloc(sizeof(*info->prstatus), GFP_KERNEL); | 1700 | info->prstatus = kmalloc(sizeof(*info->prstatus), GFP_KERNEL); |
1701 | if (!info->prstatus) | 1701 | if (!info->prstatus) |
1702 | goto psinfo_free; | 1702 | return 0; |
1703 | info->fpu = kmalloc(sizeof(*info->fpu), GFP_KERNEL); | 1703 | info->fpu = kmalloc(sizeof(*info->fpu), GFP_KERNEL); |
1704 | if (!info->fpu) | 1704 | if (!info->fpu) |
1705 | goto prstatus_free; | 1705 | return 0; |
1706 | #ifdef ELF_CORE_COPY_XFPREGS | 1706 | #ifdef ELF_CORE_COPY_XFPREGS |
1707 | info->xfpu = kmalloc(sizeof(*info->xfpu), GFP_KERNEL); | 1707 | info->xfpu = kmalloc(sizeof(*info->xfpu), GFP_KERNEL); |
1708 | if (!info->xfpu) | 1708 | if (!info->xfpu) |
1709 | goto fpu_free; | 1709 | return 0; |
1710 | #endif | 1710 | #endif |
1711 | return 1; | 1711 | return 1; |
1712 | #ifdef ELF_CORE_COPY_XFPREGS | ||
1713 | fpu_free: | ||
1714 | kfree(info->fpu); | ||
1715 | #endif | ||
1716 | prstatus_free: | ||
1717 | kfree(info->prstatus); | ||
1718 | psinfo_free: | ||
1719 | kfree(info->psinfo); | ||
1720 | notes_free: | ||
1721 | kfree(info->notes); | ||
1722 | return 0; | ||
1723 | } | 1712 | } |
1724 | 1713 | ||
1725 | static int fill_note_info(struct elfhdr *elf, int phdrs, | 1714 | static int fill_note_info(struct elfhdr *elf, int phdrs, |