coredump: add a new elf note with siginfo of the signal
Existing PRSTATUS note contains only si_signo, si_code, si_errno fields from the siginfo of the signal which caused core to be dumped. There are tools which try to analyze crashes for possible security implications, and they want to use, among other data, si_addr field from the SIGSEGV. This patch adds a new elf note, NT_SIGINFO, which contains the complete siginfo_t of the signal which killed the process. Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> Reviewed-by: Oleg Nesterov <oleg@redhat.com> Cc: Amerigo Wang <amwang@redhat.com> Cc: "Jonathan M. Foote" <jmfoote@cert.org> Cc: Roland McGrath <roland@hack.frob.com> Cc: Pedro Alves <palves@redhat.com> Cc: Fengguang Wu <fengguang.wu@intel.com> Cc: Stephen Rothwell <sfr@canb.auug.org.au> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
751f409db6
commit
49ae4d4b11
3 changed files with 36 additions and 2 deletions
|
@ -37,6 +37,10 @@
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
#include <asm/exec.h>
|
#include <asm/exec.h>
|
||||||
|
|
||||||
|
#ifndef user_siginfo_t
|
||||||
|
#define user_siginfo_t siginfo_t
|
||||||
|
#endif
|
||||||
|
|
||||||
static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs);
|
static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs);
|
||||||
static int load_elf_library(struct file *);
|
static int load_elf_library(struct file *);
|
||||||
static unsigned long elf_map(struct file *, unsigned long, struct elf_phdr *,
|
static unsigned long elf_map(struct file *, unsigned long, struct elf_phdr *,
|
||||||
|
@ -1372,6 +1376,16 @@ static void fill_auxv_note(struct memelfnote *note, struct mm_struct *mm)
|
||||||
fill_note(note, "CORE", NT_AUXV, i * sizeof(elf_addr_t), auxv);
|
fill_note(note, "CORE", NT_AUXV, i * sizeof(elf_addr_t), auxv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void fill_siginfo_note(struct memelfnote *note, user_siginfo_t *csigdata,
|
||||||
|
siginfo_t *siginfo)
|
||||||
|
{
|
||||||
|
mm_segment_t old_fs = get_fs();
|
||||||
|
set_fs(KERNEL_DS);
|
||||||
|
copy_siginfo_to_user((user_siginfo_t __user *) csigdata, siginfo);
|
||||||
|
set_fs(old_fs);
|
||||||
|
fill_note(note, "CORE", NT_SIGINFO, sizeof(*csigdata), csigdata);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CORE_DUMP_USE_REGSET
|
#ifdef CORE_DUMP_USE_REGSET
|
||||||
#include <linux/regset.h>
|
#include <linux/regset.h>
|
||||||
|
|
||||||
|
@ -1385,7 +1399,9 @@ struct elf_thread_core_info {
|
||||||
struct elf_note_info {
|
struct elf_note_info {
|
||||||
struct elf_thread_core_info *thread;
|
struct elf_thread_core_info *thread;
|
||||||
struct memelfnote psinfo;
|
struct memelfnote psinfo;
|
||||||
|
struct memelfnote signote;
|
||||||
struct memelfnote auxv;
|
struct memelfnote auxv;
|
||||||
|
user_siginfo_t csigdata;
|
||||||
size_t size;
|
size_t size;
|
||||||
int thread_notes;
|
int thread_notes;
|
||||||
};
|
};
|
||||||
|
@ -1559,6 +1575,9 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
|
||||||
fill_psinfo(psinfo, dump_task->group_leader, dump_task->mm);
|
fill_psinfo(psinfo, dump_task->group_leader, dump_task->mm);
|
||||||
info->size += notesize(&info->psinfo);
|
info->size += notesize(&info->psinfo);
|
||||||
|
|
||||||
|
fill_siginfo_note(&info->signote, &info->csigdata, siginfo);
|
||||||
|
info->size += notesize(&info->signote);
|
||||||
|
|
||||||
fill_auxv_note(&info->auxv, current->mm);
|
fill_auxv_note(&info->auxv, current->mm);
|
||||||
info->size += notesize(&info->auxv);
|
info->size += notesize(&info->auxv);
|
||||||
|
|
||||||
|
@ -1588,6 +1607,8 @@ static int write_note_info(struct elf_note_info *info,
|
||||||
|
|
||||||
if (first && !writenote(&info->psinfo, file, foffset))
|
if (first && !writenote(&info->psinfo, file, foffset))
|
||||||
return 0;
|
return 0;
|
||||||
|
if (first && !writenote(&info->signote, file, foffset))
|
||||||
|
return 0;
|
||||||
if (first && !writenote(&info->auxv, file, foffset))
|
if (first && !writenote(&info->auxv, file, foffset))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -1681,6 +1702,7 @@ struct elf_note_info {
|
||||||
#ifdef ELF_CORE_COPY_XFPREGS
|
#ifdef ELF_CORE_COPY_XFPREGS
|
||||||
elf_fpxregset_t *xfpu;
|
elf_fpxregset_t *xfpu;
|
||||||
#endif
|
#endif
|
||||||
|
user_siginfo_t csigdata;
|
||||||
int thread_status_size;
|
int thread_status_size;
|
||||||
int numnote;
|
int numnote;
|
||||||
};
|
};
|
||||||
|
@ -1690,8 +1712,8 @@ static int elf_note_info_init(struct elf_note_info *info)
|
||||||
memset(info, 0, sizeof(*info));
|
memset(info, 0, sizeof(*info));
|
||||||
INIT_LIST_HEAD(&info->thread_list);
|
INIT_LIST_HEAD(&info->thread_list);
|
||||||
|
|
||||||
/* Allocate space for six ELF notes */
|
/* Allocate space for ELF notes */
|
||||||
info->notes = kmalloc(6 * sizeof(struct memelfnote), GFP_KERNEL);
|
info->notes = kmalloc(7 * sizeof(struct memelfnote), GFP_KERNEL);
|
||||||
if (!info->notes)
|
if (!info->notes)
|
||||||
return 0;
|
return 0;
|
||||||
info->psinfo = kmalloc(sizeof(*info->psinfo), GFP_KERNEL);
|
info->psinfo = kmalloc(sizeof(*info->psinfo), GFP_KERNEL);
|
||||||
|
@ -1763,6 +1785,7 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
|
||||||
|
|
||||||
info->numnote = 2;
|
info->numnote = 2;
|
||||||
|
|
||||||
|
fill_siginfo_note(&info->notes[info->numnote++], &info->csigdata, siginfo);
|
||||||
fill_auxv_note(&info->notes[info->numnote++], current->mm);
|
fill_auxv_note(&info->notes[info->numnote++], current->mm);
|
||||||
|
|
||||||
/* Try to dump the FPU. */
|
/* Try to dump the FPU. */
|
||||||
|
|
|
@ -37,6 +37,12 @@
|
||||||
#define elf_note elf32_note
|
#define elf_note elf32_note
|
||||||
#define elf_addr_t Elf32_Addr
|
#define elf_addr_t Elf32_Addr
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some data types as stored in coredump.
|
||||||
|
*/
|
||||||
|
#define user_siginfo_t compat_siginfo_t
|
||||||
|
#define copy_siginfo_to_user copy_siginfo_to_user32
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The machine-dependent core note format types are defined in elfcore-compat.h,
|
* The machine-dependent core note format types are defined in elfcore-compat.h,
|
||||||
* which requires asm/elf.h to define compat_elf_gregset_t et al.
|
* which requires asm/elf.h to define compat_elf_gregset_t et al.
|
||||||
|
|
|
@ -372,6 +372,11 @@ typedef struct elf64_shdr {
|
||||||
#define NT_PRPSINFO 3
|
#define NT_PRPSINFO 3
|
||||||
#define NT_TASKSTRUCT 4
|
#define NT_TASKSTRUCT 4
|
||||||
#define NT_AUXV 6
|
#define NT_AUXV 6
|
||||||
|
/*
|
||||||
|
* Note to userspace developers: size of NT_SIGINFO note may increase
|
||||||
|
* in the future to accomodate more fields, don't assume it is fixed!
|
||||||
|
*/
|
||||||
|
#define NT_SIGINFO 0x53494749
|
||||||
#define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */
|
#define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */
|
||||||
#define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */
|
#define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */
|
||||||
#define NT_PPC_SPE 0x101 /* PowerPC SPE/EVR registers */
|
#define NT_PPC_SPE 0x101 /* PowerPC SPE/EVR registers */
|
||||||
|
|
Loading…
Reference in a new issue